From c8aa431253246e619045b8cbdabedb327ab03b3a Mon Sep 17 00:00:00 2001 From: Mark Dittmer Date: Sat, 23 May 2026 14:32:44 +0000 Subject: [PATCH] [anneal][v2] Import vendored cargo dependencies gherrit-pr-id: Gidzrynm2d4gpg6tdthfg66sexvlcu4nt --- anneal/v2/Cargo.lock | 564 +- anneal/v2/Cargo.toml | 13 + .../v2/vendor/addr2line/.cargo-checksum.json | 1 + .../v2/vendor/addr2line/.cargo_vcs_info.json | 6 + anneal/v2/vendor/addr2line/CHANGELOG.md | 485 + anneal/v2/vendor/addr2line/Cargo.lock | 1089 + anneal/v2/vendor/addr2line/Cargo.toml | 164 + anneal/v2/vendor/addr2line/Cargo.toml.orig | 92 + anneal/v2/vendor/addr2line/LICENSE-APACHE | 201 + anneal/v2/vendor/addr2line/LICENSE-MIT | 25 + anneal/v2/vendor/addr2line/README.md | 50 + .../v2/vendor/addr2line/src/bin/addr2line.rs | 313 + anneal/v2/vendor/addr2line/src/frame.rs | 221 + anneal/v2/vendor/addr2line/src/function.rs | 563 + anneal/v2/vendor/addr2line/src/lib.rs | 418 + anneal/v2/vendor/addr2line/src/line.rs | 313 + anneal/v2/vendor/addr2line/src/loader.rs | 499 + anneal/v2/vendor/addr2line/src/lookup.rs | 261 + anneal/v2/vendor/addr2line/src/unit.rs | 598 + .../vendor/backtrace-ext/.cargo-checksum.json | 1 + .../vendor/backtrace-ext/.cargo_vcs_info.json | 5 + .../backtrace-ext/.github/workflows/ci.yml | 88 + anneal/v2/vendor/backtrace-ext/Cargo.lock | 515 + anneal/v2/vendor/backtrace-ext/Cargo.toml | 27 + .../v2/vendor/backtrace-ext/Cargo.toml.orig | 17 + anneal/v2/vendor/backtrace-ext/README.md | 8 + .../vendor/backtrace-ext/examples/miette.rs | 99 + anneal/v2/vendor/backtrace-ext/src/lib.rs | 277 + anneal/v2/vendor/backtrace-ext/src/test.rs | 524 + .../v2/vendor/backtrace/.cargo-checksum.json | 1 + .../v2/vendor/backtrace/.cargo_vcs_info.json | 6 + .../backtrace/.github/workflows/main.yml | 283 + .../backtrace/.github/workflows/publish.yml | 52 + anneal/v2/vendor/backtrace/CHANGELOG.md | 33 + anneal/v2/vendor/backtrace/Cargo.lock | 169 + anneal/v2/vendor/backtrace/Cargo.toml | 157 + anneal/v2/vendor/backtrace/Cargo.toml.orig | 121 + anneal/v2/vendor/backtrace/LICENSE-APACHE | 201 + anneal/v2/vendor/backtrace/LICENSE-MIT | 25 + anneal/v2/vendor/backtrace/README.md | 85 + .../v2/vendor/backtrace/benches/benchmarks.rs | 92 + anneal/v2/vendor/backtrace/bindings.txt | 63 + .../v2/vendor/backtrace/examples/backtrace.rs | 5 + anneal/v2/vendor/backtrace/examples/raw.rs | 52 + .../backtrace/src/backtrace/libunwind.rs | 301 + .../v2/vendor/backtrace/src/backtrace/miri.rs | 119 + .../v2/vendor/backtrace/src/backtrace/mod.rs | 206 + .../v2/vendor/backtrace/src/backtrace/noop.rs | 32 + .../vendor/backtrace/src/backtrace/win32.rs | 214 + .../vendor/backtrace/src/backtrace/win64.rs | 151 + anneal/v2/vendor/backtrace/src/capture.rs | 621 + anneal/v2/vendor/backtrace/src/dbghelp.rs | 487 + anneal/v2/vendor/backtrace/src/lib.rs | 242 + anneal/v2/vendor/backtrace/src/print.rs | 310 + .../v2/vendor/backtrace/src/print/fuchsia.rs | 432 + .../vendor/backtrace/src/symbolize/dbghelp.rs | 325 + .../vendor/backtrace/src/symbolize/gimli.rs | 567 + .../backtrace/src/symbolize/gimli/coff.rs | 116 + .../backtrace/src/symbolize/gimli/elf.rs | 567 + .../backtrace/src/symbolize/gimli/libs_aix.rs | 85 + .../symbolize/gimli/libs_dl_iterate_phdr.rs | 122 + .../src/symbolize/gimli/libs_haiku.rs | 50 + .../src/symbolize/gimli/libs_illumos.rs | 101 + .../src/symbolize/gimli/libs_libnx.rs | 28 + .../src/symbolize/gimli/libs_macos.rs | 154 + .../src/symbolize/gimli/libs_windows.rs | 158 + .../backtrace/src/symbolize/gimli/lru.rs | 75 + .../backtrace/src/symbolize/gimli/macho.rs | 318 + .../src/symbolize/gimli/mmap_fake.rs | 27 + .../src/symbolize/gimli/mmap_unix.rs | 51 + .../src/symbolize/gimli/mmap_windows.rs | 67 + .../gimli/parse_running_mmaps_unix.rs | 304 + .../backtrace/src/symbolize/gimli/stash.rs | 51 + .../backtrace/src/symbolize/gimli/xcoff.rs | 188 + .../v2/vendor/backtrace/src/symbolize/miri.rs | 56 + .../v2/vendor/backtrace/src/symbolize/mod.rs | 452 + .../v2/vendor/backtrace/src/symbolize/noop.rs | 41 + anneal/v2/vendor/backtrace/src/types.rs | 83 + anneal/v2/vendor/backtrace/src/windows_sys.rs | 668 + .../backtrace/src/windows_sys_arm32_shim.rs | 53 + .../backtrace/tests/accuracy/auxiliary.rs | 15 + .../vendor/backtrace/tests/accuracy/main.rs | 121 + .../v2/vendor/backtrace/tests/common/mod.rs | 14 + .../backtrace/tests/concurrent-panics.rs | 72 + .../backtrace/tests/current-exe-mismatch.rs | 139 + .../v2/vendor/backtrace/tests/long_fn_name.rs | 48 + .../vendor/backtrace/tests/sgx-image-base.rs | 56 + .../backtrace/tests/skip_inner_frames.rs | 51 + anneal/v2/vendor/backtrace/tests/smoke.rs | 325 + .../block-buffer-0.10.4/.cargo-checksum.json | 1 + .../block-buffer-0.10.4/.cargo_vcs_info.json | 6 + .../vendor/block-buffer-0.10.4/CHANGELOG.md | 53 + .../v2/vendor/block-buffer-0.10.4/Cargo.toml | 32 + .../block-buffer-0.10.4/Cargo.toml.orig | 15 + .../vendor/block-buffer-0.10.4/LICENSE-APACHE | 201 + .../v2/vendor/block-buffer-0.10.4/LICENSE-MIT | 25 + .../v2/vendor/block-buffer-0.10.4/README.md | 40 + .../v2/vendor/block-buffer-0.10.4/src/lib.rs | 350 + .../vendor/block-buffer-0.10.4/src/sealed.rs | 67 + .../vendor/block-buffer-0.10.4/tests/mod.rs | 196 + anneal/v2/vendor/bumpalo/.cargo-checksum.json | 1 + anneal/v2/vendor/bumpalo/.cargo_vcs_info.json | 6 + anneal/v2/vendor/bumpalo/CHANGELOG.md | 929 + anneal/v2/vendor/bumpalo/Cargo.lock | 697 + anneal/v2/vendor/bumpalo/Cargo.toml | 99 + anneal/v2/vendor/bumpalo/Cargo.toml.orig | 73 + anneal/v2/vendor/bumpalo/LICENSE-APACHE | 201 + anneal/v2/vendor/bumpalo/LICENSE-MIT | 25 + anneal/v2/vendor/bumpalo/README.md | 261 + anneal/v2/vendor/bumpalo/rustfmt.toml | 1 + anneal/v2/vendor/bumpalo/src/alloc.rs | 794 + anneal/v2/vendor/bumpalo/src/boxed.rs | 747 + .../bumpalo/src/collections/collect_in.rs | 152 + .../v2/vendor/bumpalo/src/collections/mod.rs | 93 + .../vendor/bumpalo/src/collections/raw_vec.rs | 781 + .../bumpalo/src/collections/str/lossy.rs | 209 + .../vendor/bumpalo/src/collections/str/mod.rs | 43 + .../vendor/bumpalo/src/collections/string.rs | 2191 ++ .../v2/vendor/bumpalo/src/collections/vec.rs | 3051 +++ anneal/v2/vendor/bumpalo/src/lib.rs | 2710 ++ anneal/v2/vendor/camino/.cargo-checksum.json | 1 + anneal/v2/vendor/camino/.cargo_vcs_info.json | 6 + anneal/v2/vendor/camino/.claude/settings.json | 11 + anneal/v2/vendor/camino/CHANGELOG.md | 223 + anneal/v2/vendor/camino/Cargo.lock | 379 + anneal/v2/vendor/camino/Cargo.lock.rust161 | 516 + anneal/v2/vendor/camino/Cargo.toml | 82 + anneal/v2/vendor/camino/Cargo.toml.orig | 39 + anneal/v2/vendor/camino/LICENSE-APACHE | 201 + anneal/v2/vendor/camino/LICENSE-MIT | 23 + anneal/v2/vendor/camino/README.md | 135 + anneal/v2/vendor/camino/build.rs | 104 + anneal/v2/vendor/camino/clippy.toml | 1 + anneal/v2/vendor/camino/release.toml | 8 + anneal/v2/vendor/camino/rustfmt.toml | 3 + anneal/v2/vendor/camino/src/lib.rs | 3544 +++ anneal/v2/vendor/camino/src/proptest_impls.rs | 60 + anneal/v2/vendor/camino/src/serde_impls.rs | 276 + anneal/v2/vendor/camino/src/tests.rs | 54 + .../vendor/camino/tests/integration_tests.rs | 115 + .../cargo-platform/.cargo-checksum.json | 1 + .../cargo-platform/.cargo_vcs_info.json | 6 + anneal/v2/vendor/cargo-platform/Cargo.lock | 75 + anneal/v2/vendor/cargo-platform/Cargo.toml | 67 + .../v2/vendor/cargo-platform/Cargo.toml.orig | 20 + .../v2/vendor/cargo-platform/LICENSE-APACHE | 201 + anneal/v2/vendor/cargo-platform/LICENSE-MIT | 23 + anneal/v2/vendor/cargo-platform/README.md | 2 + .../vendor/cargo-platform/examples/matches.rs | 57 + anneal/v2/vendor/cargo-platform/src/cfg.rs | 429 + anneal/v2/vendor/cargo-platform/src/error.rs | 67 + anneal/v2/vendor/cargo-platform/src/lib.rs | 182 + .../vendor/cargo-platform/tests/test_cfg.rs | 292 + .../cargo_metadata/.cargo-checksum.json | 1 + .../cargo_metadata/.cargo_vcs_info.json | 6 + .../cargo_metadata/.github/workflows/main.yml | 52 + .../.github/workflows/release.yml | 72 + anneal/v2/vendor/cargo_metadata/CHANGELOG.md | 103 + anneal/v2/vendor/cargo_metadata/Cargo.lock | 244 + anneal/v2/vendor/cargo_metadata/Cargo.toml | 77 + .../v2/vendor/cargo_metadata/Cargo.toml.orig | 31 + anneal/v2/vendor/cargo_metadata/LICENSE-MIT | 23 + anneal/v2/vendor/cargo_metadata/README.md | 12 + anneal/v2/vendor/cargo_metadata/clippy.toml | 3 + .../vendor/cargo_metadata/src/dependency.rs | 87 + .../vendor/cargo_metadata/src/diagnostic.rs | 160 + anneal/v2/vendor/cargo_metadata/src/errors.rs | 52 + anneal/v2/vendor/cargo_metadata/src/lib.rs | 1330 + .../v2/vendor/cargo_metadata/src/libtest.rs | 165 + .../v2/vendor/cargo_metadata/src/messages.rs | 297 + .../vendor/cargo_metadata/tests/selftest.rs | 214 + .../cargo_metadata/tests/test_samples.rs | 961 + .../v2/vendor/clap-cargo/.cargo-checksum.json | 1 + .../v2/vendor/clap-cargo/.cargo_vcs_info.json | 6 + anneal/v2/vendor/clap-cargo/Cargo.lock | 378 + anneal/v2/vendor/clap-cargo/Cargo.toml | 203 + anneal/v2/vendor/clap-cargo/Cargo.toml.orig | 146 + anneal/v2/vendor/clap-cargo/LICENSE-APACHE | 202 + anneal/v2/vendor/clap-cargo/LICENSE-MIT | 19 + anneal/v2/vendor/clap-cargo/README.md | 54 + anneal/v2/vendor/clap-cargo/examples/flags.rs | 16 + anneal/v2/vendor/clap-cargo/src/features.rs | 170 + anneal/v2/vendor/clap-cargo/src/lib.rs | 60 + anneal/v2/vendor/clap-cargo/src/manifest.rs | 69 + anneal/v2/vendor/clap-cargo/src/style.rs | 101 + anneal/v2/vendor/clap-cargo/src/workspace.rs | 394 + anneal/v2/vendor/console/.cargo-checksum.json | 1 + anneal/v2/vendor/console/.cargo_vcs_info.json | 6 + anneal/v2/vendor/console/CHANGELOG.md | 120 + anneal/v2/vendor/console/Cargo.lock | 303 + anneal/v2/vendor/console/Cargo.toml | 92 + anneal/v2/vendor/console/Cargo.toml.orig | 72 + anneal/v2/vendor/console/LICENSE | 22 + anneal/v2/vendor/console/README.md | 76 + anneal/v2/vendor/console/src/ansi.rs | 471 + anneal/v2/vendor/console/src/common_term.rs | 72 + anneal/v2/vendor/console/src/kb.rs | 32 + anneal/v2/vendor/console/src/lib.rs | 123 + anneal/v2/vendor/console/src/term.rs | 672 + anneal/v2/vendor/console/src/unix_term.rs | 424 + anneal/v2/vendor/console/src/utils.rs | 1197 + anneal/v2/vendor/console/src/wasm_term.rs | 60 + .../vendor/console/src/windows_term/colors.rs | 450 + .../v2/vendor/console/src/windows_term/mod.rs | 639 + .../cpufeatures-0.2.17/.cargo-checksum.json | 1 + .../cpufeatures-0.2.17/.cargo_vcs_info.json | 6 + .../v2/vendor/cpufeatures-0.2.17/CHANGELOG.md | 168 + .../v2/vendor/cpufeatures-0.2.17/Cargo.lock | 16 + .../v2/vendor/cpufeatures-0.2.17/Cargo.toml | 71 + .../vendor/cpufeatures-0.2.17/Cargo.toml.orig | 27 + .../vendor/cpufeatures-0.2.17/LICENSE-APACHE | 201 + .../v2/vendor/cpufeatures-0.2.17/LICENSE-MIT | 25 + anneal/v2/vendor/cpufeatures-0.2.17/README.md | 126 + .../vendor/cpufeatures-0.2.17/src/aarch64.rs | 167 + .../v2/vendor/cpufeatures-0.2.17/src/lib.rs | 220 + .../cpufeatures-0.2.17/src/loongarch64.rs | 106 + .../v2/vendor/cpufeatures-0.2.17/src/miri.rs | 20 + .../v2/vendor/cpufeatures-0.2.17/src/x86.rs | 152 + .../cpufeatures-0.2.17/tests/aarch64.rs | 17 + .../cpufeatures-0.2.17/tests/loongarch64.rs | 20 + .../v2/vendor/cpufeatures-0.2.17/tests/x86.rs | 17 + .../crossbeam-deque/.cargo-checksum.json | 1 + .../crossbeam-deque/.cargo_vcs_info.json | 6 + anneal/v2/vendor/crossbeam-deque/CHANGELOG.md | 141 + anneal/v2/vendor/crossbeam-deque/Cargo.toml | 92 + .../v2/vendor/crossbeam-deque/Cargo.toml.orig | 34 + .../v2/vendor/crossbeam-deque/LICENSE-APACHE | 201 + anneal/v2/vendor/crossbeam-deque/LICENSE-MIT | 27 + anneal/v2/vendor/crossbeam-deque/README.md | 46 + anneal/v2/vendor/crossbeam-deque/src/deque.rs | 2216 ++ anneal/v2/vendor/crossbeam-deque/src/lib.rs | 106 + .../v2/vendor/crossbeam-deque/tests/fifo.rs | 357 + .../vendor/crossbeam-deque/tests/injector.rs | 391 + .../v2/vendor/crossbeam-deque/tests/lifo.rs | 359 + .../v2/vendor/crossbeam-deque/tests/steal.rs | 212 + .../crossbeam-epoch/.cargo-checksum.json | 1 + .../crossbeam-epoch/.cargo_vcs_info.json | 6 + anneal/v2/vendor/crossbeam-epoch/CHANGELOG.md | 204 + anneal/v2/vendor/crossbeam-epoch/Cargo.lock | 457 + anneal/v2/vendor/crossbeam-epoch/Cargo.toml | 57 + .../v2/vendor/crossbeam-epoch/Cargo.toml.orig | 56 + .../v2/vendor/crossbeam-epoch/LICENSE-APACHE | 201 + anneal/v2/vendor/crossbeam-epoch/LICENSE-MIT | 27 + anneal/v2/vendor/crossbeam-epoch/README.md | 53 + .../vendor/crossbeam-epoch/benches/defer.rs | 69 + .../vendor/crossbeam-epoch/benches/flush.rs | 52 + .../v2/vendor/crossbeam-epoch/benches/pin.rs | 31 + .../crossbeam-epoch/examples/sanitize.rs | 66 + .../v2/vendor/crossbeam-epoch/src/atomic.rs | 1702 ++ .../vendor/crossbeam-epoch/src/collector.rs | 464 + .../v2/vendor/crossbeam-epoch/src/default.rs | 93 + .../v2/vendor/crossbeam-epoch/src/deferred.rs | 146 + anneal/v2/vendor/crossbeam-epoch/src/epoch.rs | 132 + anneal/v2/vendor/crossbeam-epoch/src/guard.rs | 523 + .../v2/vendor/crossbeam-epoch/src/internal.rs | 600 + anneal/v2/vendor/crossbeam-epoch/src/lib.rs | 166 + .../vendor/crossbeam-epoch/src/sync/list.rs | 487 + .../v2/vendor/crossbeam-epoch/src/sync/mod.rs | 7 + .../crossbeam-epoch/src/sync/once_lock.rs | 88 + .../vendor/crossbeam-epoch/src/sync/queue.rs | 468 + .../v2/vendor/crossbeam-epoch/tests/loom.rs | 157 + .../crossbeam-utils/.cargo-checksum.json | 1 + .../crossbeam-utils/.cargo_vcs_info.json | 6 + anneal/v2/vendor/crossbeam-utils/CHANGELOG.md | 243 + anneal/v2/vendor/crossbeam-utils/Cargo.toml | 101 + .../v2/vendor/crossbeam-utils/Cargo.toml.orig | 46 + .../v2/vendor/crossbeam-utils/LICENSE-APACHE | 201 + anneal/v2/vendor/crossbeam-utils/LICENSE-MIT | 27 + anneal/v2/vendor/crossbeam-utils/README.md | 73 + .../crossbeam-utils/benches/atomic_cell.rs | 156 + .../v2/vendor/crossbeam-utils/build-common.rs | 13 + anneal/v2/vendor/crossbeam-utils/build.rs | 48 + anneal/v2/vendor/crossbeam-utils/no_atomic.rs | 9 + .../crossbeam-utils/src/atomic/atomic_cell.rs | 1182 + .../crossbeam-utils/src/atomic/consume.rs | 111 + .../vendor/crossbeam-utils/src/atomic/mod.rs | 32 + .../crossbeam-utils/src/atomic/seq_lock.rs | 112 + .../src/atomic/seq_lock_wide.rs | 155 + .../v2/vendor/crossbeam-utils/src/backoff.rs | 287 + .../crossbeam-utils/src/cache_padded.rs | 217 + anneal/v2/vendor/crossbeam-utils/src/lib.rs | 110 + .../v2/vendor/crossbeam-utils/src/sync/mod.rs | 17 + .../crossbeam-utils/src/sync/once_lock.rs | 88 + .../vendor/crossbeam-utils/src/sync/parker.rs | 415 + .../crossbeam-utils/src/sync/sharded_lock.rs | 638 + .../crossbeam-utils/src/sync/wait_group.rs | 145 + .../v2/vendor/crossbeam-utils/src/thread.rs | 611 + .../crossbeam-utils/tests/atomic_cell.rs | 374 + .../crossbeam-utils/tests/cache_padded.rs | 113 + .../v2/vendor/crossbeam-utils/tests/parker.rs | 41 + .../crossbeam-utils/tests/sharded_lock.rs | 252 + .../v2/vendor/crossbeam-utils/tests/thread.rs | 215 + .../crossbeam-utils/tests/wait_group.rs | 67 + .../crypto-common-0.1.7/.cargo-checksum.json | 1 + .../crypto-common-0.1.7/.cargo_vcs_info.json | 6 + .../vendor/crypto-common-0.1.7/CHANGELOG.md | 53 + .../v2/vendor/crypto-common-0.1.7/Cargo.lock | 72 + .../v2/vendor/crypto-common-0.1.7/Cargo.toml | 62 + .../crypto-common-0.1.7/Cargo.toml.orig | 27 + .../vendor/crypto-common-0.1.7/LICENSE-APACHE | 201 + .../v2/vendor/crypto-common-0.1.7/LICENSE-MIT | 25 + .../v2/vendor/crypto-common-0.1.7/README.md | 53 + .../v2/vendor/crypto-common-0.1.7/src/lib.rs | 311 + .../vendor/digest-0.10.7/.cargo-checksum.json | 1 + .../vendor/digest-0.10.7/.cargo_vcs_info.json | 6 + anneal/v2/vendor/digest-0.10.7/CHANGELOG.md | 137 + anneal/v2/vendor/digest-0.10.7/Cargo.toml | 70 + .../v2/vendor/digest-0.10.7/Cargo.toml.orig | 35 + anneal/v2/vendor/digest-0.10.7/LICENSE-APACHE | 201 + anneal/v2/vendor/digest-0.10.7/LICENSE-MIT | 25 + anneal/v2/vendor/digest-0.10.7/README.md | 164 + .../v2/vendor/digest-0.10.7/src/core_api.rs | 119 + .../digest-0.10.7/src/core_api/ct_variable.rs | 204 + .../digest-0.10.7/src/core_api/rt_variable.rs | 166 + .../digest-0.10.7/src/core_api/wrapper.rs | 290 + .../digest-0.10.7/src/core_api/xof_reader.rs | 63 + anneal/v2/vendor/digest-0.10.7/src/dev.rs | 78 + .../v2/vendor/digest-0.10.7/src/dev/fixed.rs | 65 + anneal/v2/vendor/digest-0.10.7/src/dev/mac.rs | 159 + anneal/v2/vendor/digest-0.10.7/src/dev/rng.rs | 38 + .../vendor/digest-0.10.7/src/dev/variable.rs | 82 + anneal/v2/vendor/digest-0.10.7/src/dev/xof.rs | 51 + anneal/v2/vendor/digest-0.10.7/src/digest.rs | 236 + anneal/v2/vendor/digest-0.10.7/src/lib.rs | 301 + anneal/v2/vendor/digest-0.10.7/src/mac.rs | 305 + anneal/v2/vendor/either/.cargo-checksum.json | 1 + anneal/v2/vendor/either/.cargo_vcs_info.json | 6 + .../v2/vendor/either/.github/workflows/ci.yml | 90 + anneal/v2/vendor/either/Cargo.lock | 89 + anneal/v2/vendor/either/Cargo.toml | 69 + anneal/v2/vendor/either/Cargo.toml.orig | 39 + anneal/v2/vendor/either/LICENSE-APACHE | 201 + anneal/v2/vendor/either/LICENSE-MIT | 25 + anneal/v2/vendor/either/README-crates.io.md | 10 + anneal/v2/vendor/either/README.rst | 220 + anneal/v2/vendor/either/src/into_either.rs | 64 + anneal/v2/vendor/either/src/iterator.rs | 315 + anneal/v2/vendor/either/src/lib.rs | 1826 ++ anneal/v2/vendor/either/src/serde_untagged.rs | 69 + .../either/src/serde_untagged_optional.rs | 74 + .../encode_unicode/.cargo-checksum.json | 1 + .../encode_unicode/.cargo_vcs_info.json | 6 + anneal/v2/vendor/encode_unicode/.cirrus.yml | 90 + anneal/v2/vendor/encode_unicode/AUTHORS.md | 4 + anneal/v2/vendor/encode_unicode/Cargo.lock | 368 + anneal/v2/vendor/encode_unicode/Cargo.toml | 59 + .../v2/vendor/encode_unicode/Cargo.toml.orig | 41 + .../v2/vendor/encode_unicode/LICENSE-APACHE | 202 + anneal/v2/vendor/encode_unicode/LICENSE-MIT | 17 + anneal/v2/vendor/encode_unicode/README.md | 71 + anneal/v2/vendor/encode_unicode/RELEASES.md | 104 + .../vendor/encode_unicode/benches/length.rs | 282 + .../encode_unicode/benches/multiiterators.rs | 122 + anneal/v2/vendor/encode_unicode/do.sh | 96 + .../examples/length_distribution.rs | 89 + .../encode_unicode/src/decoding_iterators.rs | 490 + anneal/v2/vendor/encode_unicode/src/errors.rs | 309 + anneal/v2/vendor/encode_unicode/src/lib.rs | 89 + anneal/v2/vendor/encode_unicode/src/traits.rs | 1012 + .../vendor/encode_unicode/src/utf16_char.rs | 692 + .../encode_unicode/src/utf16_iterators.rs | 265 + .../v2/vendor/encode_unicode/src/utf8_char.rs | 647 + .../encode_unicode/src/utf8_iterators.rs | 346 + anneal/v2/vendor/encode_unicode/tests/errs.rs | 227 + .../vendor/encode_unicode/tests/exhaustive.rs | 35 + .../vendor/encode_unicode/tests/iterators.rs | 186 + anneal/v2/vendor/encode_unicode/tests/oks.rs | 311 + anneal/v2/vendor/fs2/.appveyor.yml | 18 + anneal/v2/vendor/fs2/.cargo-checksum.json | 1 + anneal/v2/vendor/fs2/.travis.yml | 21 + anneal/v2/vendor/fs2/Cargo.toml | 33 + anneal/v2/vendor/fs2/Cargo.toml.orig | 23 + anneal/v2/vendor/fs2/LICENSE-APACHE | 201 + anneal/v2/vendor/fs2/LICENSE-MIT | 25 + anneal/v2/vendor/fs2/README.md | 50 + anneal/v2/vendor/fs2/src/lib.rs | 458 + anneal/v2/vendor/fs2/src/unix.rs | 250 + anneal/v2/vendor/fs2/src/windows.rs | 279 + .../vendor/futures-core/.cargo-checksum.json | 1 + .../vendor/futures-core/.cargo_vcs_info.json | 6 + anneal/v2/vendor/futures-core/Cargo.lock | 16 + anneal/v2/vendor/futures-core/Cargo.toml | 66 + anneal/v2/vendor/futures-core/Cargo.toml.orig | 35 + anneal/v2/vendor/futures-core/LICENSE-APACHE | 202 + anneal/v2/vendor/futures-core/LICENSE-MIT | 26 + anneal/v2/vendor/futures-core/README.md | 23 + anneal/v2/vendor/futures-core/src/future.rs | 113 + anneal/v2/vendor/futures-core/src/lib.rs | 27 + anneal/v2/vendor/futures-core/src/stream.rs | 245 + .../src/task/__internal/atomic_waker.rs | 423 + .../futures-core/src/task/__internal/mod.rs | 7 + anneal/v2/vendor/futures-core/src/task/mod.rs | 10 + .../v2/vendor/futures-core/src/task/poll.rs | 15 + .../vendor/futures-task/.cargo-checksum.json | 1 + .../vendor/futures-task/.cargo_vcs_info.json | 6 + anneal/v2/vendor/futures-task/Cargo.lock | 6 + anneal/v2/vendor/futures-task/Cargo.toml | 58 + anneal/v2/vendor/futures-task/Cargo.toml.orig | 33 + anneal/v2/vendor/futures-task/LICENSE-APACHE | 202 + anneal/v2/vendor/futures-task/LICENSE-MIT | 26 + anneal/v2/vendor/futures-task/README.md | 23 + anneal/v2/vendor/futures-task/src/arc_wake.rs | 49 + .../v2/vendor/futures-task/src/future_obj.rs | 335 + anneal/v2/vendor/futures-task/src/lib.rs | 50 + .../v2/vendor/futures-task/src/noop_waker.rs | 63 + anneal/v2/vendor/futures-task/src/spawn.rs | 192 + anneal/v2/vendor/futures-task/src/waker.rs | 60 + .../v2/vendor/futures-task/src/waker_ref.rs | 66 + .../vendor/futures-util/.cargo-checksum.json | 1 + .../vendor/futures-util/.cargo_vcs_info.json | 6 + anneal/v2/vendor/futures-util/Cargo.lock | 693 + anneal/v2/vendor/futures-util/Cargo.toml | 181 + anneal/v2/vendor/futures-util/Cargo.toml.orig | 65 + anneal/v2/vendor/futures-util/LICENSE-APACHE | 202 + anneal/v2/vendor/futures-util/LICENSE-MIT | 26 + anneal/v2/vendor/futures-util/README.md | 23 + .../v2/vendor/futures-util/benches/bilock.rs | 68 + .../futures-util/benches/flatten_unordered.rs | 58 + .../futures-util/benches/futures_unordered.rs | 43 + .../v2/vendor/futures-util/benches/select.rs | 35 + .../v2/vendor/futures-util/src/abortable.rs | 209 + .../futures-util/src/async_await/join_mod.rs | 110 + .../futures-util/src/async_await/mod.rs | 60 + .../futures-util/src/async_await/pending.rs | 43 + .../futures-util/src/async_await/poll.rs | 39 + .../futures-util/src/async_await/random.rs | 54 + .../src/async_await/select_mod.rs | 340 + .../src/async_await/stream_select_mod.rs | 39 + .../futures-util/src/compat/compat01as03.rs | 455 + .../futures-util/src/compat/compat03as01.rs | 268 + .../futures-util/src/compat/executor.rs | 86 + .../v2/vendor/futures-util/src/compat/mod.rs | 22 + anneal/v2/vendor/futures-util/src/fns.rs | 372 + .../futures-util/src/future/abortable.rs | 19 + .../futures-util/src/future/always_ready.rs | 62 + .../vendor/futures-util/src/future/either.rs | 314 + .../src/future/future/catch_unwind.rs | 39 + .../futures-util/src/future/future/flatten.rs | 153 + .../futures-util/src/future/future/fuse.rs | 92 + .../futures-util/src/future/future/map.rs | 66 + .../futures-util/src/future/future/mod.rs | 603 + .../src/future/future/remote_handle.rs | 127 + .../futures-util/src/future/future/shared.rs | 430 + .../v2/vendor/futures-util/src/future/join.rs | 217 + .../futures-util/src/future/join_all.rs | 167 + .../v2/vendor/futures-util/src/future/lazy.rs | 60 + .../futures-util/src/future/maybe_done.rs | 105 + .../v2/vendor/futures-util/src/future/mod.rs | 134 + .../vendor/futures-util/src/future/option.rs | 64 + .../vendor/futures-util/src/future/pending.rs | 55 + .../vendor/futures-util/src/future/poll_fn.rs | 58 + .../futures-util/src/future/poll_immediate.rs | 131 + .../vendor/futures-util/src/future/ready.rs | 82 + .../vendor/futures-util/src/future/select.rs | 133 + .../futures-util/src/future/select_all.rs | 75 + .../futures-util/src/future/select_ok.rs | 85 + .../src/future/try_future/into_future.rs | 36 + .../futures-util/src/future/try_future/mod.rs | 625 + .../src/future/try_future/try_flatten.rs | 162 + .../src/future/try_future/try_flatten_err.rs | 62 + .../futures-util/src/future/try_join.rs | 256 + .../futures-util/src/future/try_join_all.rs | 201 + .../futures-util/src/future/try_maybe_done.rs | 92 + .../futures-util/src/future/try_select.rs | 85 + .../vendor/futures-util/src/io/allow_std.rs | 202 + .../vendor/futures-util/src/io/buf_reader.rs | 264 + .../vendor/futures-util/src/io/buf_writer.rs | 229 + anneal/v2/vendor/futures-util/src/io/chain.rs | 142 + anneal/v2/vendor/futures-util/src/io/close.rs | 28 + anneal/v2/vendor/futures-util/src/io/copy.rs | 58 + .../v2/vendor/futures-util/src/io/copy_buf.rs | 78 + .../futures-util/src/io/copy_buf_abortable.rs | 124 + .../v2/vendor/futures-util/src/io/cursor.rs | 234 + anneal/v2/vendor/futures-util/src/io/empty.rs | 59 + .../v2/vendor/futures-util/src/io/fill_buf.rs | 47 + anneal/v2/vendor/futures-util/src/io/flush.rs | 31 + .../vendor/futures-util/src/io/into_sink.rs | 82 + .../vendor/futures-util/src/io/line_writer.rs | 155 + anneal/v2/vendor/futures-util/src/io/lines.rs | 50 + anneal/v2/vendor/futures-util/src/io/mod.rs | 833 + anneal/v2/vendor/futures-util/src/io/read.rs | 30 + .../vendor/futures-util/src/io/read_exact.rs | 42 + .../vendor/futures-util/src/io/read_line.rs | 77 + .../vendor/futures-util/src/io/read_to_end.rs | 90 + .../futures-util/src/io/read_to_string.rs | 60 + .../vendor/futures-util/src/io/read_until.rs | 60 + .../futures-util/src/io/read_vectored.rs | 30 + .../v2/vendor/futures-util/src/io/repeat.rs | 66 + anneal/v2/vendor/futures-util/src/io/seek.rs | 30 + anneal/v2/vendor/futures-util/src/io/sink.rs | 67 + anneal/v2/vendor/futures-util/src/io/split.rs | 129 + anneal/v2/vendor/futures-util/src/io/take.rs | 125 + .../v2/vendor/futures-util/src/io/window.rs | 104 + anneal/v2/vendor/futures-util/src/io/write.rs | 30 + .../vendor/futures-util/src/io/write_all.rs | 43 + .../futures-util/src/io/write_all_vectored.rs | 195 + .../futures-util/src/io/write_vectored.rs | 30 + anneal/v2/vendor/futures-util/src/lib.rs | 332 + .../v2/vendor/futures-util/src/lock/bilock.rs | 297 + anneal/v2/vendor/futures-util/src/lock/mod.rs | 27 + .../v2/vendor/futures-util/src/lock/mutex.rs | 560 + anneal/v2/vendor/futures-util/src/macros.rs | 31 + anneal/v2/vendor/futures-util/src/never.rs | 18 + .../v2/vendor/futures-util/src/sink/buffer.rs | 105 + .../v2/vendor/futures-util/src/sink/close.rs | 32 + .../v2/vendor/futures-util/src/sink/drain.rs | 59 + .../vendor/futures-util/src/sink/err_into.rs | 57 + .../v2/vendor/futures-util/src/sink/fanout.rs | 111 + .../v2/vendor/futures-util/src/sink/feed.rs | 43 + .../v2/vendor/futures-util/src/sink/flush.rs | 36 + .../vendor/futures-util/src/sink/map_err.rs | 65 + anneal/v2/vendor/futures-util/src/sink/mod.rs | 344 + .../v2/vendor/futures-util/src/sink/send.rs | 41 + .../vendor/futures-util/src/sink/send_all.rs | 100 + .../v2/vendor/futures-util/src/sink/unfold.rs | 92 + .../v2/vendor/futures-util/src/sink/with.rs | 145 + .../futures-util/src/sink/with_flat_map.rs | 127 + .../futures-util/src/stream/abortable.rs | 19 + .../vendor/futures-util/src/stream/empty.rs | 45 + .../src/stream/futures_ordered.rs | 260 + .../src/stream/futures_unordered/abort.rs | 12 + .../src/stream/futures_unordered/iter.rs | 172 + .../src/stream/futures_unordered/mod.rs | 674 + .../futures_unordered/ready_to_run_queue.rs | 113 + .../src/stream/futures_unordered/task.rs | 214 + .../v2/vendor/futures-util/src/stream/iter.rs | 66 + .../v2/vendor/futures-util/src/stream/mod.rs | 148 + .../v2/vendor/futures-util/src/stream/once.rs | 67 + .../vendor/futures-util/src/stream/pending.rs | 45 + .../vendor/futures-util/src/stream/poll_fn.rs | 57 + .../futures-util/src/stream/poll_immediate.rs | 80 + .../vendor/futures-util/src/stream/repeat.rs | 58 + .../futures-util/src/stream/repeat_with.rs | 93 + .../vendor/futures-util/src/stream/select.rs | 117 + .../futures-util/src/stream/select_all.rs | 249 + .../src/stream/select_with_strategy.rs | 304 + .../futures-util/src/stream/stream/all.rs | 93 + .../futures-util/src/stream/stream/any.rs | 93 + .../src/stream/stream/buffer_unordered.rs | 120 + .../src/stream/stream/buffered.rs | 118 + .../src/stream/stream/catch_unwind.rs | 62 + .../futures-util/src/stream/stream/chain.rs | 76 + .../futures-util/src/stream/stream/chunks.rs | 103 + .../futures-util/src/stream/stream/collect.rs | 56 + .../futures-util/src/stream/stream/concat.rs | 62 + .../futures-util/src/stream/stream/count.rs | 53 + .../futures-util/src/stream/stream/cycle.rs | 67 + .../src/stream/stream/enumerate.rs | 64 + .../futures-util/src/stream/stream/filter.rs | 117 + .../src/stream/stream/filter_map.rs | 111 + .../futures-util/src/stream/stream/flatten.rs | 73 + .../src/stream/stream/flatten_unordered.rs | 531 + .../futures-util/src/stream/stream/fold.rs | 88 + .../src/stream/stream/for_each.rs | 78 + .../src/stream/stream/for_each_concurrent.rs | 119 + .../futures-util/src/stream/stream/forward.rs | 75 + .../futures-util/src/stream/stream/fuse.rs | 75 + .../src/stream/stream/into_future.rs | 90 + .../futures-util/src/stream/stream/map.rs | 77 + .../futures-util/src/stream/stream/mod.rs | 1697 ++ .../futures-util/src/stream/stream/next.rs | 34 + .../futures-util/src/stream/stream/peek.rs | 441 + .../src/stream/stream/ready_chunks.rs | 93 + .../futures-util/src/stream/stream/scan.rs | 128 + .../src/stream/stream/select_next_some.rs | 42 + .../futures-util/src/stream/stream/skip.rs | 70 + .../src/stream/stream/skip_while.rs | 124 + .../futures-util/src/stream/stream/split.rs | 224 + .../futures-util/src/stream/stream/take.rs | 86 + .../src/stream/stream/take_until.rs | 170 + .../src/stream/stream/take_while.rs | 124 + .../futures-util/src/stream/stream/then.rs | 101 + .../futures-util/src/stream/stream/unzip.rs | 63 + .../futures-util/src/stream/stream/zip.rs | 128 + .../src/stream/try_stream/and_then.rs | 105 + .../src/stream/try_stream/into_async_read.rs | 166 + .../src/stream/try_stream/into_stream.rs | 52 + .../futures-util/src/stream/try_stream/mod.rs | 1254 + .../src/stream/try_stream/or_else.rs | 109 + .../src/stream/try_stream/try_all.rs | 98 + .../src/stream/try_stream/try_any.rs | 98 + .../stream/try_stream/try_buffer_unordered.rs | 86 + .../src/stream/try_stream/try_buffered.rs | 87 + .../src/stream/try_stream/try_chunks.rs | 132 + .../src/stream/try_stream/try_collect.rs | 52 + .../src/stream/try_stream/try_concat.rs | 51 + .../src/stream/try_stream/try_filter.rs | 112 + .../src/stream/try_stream/try_filter_map.rs | 106 + .../src/stream/try_stream/try_flatten.rs | 84 + .../try_stream/try_flatten_unordered.rs | 176 + .../src/stream/try_stream/try_fold.rs | 93 + .../src/stream/try_stream/try_for_each.rs | 68 + .../try_stream/try_for_each_concurrent.rs | 132 + .../src/stream/try_stream/try_next.rs | 34 + .../src/stream/try_stream/try_ready_chunks.rs | 126 + .../src/stream/try_stream/try_skip_while.rs | 120 + .../src/stream/try_stream/try_take_while.rs | 129 + .../src/stream/try_stream/try_unfold.rs | 122 + .../vendor/futures-util/src/stream/unfold.rs | 119 + anneal/v2/vendor/futures-util/src/task/mod.rs | 40 + .../v2/vendor/futures-util/src/task/spawn.rs | 169 + .../vendor/futures-util/src/unfold_state.rs | 39 + .../vendor/generic-array/.cargo-checksum.json | 1 + .../vendor/generic-array/.cargo_vcs_info.json | 6 + anneal/v2/vendor/generic-array/CHANGELOG.md | 101 + anneal/v2/vendor/generic-array/Cargo.toml | 75 + .../v2/vendor/generic-array/Cargo.toml.orig | 43 + anneal/v2/vendor/generic-array/LICENSE | 21 + anneal/v2/vendor/generic-array/README.md | 62 + anneal/v2/vendor/generic-array/build.rs | 5 + anneal/v2/vendor/generic-array/src/arr.rs | 125 + .../v2/vendor/generic-array/src/functional.rs | 95 + anneal/v2/vendor/generic-array/src/hex.rs | 105 + .../v2/vendor/generic-array/src/impl_serde.rs | 108 + .../vendor/generic-array/src/impl_zeroize.rs | 24 + anneal/v2/vendor/generic-array/src/impls.rs | 269 + anneal/v2/vendor/generic-array/src/iter.rs | 251 + anneal/v2/vendor/generic-array/src/lib.rs | 690 + .../v2/vendor/generic-array/src/sequence.rs | 380 + anneal/v2/vendor/gimli/.cargo-checksum.json | 1 + anneal/v2/vendor/gimli/.cargo_vcs_info.json | 6 + anneal/v2/vendor/gimli/CHANGELOG.md | 1280 + anneal/v2/vendor/gimli/Cargo.lock | 76 + anneal/v2/vendor/gimli/Cargo.toml | 114 + anneal/v2/vendor/gimli/Cargo.toml.orig | 60 + anneal/v2/vendor/gimli/LICENSE-APACHE | 201 + anneal/v2/vendor/gimli/LICENSE-MIT | 25 + anneal/v2/vendor/gimli/README.md | 84 + anneal/v2/vendor/gimli/src/arch.rs | 1118 + anneal/v2/vendor/gimli/src/common.rs | 401 + anneal/v2/vendor/gimli/src/constants.rs | 1495 + anneal/v2/vendor/gimli/src/endianity.rs | 256 + anneal/v2/vendor/gimli/src/leb128.rs | 612 + anneal/v2/vendor/gimli/src/lib.rs | 80 + anneal/v2/vendor/gimli/src/read/abbrev.rs | 1098 + anneal/v2/vendor/gimli/src/read/addr.rs | 353 + anneal/v2/vendor/gimli/src/read/aranges.rs | 809 + anneal/v2/vendor/gimli/src/read/cfi.rs | 7951 ++++++ anneal/v2/vendor/gimli/src/read/dwarf.rs | 1724 ++ .../v2/vendor/gimli/src/read/endian_reader.rs | 651 + .../v2/vendor/gimli/src/read/endian_slice.rs | 360 + anneal/v2/vendor/gimli/src/read/index.rs | 631 + anneal/v2/vendor/gimli/src/read/line.rs | 3185 +++ anneal/v2/vendor/gimli/src/read/lists.rs | 68 + anneal/v2/vendor/gimli/src/read/loclists.rs | 1126 + anneal/v2/vendor/gimli/src/read/lookup.rs | 202 + anneal/v2/vendor/gimli/src/read/macros.rs | 872 + anneal/v2/vendor/gimli/src/read/mod.rs | 868 + anneal/v2/vendor/gimli/src/read/op.rs | 4182 +++ anneal/v2/vendor/gimli/src/read/pubnames.rs | 141 + anneal/v2/vendor/gimli/src/read/pubtypes.rs | 141 + anneal/v2/vendor/gimli/src/read/reader.rs | 594 + anneal/v2/vendor/gimli/src/read/relocate.rs | 153 + anneal/v2/vendor/gimli/src/read/rnglists.rs | 1044 + anneal/v2/vendor/gimli/src/read/str.rs | 291 + anneal/v2/vendor/gimli/src/read/unit.rs | 6128 +++++ anneal/v2/vendor/gimli/src/read/util.rs | 265 + anneal/v2/vendor/gimli/src/read/value.rs | 1621 ++ anneal/v2/vendor/gimli/src/test_util.rs | 53 + anneal/v2/vendor/gimli/src/write/abbrev.rs | 188 + anneal/v2/vendor/gimli/src/write/cfi.rs | 1070 + anneal/v2/vendor/gimli/src/write/dwarf.rs | 148 + .../v2/vendor/gimli/src/write/endian_vec.rs | 117 + anneal/v2/vendor/gimli/src/write/line.rs | 2165 ++ anneal/v2/vendor/gimli/src/write/loc.rs | 561 + anneal/v2/vendor/gimli/src/write/mod.rs | 428 + anneal/v2/vendor/gimli/src/write/op.rs | 1762 ++ anneal/v2/vendor/gimli/src/write/range.rs | 427 + anneal/v2/vendor/gimli/src/write/relocate.rs | 280 + anneal/v2/vendor/gimli/src/write/section.rs | 227 + anneal/v2/vendor/gimli/src/write/str.rs | 198 + anneal/v2/vendor/gimli/src/write/unit.rs | 3107 +++ anneal/v2/vendor/gimli/src/write/writer.rs | 493 + .../v2/vendor/indicatif/.cargo-checksum.json | 1 + .../v2/vendor/indicatif/.cargo_vcs_info.json | 7 + .../vendor/indicatif/.github/dependabot.yml | 10 + .../indicatif/.github/workflows/rust.yml | 89 + anneal/v2/vendor/indicatif/Cargo.lock | 664 + anneal/v2/vendor/indicatif/Cargo.toml | 227 + anneal/v2/vendor/indicatif/Cargo.toml.orig | 47 + anneal/v2/vendor/indicatif/LICENSE | 22 + anneal/v2/vendor/indicatif/README.md | 35 + anneal/v2/vendor/indicatif/deny.toml | 2 + anneal/v2/vendor/indicatif/examples/cargo.rs | 122 + .../v2/vendor/indicatif/examples/cargowrap.rs | 41 + .../indicatif/examples/download-continued.rs | 29 + .../indicatif/examples/download-speed.rs | 24 + .../v2/vendor/indicatif/examples/download.rs | 25 + .../v2/vendor/indicatif/examples/fastbar.rs | 23 + .../v2/vendor/indicatif/examples/finebars.rs | 43 + .../v2/vendor/indicatif/examples/iterator.rs | 31 + anneal/v2/vendor/indicatif/examples/log.rs | 14 + .../vendor/indicatif/examples/long-spinner.rs | 27 + .../v2/vendor/indicatif/examples/message.rs | 11 + .../v2/vendor/indicatif/examples/morebars.rs | 28 + .../indicatif/examples/multi-tree-ext.rs | 280 + .../vendor/indicatif/examples/multi-tree.rs | 189 + anneal/v2/vendor/indicatif/examples/multi.rs | 62 + anneal/v2/vendor/indicatif/examples/single.rs | 13 + anneal/v2/vendor/indicatif/examples/slow.rs | 12 + .../vendor/indicatif/examples/spinner-loop.rs | 20 + anneal/v2/vendor/indicatif/examples/steady.rs | 50 + anneal/v2/vendor/indicatif/examples/tokio.rs | 34 + .../v2/vendor/indicatif/examples/yarnish.rs | 97 + anneal/v2/vendor/indicatif/src/draw_target.rs | 805 + anneal/v2/vendor/indicatif/src/format.rs | 381 + anneal/v2/vendor/indicatif/src/in_memory.rs | 399 + anneal/v2/vendor/indicatif/src/iter.rs | 506 + anneal/v2/vendor/indicatif/src/lib.rs | 295 + anneal/v2/vendor/indicatif/src/multi.rs | 690 + .../v2/vendor/indicatif/src/progress_bar.rs | 876 + anneal/v2/vendor/indicatif/src/rayon.rs | 240 + anneal/v2/vendor/indicatif/src/state.rs | 884 + anneal/v2/vendor/indicatif/src/style.rs | 1181 + anneal/v2/vendor/indicatif/src/term_like.rs | 79 + .../vendor/indicatif/tests/multi-autodrop.rs | 27 + anneal/v2/vendor/indicatif/tests/render.rs | 1956 ++ anneal/v2/vendor/is_ci/.cargo-checksum.json | 1 + anneal/v2/vendor/is_ci/.cargo_vcs_info.json | 6 + anneal/v2/vendor/is_ci/.editorconfig | 7 + anneal/v2/vendor/is_ci/CHANGELOG.md | 31 + anneal/v2/vendor/is_ci/Cargo.lock | 7 + anneal/v2/vendor/is_ci/Cargo.toml | 38 + anneal/v2/vendor/is_ci/Cargo.toml.orig | 26 + anneal/v2/vendor/is_ci/LICENSE | 15 + anneal/v2/vendor/is_ci/Makefile.toml | 11 + anneal/v2/vendor/is_ci/README.md | 27 + anneal/v2/vendor/is_ci/cliff.toml | 62 + anneal/v2/vendor/is_ci/src/lib.rs | 70 + anneal/v2/vendor/is_ci/src/main.rs | 6 + anneal/v2/vendor/js-sys/.cargo-checksum.json | 1 + anneal/v2/vendor/js-sys/.cargo_vcs_info.json | 6 + anneal/v2/vendor/js-sys/Cargo.lock | 213 + anneal/v2/vendor/js-sys/Cargo.toml | 102 + anneal/v2/vendor/js-sys/Cargo.toml.orig | 58 + anneal/v2/vendor/js-sys/LICENSE-APACHE | 201 + anneal/v2/vendor/js-sys/LICENSE-MIT | 25 + anneal/v2/vendor/js-sys/README.md | 7 + anneal/v2/vendor/js-sys/src/Temporal.rs | 3384 +++ anneal/v2/vendor/js-sys/src/futures/mod.rs | 360 + anneal/v2/vendor/js-sys/src/futures/queue.rs | 131 + anneal/v2/vendor/js-sys/src/futures/stream.rs | 81 + .../v2/vendor/js-sys/src/futures/task/mod.rs | 13 + .../js-sys/src/futures/task/multithread.rs | 212 + .../js-sys/src/futures/task/singlethread.rs | 184 + .../src/futures/task/wait_async_polyfill.rs | 77 + .../vendor/js-sys/src/futures/task/worker.js | 6 + anneal/v2/vendor/js-sys/src/lib.rs | 14197 ++++++++++ .../vendor/miette-derive/.cargo-checksum.json | 1 + .../vendor/miette-derive/.cargo_vcs_info.json | 6 + anneal/v2/vendor/miette-derive/Cargo.lock | 47 + anneal/v2/vendor/miette-derive/Cargo.toml | 40 + .../v2/vendor/miette-derive/Cargo.toml.orig | 16 + anneal/v2/vendor/miette-derive/LICENSE | 229 + anneal/v2/vendor/miette-derive/src/code.rs | 80 + .../v2/vendor/miette-derive/src/diagnostic.rs | 397 + .../miette-derive/src/diagnostic_arg.rs | 42 + .../miette-derive/src/diagnostic_source.rs | 78 + anneal/v2/vendor/miette-derive/src/fmt.rs | 235 + anneal/v2/vendor/miette-derive/src/forward.rs | 161 + anneal/v2/vendor/miette-derive/src/help.rs | 146 + anneal/v2/vendor/miette-derive/src/label.rs | 333 + anneal/v2/vendor/miette-derive/src/lib.rs | 32 + anneal/v2/vendor/miette-derive/src/related.rs | 79 + .../v2/vendor/miette-derive/src/severity.rs | 89 + .../vendor/miette-derive/src/source_code.rs | 117 + anneal/v2/vendor/miette-derive/src/url.rs | 139 + anneal/v2/vendor/miette-derive/src/utils.rs | 140 + anneal/v2/vendor/miette/.cargo-checksum.json | 1 + anneal/v2/vendor/miette/.cargo_vcs_info.json | 6 + anneal/v2/vendor/miette/.editorconfig | 7 + anneal/v2/vendor/miette/.github/FUNDING.yml | 12 + .../v2/vendor/miette/.github/workflows/ci.yml | 101 + anneal/v2/vendor/miette/CHANGELOG.md | 1091 + anneal/v2/vendor/miette/CODE_OF_CONDUCT.md | 150 + anneal/v2/vendor/miette/CONTRIBUTING.md | 257 + anneal/v2/vendor/miette/Cargo.lock | 927 + anneal/v2/vendor/miette/Cargo.toml | 168 + anneal/v2/vendor/miette/Cargo.toml.orig | 77 + anneal/v2/vendor/miette/LICENSE | 202 + anneal/v2/vendor/miette/Makefile.toml | 17 + anneal/v2/vendor/miette/README.md | 819 + anneal/v2/vendor/miette/README.tpl | 18 + anneal/v2/vendor/miette/cliff.toml | 62 + anneal/v2/vendor/miette/clippy.toml | 1 + .../v2/vendor/miette/examples/serde_json.rs | 48 + anneal/v2/vendor/miette/rustfmt.toml | 1 + anneal/v2/vendor/miette/src/chain.rs | 118 + .../v2/vendor/miette/src/diagnostic_chain.rs | 93 + .../v2/vendor/miette/src/diagnostic_impls.rs | 55 + anneal/v2/vendor/miette/src/error.rs | 125 + .../v2/vendor/miette/src/eyreish/context.rs | 255 + anneal/v2/vendor/miette/src/eyreish/error.rs | 823 + anneal/v2/vendor/miette/src/eyreish/fmt.rs | 20 + .../miette/src/eyreish/into_diagnostic.rs | 68 + anneal/v2/vendor/miette/src/eyreish/kind.rs | 114 + anneal/v2/vendor/miette/src/eyreish/macros.rs | 300 + anneal/v2/vendor/miette/src/eyreish/mod.rs | 485 + anneal/v2/vendor/miette/src/eyreish/ptr.rs | 188 + .../v2/vendor/miette/src/eyreish/wrapper.rs | 302 + anneal/v2/vendor/miette/src/handler.rs | 628 + anneal/v2/vendor/miette/src/handlers/debug.rs | 71 + .../vendor/miette/src/handlers/graphical.rs | 1506 + anneal/v2/vendor/miette/src/handlers/json.rs | 182 + anneal/v2/vendor/miette/src/handlers/mod.rs | 24 + .../vendor/miette/src/handlers/narratable.rs | 423 + anneal/v2/vendor/miette/src/handlers/theme.rs | 277 + .../vendor/miette/src/highlighters/blank.rs | 36 + .../v2/vendor/miette/src/highlighters/mod.rs | 116 + .../vendor/miette/src/highlighters/syntect.rs | 171 + anneal/v2/vendor/miette/src/lib.rs | 838 + anneal/v2/vendor/miette/src/macro_helpers.rs | 61 + .../v2/vendor/miette/src/miette_diagnostic.rs | 369 + anneal/v2/vendor/miette/src/named_source.rs | 78 + anneal/v2/vendor/miette/src/panic.rs | 132 + anneal/v2/vendor/miette/src/protocol.rs | 770 + anneal/v2/vendor/miette/src/source_impls.rs | 296 + anneal/v2/vendor/object/.cargo-checksum.json | 1 + anneal/v2/vendor/object/.cargo_vcs_info.json | 6 + anneal/v2/vendor/object/CHANGELOG.md | 1252 + anneal/v2/vendor/object/Cargo.lock | 140 + anneal/v2/vendor/object/Cargo.toml | 209 + anneal/v2/vendor/object/Cargo.toml.orig | 137 + anneal/v2/vendor/object/LICENSE-APACHE | 201 + anneal/v2/vendor/object/LICENSE-MIT | 25 + anneal/v2/vendor/object/README.md | 61 + anneal/v2/vendor/object/build.rs | 27 + anneal/v2/vendor/object/src/archive.rs | 91 + anneal/v2/vendor/object/src/build/bytes.rs | 146 + anneal/v2/vendor/object/src/build/elf.rs | 3131 +++ anneal/v2/vendor/object/src/build/error.rs | 43 + anneal/v2/vendor/object/src/build/mod.rs | 18 + anneal/v2/vendor/object/src/build/table.rs | 128 + anneal/v2/vendor/object/src/common.rs | 619 + anneal/v2/vendor/object/src/elf.rs | 6533 +++++ anneal/v2/vendor/object/src/endian.rs | 831 + anneal/v2/vendor/object/src/lib.rs | 94 + anneal/v2/vendor/object/src/macho.rs | 3606 +++ anneal/v2/vendor/object/src/pe.rs | 3062 +++ anneal/v2/vendor/object/src/pod.rs | 281 + anneal/v2/vendor/object/src/read/any.rs | 1374 + anneal/v2/vendor/object/src/read/archive.rs | 1147 + .../v2/vendor/object/src/read/coff/comdat.rs | 220 + anneal/v2/vendor/object/src/read/coff/file.rs | 427 + .../v2/vendor/object/src/read/coff/import.rs | 223 + anneal/v2/vendor/object/src/read/coff/mod.rs | 66 + .../vendor/object/src/read/coff/relocation.rs | 119 + .../v2/vendor/object/src/read/coff/section.rs | 619 + .../v2/vendor/object/src/read/coff/symbol.rs | 695 + .../vendor/object/src/read/elf/attributes.rs | 340 + .../v2/vendor/object/src/read/elf/comdat.rs | 186 + .../vendor/object/src/read/elf/compression.rs | 56 + .../v2/vendor/object/src/read/elf/dynamic.rs | 117 + anneal/v2/vendor/object/src/read/elf/file.rs | 1015 + anneal/v2/vendor/object/src/read/elf/hash.rs | 236 + anneal/v2/vendor/object/src/read/elf/mod.rs | 78 + anneal/v2/vendor/object/src/read/elf/note.rs | 302 + .../vendor/object/src/read/elf/relocation.rs | 991 + .../v2/vendor/object/src/read/elf/section.rs | 1282 + .../v2/vendor/object/src/read/elf/segment.rs | 365 + .../v2/vendor/object/src/read/elf/symbol.rs | 654 + .../v2/vendor/object/src/read/elf/version.rs | 513 + .../vendor/object/src/read/gnu_compression.rs | 36 + .../object/src/read/macho/dyld_cache.rs | 1148 + anneal/v2/vendor/object/src/read/macho/fat.rs | 140 + .../v2/vendor/object/src/read/macho/file.rs | 819 + .../object/src/read/macho/load_command.rs | 402 + anneal/v2/vendor/object/src/read/macho/mod.rs | 72 + .../object/src/read/macho/relocation.rs | 144 + .../vendor/object/src/read/macho/section.rs | 420 + .../vendor/object/src/read/macho/segment.rs | 317 + .../v2/vendor/object/src/read/macho/symbol.rs | 546 + anneal/v2/vendor/object/src/read/mod.rs | 1041 + .../object/src/read/pe/data_directory.rs | 214 + anneal/v2/vendor/object/src/read/pe/export.rs | 334 + anneal/v2/vendor/object/src/read/pe/file.rs | 1073 + anneal/v2/vendor/object/src/read/pe/import.rs | 381 + anneal/v2/vendor/object/src/read/pe/mod.rs | 68 + .../vendor/object/src/read/pe/relocation.rs | 109 + .../v2/vendor/object/src/read/pe/resource.rs | 210 + anneal/v2/vendor/object/src/read/pe/rich.rs | 92 + .../v2/vendor/object/src/read/pe/section.rs | 476 + .../v2/vendor/object/src/read/read_cache.rs | 261 + anneal/v2/vendor/object/src/read/read_ref.rs | 153 + anneal/v2/vendor/object/src/read/traits.rs | 589 + anneal/v2/vendor/object/src/read/util.rs | 425 + anneal/v2/vendor/object/src/read/wasm.rs | 1147 + .../v2/vendor/object/src/read/xcoff/comdat.rs | 134 + .../v2/vendor/object/src/read/xcoff/file.rs | 756 + anneal/v2/vendor/object/src/read/xcoff/mod.rs | 63 + .../object/src/read/xcoff/relocation.rs | 138 + .../vendor/object/src/read/xcoff/section.rs | 452 + .../vendor/object/src/read/xcoff/segment.rs | 117 + .../v2/vendor/object/src/read/xcoff/symbol.rs | 836 + anneal/v2/vendor/object/src/write/coff/mod.rs | 10 + .../v2/vendor/object/src/write/coff/object.rs | 831 + .../v2/vendor/object/src/write/coff/writer.rs | 551 + anneal/v2/vendor/object/src/write/elf/mod.rs | 9 + .../v2/vendor/object/src/write/elf/object.rs | 869 + .../v2/vendor/object/src/write/elf/writer.rs | 2394 ++ anneal/v2/vendor/object/src/write/macho.rs | 1119 + anneal/v2/vendor/object/src/write/mod.rs | 1140 + anneal/v2/vendor/object/src/write/pe.rs | 849 + anneal/v2/vendor/object/src/write/string.rs | 186 + anneal/v2/vendor/object/src/write/util.rs | 261 + anneal/v2/vendor/object/src/write/xcoff.rs | 608 + anneal/v2/vendor/object/src/xcoff.rs | 905 + anneal/v2/vendor/object/tests/build/elf.rs | 254 + anneal/v2/vendor/object/tests/build/mod.rs | 3 + anneal/v2/vendor/object/tests/integration.rs | 3 + anneal/v2/vendor/object/tests/parse_self.rs | 25 + anneal/v2/vendor/object/tests/read/coff.rs | 23 + anneal/v2/vendor/object/tests/read/elf.rs | 62 + anneal/v2/vendor/object/tests/read/macho.rs | 49 + anneal/v2/vendor/object/tests/read/mod.rs | 5 + .../v2/vendor/object/tests/round_trip/bss.rs | 256 + .../v2/vendor/object/tests/round_trip/coff.rs | 58 + .../vendor/object/tests/round_trip/comdat.rs | 217 + .../vendor/object/tests/round_trip/common.rs | 241 + .../v2/vendor/object/tests/round_trip/elf.rs | 302 + .../vendor/object/tests/round_trip/macho.rs | 64 + .../v2/vendor/object/tests/round_trip/mod.rs | 690 + .../object/tests/round_trip/section_flags.rs | 89 + .../v2/vendor/object/tests/round_trip/tls.rs | 308 + .../v2/vendor/owo-colors/.cargo-checksum.json | 1 + .../v2/vendor/owo-colors/.cargo_vcs_info.json | 6 + anneal/v2/vendor/owo-colors/CHANGELOG.md | 74 + anneal/v2/vendor/owo-colors/Cargo.lock | 74 + anneal/v2/vendor/owo-colors/Cargo.toml | 74 + anneal/v2/vendor/owo-colors/Cargo.toml.orig | 39 + anneal/v2/vendor/owo-colors/LICENSE | 21 + anneal/v2/vendor/owo-colors/README.md | 104 + anneal/v2/vendor/owo-colors/build.rs | 58 + anneal/v2/vendor/owo-colors/src/colors.rs | 213 + anneal/v2/vendor/owo-colors/src/colors/css.rs | 232 + .../v2/vendor/owo-colors/src/colors/custom.rs | 116 + .../vendor/owo-colors/src/colors/dynamic.rs | 105 + .../v2/vendor/owo-colors/src/colors/xterm.rs | 380 + anneal/v2/vendor/owo-colors/src/combo.rs | 945 + anneal/v2/vendor/owo-colors/src/dyn_colors.rs | 115 + anneal/v2/vendor/owo-colors/src/dyn_styles.rs | 797 + anneal/v2/vendor/owo-colors/src/lib.rs | 557 + anneal/v2/vendor/owo-colors/src/overrides.rs | 135 + .../v2/vendor/owo-colors/src/styled_list.rs | 276 + anneal/v2/vendor/owo-colors/src/styles.rs | 478 + .../vendor/owo-colors/src/supports_colors.rs | 106 + anneal/v2/vendor/owo-colors/src/tests.rs | 93 + .../pin-project-lite/.cargo-checksum.json | 1 + .../pin-project-lite/.cargo_vcs_info.json | 6 + .../v2/vendor/pin-project-lite/CHANGELOG.md | 264 + anneal/v2/vendor/pin-project-lite/Cargo.lock | 23 + anneal/v2/vendor/pin-project-lite/Cargo.toml | 198 + .../vendor/pin-project-lite/Cargo.toml.orig | 91 + .../v2/vendor/pin-project-lite/LICENSE-APACHE | 177 + anneal/v2/vendor/pin-project-lite/LICENSE-MIT | 23 + anneal/v2/vendor/pin-project-lite/README.md | 129 + anneal/v2/vendor/pin-project-lite/src/lib.rs | 1770 ++ .../pin-project-lite/tests/auxiliary/mod.rs | 14 + .../pin-project-lite/tests/compiletest.rs | 11 + .../pin-project-lite/tests/drop_order.rs | 169 + .../tests/expand/.rustfmt.toml | 1 + .../tests/expand/default/enum.expanded.rs | 166 + .../tests/expand/default/enum.rs | 19 + .../tests/expand/default/struct.expanded.rs | 107 + .../tests/expand/default/struct.rs | 13 + .../tests/expand/multifields/enum.expanded.rs | 102 + .../tests/expand/multifields/enum.rs | 20 + .../expand/multifields/struct.expanded.rs | 174 + .../tests/expand/multifields/struct.rs | 17 + .../tests/expand/naming/enum-all.expanded.rs | 166 + .../tests/expand/naming/enum-all.rs | 19 + .../tests/expand/naming/enum-mut.expanded.rs | 76 + .../tests/expand/naming/enum-mut.rs | 17 + .../tests/expand/naming/enum-none.expanded.rs | 33 + .../tests/expand/naming/enum-none.rs | 16 + .../tests/expand/naming/enum-ref.expanded.rs | 76 + .../tests/expand/naming/enum-ref.rs | 17 + .../expand/naming/struct-all.expanded.rs | 151 + .../tests/expand/naming/struct-all.rs | 16 + .../expand/naming/struct-mut.expanded.rs | 107 + .../tests/expand/naming/struct-mut.rs | 14 + .../expand/naming/struct-none.expanded.rs | 107 + .../tests/expand/naming/struct-none.rs | 13 + .../expand/naming/struct-ref.expanded.rs | 107 + .../tests/expand/naming/struct-ref.rs | 14 + .../tests/expand/not_unpin/enum.expanded.rs | 114 + .../tests/expand/not_unpin/enum.rs | 19 + .../tests/expand/not_unpin/struct.expanded.rs | 103 + .../tests/expand/not_unpin/struct.rs | 16 + .../tests/expand/pinned_drop/enum.expanded.rs | 128 + .../tests/expand/pinned_drop/enum.rs | 23 + .../expand/pinned_drop/struct.expanded.rs | 117 + .../tests/expand/pinned_drop/struct.rs | 18 + .../tests/expand/pub/enum.expanded.rs | 118 + .../pin-project-lite/tests/expand/pub/enum.rs | 18 + .../tests/expand/pub/struct.expanded.rs | 107 + .../tests/expand/pub/struct.rs | 13 + .../pin-project-lite/tests/expandtest.rs | 10 + .../pin-project-lite/tests/include/basic.rs | 81 + .../pin-project-lite/tests/proper_unpin.rs | 101 + .../v2/vendor/pin-project-lite/tests/test.rs | 699 + .../tests/ui/not_unpin/conflict-unpin.rs | 38 + .../tests/ui/not_unpin/conflict-unpin.stderr | 50 + .../ui/not_unpin/negative_impls_stable.rs | 22 + .../ui/not_unpin/negative_impls_stable.stderr | 16 + .../tests/ui/pin_project/conflict-drop.rs | 17 + .../tests/ui/pin_project/conflict-drop.stderr | 15 + .../tests/ui/pin_project/conflict-unpin.rs | 66 + .../ui/pin_project/conflict-unpin.stderr | 81 + .../tests/ui/pin_project/invalid-bounds.rs | 95 + .../ui/pin_project/invalid-bounds.stderr | 512 + .../tests/ui/pin_project/invalid.rs | 27 + .../tests/ui/pin_project/invalid.stderr | 47 + .../ui/pin_project/negative_impls_stable.rs | 21 + .../pin_project/negative_impls_stable.stderr | 15 + .../pin_project/overlapping_lifetime_names.rs | 12 + .../overlapping_lifetime_names.stderr | 75 + .../pin_project/overlapping_unpin_struct.rs | 22 + .../overlapping_unpin_struct.stderr | 34 + .../tests/ui/pin_project/packed.rs | 21 + .../tests/ui/pin_project/packed.stderr | 95 + .../tests/ui/pin_project/unpin_sneaky.rs | 14 + .../tests/ui/pin_project/unpin_sneaky.stderr | 5 + .../tests/ui/pin_project/unsupported.rs | 29 + .../tests/ui/pin_project/unsupported.stderr | 111 + .../tests/ui/pinned_drop/call-drop-inner.rs | 19 + .../ui/pinned_drop/call-drop-inner.stderr | 22 + .../ui/pinned_drop/conditional-drop-impl.rs | 28 + .../pinned_drop/conditional-drop-impl.stderr | 34 + .../v2/vendor/rayon-core/.cargo-checksum.json | 1 + .../v2/vendor/rayon-core/.cargo_vcs_info.json | 6 + anneal/v2/vendor/rayon-core/Cargo.lock | 309 + anneal/v2/vendor/rayon-core/Cargo.toml | 93 + anneal/v2/vendor/rayon-core/Cargo.toml.orig | 35 + anneal/v2/vendor/rayon-core/LICENSE-APACHE | 201 + anneal/v2/vendor/rayon-core/LICENSE-MIT | 25 + anneal/v2/vendor/rayon-core/README.md | 11 + anneal/v2/vendor/rayon-core/build.rs | 7 + .../v2/vendor/rayon-core/src/broadcast/mod.rs | 150 + .../vendor/rayon-core/src/broadcast/test.rs | 263 + .../vendor/rayon-core/src/compile_fail/mod.rs | 7 + .../src/compile_fail/quicksort_race1.rs | 28 + .../src/compile_fail/quicksort_race2.rs | 28 + .../src/compile_fail/quicksort_race3.rs | 28 + .../rayon-core/src/compile_fail/rc_return.rs | 17 + .../rayon-core/src/compile_fail/rc_upvar.rs | 9 + .../src/compile_fail/scope_join_bad.rs | 24 + anneal/v2/vendor/rayon-core/src/job.rs | 270 + anneal/v2/vendor/rayon-core/src/join/mod.rs | 186 + anneal/v2/vendor/rayon-core/src/join/test.rs | 150 + anneal/v2/vendor/rayon-core/src/latch.rs | 457 + anneal/v2/vendor/rayon-core/src/lib.rs | 864 + anneal/v2/vendor/rayon-core/src/private.rs | 26 + anneal/v2/vendor/rayon-core/src/registry.rs | 1002 + anneal/v2/vendor/rayon-core/src/scope/mod.rs | 773 + anneal/v2/vendor/rayon-core/src/scope/test.rs | 621 + .../v2/vendor/rayon-core/src/sleep/README.md | 219 + .../vendor/rayon-core/src/sleep/counters.rs | 273 + anneal/v2/vendor/rayon-core/src/sleep/mod.rs | 324 + anneal/v2/vendor/rayon-core/src/spawn/mod.rs | 163 + anneal/v2/vendor/rayon-core/src/spawn/test.rs | 255 + anneal/v2/vendor/rayon-core/src/test.rs | 200 + .../vendor/rayon-core/src/thread_pool/mod.rs | 502 + .../vendor/rayon-core/src/thread_pool/test.rs | 418 + anneal/v2/vendor/rayon-core/src/unwind.rs | 31 + .../rayon-core/tests/double_init_fail.rs | 15 + .../rayon-core/tests/init_zero_threads.rs | 10 + .../v2/vendor/rayon-core/tests/scope_join.rs | 45 + .../rayon-core/tests/scoped_threadpool.rs | 99 + .../vendor/rayon-core/tests/simple_panic.rs | 7 + .../rayon-core/tests/stack_overflow_crash.rs | 97 + .../rayon-core/tests/use_current_thread.rs | 57 + anneal/v2/vendor/rayon/.cargo-checksum.json | 1 + anneal/v2/vendor/rayon/.cargo_vcs_info.json | 6 + anneal/v2/vendor/rayon/Cargo.lock | 297 + anneal/v2/vendor/rayon/Cargo.toml | 130 + anneal/v2/vendor/rayon/Cargo.toml.orig | 57 + anneal/v2/vendor/rayon/FAQ.md | 213 + anneal/v2/vendor/rayon/LICENSE-APACHE | 201 + anneal/v2/vendor/rayon/LICENSE-MIT | 25 + anneal/v2/vendor/rayon/README.md | 150 + anneal/v2/vendor/rayon/RELEASES.md | 929 + anneal/v2/vendor/rayon/src/array.rs | 85 + .../rayon/src/collections/binary_heap.rs | 129 + .../vendor/rayon/src/collections/btree_map.rs | 66 + .../vendor/rayon/src/collections/btree_set.rs | 52 + .../vendor/rayon/src/collections/hash_map.rs | 93 + .../vendor/rayon/src/collections/hash_set.rs | 79 + .../rayon/src/collections/linked_list.rs | 66 + anneal/v2/vendor/rayon/src/collections/mod.rs | 84 + .../vendor/rayon/src/collections/vec_deque.rs | 159 + .../cannot_collect_filtermap_data.rs | 14 + .../compile_fail/cannot_zip_filtered_data.rs | 14 + .../rayon/src/compile_fail/cell_par_iter.rs | 13 + .../v2/vendor/rayon/src/compile_fail/mod.rs | 7 + .../vendor/rayon/src/compile_fail/must_use.rs | 71 + .../src/compile_fail/no_send_par_iter.rs | 58 + .../rayon/src/compile_fail/rc_par_iter.rs | 15 + anneal/v2/vendor/rayon/src/delegate.rs | 109 + anneal/v2/vendor/rayon/src/iter/blocks.rs | 129 + anneal/v2/vendor/rayon/src/iter/chain.rs | 258 + anneal/v2/vendor/rayon/src/iter/chunks.rs | 216 + anneal/v2/vendor/rayon/src/iter/cloned.rs | 219 + .../vendor/rayon/src/iter/collect/consumer.rs | 185 + .../v2/vendor/rayon/src/iter/collect/mod.rs | 114 + .../v2/vendor/rayon/src/iter/collect/test.rs | 368 + anneal/v2/vendor/rayon/src/iter/copied.rs | 219 + anneal/v2/vendor/rayon/src/iter/empty.rs | 108 + anneal/v2/vendor/rayon/src/iter/enumerate.rs | 128 + anneal/v2/vendor/rayon/src/iter/extend.rs | 619 + anneal/v2/vendor/rayon/src/iter/filter.rs | 137 + anneal/v2/vendor/rayon/src/iter/filter_map.rs | 141 + anneal/v2/vendor/rayon/src/iter/find.rs | 120 + .../rayon/src/iter/find_first_last/mod.rs | 230 + .../rayon/src/iter/find_first_last/test.rs | 102 + anneal/v2/vendor/rayon/src/iter/flat_map.rs | 153 + .../v2/vendor/rayon/src/iter/flat_map_iter.rs | 145 + anneal/v2/vendor/rayon/src/iter/flatten.rs | 134 + .../v2/vendor/rayon/src/iter/flatten_iter.rs | 124 + anneal/v2/vendor/rayon/src/iter/fold.rs | 289 + .../v2/vendor/rayon/src/iter/fold_chunks.rs | 224 + .../vendor/rayon/src/iter/fold_chunks_with.rs | 220 + anneal/v2/vendor/rayon/src/iter/for_each.rs | 77 + .../v2/vendor/rayon/src/iter/from_par_iter.rs | 280 + anneal/v2/vendor/rayon/src/iter/inspect.rs | 253 + anneal/v2/vendor/rayon/src/iter/interleave.rs | 326 + .../rayon/src/iter/interleave_shortest.rs | 80 + .../v2/vendor/rayon/src/iter/intersperse.rs | 401 + anneal/v2/vendor/rayon/src/iter/len.rs | 262 + anneal/v2/vendor/rayon/src/iter/map.rs | 255 + anneal/v2/vendor/rayon/src/iter/map_with.rs | 565 + anneal/v2/vendor/rayon/src/iter/mod.rs | 3628 +++ anneal/v2/vendor/rayon/src/iter/multizip.rs | 335 + anneal/v2/vendor/rayon/src/iter/noop.rs | 59 + anneal/v2/vendor/rayon/src/iter/once.rs | 70 + anneal/v2/vendor/rayon/src/iter/panic_fuse.rs | 338 + anneal/v2/vendor/rayon/src/iter/par_bridge.rs | 157 + .../vendor/rayon/src/iter/plumbing/README.md | 315 + .../v2/vendor/rayon/src/iter/plumbing/mod.rs | 476 + anneal/v2/vendor/rayon/src/iter/positions.rs | 133 + anneal/v2/vendor/rayon/src/iter/product.rs | 114 + anneal/v2/vendor/rayon/src/iter/reduce.rs | 116 + anneal/v2/vendor/rayon/src/iter/repeat.rs | 295 + anneal/v2/vendor/rayon/src/iter/rev.rs | 119 + anneal/v2/vendor/rayon/src/iter/skip.rs | 93 + anneal/v2/vendor/rayon/src/iter/skip_any.rs | 140 + .../vendor/rayon/src/iter/skip_any_while.rs | 162 + anneal/v2/vendor/rayon/src/iter/splitter.rs | 172 + anneal/v2/vendor/rayon/src/iter/step_by.rs | 135 + anneal/v2/vendor/rayon/src/iter/sum.rs | 110 + anneal/v2/vendor/rayon/src/iter/take.rs | 84 + anneal/v2/vendor/rayon/src/iter/take_any.rs | 140 + .../vendor/rayon/src/iter/take_any_while.rs | 162 + anneal/v2/vendor/rayon/src/iter/test.rs | 2392 ++ anneal/v2/vendor/rayon/src/iter/try_fold.rs | 282 + anneal/v2/vendor/rayon/src/iter/try_reduce.rs | 131 + .../vendor/rayon/src/iter/try_reduce_with.rs | 132 + anneal/v2/vendor/rayon/src/iter/unzip.rs | 524 + anneal/v2/vendor/rayon/src/iter/update.rs | 323 + anneal/v2/vendor/rayon/src/iter/walk_tree.rs | 524 + anneal/v2/vendor/rayon/src/iter/while_some.rs | 150 + anneal/v2/vendor/rayon/src/iter/zip.rs | 153 + anneal/v2/vendor/rayon/src/iter/zip_eq.rs | 67 + anneal/v2/vendor/rayon/src/lib.rs | 156 + anneal/v2/vendor/rayon/src/math.rs | 25 + anneal/v2/vendor/rayon/src/option.rs | 197 + anneal/v2/vendor/rayon/src/par_either.rs | 74 + anneal/v2/vendor/rayon/src/prelude.rs | 17 + anneal/v2/vendor/rayon/src/private.rs | 26 + anneal/v2/vendor/rayon/src/range.rs | 474 + anneal/v2/vendor/rayon/src/range_inclusive.rs | 398 + anneal/v2/vendor/rayon/src/result.rs | 132 + anneal/v2/vendor/rayon/src/slice/chunk_by.rs | 239 + anneal/v2/vendor/rayon/src/slice/chunks.rs | 387 + anneal/v2/vendor/rayon/src/slice/mod.rs | 1173 + anneal/v2/vendor/rayon/src/slice/rchunks.rs | 385 + anneal/v2/vendor/rayon/src/slice/sort.rs | 1686 ++ anneal/v2/vendor/rayon/src/slice/test.rs | 216 + anneal/v2/vendor/rayon/src/slice/windows.rs | 147 + anneal/v2/vendor/rayon/src/split_producer.rs | 152 + anneal/v2/vendor/rayon/src/str.rs | 1006 + anneal/v2/vendor/rayon/src/string.rs | 48 + anneal/v2/vendor/rayon/src/vec.rs | 292 + anneal/v2/vendor/rayon/tests/chars.rs | 38 + anneal/v2/vendor/rayon/tests/clones.rs | 223 + anneal/v2/vendor/rayon/tests/collect.rs | 113 + anneal/v2/vendor/rayon/tests/cross-pool.rs | 22 + anneal/v2/vendor/rayon/tests/debug.rs | 234 + anneal/v2/vendor/rayon/tests/drain_vec.rs | 41 + anneal/v2/vendor/rayon/tests/intersperse.rs | 60 + .../v2/vendor/rayon/tests/issue671-unzip.rs | 17 + anneal/v2/vendor/rayon/tests/issue671.rs | 16 + anneal/v2/vendor/rayon/tests/iter_panic.rs | 53 + anneal/v2/vendor/rayon/tests/named-threads.rs | 25 + anneal/v2/vendor/rayon/tests/octillion.rs | 156 + .../rayon/tests/par_bridge_recursion.rs | 31 + .../vendor/rayon/tests/producer_split_at.rs | 393 + .../v2/vendor/rayon/tests/sort-panic-safe.rs | 164 + anneal/v2/vendor/rayon/tests/str.rs | 122 + .../rustc-demangle/.cargo-checksum.json | 1 + .../rustc-demangle/.cargo_vcs_info.json | 6 + .../rustc-demangle/.github/dependabot.yml | 8 + .../rustc-demangle/.github/workflows/main.yml | 56 + .../.github/workflows/release.yml | 27 + anneal/v2/vendor/rustc-demangle/CHANGELOG.md | 23 + anneal/v2/vendor/rustc-demangle/Cargo.lock | 16 + anneal/v2/vendor/rustc-demangle/Cargo.toml | 52 + .../v2/vendor/rustc-demangle/Cargo.toml.orig | 33 + .../v2/vendor/rustc-demangle/LICENSE-APACHE | 201 + anneal/v2/vendor/rustc-demangle/LICENSE-MIT | 25 + anneal/v2/vendor/rustc-demangle/README.md | 57 + anneal/v2/vendor/rustc-demangle/src/legacy.rs | 392 + anneal/v2/vendor/rustc-demangle/src/lib.rs | 588 + .../early-recursion-limit | 10 + anneal/v2/vendor/rustc-demangle/src/v0.rs | 1587 ++ .../vendor/rustversion/.cargo-checksum.json | 1 + .../vendor/rustversion/.cargo_vcs_info.json | 6 + .../v2/vendor/rustversion/.github/FUNDING.yml | 1 + .../rustversion/.github/workflows/ci.yml | 117 + anneal/v2/vendor/rustversion/Cargo.lock | 296 + anneal/v2/vendor/rustversion/Cargo.toml | 68 + anneal/v2/vendor/rustversion/Cargo.toml.orig | 28 + anneal/v2/vendor/rustversion/LICENSE-APACHE | 176 + anneal/v2/vendor/rustversion/LICENSE-MIT | 23 + anneal/v2/vendor/rustversion/README.md | 167 + anneal/v2/vendor/rustversion/build/build.rs | 114 + anneal/v2/vendor/rustversion/build/rustc.rs | 126 + anneal/v2/vendor/rustversion/src/attr.rs | 35 + anneal/v2/vendor/rustversion/src/bound.rs | 63 + anneal/v2/vendor/rustversion/src/constfn.rs | 58 + anneal/v2/vendor/rustversion/src/date.rs | 50 + anneal/v2/vendor/rustversion/src/error.rs | 56 + anneal/v2/vendor/rustversion/src/expand.rs | 100 + anneal/v2/vendor/rustversion/src/expr.rs | 163 + anneal/v2/vendor/rustversion/src/iter.rs | 42 + anneal/v2/vendor/rustversion/src/lib.rs | 282 + anneal/v2/vendor/rustversion/src/release.rs | 34 + anneal/v2/vendor/rustversion/src/time.rs | 51 + anneal/v2/vendor/rustversion/src/token.rs | 78 + anneal/v2/vendor/rustversion/src/version.rs | 18 + .../vendor/rustversion/tests/compiletest.rs | 7 + .../v2/vendor/rustversion/tests/test_const.rs | 42 + .../v2/vendor/rustversion/tests/test_eval.rs | 20 + .../v2/vendor/rustversion/tests/test_parse.rs | 103 + .../vendor/rustversion/tests/ui/bad-bound.rs | 7 + .../rustversion/tests/ui/bad-bound.stderr | 11 + .../vendor/rustversion/tests/ui/bad-date.rs | 7 + .../rustversion/tests/ui/bad-date.stderr | 11 + .../v2/vendor/rustversion/tests/ui/bad-not.rs | 7 + .../rustversion/tests/ui/bad-not.stderr | 11 + .../rustversion/tests/ui/bad-version.rs | 7 + .../rustversion/tests/ui/bad-version.stderr | 11 + .../rustversion/tests/ui/const-not-fn.rs | 4 + .../rustversion/tests/ui/const-not-fn.stderr | 5 + .../v2/vendor/same-file/.cargo-checksum.json | 1 + .../v2/vendor/same-file/.cargo_vcs_info.json | 5 + anneal/v2/vendor/same-file/COPYING | 3 + anneal/v2/vendor/same-file/Cargo.lock | 48 + anneal/v2/vendor/same-file/Cargo.toml | 29 + anneal/v2/vendor/same-file/Cargo.toml.orig | 21 + anneal/v2/vendor/same-file/LICENSE-MIT | 21 + anneal/v2/vendor/same-file/README.md | 49 + anneal/v2/vendor/same-file/UNLICENSE | 24 + .../vendor/same-file/examples/is_same_file.rs | 11 + .../v2/vendor/same-file/examples/is_stderr.rs | 31 + anneal/v2/vendor/same-file/rustfmt.toml | 2 + anneal/v2/vendor/same-file/src/lib.rs | 572 + anneal/v2/vendor/same-file/src/unix.rs | 112 + anneal/v2/vendor/same-file/src/unknown.rs | 52 + anneal/v2/vendor/same-file/src/win.rs | 172 + .../vendor/sha2-0.10.9/.cargo-checksum.json | 1 + .../vendor/sha2-0.10.9/.cargo_vcs_info.json | 6 + anneal/v2/vendor/sha2-0.10.9/CHANGELOG.md | 188 + anneal/v2/vendor/sha2-0.10.9/Cargo.lock | 143 + anneal/v2/vendor/sha2-0.10.9/Cargo.toml | 90 + anneal/v2/vendor/sha2-0.10.9/Cargo.toml.orig | 44 + anneal/v2/vendor/sha2-0.10.9/LICENSE-APACHE | 201 + anneal/v2/vendor/sha2-0.10.9/LICENSE-MIT | 27 + anneal/v2/vendor/sha2-0.10.9/README.md | 59 + anneal/v2/vendor/sha2-0.10.9/benches/mod.rs | 22 + anneal/v2/vendor/sha2-0.10.9/src/consts.rs | 107 + anneal/v2/vendor/sha2-0.10.9/src/core_api.rs | 157 + anneal/v2/vendor/sha2-0.10.9/src/lib.rs | 110 + anneal/v2/vendor/sha2-0.10.9/src/sha256.rs | 43 + .../vendor/sha2-0.10.9/src/sha256/aarch64.rs | 159 + .../sha2-0.10.9/src/sha256/loongarch64_asm.rs | 227 + .../v2/vendor/sha2-0.10.9/src/sha256/soft.rs | 218 + .../sha2-0.10.9/src/sha256/soft_compact.rs | 66 + .../v2/vendor/sha2-0.10.9/src/sha256/x86.rs | 112 + anneal/v2/vendor/sha2-0.10.9/src/sha512.rs | 45 + .../vendor/sha2-0.10.9/src/sha512/aarch64.rs | 235 + .../sha2-0.10.9/src/sha512/loongarch64_asm.rs | 242 + .../v2/vendor/sha2-0.10.9/src/sha512/soft.rs | 215 + .../sha2-0.10.9/src/sha512/soft_compact.rs | 66 + .../v2/vendor/sha2-0.10.9/src/sha512/x86.rs | 357 + .../vendor/sha2-0.10.9/tests/data/sha224.blb | Bin 0 -> 178 bytes .../vendor/sha2-0.10.9/tests/data/sha256.blb | Bin 0 -> 190 bytes .../vendor/sha2-0.10.9/tests/data/sha384.blb | Bin 0 -> 238 bytes .../vendor/sha2-0.10.9/tests/data/sha512.blb | Bin 0 -> 289 bytes .../sha2-0.10.9/tests/data/sha512_224.blb | Bin 0 -> 178 bytes .../sha2-0.10.9/tests/data/sha512_256.blb | Bin 0 -> 190 bytes anneal/v2/vendor/sha2-0.10.9/tests/mod.rs | 35 + anneal/v2/vendor/slab/.cargo-checksum.json | 1 + anneal/v2/vendor/slab/.cargo_vcs_info.json | 6 + anneal/v2/vendor/slab/CHANGELOG.md | 71 + anneal/v2/vendor/slab/Cargo.lock | 83 + anneal/v2/vendor/slab/Cargo.toml | 67 + anneal/v2/vendor/slab/Cargo.toml.orig | 29 + anneal/v2/vendor/slab/LICENSE | 25 + anneal/v2/vendor/slab/README.md | 51 + anneal/v2/vendor/slab/SECURITY.md | 9 + anneal/v2/vendor/slab/src/builder.rs | 63 + anneal/v2/vendor/slab/src/lib.rs | 1653 ++ anneal/v2/vendor/slab/src/serde.rs | 62 + anneal/v2/vendor/slab/tests/serde.rs | 49 + anneal/v2/vendor/slab/tests/slab.rs | 782 + .../supports-color/.cargo-checksum.json | 1 + .../supports-color/.cargo_vcs_info.json | 6 + anneal/v2/vendor/supports-color/.editorconfig | 7 + .../vendor/supports-color/.github/FUNDING.yml | 12 + .../supports-color/.github/workflows/miri.yml | 22 + anneal/v2/vendor/supports-color/CHANGELOG.md | 115 + anneal/v2/vendor/supports-color/Cargo.toml | 39 + .../v2/vendor/supports-color/Cargo.toml.orig | 17 + anneal/v2/vendor/supports-color/LICENSE | 229 + anneal/v2/vendor/supports-color/Makefile.toml | 11 + anneal/v2/vendor/supports-color/README.md | 23 + anneal/v2/vendor/supports-color/cliff.toml | 62 + anneal/v2/vendor/supports-color/src/lib.rs | 276 + .../v2/vendor/supports-color/tests/cached.rs | 12 + .../supports-hyperlinks/.cargo-checksum.json | 1 + .../supports-hyperlinks/.cargo_vcs_info.json | 6 + .../vendor/supports-hyperlinks/.editorconfig | 7 + .../supports-hyperlinks/.github/FUNDING.yml | 12 + .../vendor/supports-hyperlinks/CHANGELOG.md | 83 + .../v2/vendor/supports-hyperlinks/Cargo.lock | 7 + .../v2/vendor/supports-hyperlinks/Cargo.toml | 32 + .../supports-hyperlinks/Cargo.toml.orig | 11 + anneal/v2/vendor/supports-hyperlinks/LICENSE | 229 + .../vendor/supports-hyperlinks/Makefile.toml | 11 + .../v2/vendor/supports-hyperlinks/README.md | 32 + .../v2/vendor/supports-hyperlinks/cliff.toml | 62 + .../v2/vendor/supports-hyperlinks/src/lib.rs | 67 + .../supports-unicode/.cargo-checksum.json | 1 + .../supports-unicode/.cargo_vcs_info.json | 6 + .../v2/vendor/supports-unicode/.editorconfig | 7 + .../supports-unicode/.github/FUNDING.yml | 12 + .../v2/vendor/supports-unicode/CHANGELOG.md | 49 + anneal/v2/vendor/supports-unicode/Cargo.toml | 23 + .../vendor/supports-unicode/Cargo.toml.orig | 12 + anneal/v2/vendor/supports-unicode/LICENSE | 229 + .../v2/vendor/supports-unicode/Makefile.toml | 11 + anneal/v2/vendor/supports-unicode/README.md | 23 + anneal/v2/vendor/supports-unicode/cliff.toml | 62 + anneal/v2/vendor/supports-unicode/src/lib.rs | 52 + .../vendor/terminal_size/.cargo-checksum.json | 1 + .../vendor/terminal_size/.cargo_vcs_info.json | 6 + .../terminal_size/.github/dependabot.yml | 13 + .../terminal_size/.github/workflows/main.yml | 62 + anneal/v2/vendor/terminal_size/Cargo.lock | 125 + anneal/v2/vendor/terminal_size/Cargo.toml | 54 + .../v2/vendor/terminal_size/Cargo.toml.orig | 22 + anneal/v2/vendor/terminal_size/LICENSE-APACHE | 202 + anneal/v2/vendor/terminal_size/LICENSE-MIT | 19 + anneal/v2/vendor/terminal_size/README.md | 41 + .../vendor/terminal_size/examples/get_size.rs | 19 + anneal/v2/vendor/terminal_size/src/lib.rs | 41 + anneal/v2/vendor/terminal_size/src/unix.rs | 130 + anneal/v2/vendor/terminal_size/src/windows.rs | 85 + .../v2/vendor/textwrap/.cargo-checksum.json | 1 + .../v2/vendor/textwrap/.cargo_vcs_info.json | 6 + anneal/v2/vendor/textwrap/CHANGELOG.md | 610 + anneal/v2/vendor/textwrap/Cargo.lock | 805 + anneal/v2/vendor/textwrap/Cargo.toml | 104 + anneal/v2/vendor/textwrap/Cargo.toml.orig | 47 + anneal/v2/vendor/textwrap/LICENSE | 21 + anneal/v2/vendor/textwrap/README.md | 174 + anneal/v2/vendor/textwrap/dprint.json | 19 + anneal/v2/vendor/textwrap/rustfmt.toml | 1 + anneal/v2/vendor/textwrap/src/columns.rs | 193 + anneal/v2/vendor/textwrap/src/core.rs | 461 + anneal/v2/vendor/textwrap/src/fill.rs | 298 + anneal/v2/vendor/textwrap/src/fuzzing.rs | 23 + anneal/v2/vendor/textwrap/src/indentation.rs | 347 + anneal/v2/vendor/textwrap/src/lib.rs | 235 + anneal/v2/vendor/textwrap/src/line_ending.rs | 88 + anneal/v2/vendor/textwrap/src/options.rs | 300 + anneal/v2/vendor/textwrap/src/refill.rs | 352 + anneal/v2/vendor/textwrap/src/termwidth.rs | 52 + .../v2/vendor/textwrap/src/word_separators.rs | 470 + .../v2/vendor/textwrap/src/word_splitters.rs | 302 + anneal/v2/vendor/textwrap/src/wrap.rs | 686 + .../v2/vendor/textwrap/src/wrap_algorithms.rs | 399 + .../src/wrap_algorithms/optimal_fit.rs | 433 + anneal/v2/vendor/textwrap/tests/indent.rs | 88 + .../vendor/textwrap/tests/version-numbers.rs | 22 + .../unicode-linebreak/.cargo-checksum.json | 1 + anneal/v2/vendor/unicode-linebreak/Cargo.toml | 32 + .../vendor/unicode-linebreak/Cargo.toml.orig | 14 + anneal/v2/vendor/unicode-linebreak/LICENSE | 201 + anneal/v2/vendor/unicode-linebreak/README.md | 36 + anneal/v2/vendor/unicode-linebreak/src/lib.rs | 160 + .../v2/vendor/unicode-linebreak/src/shared.rs | 134 + .../v2/vendor/unicode-linebreak/src/tables.rs | 10 + .../unicode-segmentation/.cargo-checksum.json | 1 + .../unicode-segmentation/.cargo_vcs_info.json | 6 + .../v2/vendor/unicode-segmentation/COPYRIGHT | 7 + .../v2/vendor/unicode-segmentation/Cargo.lock | 1059 + .../v2/vendor/unicode-segmentation/Cargo.toml | 91 + .../unicode-segmentation/Cargo.toml.orig | 54 + .../unicode-segmentation/LICENSE-APACHE | 201 + .../vendor/unicode-segmentation/LICENSE-MIT | 25 + .../v2/vendor/unicode-segmentation/README.md | 141 + .../unicode-segmentation/benches/chars.rs | 59 + .../benches/unicode_word_indices.rs | 37 + .../benches/word_bounds.rs | 37 + .../unicode-segmentation/benches/words.rs | 59 + .../unicode-segmentation/src/grapheme.rs | 884 + .../v2/vendor/unicode-segmentation/src/lib.rs | 297 + .../unicode-segmentation/src/sentence.rs | 418 + .../vendor/unicode-segmentation/src/tables.rs | 3341 +++ .../vendor/unicode-segmentation/src/word.rs | 1132 + .../vendor/unicode-segmentation/tests/test.rs | 247 + .../tests/testdata/mod.rs | 2340 ++ .../unicode-width-0.1.14/.cargo-checksum.json | 1 + .../unicode-width-0.1.14/.cargo_vcs_info.json | 6 + .../v2/vendor/unicode-width-0.1.14/COPYRIGHT | 7 + .../v2/vendor/unicode-width-0.1.14/Cargo.toml | 80 + .../unicode-width-0.1.14/Cargo.toml.orig | 40 + .../unicode-width-0.1.14/LICENSE-APACHE | 201 + .../vendor/unicode-width-0.1.14/LICENSE-MIT | 25 + .../v2/vendor/unicode-width-0.1.14/README.md | 57 + .../unicode-width-0.1.14/benches/benches.rs | 114 + .../unicode-width-0.1.14/scripts/unicode.py | 2156 ++ .../v2/vendor/unicode-width-0.1.14/src/lib.rs | 258 + .../vendor/unicode-width-0.1.14/src/tables.rs | 21762 +++++++++++++++ .../unicode-width-0.1.14/tests/emoji-test.txt | 5325 ++++ .../unicode-width-0.1.14/tests/tests.rs | 631 + .../vendor/unicode-width/.cargo-checksum.json | 1 + .../vendor/unicode-width/.cargo_vcs_info.json | 6 + anneal/v2/vendor/unicode-width/COPYRIGHT | 7 + anneal/v2/vendor/unicode-width/Cargo.lock | 23 + anneal/v2/vendor/unicode-width/Cargo.toml | 77 + .../v2/vendor/unicode-width/Cargo.toml.orig | 40 + anneal/v2/vendor/unicode-width/LICENSE-APACHE | 201 + anneal/v2/vendor/unicode-width/LICENSE-MIT | 25 + anneal/v2/vendor/unicode-width/README.md | 70 + .../vendor/unicode-width/benches/benches.rs | 114 + .../vendor/unicode-width/scripts/unicode.py | 2250 ++ anneal/v2/vendor/unicode-width/src/lib.rs | 259 + anneal/v2/vendor/unicode-width/src/tables.rs | 22869 ++++++++++++++++ .../vendor/unicode-width/tests/emoji-test.txt | 5518 ++++ anneal/v2/vendor/unicode-width/tests/tests.rs | 678 + .../vendor/unit-prefix/.cargo-checksum.json | 1 + .../vendor/unit-prefix/.cargo_vcs_info.json | 6 + .../unit-prefix/.forgejo/workflows/ci.yaml | 58 + anneal/v2/vendor/unit-prefix/Cargo.lock | 7 + anneal/v2/vendor/unit-prefix/Cargo.toml | 54 + anneal/v2/vendor/unit-prefix/Cargo.toml.orig | 28 + anneal/v2/vendor/unit-prefix/LICENSE | 21 + anneal/v2/vendor/unit-prefix/README.md | 10 + .../unit-prefix/examples/conversions.rs | 59 + anneal/v2/vendor/unit-prefix/src/lib.rs | 637 + anneal/v2/vendor/unit-prefix/src/parse.rs | 82 + .../vendor/version_check/.cargo-checksum.json | 1 + .../vendor/version_check/.cargo_vcs_info.json | 6 + .../version_check/.github/workflows/ci.yml | 42 + anneal/v2/vendor/version_check/.travis.yml | 6 + anneal/v2/vendor/version_check/Cargo.toml | 38 + .../v2/vendor/version_check/Cargo.toml.orig | 13 + anneal/v2/vendor/version_check/LICENSE-APACHE | 201 + anneal/v2/vendor/version_check/LICENSE-MIT | 19 + anneal/v2/vendor/version_check/README.md | 80 + anneal/v2/vendor/version_check/src/channel.rs | 195 + anneal/v2/vendor/version_check/src/date.rs | 203 + anneal/v2/vendor/version_check/src/lib.rs | 528 + anneal/v2/vendor/version_check/src/version.rs | 316 + anneal/v2/vendor/walkdir/.cargo-checksum.json | 1 + anneal/v2/vendor/walkdir/.cargo_vcs_info.json | 6 + .../vendor/walkdir/.github/workflows/ci.yml | 94 + anneal/v2/vendor/walkdir/COPYING | 3 + anneal/v2/vendor/walkdir/Cargo.toml | 49 + anneal/v2/vendor/walkdir/Cargo.toml.orig | 30 + anneal/v2/vendor/walkdir/LICENSE-MIT | 21 + anneal/v2/vendor/walkdir/README.md | 139 + anneal/v2/vendor/walkdir/UNLICENSE | 24 + anneal/v2/vendor/walkdir/compare/nftw.c | 25 + anneal/v2/vendor/walkdir/compare/walk.py | 10 + anneal/v2/vendor/walkdir/rustfmt.toml | 2 + anneal/v2/vendor/walkdir/src/dent.rs | 352 + anneal/v2/vendor/walkdir/src/error.rs | 262 + anneal/v2/vendor/walkdir/src/lib.rs | 1194 + anneal/v2/vendor/walkdir/src/tests/mod.rs | 4 + .../v2/vendor/walkdir/src/tests/recursive.rs | 1092 + anneal/v2/vendor/walkdir/src/tests/util.rs | 252 + anneal/v2/vendor/walkdir/src/util.rs | 25 + .../.cargo-checksum.json | 1 + .../.cargo_vcs_info.json | 6 + .../wasm-bindgen-macro-support/Cargo.lock | 64 + .../wasm-bindgen-macro-support/Cargo.toml | 82 + .../Cargo.toml.orig | 26 + .../wasm-bindgen-macro-support/LICENSE-APACHE | 201 + .../wasm-bindgen-macro-support/LICENSE-MIT | 25 + .../wasm-bindgen-macro-support/src/ast.rs | 708 + .../wasm-bindgen-macro-support/src/codegen.rs | 3383 +++ .../wasm-bindgen-macro-support/src/encode.rs | 714 + .../wasm-bindgen-macro-support/src/error.rs | 132 + .../src/generics.rs | 1031 + .../wasm-bindgen-macro-support/src/hash.rs | 45 + .../wasm-bindgen-macro-support/src/lib.rs | 239 + .../wasm-bindgen-macro-support/src/parser.rs | 3076 +++ .../wasm-bindgen-macro/.cargo-checksum.json | 1 + .../wasm-bindgen-macro/.cargo_vcs_info.json | 6 + .../v2/vendor/wasm-bindgen-macro/Cargo.lock | 271 + .../v2/vendor/wasm-bindgen-macro/Cargo.toml | 72 + .../vendor/wasm-bindgen-macro/Cargo.toml.orig | 34 + .../vendor/wasm-bindgen-macro/LICENSE-APACHE | 201 + .../v2/vendor/wasm-bindgen-macro/LICENSE-MIT | 25 + anneal/v2/vendor/wasm-bindgen-macro/README.md | 26 + .../v2/vendor/wasm-bindgen-macro/src/lib.rs | 75 + .../vendor/wasm-bindgen-macro/src/worker.js | 1 + .../wasm-bindgen-shared/.cargo-checksum.json | 1 + .../wasm-bindgen-shared/.cargo_vcs_info.json | 6 + .../v2/vendor/wasm-bindgen-shared/Cargo.lock | 16 + .../v2/vendor/wasm-bindgen-shared/Cargo.toml | 65 + .../wasm-bindgen-shared/Cargo.toml.orig | 26 + .../vendor/wasm-bindgen-shared/LICENSE-APACHE | 201 + .../v2/vendor/wasm-bindgen-shared/LICENSE-MIT | 25 + anneal/v2/vendor/wasm-bindgen-shared/build.rs | 37 + .../wasm-bindgen-shared/src/identifier.rs | 151 + .../v2/vendor/wasm-bindgen-shared/src/lib.rs | 359 + .../src/schema_hash_approval.rs | 16 + .../v2/vendor/wasm-bindgen-shared/src/tys.rs | 48 + .../vendor/wasm-bindgen/.cargo-checksum.json | 1 + .../vendor/wasm-bindgen/.cargo_vcs_info.json | 6 + anneal/v2/vendor/wasm-bindgen/Cargo.lock | 175 + anneal/v2/vendor/wasm-bindgen/Cargo.toml | 121 + anneal/v2/vendor/wasm-bindgen/Cargo.toml.orig | 150 + anneal/v2/vendor/wasm-bindgen/LICENSE-APACHE | 201 + anneal/v2/vendor/wasm-bindgen/LICENSE-MIT | 25 + anneal/v2/vendor/wasm-bindgen/README.md | 143 + anneal/v2/vendor/wasm-bindgen/build.rs | 49 + .../vendor/wasm-bindgen/src/cache/intern.rs | 103 + .../v2/vendor/wasm-bindgen/src/cache/mod.rs | 1 + anneal/v2/vendor/wasm-bindgen/src/cast.rs | 172 + anneal/v2/vendor/wasm-bindgen/src/closure.rs | 1000 + .../wasm-bindgen/src/convert/closures.rs | 506 + .../vendor/wasm-bindgen/src/convert/impls.rs | 856 + .../v2/vendor/wasm-bindgen/src/convert/mod.rs | 15 + .../vendor/wasm-bindgen/src/convert/slices.rs | 581 + .../vendor/wasm-bindgen/src/convert/traits.rs | 608 + anneal/v2/vendor/wasm-bindgen/src/describe.rs | 223 + .../v2/vendor/wasm-bindgen/src/externref.rs | 162 + anneal/v2/vendor/wasm-bindgen/src/handler.rs | 33 + anneal/v2/vendor/wasm-bindgen/src/lib.rs | 1874 ++ anneal/v2/vendor/wasm-bindgen/src/link.rs | 4 + anneal/v2/vendor/wasm-bindgen/src/parent.rs | 95 + .../v2/vendor/wasm-bindgen/src/rt/marker.rs | 142 + anneal/v2/vendor/wasm-bindgen/src/rt/mod.rs | 1085 + anneal/v2/vendor/wasm-bindgen/src/sys.rs | 270 + .../v2/vendor/web-time/.cargo-checksum.json | 1 + .../v2/vendor/web-time/.cargo_vcs_info.json | 6 + anneal/v2/vendor/web-time/CHANGELOG.md | 74 + anneal/v2/vendor/web-time/Cargo.lock | 393 + anneal/v2/vendor/web-time/Cargo.toml | 246 + anneal/v2/vendor/web-time/Cargo.toml.orig | 174 + anneal/v2/vendor/web-time/LICENSE-APACHE | 201 + anneal/v2/vendor/web-time/LICENSE-MIT | 21 + anneal/v2/vendor/web-time/README.md | 135 + anneal/v2/vendor/web-time/src/lib.rs | 144 + anneal/v2/vendor/web-time/src/time/instant.rs | 242 + anneal/v2/vendor/web-time/src/time/js.rs | 39 + anneal/v2/vendor/web-time/src/time/mod.rs | 15 + anneal/v2/vendor/web-time/src/time/serde.rs | 177 + .../vendor/web-time/src/time/system_time.rs | 111 + anneal/v2/vendor/web-time/src/web.rs | 49 + .../.cargo-checksum.json | 1 + .../winapi-i686-pc-windows-gnu/Cargo.toml | 22 + .../Cargo.toml.orig | 10 + .../winapi-i686-pc-windows-gnu/build.rs | 18 + .../lib/libwinapi_aclui.a | Bin 0 -> 6530 bytes .../lib/libwinapi_activeds.a | Bin 0 -> 23432 bytes .../lib/libwinapi_advapi32.a | Bin 0 -> 638848 bytes .../lib/libwinapi_advpack.a | Bin 0 -> 59044 bytes .../lib/libwinapi_amsi.a | Bin 0 -> 8748 bytes ...ibwinapi_api-ms-win-net-isolation-l1-1-0.a | Bin 0 -> 9332 bytes .../lib/libwinapi_apidll.a | Bin 0 -> 2414 bytes .../lib/libwinapi_appmgmts.a | Bin 0 -> 14600 bytes .../lib/libwinapi_appnotify.a | Bin 0 -> 3514 bytes .../lib/libwinapi_asycfilt.a | Bin 0 -> 2516 bytes .../lib/libwinapi_audioeng.a | Bin 0 -> 3232 bytes .../lib/libwinapi_authz.a | Bin 0 -> 32246 bytes .../lib/libwinapi_avifil32.a | Bin 0 -> 60434 bytes .../lib/libwinapi_avrt.a | Bin 0 -> 18480 bytes .../lib/libwinapi_basesrv.a | Bin 0 -> 6636 bytes .../lib/libwinapi_bcrypt.a | Bin 0 -> 46134 bytes .../lib/libwinapi_bluetoothapis.a | Bin 0 -> 83674 bytes .../lib/libwinapi_bthprops.a | Bin 0 -> 35596 bytes .../lib/libwinapi_cabinet.a | Bin 0 -> 22048 bytes .../lib/libwinapi_certadm.a | Bin 0 -> 26176 bytes .../lib/libwinapi_certpoleng.a | Bin 0 -> 13278 bytes .../lib/libwinapi_cfgmgr32.a | Bin 0 -> 195160 bytes .../lib/libwinapi_chakrart.a | Bin 0 -> 97940 bytes .../lib/libwinapi_cldapi.a | Bin 0 -> 37550 bytes .../lib/libwinapi_clfsw32.a | Bin 0 -> 51152 bytes .../lib/libwinapi_clusapi.a | Bin 0 -> 228586 bytes .../lib/libwinapi_comctl32.a | Bin 0 -> 103756 bytes .../lib/libwinapi_comdlg32.a | Bin 0 -> 17976 bytes .../lib/libwinapi_comppkgsup.a | Bin 0 -> 9324 bytes .../lib/libwinapi_compstui.a | Bin 0 -> 4940 bytes .../lib/libwinapi_comsvcs.a | Bin 0 -> 15250 bytes .../lib/libwinapi_coremessaging.a | Bin 0 -> 24934 bytes .../lib/libwinapi_credui.a | Bin 0 -> 20262 bytes .../lib/libwinapi_crypt32.a | Bin 0 -> 201352 bytes .../lib/libwinapi_cryptdll.a | Bin 0 -> 17408 bytes .../lib/libwinapi_cryptnet.a | Bin 0 -> 5888 bytes .../lib/libwinapi_cryptui.a | Bin 0 -> 36956 bytes .../lib/libwinapi_cryptxml.a | Bin 0 -> 17188 bytes .../lib/libwinapi_cscapi.a | Bin 0 -> 6646 bytes .../lib/libwinapi_cscdll.a | Bin 0 -> 16026 bytes .../lib/libwinapi_d2d1.a | Bin 0 -> 12224 bytes .../lib/libwinapi_d3d10.a | Bin 0 -> 25950 bytes .../lib/libwinapi_d3d10_1.a | Bin 0 -> 26034 bytes .../lib/libwinapi_d3d11.a | Bin 0 -> 28246 bytes .../lib/libwinapi_d3d12.a | Bin 0 -> 10262 bytes .../lib/libwinapi_d3d9.a | Bin 0 -> 10368 bytes .../lib/libwinapi_d3dcompiler.a | Bin 0 -> 23522 bytes .../lib/libwinapi_d3dcsx.a | Bin 0 -> 9064 bytes .../lib/libwinapi_d3dcsxd.a | Bin 0 -> 9070 bytes .../lib/libwinapi_davclnt.a | Bin 0 -> 19272 bytes .../lib/libwinapi_dbgeng.a | Bin 0 -> 4798 bytes .../lib/libwinapi_dbghelp.a | Bin 0 -> 188614 bytes .../lib/libwinapi_dciman32.a | Bin 0 -> 17464 bytes .../lib/libwinapi_dcomp.a | Bin 0 -> 6814 bytes .../lib/libwinapi_ddraw.a | Bin 0 -> 12118 bytes .../lib/libwinapi_deviceaccess.a | Bin 0 -> 4240 bytes .../lib/libwinapi_devmgr.a | Bin 0 -> 17380 bytes .../lib/libwinapi_dflayout.a | Bin 0 -> 2516 bytes .../lib/libwinapi_dhcpcsvc.a | Bin 0 -> 54208 bytes .../lib/libwinapi_dhcpcsvc6.a | Bin 0 -> 19586 bytes .../lib/libwinapi_dhcpsapi.a | Bin 0 -> 173528 bytes .../lib/libwinapi_difxapi.a | Bin 0 -> 11540 bytes .../lib/libwinapi_dinput8.a | Bin 0 -> 2498 bytes .../lib/libwinapi_dmprocessxmlfiltered.a | Bin 0 -> 4340 bytes .../lib/libwinapi_dnsapi.a | Bin 0 -> 222244 bytes .../lib/libwinapi_dnsperf.a | Bin 0 -> 4178 bytes .../lib/libwinapi_dnsrslvr.a | Bin 0 -> 4908 bytes .../lib/libwinapi_dpx.a | Bin 0 -> 5510 bytes .../lib/libwinapi_drt.a | Bin 0 -> 14256 bytes .../lib/libwinapi_drtprov.a | Bin 0 -> 9422 bytes .../lib/libwinapi_drttransport.a | Bin 0 -> 3408 bytes .../lib/libwinapi_dsound.a | Bin 0 -> 9906 bytes .../lib/libwinapi_dsprop.a | Bin 0 -> 9802 bytes .../lib/libwinapi_dssec.a | Bin 0 -> 4982 bytes .../lib/libwinapi_dststlog.a | Bin 0 -> 2440 bytes .../lib/libwinapi_dsuiext.a | Bin 0 -> 28246 bytes .../lib/libwinapi_dwmapi.a | Bin 0 -> 26370 bytes .../lib/libwinapi_dwrite.a | Bin 0 -> 2496 bytes .../lib/libwinapi_dxgi.a | Bin 0 -> 9100 bytes .../lib/libwinapi_dxva2.a | Bin 0 -> 33790 bytes .../lib/libwinapi_eappcfg.a | Bin 0 -> 14754 bytes .../lib/libwinapi_eappprxy.a | Bin 0 -> 16904 bytes .../lib/libwinapi_easregprov.a | Bin 0 -> 3434 bytes .../lib/libwinapi_efswrt.a | Bin 0 -> 16522 bytes .../lib/libwinapi_elscore.a | Bin 0 -> 5730 bytes .../lib/libwinapi_esent.a | Bin 0 -> 297340 bytes .../lib/libwinapi_evr.a | Bin 0 -> 9022 bytes .../lib/libwinapi_faultrep.a | Bin 0 -> 9740 bytes .../lib/libwinapi_feclient.a | Bin 0 -> 38976 bytes .../lib/libwinapi_fhsvcctl.a | Bin 0 -> 13264 bytes .../lib/libwinapi_fltlib.a | Bin 0 -> 25124 bytes .../lib/libwinapi_fontsub.a | Bin 0 -> 3260 bytes .../lib/libwinapi_framedyd.a | Bin 0 -> 2448 bytes .../lib/libwinapi_framedyn.a | Bin 0 -> 2448 bytes .../lib/libwinapi_fwpuclnt.a | Bin 0 -> 230628 bytes .../lib/libwinapi_fxsutility.a | Bin 0 -> 3334 bytes .../lib/libwinapi_gdi32.a | Bin 0 -> 467986 bytes .../lib/libwinapi_gdiplus.a | Bin 0 -> 519444 bytes .../lib/libwinapi_glmf32.a | Bin 0 -> 105898 bytes .../lib/libwinapi_glu32.a | Bin 0 -> 42450 bytes .../lib/libwinapi_gpedit.a | Bin 0 -> 9510 bytes .../lib/libwinapi_hbaapi.a | Bin 0 -> 77788 bytes .../lib/libwinapi_hid.a | Bin 0 -> 37396 bytes .../lib/libwinapi_hlink.a | Bin 0 -> 24690 bytes .../lib/libwinapi_hrtfapo.a | Bin 0 -> 4928 bytes .../lib/libwinapi_httpapi.a | Bin 0 -> 37110 bytes .../lib/libwinapi_iashlpr.a | Bin 0 -> 10976 bytes .../lib/libwinapi_icm32.a | Bin 0 -> 18518 bytes .../lib/libwinapi_icmui.a | Bin 0 -> 3290 bytes .../lib/libwinapi_icuin.a | Bin 0 -> 472558 bytes .../lib/libwinapi_icuuc.a | Bin 0 -> 672918 bytes .../lib/libwinapi_imagehlp.a | Bin 0 -> 121240 bytes .../lib/libwinapi_imgutil.a | Bin 0 -> 8742 bytes .../lib/libwinapi_imm32.a | Bin 0 -> 67314 bytes .../lib/libwinapi_infocardapi.a | Bin 0 -> 14986 bytes .../lib/libwinapi_inkobjcore.a | Bin 0 -> 25390 bytes .../lib/libwinapi_inseng.a | Bin 0 -> 7268 bytes .../lib/libwinapi_iphlpapi.a | Bin 0 -> 232092 bytes .../lib/libwinapi_iprop.a | Bin 0 -> 7970 bytes .../lib/libwinapi_irprops.a | Bin 0 -> 31162 bytes .../lib/libwinapi_iscsidsc.a | Bin 0 -> 68212 bytes .../lib/libwinapi_jsrt.a | Bin 0 -> 75092 bytes .../lib/libwinapi_kernel32.a | Bin 0 -> 1061514 bytes .../lib/libwinapi_ksproxy.a | Bin 0 -> 6644 bytes .../lib/libwinapi_ksuser.a | Bin 0 -> 8030 bytes .../lib/libwinapi_ktmw32.a | Bin 0 -> 37906 bytes .../lib/libwinapi_loadperf.a | Bin 0 -> 13324 bytes .../lib/libwinapi_lz32.a | Bin 0 -> 12284 bytes .../lib/libwinapi_magnification.a | Bin 0 -> 17366 bytes .../lib/libwinapi_mapi32.a | Bin 0 -> 123408 bytes .../lib/libwinapi_mciole32.a | Bin 0 -> 10428 bytes .../lib/libwinapi_mdmlocalmanagement.a | Bin 0 -> 4396 bytes .../lib/libwinapi_mdmregistration.a | Bin 0 -> 10384 bytes .../lib/libwinapi_mf.a | Bin 0 -> 63716 bytes .../lib/libwinapi_mfcore.a | Bin 0 -> 31378 bytes .../lib/libwinapi_mfplat.a | Bin 0 -> 126538 bytes .../lib/libwinapi_mfplay.a | Bin 0 -> 2500 bytes .../lib/libwinapi_mfreadwrite.a | Bin 0 -> 6070 bytes .../lib/libwinapi_mfsensorgroup.a | Bin 0 -> 4222 bytes .../lib/libwinapi_mfsrcsnk.a | Bin 0 -> 3336 bytes .../lib/libwinapi_mgmtapi.a | Bin 0 -> 8730 bytes .../lib/libwinapi_mi.a | Bin 0 -> 2496 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68470 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3554 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3470 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66136 bytes ...napi_mincore-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16372 bytes ...napi_mincore-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2654 bytes ...i_mincore-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13390 bytes ...i_mincore-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34426 bytes ..._mincore-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5148 bytes ..._mincore-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3520 bytes ..._mincore-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2718 bytes ...api_mincore-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5140 bytes ...api_mincore-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6076 bytes ...api_mincore-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2696 bytes ...mincore-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2728 bytes ...mincore-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3604 bytes ...ore-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7716 bytes ...ore-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6292 bytes ...ore-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2772 bytes ...ore-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6132 bytes ...pi_mincore-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5014 bytes ...pi_mincore-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2678 bytes ...napi_mincore-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63546 bytes ...napi_mincore-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5256 bytes ...napi_mincore-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4414 bytes ...napi_mincore-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10068 bytes ...napi_mincore-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10894 bytes ...napi_mincore-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2654 bytes ...napi_mincore-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3456 bytes ...napi_mincore-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2710 bytes ..._mincore-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5500 bytes ...pi_mincore-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6006 bytes ...napi_mincore-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13830 bytes ...napi_mincore-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7386 bytes ...ncore-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 11308 bytes ...ncore-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2776 bytes ...winapi_mincore-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7746 bytes ...winapi_mincore-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4294 bytes ...inapi_mincore-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2660 bytes ...ore-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 26160 bytes ...ore-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4340 bytes ...ore-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2752 bytes ...ore-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3640 bytes ...core-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 50966 bytes ...core-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2746 bytes ...core-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3608 bytes ...core-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 11980 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 14938 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15422 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11358 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5286 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2754 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3526 bytes ...mincore-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10280 bytes ...mincore-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3580 bytes ...mincore-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2704 bytes ...mincore-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7052 bytes ...napi_mincore-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20152 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19826 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4566 bytes ...e-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10418 bytes ...re-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 42834 bytes ...re-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 13938 bytes ...re-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9554 bytes ...re-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12298 bytes ...e-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4516 bytes ...i_mincore-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3594 bytes ...api_mincore-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19748 bytes ...pi_mincore-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8514 bytes ...pi_mincore-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3602 bytes ..._mincore-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6206 bytes ..._mincore-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4482 bytes ..._mincore-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4694 bytes ..._mincore-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 37102 bytes ..._mincore-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5196 bytes ..._mincore-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3600 bytes ...incore-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 4378 bytes ...incore-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4374 bytes ..._mincore-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3588 bytes ..._mincore-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2706 bytes ...pi_mincore-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8466 bytes ...pi_mincore-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9878 bytes ...pi_mincore-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2710 bytes ...api_mincore-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35956 bytes ...api_mincore-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16246 bytes ...api_mincore-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4384 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20254 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9452 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6244 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2752 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6064 bytes ...re-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3662 bytes ...re-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2774 bytes ...incore-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33978 bytes ..._mincore-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13410 bytes ...napi_mincore-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5874 bytes ...napi_mincore-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3528 bytes ...i_mincore-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5214 bytes ...i_mincore-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3570 bytes ...ncore-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11324 bytes ...ncore-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8858 bytes ...api_mincore-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9580 bytes ...core-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 21686 bytes ...core-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2754 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4448 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7040 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2740 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-0.a | Bin 0 -> 8830 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-1.a | Bin 0 -> 2682 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-2.a | Bin 0 -> 2734 bytes ...pi_mincore-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6886 bytes ...mincore-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35652 bytes ...mincore-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14264 bytes ...ncore-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7800 bytes ...ncore-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3578 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8650 bytes ...core-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4306 bytes ...core-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2782 bytes ...re-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11062 bytes ...core-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10184 bytes ...api_mincore-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6304 bytes ..._mincore-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8748 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2830 bytes ..._mincore-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 82690 bytes ..._mincore-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7826 bytes ..._mincore-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2682 bytes ..._mincore-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2762 bytes ...e-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26312 bytes ...ore-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7068 bytes ...ore-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2776 bytes ..._mincore-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5596 bytes ...i_mincore-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4460 bytes ...i_mincore-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4476 bytes ...i_mincore-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3566 bytes ...ore-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7672 bytes ...ore-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8808 bytes ...mincore-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15436 bytes .../lib/libwinapi_mincore-authz.a | Bin 0 -> 32574 bytes .../lib/libwinapi_mincore-bcrypt.a | Bin 0 -> 46606 bytes .../lib/libwinapi_mincore-cabinet.a | Bin 0 -> 22296 bytes .../lib/libwinapi_mincore-crypt32.a | Bin 0 -> 203312 bytes .../lib/libwinapi_mincore-cryptbase.a | Bin 0 -> 10618 bytes .../lib/libwinapi_mincore-cryptnet.a | Bin 0 -> 5968 bytes .../lib/libwinapi_mincore-dfscli.a | Bin 0 -> 23046 bytes .../lib/libwinapi_mincore-dnsapi.a | Bin 0 -> 224436 bytes .../lib/libwinapi_mincore-dsparse.a | Bin 0 -> 17672 bytes .../lib/libwinapi_mincore-dsrole.a | Bin 0 -> 3410 bytes .../lib/libwinapi_mincore-iphlpapi.a | Bin 0 -> 234364 bytes .../lib/libwinapi_mincore-logoncli.a | Bin 0 -> 29748 bytes .../lib/libwinapi_mincore-mpr.a | Bin 0 -> 36858 bytes .../lib/libwinapi_mincore-mswsock.a | Bin 0 -> 23796 bytes .../lib/libwinapi_mincore-ncrypt.a | Bin 0 -> 65180 bytes .../lib/libwinapi_mincore-netutils.a | Bin 0 -> 5844 bytes .../lib/libwinapi_mincore-oleaut32.a | Bin 0 -> 318008 bytes .../lib/libwinapi_mincore-rpcrt4.a | Bin 0 -> 432018 bytes .../lib/libwinapi_mincore-samcli.a | Bin 0 -> 30998 bytes .../lib/libwinapi_mincore-schedcli.a | Bin 0 -> 5000 bytes .../lib/libwinapi_mincore-srvcli.a | Bin 0 -> 40282 bytes .../lib/libwinapi_mincore-sspicli.a | Bin 0 -> 78252 bytes .../lib/libwinapi_mincore-userenv.a | Bin 0 -> 61414 bytes .../lib/libwinapi_mincore-websocket.a | Bin 0 -> 12666 bytes .../lib/libwinapi_mincore-winhttp.a | Bin 0 -> 53936 bytes .../lib/libwinapi_mincore-wkscli.a | Bin 0 -> 20428 bytes .../lib/libwinapi_mincore-wldap32.a | Bin 0 -> 195518 bytes .../lib/libwinapi_mincore-ws2_32.a | Bin 0 -> 145518 bytes .../lib/libwinapi_mincore.a | 167 + ...vel-api-ms-win-downlevel-advapi32-l1-1-0.a | Bin 0 -> 125780 bytes ...vel-api-ms-win-downlevel-advapi32-l2-1-0.a | Bin 0 -> 13942 bytes ...vel-api-ms-win-downlevel-normaliz-l1-1-0.a | Bin 0 -> 3594 bytes ...nlevel-api-ms-win-downlevel-ole32-l1-1-0.a | Bin 0 -> 42620 bytes ...evel-api-ms-win-downlevel-shell32-l1-1-0.a | Bin 0 -> 4702 bytes ...evel-api-ms-win-downlevel-shlwapi-l1-1-0.a | Bin 0 -> 129802 bytes ...evel-api-ms-win-downlevel-shlwapi-l2-1-0.a | Bin 0 -> 48534 bytes ...level-api-ms-win-downlevel-user32-l1-1-0.a | Bin 0 -> 19920 bytes ...evel-api-ms-win-downlevel-version-l1-1-0.a | Bin 0 -> 7002 bytes .../lib/libwinapi_mincore_downlevel.a | 11 + .../lib/libwinapi_mmdevapi.a | Bin 0 -> 26384 bytes .../lib/libwinapi_mpr.a | Bin 0 -> 36474 bytes .../lib/libwinapi_mprapi.a | Bin 0 -> 135866 bytes .../lib/libwinapi_mprsnap.a | Bin 0 -> 38338 bytes .../lib/libwinapi_mqrt.a | Bin 0 -> 38392 bytes .../lib/libwinapi_mrmsupport.a | Bin 0 -> 4962 bytes .../lib/libwinapi_msacm32.a | Bin 0 -> 36536 bytes .../lib/libwinapi_msajapi.a | Bin 0 -> 498052 bytes .../lib/libwinapi_mscms.a | Bin 0 -> 94602 bytes .../lib/libwinapi_msctfmonitor.a | Bin 0 -> 4164 bytes .../lib/libwinapi_msdelta.a | Bin 0 -> 13462 bytes .../lib/libwinapi_msdmo.a | Bin 0 -> 13330 bytes .../lib/libwinapi_msdrm.a | Bin 0 -> 70802 bytes .../lib/libwinapi_msi.a | Bin 0 -> 237408 bytes .../lib/libwinapi_msimg32.a | Bin 0 -> 4018 bytes .../lib/libwinapi_mspatcha.a | Bin 0 -> 15060 bytes .../lib/libwinapi_mspatchc.a | Bin 0 -> 13384 bytes .../lib/libwinapi_msports.a | Bin 0 -> 10614 bytes .../lib/libwinapi_msrating.a | Bin 0 -> 27912 bytes .../lib/libwinapi_mstask.a | Bin 0 -> 19574 bytes .../lib/libwinapi_msv1_0.a | Bin 0 -> 14662 bytes .../lib/libwinapi_msvfw32.a | Bin 0 -> 38466 bytes .../lib/libwinapi_mswsock.a | Bin 0 -> 23532 bytes .../lib/libwinapi_mtx.a | Bin 0 -> 3966 bytes .../lib/libwinapi_mtxdm.a | Bin 0 -> 2478 bytes .../lib/libwinapi_ncrypt.a | Bin 0 -> 107300 bytes .../lib/libwinapi_nddeapi.a | Bin 0 -> 24260 bytes .../lib/libwinapi_ndfapi.a | Bin 0 -> 16402 bytes .../lib/libwinapi_netapi32.a | Bin 0 -> 172880 bytes .../lib/libwinapi_netsh.a | Bin 0 -> 19686 bytes .../lib/libwinapi_newdev.a | Bin 0 -> 20704 bytes .../lib/libwinapi_ninput.a | Bin 0 -> 21960 bytes .../lib/libwinapi_normaliz.a | Bin 0 -> 5660 bytes .../lib/libwinapi_ntdll.a | Bin 0 -> 1658338 bytes .../lib/libwinapi_ntdsa.a | Bin 0 -> 118658 bytes .../lib/libwinapi_ntdsapi.a | Bin 0 -> 97408 bytes .../lib/libwinapi_ntdsatq.a | Bin 0 -> 37806 bytes .../lib/libwinapi_ntdsetup.a | Bin 0 -> 21280 bytes .../lib/libwinapi_ntfrsapi.a | Bin 0 -> 29692 bytes .../lib/libwinapi_ntlanman.a | Bin 0 -> 16208 bytes .../lib/libwinapi_ntmarta.a | Bin 0 -> 36872 bytes .../lib/libwinapi_ntquery.a | Bin 0 -> 12258 bytes .../lib/libwinapi_ntvdm.a | Bin 0 -> 119370 bytes .../lib/libwinapi_odbc32.a | Bin 0 -> 139488 bytes .../lib/libwinapi_odbcbcp.a | Bin 0 -> 23320 bytes .../lib/libwinapi_oemlicense.a | Bin 0 -> 3322 bytes .../lib/libwinapi_ole32.a | Bin 0 -> 330598 bytes .../lib/libwinapi_oleacc.a | Bin 0 -> 18098 bytes .../lib/libwinapi_oleaut32.a | Bin 0 -> 314768 bytes .../lib/libwinapi_olecli32.a | Bin 0 -> 140360 bytes .../lib/libwinapi_oledlg.a | Bin 0 -> 19972 bytes .../lib/libwinapi_olepro32.a | Bin 0 -> 7424 bytes .../lib/libwinapi_olesvr32.a | Bin 0 -> 19820 bytes .../lib/libwinapi_ondemandconnroutehelper.a | Bin 0 -> 8696 bytes ...api_onecore-api-ms-win-core-atoms-l1-1-0.a | Bin 0 -> 15580 bytes ..._onecore-api-ms-win-core-calendar-l1-1-0.a | Bin 0 -> 7954 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68470 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3554 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3470 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66136 bytes ...napi_onecore-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16372 bytes ...napi_onecore-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2654 bytes ...core-api-ms-win-core-console-ansi-l2-1-0.a | Bin 0 -> 2726 bytes ...i_onecore-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13390 bytes ...i_onecore-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34426 bytes ...i_onecore-api-ms-win-core-console-l3-1-0.a | Bin 0 -> 2716 bytes ..._onecore-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5148 bytes ..._onecore-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3520 bytes ..._onecore-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2718 bytes ...api_onecore-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5140 bytes ...api_onecore-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6076 bytes ...api_onecore-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2696 bytes ...onecore-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2728 bytes ...onecore-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3604 bytes ...i_onecore-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5186 bytes ...i_onecore-api-ms-win-core-enclave-l1-1-1.a | Bin 0 -> 5952 bytes ...ore-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7716 bytes ...ore-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6292 bytes ...ore-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2772 bytes ...ore-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6132 bytes ...re-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6358 bytes ...re-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2750 bytes ...pi_onecore-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5014 bytes ...pi_onecore-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2678 bytes ...pi_onecore-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 5946 bytes ...pi_onecore-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3526 bytes ...onecore-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 9564 bytes ...onecore-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 6032 bytes ...napi_onecore-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63546 bytes ...napi_onecore-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5256 bytes ...napi_onecore-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4414 bytes ...napi_onecore-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10068 bytes ...napi_onecore-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10894 bytes ...napi_onecore-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2654 bytes ...napi_onecore-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3456 bytes ...napi_onecore-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2710 bytes ..._onecore-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5500 bytes ...pi_onecore-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6006 bytes ...napi_onecore-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13830 bytes ...napi_onecore-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7386 bytes ...ore-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 8336 bytes ...ecore-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 11308 bytes ...ecore-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2776 bytes ...winapi_onecore-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7746 bytes ...winapi_onecore-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4294 bytes ...inapi_onecore-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2660 bytes ...inapi_onecore-api-ms-win-core-job-l2-1-0.a | Bin 0 -> 6890 bytes ...inapi_onecore-api-ms-win-core-job-l2-1-1.a | Bin 0 -> 4532 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 11438 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 34764 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-1.a | Bin 0 -> 13926 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-2.a | Bin 0 -> 8550 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-3.a | Bin 0 -> 14122 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-4.a | Bin 0 -> 2748 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-5.a | Bin 0 -> 3614 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-6.a | Bin 0 -> 2788 bytes ...core-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2682 bytes ...ore-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 26160 bytes ...ore-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4340 bytes ...ore-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2752 bytes ...ore-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3640 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 17052 bytes ...core-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 50966 bytes ...core-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2746 bytes ...core-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3608 bytes ...core-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 11980 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 8832 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 14938 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15422 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11358 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5286 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2754 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3526 bytes ...re-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4514 bytes ...re-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2738 bytes ...onecore-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10280 bytes ...onecore-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3580 bytes ...onecore-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2704 bytes ...re-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4506 bytes ...onecore-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7052 bytes ...ore-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6080 bytes ...napi_onecore-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20152 bytes ...core-api-ms-win-core-perfcounters-l1-1-0.a | Bin 0 -> 14044 bytes ...re-api-ms-win-core-privateprofile-l1-1-0.a | Bin 0 -> 13910 bytes ...re-api-ms-win-core-privateprofile-l1-1-1.a | Bin 0 -> 3678 bytes ...-win-core-processenvironment-ansi-l1-1-0.a | Bin 0 -> 2836 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19826 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4566 bytes ...e-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10418 bytes ...re-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 42834 bytes ...re-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 13938 bytes ...re-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9554 bytes ...re-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12298 bytes ...e-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4516 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 6310 bytes ...win-core-processtopology-obsolete-l1-1-1.a | Bin 0 -> 2870 bytes ...i_onecore-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3594 bytes ...necore-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 8818 bytes ...api_onecore-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19748 bytes ...pi_onecore-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8514 bytes ...pi_onecore-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3602 bytes ..._onecore-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6206 bytes ..._onecore-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4482 bytes ..._onecore-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4694 bytes ..._onecore-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 37102 bytes ..._onecore-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5196 bytes ..._onecore-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3600 bytes ..._onecore-api-ms-win-core-registry-l2-1-0.a | Bin 0 -> 24150 bytes ...necore-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 4378 bytes ...necore-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4374 bytes ...ore-api-ms-win-core-shutdown-ansi-l1-1-0.a | Bin 0 -> 4500 bytes ..._onecore-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3588 bytes ..._onecore-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2706 bytes ...e-api-ms-win-core-sidebyside-ansi-l1-1-0.a | Bin 0 -> 3606 bytes ...necore-api-ms-win-core-sidebyside-l1-1-0.a | Bin 0 -> 10958 bytes ...pi_onecore-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8466 bytes ...pi_onecore-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9878 bytes ...pi_onecore-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2710 bytes ...e-api-ms-win-core-string-obsolete-l1-1-0.a | Bin 0 -> 9842 bytes ...e-api-ms-win-core-string-obsolete-l1-1-1.a | Bin 0 -> 3498 bytes ...necore-api-ms-win-core-stringansi-l1-1-0.a | Bin 0 -> 11550 bytes ...necore-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 7726 bytes ...api_onecore-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35956 bytes ...api_onecore-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16246 bytes ...api_onecore-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4384 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20254 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9452 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6244 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2752 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6064 bytes ...re-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3662 bytes ...re-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2774 bytes ...necore-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33978 bytes ...api-ms-win-core-threadpool-legacy-l1-1-0.a | Bin 0 -> 7860 bytes ..._onecore-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13410 bytes ..._onecore-api-ms-win-core-toolhelp-l1-1-0.a | Bin 0 -> 7598 bytes ..._onecore-api-ms-win-core-toolhelp-l1-1-1.a | Bin 0 -> 5104 bytes ...inapi_onecore-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 32470 bytes ...napi_onecore-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5874 bytes ...napi_onecore-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3528 bytes ...i_onecore-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5214 bytes ...i_onecore-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3570 bytes ...ecore-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 5254 bytes ...ecore-api-ms-win-core-versionansi-l1-1-1.a | Bin 0 -> 3602 bytes ...ecore-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2704 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 12460 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7356 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3708 bytes ...ecore-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11324 bytes ...ecore-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8858 bytes ...api_onecore-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9580 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3754 bytes ...re-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2762 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4754 bytes ...core-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 21686 bytes ...core-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2754 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4448 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7040 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2740 bytes ...pi_onecore-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6886 bytes ...onecore-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35652 bytes ...onecore-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14264 bytes ...ecore-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7800 bytes ...ecore-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3578 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8650 bytes ...core-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4306 bytes ...core-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2782 bytes ...re-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11062 bytes ...necore-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 13218 bytes ...core-api-ms-win-eventing-obsolete-l1-1-0.a | Bin 0 -> 4414 bytes ...core-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10184 bytes ...i_onecore-api-ms-win-eventing-tdh-l1-1-0.a | Bin 0 -> 12222 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2852 bytes ...winapi_onecore-api-ms-win-mm-time-l1-1-0.a | Bin 0 -> 5874 bytes ...core-api-ms-win-oobe-notification-l1-1-0.a | Bin 0 -> 4514 bytes ...pi_onecore-api-ms-win-perf-legacy-l1-1-0.a | Bin 0 -> 9570 bytes ...api_onecore-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6304 bytes ...api-ms-win-power-limitsmanagement-l1-1-0.a | Bin 0 -> 10920 bytes ..._onecore-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8748 bytes ...core-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4402 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2830 bytes ...ore-api-ms-win-security-base-ansi-l1-1-0.a | Bin 0 -> 3572 bytes ..._onecore-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 82690 bytes ..._onecore-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7826 bytes ..._onecore-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2682 bytes ..._onecore-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2762 bytes ...e-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26312 bytes ...ore-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 34584 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2852 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6234 bytes ...ore-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7068 bytes ...ore-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2776 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5376 bytes ...core-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 6972 bytes ...ore-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3628 bytes ..._onecore-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5596 bytes ...i-ms-win-security-systemfunctions-l1-1-0.a | Bin 0 -> 4464 bytes ...core-api-ms-win-service-core-ansi-l1-1-0.a | Bin 0 -> 4458 bytes ...core-api-ms-win-service-core-ansi-l1-1-1.a | Bin 0 -> 2762 bytes ...i_onecore-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4460 bytes ...i_onecore-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4476 bytes ...i_onecore-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3566 bytes ...ore-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7672 bytes ...ore-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8808 bytes ...onecore-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15436 bytes ...pi_onecore-api-ms-win-shcore-path-l1-1-0.a | Bin 0 -> 5154 bytes ...necore-api-ms-win-shcore-registry-l1-1-0.a | Bin 0 -> 24670 bytes ...necore-api-ms-win-shcore-registry-l1-1-1.a | Bin 0 -> 2762 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4548 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7028 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2752 bytes ...re-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4666 bytes ...onecore-api-ms-win-shcore-sysinfo-l1-1-0.a | Bin 0 -> 4520 bytes ...ore-api-ms-win-shcore-unicodeansi-l1-1-0.a | Bin 0 -> 5220 bytes ...core-api-ms-win-shell-shdirectory-l1-1-0.a | Bin 0 -> 4430 bytes .../lib/libwinapi_onecore-authz.a | Bin 0 -> 32574 bytes .../lib/libwinapi_onecore-bcrypt.a | Bin 0 -> 46606 bytes .../lib/libwinapi_onecore-cabinet.a | Bin 0 -> 22296 bytes .../lib/libwinapi_onecore-crypt32.a | Bin 0 -> 203312 bytes .../lib/libwinapi_onecore-cryptbase.a | Bin 0 -> 8198 bytes .../lib/libwinapi_onecore-cryptnet.a | Bin 0 -> 5968 bytes .../lib/libwinapi_onecore-dfscli.a | Bin 0 -> 23046 bytes .../lib/libwinapi_onecore-dnsapi.a | Bin 0 -> 224436 bytes .../lib/libwinapi_onecore-dsparse.a | Bin 0 -> 17672 bytes .../lib/libwinapi_onecore-dsrole.a | Bin 0 -> 3410 bytes .../lib/libwinapi_onecore-fltlib.a | Bin 0 -> 25396 bytes .../lib/libwinapi_onecore-iphlpapi.a | Bin 0 -> 234364 bytes .../lib/libwinapi_onecore-logoncli.a | Bin 0 -> 29748 bytes .../lib/libwinapi_onecore-mpr.a | Bin 0 -> 36858 bytes .../lib/libwinapi_onecore-mswsock.a | Bin 0 -> 23796 bytes .../lib/libwinapi_onecore-ncrypt.a | Bin 0 -> 65180 bytes .../lib/libwinapi_onecore-netutils.a | Bin 0 -> 5844 bytes .../lib/libwinapi_onecore-ntdll.a | Bin 0 -> 18562 bytes .../lib/libwinapi_onecore-oleaut32.a | Bin 0 -> 318008 bytes .../lib/libwinapi_onecore-powrprof.a | Bin 0 -> 59416 bytes .../lib/libwinapi_onecore-profapi.a | Bin 0 -> 15208 bytes .../lib/libwinapi_onecore-rpcrt4.a | Bin 0 -> 432018 bytes .../lib/libwinapi_onecore-samcli.a | Bin 0 -> 30998 bytes .../lib/libwinapi_onecore-schedcli.a | Bin 0 -> 5000 bytes .../lib/libwinapi_onecore-srvcli.a | Bin 0 -> 40282 bytes .../lib/libwinapi_onecore-sspicli.a | Bin 0 -> 78252 bytes .../lib/libwinapi_onecore-tokenbinding.a | Bin 0 -> 8636 bytes .../lib/libwinapi_onecore-userenv.a | Bin 0 -> 61414 bytes .../lib/libwinapi_onecore-websocket.a | Bin 0 -> 12666 bytes .../lib/libwinapi_onecore-winhttp.a | Bin 0 -> 53936 bytes .../lib/libwinapi_onecore-wkscli.a | Bin 0 -> 20428 bytes .../lib/libwinapi_onecore-wldap32.a | Bin 0 -> 195518 bytes .../lib/libwinapi_onecore-ws2_32.a | Bin 0 -> 145518 bytes .../lib/libwinapi_onecore-xmllite.a | Bin 0 -> 6984 bytes .../lib/libwinapi_onecore.a | 257 + .../libwinapi_onecore_downlevel-advapi32.a | Bin 0 -> 515126 bytes .../lib/libwinapi_onecore_downlevel-apphelp.a | Bin 0 -> 8238 bytes .../libwinapi_onecore_downlevel-comctl32.a | Bin 0 -> 61116 bytes .../libwinapi_onecore_downlevel-comdlg32.a | Bin 0 -> 16872 bytes .../lib/libwinapi_onecore_downlevel-d3d10.a | Bin 0 -> 5148 bytes .../lib/libwinapi_onecore_downlevel-d3d9.a | Bin 0 -> 5812 bytes .../libwinapi_onecore_downlevel-d3dx10_47.a | Bin 0 -> 6198 bytes .../lib/libwinapi_onecore_downlevel-difxapi.a | Bin 0 -> 3466 bytes .../lib/libwinapi_onecore_downlevel-gdi32.a | Bin 0 -> 177204 bytes .../lib/libwinapi_onecore_downlevel-input.a | Bin 0 -> 11102 bytes .../libwinapi_onecore_downlevel-kernel32.a | Bin 0 -> 977870 bytes .../lib/libwinapi_onecore_downlevel-msi.a | Bin 0 -> 34674 bytes .../lib/libwinapi_onecore_downlevel-newdev.a | Bin 0 -> 10400 bytes .../lib/libwinapi_onecore_downlevel-ole32.a | Bin 0 -> 283810 bytes .../lib/libwinapi_onecore_downlevel-oleacc.a | Bin 0 -> 11912 bytes .../libwinapi_onecore_downlevel-oleaut32.a | Bin 0 -> 322058 bytes .../lib/libwinapi_onecore_downlevel-oledlg.a | Bin 0 -> 18008 bytes .../lib/libwinapi_onecore_downlevel-pdh.a | Bin 0 -> 13974 bytes .../lib/libwinapi_onecore_downlevel-psapi.a | Bin 0 -> 24030 bytes .../libwinapi_onecore_downlevel-resutils.a | Bin 0 -> 10422 bytes .../libwinapi_onecore_downlevel-rstrtmgr.a | Bin 0 -> 6558 bytes .../lib/libwinapi_onecore_downlevel-secur32.a | Bin 0 -> 76634 bytes .../libwinapi_onecore_downlevel-setupapi.a | Bin 0 -> 157680 bytes .../lib/libwinapi_onecore_downlevel-shell32.a | Bin 0 -> 136406 bytes .../lib/libwinapi_onecore_downlevel-shlwapi.a | Bin 0 -> 315638 bytes .../lib/libwinapi_onecore_downlevel-tdh.a | Bin 0 -> 11894 bytes .../lib/libwinapi_onecore_downlevel-twinapi.a | Bin 0 -> 2570 bytes .../lib/libwinapi_onecore_downlevel-user32.a | Bin 0 -> 504870 bytes .../lib/libwinapi_onecore_downlevel-uxtheme.a | Bin 0 -> 39262 bytes .../lib/libwinapi_onecore_downlevel-version.a | Bin 0 -> 10010 bytes .../lib/libwinapi_onecore_downlevel-winmm.a | Bin 0 -> 5754 bytes .../libwinapi_onecore_downlevel-winspool.a | Bin 0 -> 35048 bytes .../libwinapi_onecore_downlevel-wtsapi32.a | Bin 0 -> 15266 bytes .../libwinapi_onecore_downlevel-xinput1_4.a | Bin 0 -> 8344 bytes .../lib/libwinapi_onecore_downlevel.a | 36 + ...reuap-api-ms-win-appmodel-runtime-l1-1-0.a | Bin 0 -> 19170 bytes ...reuap-api-ms-win-appmodel-runtime-l1-1-1.a | Bin 0 -> 16054 bytes ...reuap-api-ms-win-appmodel-runtime-l1-1-2.a | Bin 0 -> 9158 bytes ..._onecoreuap-api-ms-win-core-atoms-l1-1-0.a | Bin 0 -> 15630 bytes ...ecoreuap-api-ms-win-core-calendar-l1-1-0.a | Bin 0 -> 7996 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68646 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3574 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3490 bytes ...pi_onecoreuap-api-ms-win-core-com-l2-1-1.a | Bin 0 -> 19278 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66298 bytes ...i_onecoreuap-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16458 bytes ...i_onecoreuap-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2672 bytes ...euap-api-ms-win-core-console-ansi-l2-1-0.a | Bin 0 -> 2744 bytes ...necoreuap-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13434 bytes ...necoreuap-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34518 bytes ...necoreuap-api-ms-win-core-console-l3-1-0.a | Bin 0 -> 2734 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5178 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3542 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2736 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5164 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6102 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2714 bytes ...coreuap-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2746 bytes ...coreuap-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3624 bytes ...necoreuap-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5210 bytes ...necoreuap-api-ms-win-core-enclave-l1-1-1.a | Bin 0 -> 5978 bytes ...uap-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7746 bytes ...uap-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6318 bytes ...uap-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2790 bytes ...uap-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6158 bytes ...ap-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6392 bytes ...ap-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2768 bytes ...onecoreuap-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5044 bytes ...onecoreuap-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2696 bytes ...onecoreuap-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 5980 bytes ...onecoreuap-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3548 bytes ...coreuap-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 9598 bytes ...coreuap-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 6058 bytes ...i_onecoreuap-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63860 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5286 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4440 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10122 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10952 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2672 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3478 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2728 bytes ...ecoreuap-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5530 bytes ...onecoreuap-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6040 bytes ...i_onecoreuap-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13904 bytes ...i_onecoreuap-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7428 bytes ...uap-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 8368 bytes ...reuap-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 11346 bytes ...reuap-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2794 bytes ...api_onecoreuap-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7788 bytes ...api_onecoreuap-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4320 bytes ...pi_onecoreuap-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2678 bytes ...pi_onecoreuap-api-ms-win-core-job-l2-1-0.a | Bin 0 -> 6918 bytes ...pi_onecoreuap-api-ms-win-core-job-l2-1-1.a | Bin 0 -> 4554 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 11496 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 34858 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-1.a | Bin 0 -> 13970 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-2.a | Bin 0 -> 8582 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-3.a | Bin 0 -> 14166 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-4.a | Bin 0 -> 2766 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-5.a | Bin 0 -> 3634 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-6.a | Bin 0 -> 2806 bytes ...euap-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2700 bytes ...uap-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 26234 bytes ...uap-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4362 bytes ...uap-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2770 bytes ...uap-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3660 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 17104 bytes ...euap-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 51216 bytes ...euap-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2764 bytes ...euap-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3630 bytes ...euap-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 12042 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 8864 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 15016 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15500 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11416 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5316 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2772 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3548 bytes ...ap-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4540 bytes ...ap-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2756 bytes ...coreuap-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10316 bytes ...coreuap-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3600 bytes ...coreuap-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2722 bytes ...ap-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4532 bytes ...coreuap-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7080 bytes ...uap-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6106 bytes ...i_onecoreuap-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20254 bytes ...euap-api-ms-win-core-perfcounters-l1-1-0.a | Bin 0 -> 14114 bytes ...ap-api-ms-win-core-privateprofile-l1-1-0.a | Bin 0 -> 13980 bytes ...ap-api-ms-win-core-privateprofile-l1-1-1.a | Bin 0 -> 3700 bytes ...-win-core-processenvironment-ansi-l1-1-0.a | Bin 0 -> 2854 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19924 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4592 bytes ...p-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10454 bytes ...ap-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 43044 bytes ...ap-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 14008 bytes ...ap-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9604 bytes ...ap-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12360 bytes ...p-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4538 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 6344 bytes ...win-core-processtopology-obsolete-l1-1-1.a | Bin 0 -> 2888 bytes ...necoreuap-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3614 bytes ...oreuap-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 8864 bytes ..._onecoreuap-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19806 bytes ...uap-api-ms-win-core-psm-appnotify-l1-1-0.a | Bin 0 -> 3780 bytes ...onecoreuap-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8560 bytes ...onecoreuap-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3624 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6240 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4508 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4720 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 37288 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5226 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3622 bytes ...ecoreuap-api-ms-win-core-registry-l2-1-0.a | Bin 0 -> 24272 bytes ...oreuap-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 4404 bytes ...oreuap-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4400 bytes ...uap-api-ms-win-core-shutdown-ansi-l1-1-0.a | Bin 0 -> 4522 bytes ...ecoreuap-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3610 bytes ...ecoreuap-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2724 bytes ...p-api-ms-win-core-sidebyside-ansi-l1-1-0.a | Bin 0 -> 3626 bytes ...oreuap-api-ms-win-core-sidebyside-l1-1-0.a | Bin 0 -> 11016 bytes ..._onecoreuap-api-ms-win-core-slapi-l1-1-0.a | Bin 0 -> 3632 bytes ...onecoreuap-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8512 bytes ...onecoreuap-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9932 bytes ...onecoreuap-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2728 bytes ...p-api-ms-win-core-string-obsolete-l1-1-0.a | Bin 0 -> 9878 bytes ...p-api-ms-win-core-string-obsolete-l1-1-1.a | Bin 0 -> 3518 bytes ...oreuap-api-ms-win-core-stringansi-l1-1-0.a | Bin 0 -> 11612 bytes ...oreuap-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 7768 bytes ..._onecoreuap-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 36054 bytes ..._onecoreuap-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16298 bytes ..._onecoreuap-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4406 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20314 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9486 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6270 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2770 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6090 bytes ...ap-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3684 bytes ...ap-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2792 bytes ...oreuap-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 34140 bytes ...api-ms-win-core-threadpool-legacy-l1-1-0.a | Bin 0 -> 7890 bytes ...ecoreuap-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13476 bytes ...ecoreuap-api-ms-win-core-toolhelp-l1-1-0.a | Bin 0 -> 7640 bytes ...ecoreuap-api-ms-win-core-toolhelp-l1-1-1.a | Bin 0 -> 5134 bytes ...pi_onecoreuap-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 32562 bytes ...i_onecoreuap-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5908 bytes ...i_onecoreuap-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3550 bytes ...necoreuap-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5238 bytes ...necoreuap-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3590 bytes ...reuap-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 5278 bytes ...reuap-api-ms-win-core-versionansi-l1-1-1.a | Bin 0 -> 3622 bytes ...reuap-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2722 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 12500 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7384 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3728 bytes ...reuap-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11362 bytes ...reuap-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8890 bytes ..._onecoreuap-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9614 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3776 bytes ...ap-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2780 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4780 bytes ...euap-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 21792 bytes ...euap-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2772 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4470 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7068 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2758 bytes ...onecoreuap-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6924 bytes ...coreuap-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35746 bytes ...coreuap-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14308 bytes ...reuap-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7830 bytes ...reuap-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3598 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-0.a | Bin 0 -> 87142 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-1.a | Bin 0 -> 42052 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-2.a | Bin 0 -> 20096 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-3.a | Bin 0 -> 14390 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-4.a | Bin 0 -> 19570 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8682 bytes ...euap-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4332 bytes ...euap-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2800 bytes ...ap-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11120 bytes ...oreuap-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 13288 bytes ...euap-api-ms-win-eventing-obsolete-l1-1-0.a | Bin 0 -> 4440 bytes ...euap-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10238 bytes ...necoreuap-api-ms-win-eventing-tdh-l1-1-0.a | Bin 0 -> 12262 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2870 bytes ...i-ms-win-gaming-expandedresources-l1-1-0.a | Bin 0 -> 4622 bytes ...uap-api-ms-win-gaming-gamemonitor-l1-1-0.a | Bin 0 -> 4538 bytes ...uap-api-ms-win-gaming-gamemonitor-l1-1-1.a | Bin 0 -> 2834 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-0.a | Bin 0 -> 7844 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-1.a | Bin 0 -> 3648 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-2.a | Bin 0 -> 8152 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-3.a | Bin 0 -> 3684 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-4.a | Bin 0 -> 8744 bytes ...api_onecoreuap-api-ms-win-mm-misc-l1-1-0.a | Bin 0 -> 25272 bytes ...api_onecoreuap-api-ms-win-mm-misc-l1-1-1.a | Bin 0 -> 2660 bytes ...napi_onecoreuap-api-ms-win-mm-mme-l1-1-0.a | Bin 0 -> 85380 bytes ...necoreuap-api-ms-win-mm-playsound-l1-1-0.a | Bin 0 -> 5102 bytes ...api_onecoreuap-api-ms-win-mm-time-l1-1-0.a | Bin 0 -> 5908 bytes ...reuap-api-ms-win-ntuser-sysparams-l1-1-0.a | Bin 0 -> 12194 bytes ...euap-api-ms-win-oobe-notification-l1-1-0.a | Bin 0 -> 4540 bytes ...onecoreuap-api-ms-win-perf-legacy-l1-1-0.a | Bin 0 -> 9620 bytes ..._onecoreuap-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6330 bytes ...api-ms-win-power-limitsmanagement-l1-1-0.a | Bin 0 -> 10956 bytes ...ecoreuap-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8794 bytes ...euap-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4428 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2848 bytes ...uap-api-ms-win-security-base-ansi-l1-1-0.a | Bin 0 -> 3592 bytes ...ecoreuap-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 83084 bytes ...ecoreuap-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7868 bytes ...ecoreuap-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2700 bytes ...ecoreuap-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2780 bytes ...p-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26386 bytes ...uap-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 34678 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2870 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6268 bytes ...uap-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7096 bytes ...uap-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2794 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5400 bytes ...euap-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 7010 bytes ...uap-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3648 bytes ...ecoreuap-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5626 bytes ...i-ms-win-security-systemfunctions-l1-1-0.a | Bin 0 -> 4486 bytes ...euap-api-ms-win-service-core-ansi-l1-1-0.a | Bin 0 -> 4484 bytes ...euap-api-ms-win-service-core-ansi-l1-1-1.a | Bin 0 -> 2780 bytes ...necoreuap-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4482 bytes ...necoreuap-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4498 bytes ...necoreuap-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3586 bytes ...uap-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7702 bytes ...uap-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8840 bytes ...coreuap-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15484 bytes ...onecoreuap-api-ms-win-shcore-path-l1-1-0.a | Bin 0 -> 5184 bytes ...oreuap-api-ms-win-shcore-registry-l1-1-0.a | Bin 0 -> 24796 bytes ...oreuap-api-ms-win-shcore-registry-l1-1-1.a | Bin 0 -> 2780 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4570 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7056 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2770 bytes ...ap-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4692 bytes ...coreuap-api-ms-win-shcore-sysinfo-l1-1-0.a | Bin 0 -> 4542 bytes ...uap-api-ms-win-shcore-unicodeansi-l1-1-0.a | Bin 0 -> 5244 bytes ...oreuap-api-ms-win-shell-namespace-l1-1-0.a | Bin 0 -> 20068 bytes ...euap-api-ms-win-shell-shdirectory-l1-1-0.a | Bin 0 -> 4456 bytes .../lib/libwinapi_onecoreuap-authz.a | Bin 0 -> 32732 bytes .../lib/libwinapi_onecoreuap-bcrypt.a | Bin 0 -> 46730 bytes .../lib/libwinapi_onecoreuap-cabinet.a | Bin 0 -> 22412 bytes .../lib/libwinapi_onecoreuap-chakra.a | Bin 0 -> 98938 bytes .../lib/libwinapi_onecoreuap-coremessaging.a | Bin 0 -> 24472 bytes .../lib/libwinapi_onecoreuap-crypt32.a | Bin 0 -> 204286 bytes .../lib/libwinapi_onecoreuap-cryptbase.a | Bin 0 -> 8244 bytes .../lib/libwinapi_onecoreuap-cryptnet.a | Bin 0 -> 5994 bytes .../lib/libwinapi_onecoreuap-d2d1.a | Bin 0 -> 12410 bytes .../lib/libwinapi_onecoreuap-d3d11.a | Bin 0 -> 9444 bytes .../lib/libwinapi_onecoreuap-d3d12.a | Bin 0 -> 10436 bytes .../lib/libwinapi_onecoreuap-d3dcompiler_47.a | Bin 0 -> 23970 bytes .../lib/libwinapi_onecoreuap-deviceaccess.a | Bin 0 -> 4326 bytes .../lib/libwinapi_onecoreuap-dfscli.a | Bin 0 -> 23114 bytes .../lib/libwinapi_onecoreuap-dhcpcsvc.a | Bin 0 -> 54904 bytes .../lib/libwinapi_onecoreuap-dhcpcsvc6.a | Bin 0 -> 19904 bytes .../lib/libwinapi_onecoreuap-dnsapi.a | Bin 0 -> 224990 bytes .../lib/libwinapi_onecoreuap-dsparse.a | Bin 0 -> 17766 bytes .../lib/libwinapi_onecoreuap-dsrole.a | Bin 0 -> 3430 bytes .../lib/libwinapi_onecoreuap-dwrite.a | Bin 0 -> 2562 bytes .../lib/libwinapi_onecoreuap-dxgi.a | Bin 0 -> 9246 bytes .../lib/libwinapi_onecoreuap-esent.a | Bin 0 -> 301808 bytes ...i_onecoreuap-ext-ms-win-core-iuri-l1-1-0.a | Bin 0 -> 4336 bytes ...ecoreuap-ext-ms-win-gaming-xinput-l1-1-0.a | Bin 0 -> 7780 bytes ...uap-ext-ms-win-networking-wlanapi-l1-1-0.a | Bin 0 -> 20688 bytes ...p-ext-ms-win-shell32-shellfolders-l1-1-0.a | Bin 0 -> 12946 bytes ...p-ext-ms-win-shell32-shellfolders-l1-1-1.a | Bin 0 -> 3606 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-0.a | Bin 0 -> 3592 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-1.a | Bin 0 -> 8828 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-2.a | Bin 0 -> 3624 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-3.a | Bin 0 -> 2700 bytes .../lib/libwinapi_onecoreuap-fltlib.a | Bin 0 -> 25470 bytes .../lib/libwinapi_onecoreuap-hid.a | Bin 0 -> 37978 bytes .../lib/libwinapi_onecoreuap-hrtfapo.a | Bin 0 -> 5030 bytes .../lib/libwinapi_onecoreuap-inkobjcore.a | Bin 0 -> 25746 bytes .../lib/libwinapi_onecoreuap-iphlpapi.a | Bin 0 -> 234938 bytes .../lib/libwinapi_onecoreuap-logoncli.a | Bin 0 -> 29832 bytes .../lib/libwinapi_onecoreuap-mf.a | Bin 0 -> 64522 bytes .../lib/libwinapi_onecoreuap-mfplat.a | Bin 0 -> 128094 bytes .../lib/libwinapi_onecoreuap-mfreadwrite.a | Bin 0 -> 6184 bytes .../lib/libwinapi_onecoreuap-mfsensorgroup.a | Bin 0 -> 4312 bytes .../lib/libwinapi_onecoreuap-mmdevapi.a | Bin 0 -> 26730 bytes .../lib/libwinapi_onecoreuap-mpr.a | Bin 0 -> 37044 bytes .../lib/libwinapi_onecoreuap-msajapi.a | Bin 0 -> 504802 bytes .../lib/libwinapi_onecoreuap-mswsock.a | Bin 0 -> 23920 bytes .../lib/libwinapi_onecoreuap-ncrypt.a | Bin 0 -> 65350 bytes .../lib/libwinapi_onecoreuap-netutils.a | Bin 0 -> 5870 bytes .../lib/libwinapi_onecoreuap-ntdll.a | Bin 0 -> 18656 bytes .../lib/libwinapi_onecoreuap-oleaut32.a | Bin 0 -> 318824 bytes .../lib/libwinapi_onecoreuap-powrprof.a | Bin 0 -> 59570 bytes .../lib/libwinapi_onecoreuap-profapi.a | Bin 0 -> 15286 bytes .../lib/libwinapi_onecoreuap-propsys.a | Bin 0 -> 187304 bytes .../lib/libwinapi_onecoreuap-rometadata.a | Bin 0 -> 2594 bytes .../lib/libwinapi_onecoreuap-rpcrt4.a | Bin 0 -> 433066 bytes .../lib/libwinapi_onecoreuap-samcli.a | Bin 0 -> 31086 bytes .../lib/libwinapi_onecoreuap-schedcli.a | Bin 0 -> 5024 bytes .../lib/libwinapi_onecoreuap-srvcli.a | Bin 0 -> 40394 bytes .../lib/libwinapi_onecoreuap-sspicli.a | Bin 0 -> 78634 bytes .../lib/libwinapi_onecoreuap-tokenbinding.a | Bin 0 -> 8668 bytes .../libwinapi_onecoreuap-uiautomationcore.a | Bin 0 -> 76102 bytes .../lib/libwinapi_onecoreuap-urlmon.a | Bin 0 -> 56266 bytes .../lib/libwinapi_onecoreuap-userenv.a | Bin 0 -> 61712 bytes .../lib/libwinapi_onecoreuap-webservices.a | Bin 0 -> 159312 bytes .../lib/libwinapi_onecoreuap-websocket.a | Bin 0 -> 12732 bytes .../libwinapi_onecoreuap-windows.data.pdf.a | Bin 0 -> 2618 bytes .../libwinapi_onecoreuap-windows.networking.a | Bin 0 -> 2682 bytes .../lib/libwinapi_onecoreuap-windowscodecs.a | Bin 0 -> 106912 bytes .../lib/libwinapi_onecoreuap-winhttp.a | Bin 0 -> 54198 bytes .../lib/libwinapi_onecoreuap-wintrust.a | Bin 0 -> 2554 bytes .../lib/libwinapi_onecoreuap-wkscli.a | Bin 0 -> 20490 bytes .../lib/libwinapi_onecoreuap-wlanapi.a | Bin 0 -> 41212 bytes .../lib/libwinapi_onecoreuap-wldap32.a | Bin 0 -> 196512 bytes .../lib/libwinapi_onecoreuap-wpprecorderum.a | Bin 0 -> 5028 bytes .../lib/libwinapi_onecoreuap-ws2_32.a | Bin 0 -> 145908 bytes .../lib/libwinapi_onecoreuap-xaudio2_9.a | Bin 0 -> 7388 bytes .../lib/libwinapi_onecoreuap-xmllite.a | Bin 0 -> 7022 bytes .../lib/libwinapi_onecoreuap.a | 324 + .../libwinapi_onecoreuap_downlevel-advapi32.a | Bin 0 -> 516378 bytes .../libwinapi_onecoreuap_downlevel-apphelp.a | Bin 0 -> 8284 bytes .../libwinapi_onecoreuap_downlevel-comctl32.a | Bin 0 -> 61278 bytes .../libwinapi_onecoreuap_downlevel-comdlg32.a | Bin 0 -> 16926 bytes .../libwinapi_onecoreuap_downlevel-d3d10.a | Bin 0 -> 5178 bytes .../lib/libwinapi_onecoreuap_downlevel-d3d9.a | Bin 0 -> 5838 bytes ...libwinapi_onecoreuap_downlevel-d3dx10_47.a | Bin 0 -> 6232 bytes .../libwinapi_onecoreuap_downlevel-difxapi.a | Bin 0 -> 3488 bytes .../libwinapi_onecoreuap_downlevel-gdi32.a | Bin 0 -> 178098 bytes .../libwinapi_onecoreuap_downlevel-input.a | Bin 0 -> 11160 bytes .../libwinapi_onecoreuap_downlevel-kernel32.a | Bin 0 -> 980250 bytes .../lib/libwinapi_onecoreuap_downlevel-msi.a | Bin 0 -> 34848 bytes .../libwinapi_onecoreuap_downlevel-newdev.a | Bin 0 -> 10436 bytes .../libwinapi_onecoreuap_downlevel-ole32.a | Bin 0 -> 285188 bytes .../libwinapi_onecoreuap_downlevel-oleacc.a | Bin 0 -> 11952 bytes .../libwinapi_onecoreuap_downlevel-oleaut32.a | Bin 0 -> 322874 bytes .../libwinapi_onecoreuap_downlevel-oledlg.a | Bin 0 -> 18064 bytes .../lib/libwinapi_onecoreuap_downlevel-pdh.a | Bin 0 -> 14048 bytes .../libwinapi_onecoreuap_downlevel-psapi.a | Bin 0 -> 24152 bytes .../libwinapi_onecoreuap_downlevel-resutils.a | Bin 0 -> 10458 bytes .../libwinapi_onecoreuap_downlevel-rstrtmgr.a | Bin 0 -> 6586 bytes .../libwinapi_onecoreuap_downlevel-secur32.a | Bin 0 -> 77004 bytes .../libwinapi_onecoreuap_downlevel-setupapi.a | Bin 0 -> 158058 bytes .../libwinapi_onecoreuap_downlevel-shell32.a | Bin 0 -> 137068 bytes .../libwinapi_onecoreuap_downlevel-shlwapi.a | Bin 0 -> 317204 bytes .../lib/libwinapi_onecoreuap_downlevel-tdh.a | Bin 0 -> 11956 bytes .../libwinapi_onecoreuap_downlevel-twinapi.a | Bin 0 -> 2588 bytes .../libwinapi_onecoreuap_downlevel-user32.a | Bin 0 -> 506128 bytes .../libwinapi_onecoreuap_downlevel-uxtheme.a | Bin 0 -> 39456 bytes .../libwinapi_onecoreuap_downlevel-version.a | Bin 0 -> 10064 bytes .../libwinapi_onecoreuap_downlevel-winmm.a | Bin 0 -> 5788 bytes .../libwinapi_onecoreuap_downlevel-winspool.a | Bin 0 -> 35146 bytes .../libwinapi_onecoreuap_downlevel-wtsapi32.a | Bin 0 -> 15314 bytes ...libwinapi_onecoreuap_downlevel-xinput1_4.a | Bin 0 -> 8390 bytes .../lib/libwinapi_onecoreuap_downlevel.a | 36 + .../lib/libwinapi_opengl32.a | Bin 0 -> 287026 bytes .../lib/libwinapi_p2p.a | Bin 0 -> 92602 bytes .../lib/libwinapi_p2pgraph.a | Bin 0 -> 32856 bytes .../lib/libwinapi_pathcch.a | Bin 0 -> 19396 bytes .../lib/libwinapi_pdh.a | Bin 0 -> 90600 bytes .../lib/libwinapi_peerdist.a | Bin 0 -> 25984 bytes .../lib/libwinapi_powrprof.a | Bin 0 -> 92844 bytes .../lib/libwinapi_prntvpt.a | Bin 0 -> 26074 bytes .../lib/libwinapi_propsys.a | Bin 0 -> 184622 bytes .../lib/libwinapi_psapi.a | Bin 0 -> 23454 bytes .../lib/libwinapi_quartz.a | Bin 0 -> 4814 bytes .../lib/libwinapi_query.a | Bin 0 -> 12222 bytes .../lib/libwinapi_qwave.a | Bin 0 -> 12778 bytes .../lib/libwinapi_rasapi32.a | Bin 0 -> 117556 bytes .../lib/libwinapi_rasdlg.a | Bin 0 -> 20232 bytes .../lib/libwinapi_resutils.a | Bin 0 -> 107496 bytes .../lib/libwinapi_rometadata.a | Bin 0 -> 2528 bytes .../lib/libwinapi_rpcexts.a | Bin 0 -> 45338 bytes .../lib/libwinapi_rpcns4.a | Bin 0 -> 52470 bytes .../lib/libwinapi_rpcproxy.a | Bin 0 -> 4884 bytes .../lib/libwinapi_rpcrt4.a | Bin 0 -> 427850 bytes .../lib/libwinapi_rstrtmgr.a | Bin 0 -> 11072 bytes .../lib/libwinapi_rtm.a | Bin 0 -> 95388 bytes .../lib/libwinapi_rtutils.a | Bin 0 -> 34134 bytes .../lib/libwinapi_rtworkq.a | Bin 0 -> 29736 bytes ...bject-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11420 bytes ...bject-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8936 bytes ...ntimeobject-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9664 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3796 bytes ...ct-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2798 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4802 bytes ...ject-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 21854 bytes ...ject-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4450 bytes .../lib/libwinapi_runtimeobject.a | 10 + .../lib/libwinapi_samlib.a | Bin 0 -> 59410 bytes .../lib/libwinapi_samsrv.a | Bin 0 -> 273012 bytes .../lib/libwinapi_sas.a | Bin 0 -> 2410 bytes .../lib/libwinapi_scarddlg.a | Bin 0 -> 5732 bytes .../lib/libwinapi_scecli.a | Bin 0 -> 52546 bytes .../lib/libwinapi_scesrv.a | Bin 0 -> 3322 bytes .../lib/libwinapi_schannel.a | Bin 0 -> 29436 bytes .../lib/libwinapi_secur32.a | Bin 0 -> 78166 bytes .../lib/libwinapi_security.a | Bin 0 -> 31228 bytes .../lib/libwinapi_sens.a | Bin 0 -> 4112 bytes .../lib/libwinapi_sensapi.a | Bin 0 -> 4126 bytes .../lib/libwinapi_sensorsutils.a | Bin 0 -> 52000 bytes .../lib/libwinapi_setupapi.a | Bin 0 -> 469960 bytes .../lib/libwinapi_sfc.a | Bin 0 -> 14364 bytes ...re-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6352 bytes ...re-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2744 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4538 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7012 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2746 bytes ...re-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4660 bytes .../lib/libwinapi_shcore.a | 8 + .../lib/libwinapi_shdocvw.a | Bin 0 -> 16814 bytes .../lib/libwinapi_shell32.a | Bin 0 -> 332466 bytes .../lib/libwinapi_shfolder.a | Bin 0 -> 3292 bytes .../lib/libwinapi_shlwapi.a | Bin 0 -> 288514 bytes .../lib/libwinapi_slc.a | Bin 0 -> 31846 bytes .../lib/libwinapi_slcext.a | Bin 0 -> 8992 bytes .../lib/libwinapi_slwga.a | Bin 0 -> 2474 bytes .../lib/libwinapi_snmpapi.a | Bin 0 -> 32012 bytes .../lib/libwinapi_spoolss.a | Bin 0 -> 159710 bytes .../lib/libwinapi_sporder.a | Bin 0 -> 3328 bytes .../lib/libwinapi_srpapi.a | Bin 0 -> 19220 bytes .../lib/libwinapi_ssdpapi.a | Bin 0 -> 25090 bytes .../lib/libwinapi_sti.a | Bin 0 -> 4956 bytes .../lib/libwinapi_swdevice.a | Bin 0 -> 8984 bytes .../lib/libwinapi_synchronization.a | Bin 0 -> 4154 bytes .../lib/libwinapi_t2embed.a | Bin 0 -> 13036 bytes .../lib/libwinapi_tapi32.a | Bin 0 -> 223330 bytes .../lib/libwinapi_tbs.a | Bin 0 -> 15378 bytes .../lib/libwinapi_tdh.a | Bin 0 -> 21500 bytes .../lib/libwinapi_thunk32.a | Bin 0 -> 52116 bytes .../lib/libwinapi_tokenbinding.a | Bin 0 -> 8532 bytes .../lib/libwinapi_traffic.a | Bin 0 -> 18952 bytes .../lib/libwinapi_tsec.a | Bin 0 -> 24376 bytes .../lib/libwinapi_twain_32.a | Bin 0 -> 5532 bytes .../lib/libwinapi_txfw32.a | Bin 0 -> 9244 bytes .../lib/libwinapi_ualapi.a | Bin 0 -> 7232 bytes .../lib/libwinapi_uiautomationcore.a | Bin 0 -> 86236 bytes .../lib/libwinapi_umpdddi.a | Bin 0 -> 64894 bytes .../lib/libwinapi_urlmon.a | Bin 0 -> 74000 bytes .../lib/libwinapi_user32.a | Bin 0 -> 606552 bytes .../lib/libwinapi_userenv.a | Bin 0 -> 60806 bytes .../lib/libwinapi_usp10.a | Bin 0 -> 33934 bytes .../lib/libwinapi_uxtheme.a | Bin 0 -> 62198 bytes .../lib/libwinapi_vdmdbg.a | Bin 0 -> 23882 bytes .../lib/libwinapi_version.a | Bin 0 -> 11320 bytes .../lib/libwinapi_vfw32-avicap32.a | Bin 0 -> 6642 bytes .../lib/libwinapi_vfw32-avifil32.a | Bin 0 -> 60908 bytes .../lib/libwinapi_vfw32-msvfw32.a | Bin 0 -> 38778 bytes .../lib/libwinapi_vfw32.a | 5 + .../lib/libwinapi_virtdisk.a | Bin 0 -> 23904 bytes .../lib/libwinapi_vssapi.a | Bin 0 -> 11036 bytes .../lib/libwinapi_wcmapi.a | Bin 0 -> 32080 bytes .../lib/libwinapi_wdsbp.a | Bin 0 -> 7278 bytes .../lib/libwinapi_wdsclientapi.a | Bin 0 -> 50204 bytes .../lib/libwinapi_wdsmc.a | Bin 0 -> 6794 bytes .../lib/libwinapi_wdspxe.a | Bin 0 -> 26732 bytes .../lib/libwinapi_wdstptc.a | Bin 0 -> 12974 bytes .../lib/libwinapi_webservices.a | Bin 0 -> 156942 bytes .../lib/libwinapi_websocket.a | Bin 0 -> 12522 bytes .../lib/libwinapi_wecapi.a | Bin 0 -> 14012 bytes .../lib/libwinapi_wer.a | Bin 0 -> 40580 bytes .../lib/libwinapi_wevtapi.a | Bin 0 -> 37372 bytes .../lib/libwinapi_wiaservc.a | Bin 0 -> 45476 bytes .../lib/libwinapi_winbio.a | Bin 0 -> 51074 bytes .../lib/libwinapi_windows.data.pdf.a | Bin 0 -> 2552 bytes .../lib/libwinapi_windows.networking.a | Bin 0 -> 2616 bytes .../lib/libwinapi_windows.ui.a | Bin 0 -> 3314 bytes ...wsapp-api-ms-win-appmodel-runtime-l1-1-0.a | Bin 0 -> 6334 bytes ...wsapp-api-ms-win-appmodel-runtime-l1-1-1.a | Bin 0 -> 8038 bytes ...pi_windowsapp-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 33662 bytes ...pi_windowsapp-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 2702 bytes ...pi_windowsapp-api-ms-win-core-com-l2-1-1.a | Bin 0 -> 19278 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66298 bytes ...i_windowsapp-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16458 bytes ...i_windowsapp-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2672 bytes ...indowsapp-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 8458 bytes ...indowsapp-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 16346 bytes ...ndowsapp-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3542 bytes ...ndowsapp-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2736 bytes ..._windowsapp-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 4370 bytes ...dowsapp-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2746 bytes ...dowsapp-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3624 bytes ...indowsapp-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5210 bytes ...app-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 6066 bytes ...app-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2790 bytes ...app-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 3608 bytes ...pp-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6392 bytes ...pp-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2768 bytes ...windowsapp-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5044 bytes ...windowsapp-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2696 bytes ...windowsapp-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 4332 bytes ...windowsapp-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3548 bytes ...dowsapp-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 2762 bytes ...dowsapp-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 3516 bytes ...i_windowsapp-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 46238 bytes ...i_windowsapp-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 3470 bytes ...i_windowsapp-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 4344 bytes ...i_windowsapp-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 6802 bytes ...i_windowsapp-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 2656 bytes ...windowsapp-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 4348 bytes ...i_windowsapp-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 9076 bytes ...i_windowsapp-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 5844 bytes ...app-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 5156 bytes ...wsapp-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 11346 bytes ...wsapp-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2794 bytes ...api_windowsapp-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 6968 bytes ...api_windowsapp-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 3484 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 2796 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 8650 bytes ...sapp-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2700 bytes ...app-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 7826 bytes ...app-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3660 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 3624 bytes ...sapp-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 25876 bytes ...sapp-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2764 bytes ...sapp-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3630 bytes ...sapp-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 6994 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 3692 bytes ...windowsapp-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 5132 bytes ...windowsapp-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 8656 bytes ...windowsapp-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 4408 bytes ...windowsapp-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5316 bytes ...pp-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4540 bytes ...pp-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2756 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10316 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3600 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2722 bytes ...pp-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4532 bytes ...dowsapp-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7080 bytes ...app-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6106 bytes ...i_windowsapp-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20254 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 16528 bytes ...pp-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 29228 bytes ...pp-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 11432 bytes ...pp-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 3664 bytes ...pp-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 10612 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 4604 bytes ...indowsapp-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3614 bytes ...owsapp-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 3628 bytes ..._windowsapp-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 6138 bytes ...app-api-ms-win-core-psm-appnotify-l1-1-0.a | Bin 0 -> 3780 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 2768 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4508 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4720 bytes ...owsapp-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 3572 bytes ...owsapp-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 2736 bytes ..._windowsapp-api-ms-win-core-slapi-l1-1-0.a | Bin 0 -> 3632 bytes ...windowsapp-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 6888 bytes ...owsapp-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 6944 bytes ..._windowsapp-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 36054 bytes ..._windowsapp-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 13632 bytes ..._windowsapp-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4406 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 12730 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 3622 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 2750 bytes ...owsapp-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 34140 bytes ...ndowsapp-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 11728 bytes ...pi_windowsapp-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 3534 bytes ...i_windowsapp-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 4232 bytes ...indowsapp-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 4430 bytes ...wsapp-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 4466 bytes ...wsapp-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2722 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 5400 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7384 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3728 bytes ...wsapp-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 10430 bytes ...wsapp-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 3662 bytes ..._windowsapp-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9614 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3776 bytes ...pp-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2780 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4780 bytes ...sapp-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 20938 bytes ..._windowsapp-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 2690 bytes ...windowsapp-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 5268 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 7038 bytes ...sapp-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4332 bytes ...pp-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 6056 bytes ...owsapp-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 5144 bytes ...sapp-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 8570 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2870 bytes ...i-ms-win-gaming-expandedresources-l1-1-0.a | Bin 0 -> 4622 bytes ...app-api-ms-win-gaming-gamemonitor-l1-1-0.a | Bin 0 -> 4538 bytes ...app-api-ms-win-gaming-gamemonitor-l1-1-1.a | Bin 0 -> 2834 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-0.a | Bin 0 -> 7844 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-1.a | Bin 0 -> 3648 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-2.a | Bin 0 -> 8152 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-3.a | Bin 0 -> 3684 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-4.a | Bin 0 -> 8744 bytes ...sapp-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4428 bytes ...ndowsapp-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 45898 bytes ...ndowsapp-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 2752 bytes ...ndowsapp-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2700 bytes ...app-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 23664 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2870 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6268 bytes ...app-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 6210 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5400 bytes ...sapp-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 7010 bytes ...app-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3648 bytes ...ndowsapp-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5626 bytes ...pp-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4692 bytes .../lib/libwinapi_windowsapp-bcrypt.a | Bin 0 -> 30326 bytes .../lib/libwinapi_windowsapp-cabinet.a | Bin 0 -> 14588 bytes .../lib/libwinapi_windowsapp-chakra.a | Bin 0 -> 92510 bytes .../lib/libwinapi_windowsapp-coremessaging.a | Bin 0 -> 2672 bytes .../lib/libwinapi_windowsapp-crypt32.a | Bin 0 -> 115994 bytes .../lib/libwinapi_windowsapp-d2d1.a | Bin 0 -> 12410 bytes .../lib/libwinapi_windowsapp-d3d11.a | Bin 0 -> 5184 bytes .../lib/libwinapi_windowsapp-d3d12.a | Bin 0 -> 7040 bytes .../lib/libwinapi_windowsapp-d3dcompiler_47.a | Bin 0 -> 22310 bytes .../lib/libwinapi_windowsapp-deviceaccess.a | Bin 0 -> 2642 bytes .../lib/libwinapi_windowsapp-dhcpcsvc.a | Bin 0 -> 4178 bytes .../lib/libwinapi_windowsapp-dhcpcsvc6.a | Bin 0 -> 4216 bytes .../lib/libwinapi_windowsapp-dwrite.a | Bin 0 -> 2562 bytes .../lib/libwinapi_windowsapp-dxgi.a | Bin 0 -> 3356 bytes .../lib/libwinapi_windowsapp-esent.a | Bin 0 -> 89180 bytes ...i_windowsapp-ext-ms-win-core-iuri-l1-1-0.a | Bin 0 -> 3506 bytes ...ndowsapp-ext-ms-win-gaming-xinput-l1-1-0.a | Bin 0 -> 7780 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-0.a | Bin 0 -> 3592 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-1.a | Bin 0 -> 8032 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-2.a | Bin 0 -> 3624 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-3.a | Bin 0 -> 2700 bytes .../lib/libwinapi_windowsapp-hrtfapo.a | Bin 0 -> 2532 bytes .../lib/libwinapi_windowsapp-inkobjcore.a | Bin 0 -> 23342 bytes .../lib/libwinapi_windowsapp-iphlpapi.a | Bin 0 -> 22034 bytes .../lib/libwinapi_windowsapp-mf.a | Bin 0 -> 14046 bytes .../lib/libwinapi_windowsapp-mfplat.a | Bin 0 -> 49178 bytes .../lib/libwinapi_windowsapp-mfreadwrite.a | Bin 0 -> 6184 bytes .../lib/libwinapi_windowsapp-mfsensorgroup.a | Bin 0 -> 3440 bytes .../lib/libwinapi_windowsapp-mmdevapi.a | Bin 0 -> 2618 bytes .../lib/libwinapi_windowsapp-msajapi.a | Bin 0 -> 494938 bytes .../lib/libwinapi_windowsapp-mswsock.a | Bin 0 -> 4124 bytes .../lib/libwinapi_windowsapp-ncrypt.a | Bin 0 -> 20346 bytes .../lib/libwinapi_windowsapp-ntdll.a | Bin 0 -> 18656 bytes .../lib/libwinapi_windowsapp-oleaut32.a | Bin 0 -> 274816 bytes .../lib/libwinapi_windowsapp-propsys.a | Bin 0 -> 16898 bytes .../lib/libwinapi_windowsapp-rometadata.a | Bin 0 -> 2594 bytes .../lib/libwinapi_windowsapp-rpcrt4.a | Bin 0 -> 221178 bytes .../lib/libwinapi_windowsapp-sspicli.a | Bin 0 -> 20006 bytes .../libwinapi_windowsapp-uiautomationcore.a | Bin 0 -> 4410 bytes .../lib/libwinapi_windowsapp-urlmon.a | Bin 0 -> 3398 bytes .../lib/libwinapi_windowsapp-webservices.a | Bin 0 -> 142748 bytes .../libwinapi_windowsapp-windows.data.pdf.a | Bin 0 -> 2618 bytes .../libwinapi_windowsapp-windows.networking.a | Bin 0 -> 2682 bytes .../lib/libwinapi_windowsapp-windowscodecs.a | Bin 0 -> 9428 bytes .../lib/libwinapi_windowsapp-ws2_32.a | Bin 0 -> 82174 bytes .../lib/libwinapi_windowsapp-xaudio2_9.a | Bin 0 -> 6560 bytes .../lib/libwinapi_windowsapp-xmllite.a | Bin 0 -> 7022 bytes .../lib/libwinapi_windowsapp.a | 183 + .../libwinapi_windowsapp_downlevel-advapi32.a | Bin 0 -> 114618 bytes ...evel-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 3604 bytes ...p_downlevel-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9754 bytes ...el-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2840 bytes .../libwinapi_windowsapp_downlevel-cabinet.a | Bin 0 -> 14798 bytes .../lib/libwinapi_windowsapp_downlevel-d2d1.a | Bin 0 -> 12590 bytes .../libwinapi_windowsapp_downlevel-d3d11.a | Bin 0 -> 5274 bytes ...napi_windowsapp_downlevel-d3dcompiler_47.a | Bin 0 -> 22610 bytes ...winapi_windowsapp_downlevel-deviceaccess.a | Bin 0 -> 2702 bytes .../libwinapi_windowsapp_downlevel-dhcpcsvc.a | Bin 0 -> 4258 bytes ...libwinapi_windowsapp_downlevel-dhcpcsvc6.a | Bin 0 -> 4296 bytes .../libwinapi_windowsapp_downlevel-dwrite.a | Bin 0 -> 2622 bytes .../lib/libwinapi_windowsapp_downlevel-dxgi.a | Bin 0 -> 3426 bytes .../libwinapi_windowsapp_downlevel-esent.a | Bin 0 -> 90310 bytes .../libwinapi_windowsapp_downlevel-kernel32.a | Bin 0 -> 433322 bytes .../lib/libwinapi_windowsapp_downlevel-mf.a | Bin 0 -> 14246 bytes .../libwinapi_windowsapp_downlevel-mfplat.a | Bin 0 -> 49798 bytes ...bwinapi_windowsapp_downlevel-mfreadwrite.a | Bin 0 -> 6284 bytes .../libwinapi_windowsapp_downlevel-mmdevapi.a | Bin 0 -> 2678 bytes .../libwinapi_windowsapp_downlevel-msajapi.a | Bin 0 -> 500448 bytes .../libwinapi_windowsapp_downlevel-mscoree.a | Bin 0 -> 2632 bytes .../libwinapi_windowsapp_downlevel-mswsock.a | Bin 0 -> 4204 bytes .../libwinapi_windowsapp_downlevel-ole32.a | Bin 0 -> 107300 bytes .../libwinapi_windowsapp_downlevel-oleaut32.a | Bin 0 -> 278326 bytes .../libwinapi_windowsapp_downlevel-propsys.a | Bin 0 -> 17128 bytes .../libwinapi_windowsapp_downlevel-rpcrt4.a | Bin 0 -> 223858 bytes ...pi_windowsapp_downlevel-uiautomationcore.a | Bin 0 -> 15014 bytes .../libwinapi_windowsapp_downlevel-urlmon.a | Bin 0 -> 5084 bytes ...bwinapi_windowsapp_downlevel-webservices.a | Bin 0 -> 144528 bytes ...pi_windowsapp_downlevel-windows.data.pdf.a | Bin 0 -> 2678 bytes ..._windowsapp_downlevel-windows.networking.a | Bin 0 -> 2742 bytes ...inapi_windowsapp_downlevel-windowscodecs.a | Bin 0 -> 9568 bytes .../libwinapi_windowsapp_downlevel-ws2_32.a | Bin 0 -> 83244 bytes ...libwinapi_windowsapp_downlevel-xaudio2_8.a | Bin 0 -> 6670 bytes ...libwinapi_windowsapp_downlevel-xinput1_4.a | Bin 0 -> 7616 bytes .../libwinapi_windowsapp_downlevel-xmllite.a | Bin 0 -> 7132 bytes .../lib/libwinapi_windowsapp_downlevel.a | 38 + .../lib/libwinapi_windowscodecs.a | Bin 0 -> 105490 bytes .../lib/libwinapi_winfax.a | Bin 0 -> 46722 bytes .../lib/libwinapi_winhttp.a | Bin 0 -> 54234 bytes .../lib/libwinapi_wininet.a | Bin 0 -> 261898 bytes .../lib/libwinapi_winmm.a | Bin 0 -> 150878 bytes .../lib/libwinapi_winscard.a | Bin 0 -> 58800 bytes .../lib/libwinapi_winspool.a | Bin 0 -> 168176 bytes .../lib/libwinapi_winsqlite3.a | Bin 0 -> 196014 bytes .../lib/libwinapi_winsta.a | Bin 0 -> 142890 bytes .../lib/libwinapi_wintrust.a | Bin 0 -> 113340 bytes .../lib/libwinapi_winusb.a | Bin 0 -> 32456 bytes .../lib/libwinapi_wlanapi.a | Bin 0 -> 54580 bytes .../lib/libwinapi_wlanui.a | Bin 0 -> 4048 bytes .../lib/libwinapi_wldap32.a | Bin 0 -> 193518 bytes .../lib/libwinapi_wmip.a | Bin 0 -> 37708 bytes .../lib/libwinapi_wmvcore.a | Bin 0 -> 12170 bytes .../lib/libwinapi_wofutil.a | Bin 0 -> 10518 bytes .../lib/libwinapi_wow32.a | Bin 0 -> 23790 bytes .../lib/libwinapi_ws2_32.a | Bin 0 -> 144046 bytes .../lib/libwinapi_wscapi.a | Bin 0 -> 32176 bytes .../lib/libwinapi_wsclient.a | Bin 0 -> 25924 bytes .../lib/libwinapi_wsdapi.a | Bin 0 -> 33720 bytes .../lib/libwinapi_wsmsvc.a | Bin 0 -> 120984 bytes .../lib/libwinapi_wsnmp32.a | Bin 0 -> 41526 bytes .../lib/libwinapi_wsock32.a | Bin 0 -> 58790 bytes .../lib/libwinapi_wtsapi32.a | Bin 0 -> 55148 bytes .../lib/libwinapi_xaudio2.a | Bin 0 -> 7226 bytes .../lib/libwinapi_xaudio2_8.a | Bin 0 -> 6434 bytes .../lib/libwinapi_xinput.a | Bin 0 -> 8078 bytes .../lib/libwinapi_xinput9_1_0.a | Bin 0 -> 5738 bytes .../lib/libwinapi_xinputuap.a | Bin 0 -> 8110 bytes .../lib/libwinapi_xmllite.a | Bin 0 -> 6896 bytes .../lib/libwinapi_xolehlp.a | Bin 0 -> 5850 bytes .../lib/libwinapi_xpsdocumenttargetprint.a | Bin 0 -> 2548 bytes .../lib/libwinapi_xpsprint.a | Bin 0 -> 3296 bytes .../winapi-i686-pc-windows-gnu/src/lib.rs | 7 + .../vendor/winapi-util/.cargo-checksum.json | 1 + .../vendor/winapi-util/.cargo_vcs_info.json | 6 + .../v2/vendor/winapi-util/.github/FUNDING.yml | 1 + .../winapi-util/.github/workflows/ci.yml | 87 + anneal/v2/vendor/winapi-util/COPYING | 3 + anneal/v2/vendor/winapi-util/Cargo.lock | 83 + anneal/v2/vendor/winapi-util/Cargo.toml | 54 + anneal/v2/vendor/winapi-util/Cargo.toml.orig | 25 + anneal/v2/vendor/winapi-util/LICENSE-MIT | 21 + anneal/v2/vendor/winapi-util/README.md | 64 + anneal/v2/vendor/winapi-util/UNLICENSE | 24 + anneal/v2/vendor/winapi-util/rustfmt.toml | 2 + anneal/v2/vendor/winapi-util/src/console.rs | 407 + anneal/v2/vendor/winapi-util/src/file.rs | 166 + anneal/v2/vendor/winapi-util/src/lib.rs | 35 + anneal/v2/vendor/winapi-util/src/sysinfo.rs | 161 + anneal/v2/vendor/winapi-util/src/win.rs | 246 + .../.cargo-checksum.json | 1 + .../winapi-x86_64-pc-windows-gnu/Cargo.toml | 22 + .../Cargo.toml.orig | 10 + .../winapi-x86_64-pc-windows-gnu/build.rs | 18 + .../lib/libwinapi_aclui.a | Bin 0 -> 6528 bytes .../lib/libwinapi_activeds.a | Bin 0 -> 23262 bytes .../lib/libwinapi_advapi32.a | Bin 0 -> 633458 bytes .../lib/libwinapi_advpack.a | Bin 0 -> 58638 bytes .../lib/libwinapi_amsi.a | Bin 0 -> 8714 bytes ...ibwinapi_api-ms-win-net-isolation-l1-1-0.a | Bin 0 -> 9318 bytes .../lib/libwinapi_appmgmts.a | Bin 0 -> 14542 bytes .../lib/libwinapi_appnotify.a | Bin 0 -> 3520 bytes .../lib/libwinapi_audioeng.a | Bin 0 -> 3238 bytes .../lib/libwinapi_authz.a | Bin 0 -> 32128 bytes .../lib/libwinapi_avifil32.a | Bin 0 -> 60014 bytes .../lib/libwinapi_avrt.a | Bin 0 -> 18382 bytes .../lib/libwinapi_basesrv.a | Bin 0 -> 6638 bytes .../lib/libwinapi_bcrypt.a | Bin 0 -> 45764 bytes .../lib/libwinapi_bluetoothapis.a | Bin 0 -> 83340 bytes .../lib/libwinapi_bthprops.a | Bin 0 -> 35386 bytes .../lib/libwinapi_cabinet.a | Bin 0 -> 22040 bytes .../lib/libwinapi_certadm.a | Bin 0 -> 26066 bytes .../lib/libwinapi_certpoleng.a | Bin 0 -> 13192 bytes .../lib/libwinapi_cfgmgr32.a | Bin 0 -> 193478 bytes .../lib/libwinapi_chakrart.a | Bin 0 -> 97288 bytes .../lib/libwinapi_cldapi.a | Bin 0 -> 37288 bytes .../lib/libwinapi_clfsw32.a | Bin 0 -> 50884 bytes .../lib/libwinapi_clusapi.a | Bin 0 -> 227522 bytes .../lib/libwinapi_comctl32.a | Bin 0 -> 102926 bytes .../lib/libwinapi_comdlg32.a | Bin 0 -> 17898 bytes .../lib/libwinapi_comppkgsup.a | Bin 0 -> 9286 bytes .../lib/libwinapi_compstui.a | Bin 0 -> 4930 bytes .../lib/libwinapi_comsvcs.a | Bin 0 -> 15234 bytes .../lib/libwinapi_coremessaging.a | Bin 0 -> 24904 bytes .../lib/libwinapi_credui.a | Bin 0 -> 20116 bytes .../lib/libwinapi_crypt32.a | Bin 0 -> 200182 bytes .../lib/libwinapi_cryptdll.a | Bin 0 -> 17280 bytes .../lib/libwinapi_cryptnet.a | Bin 0 -> 5866 bytes .../lib/libwinapi_cryptui.a | Bin 0 -> 36826 bytes .../lib/libwinapi_cryptxml.a | Bin 0 -> 17074 bytes .../lib/libwinapi_cscapi.a | Bin 0 -> 6628 bytes .../lib/libwinapi_cscdll.a | Bin 0 -> 15936 bytes .../lib/libwinapi_d2d1.a | Bin 0 -> 12142 bytes .../lib/libwinapi_d3d10.a | Bin 0 -> 25822 bytes .../lib/libwinapi_d3d10_1.a | Bin 0 -> 25906 bytes .../lib/libwinapi_d3d11.a | Bin 0 -> 28176 bytes .../lib/libwinapi_d3d12.a | Bin 0 -> 10228 bytes .../lib/libwinapi_d3d9.a | Bin 0 -> 10354 bytes .../lib/libwinapi_d3dcompiler.a | Bin 0 -> 23390 bytes .../lib/libwinapi_d3dcsx.a | Bin 0 -> 9006 bytes .../lib/libwinapi_d3dcsxd.a | Bin 0 -> 9030 bytes .../lib/libwinapi_davclnt.a | Bin 0 -> 19178 bytes .../lib/libwinapi_dbgeng.a | Bin 0 -> 4784 bytes .../lib/libwinapi_dbghelp.a | Bin 0 -> 185684 bytes .../lib/libwinapi_dciman32.a | Bin 0 -> 17342 bytes .../lib/libwinapi_dcomp.a | Bin 0 -> 6792 bytes .../lib/libwinapi_ddraw.a | Bin 0 -> 12070 bytes .../lib/libwinapi_deviceaccess.a | Bin 0 -> 4238 bytes .../lib/libwinapi_devmgr.a | Bin 0 -> 17246 bytes .../lib/libwinapi_dflayout.a | Bin 0 -> 2522 bytes .../lib/libwinapi_dhcpcsvc.a | Bin 0 -> 53862 bytes .../lib/libwinapi_dhcpcsvc6.a | Bin 0 -> 19516 bytes .../lib/libwinapi_dhcpsapi.a | Bin 0 -> 172106 bytes .../lib/libwinapi_difxapi.a | Bin 0 -> 11506 bytes .../lib/libwinapi_dinput8.a | Bin 0 -> 2506 bytes .../lib/libwinapi_dmprocessxmlfiltered.a | Bin 0 -> 4334 bytes .../lib/libwinapi_dnsapi.a | Bin 0 -> 220698 bytes .../lib/libwinapi_dnsperf.a | Bin 0 -> 4182 bytes .../lib/libwinapi_dnsrslvr.a | Bin 0 -> 4906 bytes .../lib/libwinapi_dpx.a | Bin 0 -> 5506 bytes .../lib/libwinapi_drt.a | Bin 0 -> 14192 bytes .../lib/libwinapi_drtprov.a | Bin 0 -> 9406 bytes .../lib/libwinapi_drttransport.a | Bin 0 -> 3410 bytes .../lib/libwinapi_dsound.a | Bin 0 -> 9860 bytes .../lib/libwinapi_dsprop.a | Bin 0 -> 9764 bytes .../lib/libwinapi_dssec.a | Bin 0 -> 4972 bytes .../lib/libwinapi_dststlog.a | Bin 0 -> 2450 bytes .../lib/libwinapi_dsuiext.a | Bin 0 -> 28150 bytes .../lib/libwinapi_dwmapi.a | Bin 0 -> 26216 bytes .../lib/libwinapi_dwrite.a | Bin 0 -> 2502 bytes .../lib/libwinapi_dxgi.a | Bin 0 -> 9062 bytes .../lib/libwinapi_dxva2.a | Bin 0 -> 33644 bytes .../lib/libwinapi_eappcfg.a | Bin 0 -> 14690 bytes .../lib/libwinapi_eappprxy.a | Bin 0 -> 16798 bytes .../lib/libwinapi_easregprov.a | Bin 0 -> 3440 bytes .../lib/libwinapi_efswrt.a | Bin 0 -> 16424 bytes .../lib/libwinapi_elscore.a | Bin 0 -> 5722 bytes .../lib/libwinapi_esent.a | Bin 0 -> 295300 bytes .../lib/libwinapi_evr.a | Bin 0 -> 8998 bytes .../lib/libwinapi_faultrep.a | Bin 0 -> 9702 bytes .../lib/libwinapi_feclient.a | Bin 0 -> 38710 bytes .../lib/libwinapi_fhsvcctl.a | Bin 0 -> 13206 bytes .../lib/libwinapi_fltlib.a | Bin 0 -> 24946 bytes .../lib/libwinapi_fontsub.a | Bin 0 -> 3286 bytes .../lib/libwinapi_framedyd.a | Bin 0 -> 2440 bytes .../lib/libwinapi_framedyn.a | Bin 0 -> 2440 bytes .../lib/libwinapi_fwpuclnt.a | Bin 0 -> 228790 bytes .../lib/libwinapi_fxsutility.a | Bin 0 -> 3340 bytes .../lib/libwinapi_gdi32.a | Bin 0 -> 465674 bytes .../lib/libwinapi_gdiplus.a | Bin 0 -> 516820 bytes .../lib/libwinapi_glmf32.a | Bin 0 -> 105066 bytes .../lib/libwinapi_glu32.a | Bin 0 -> 42248 bytes .../lib/libwinapi_gpedit.a | Bin 0 -> 9476 bytes .../lib/libwinapi_hbaapi.a | Bin 0 -> 78166 bytes .../lib/libwinapi_hid.a | Bin 0 -> 37186 bytes .../lib/libwinapi_hlink.a | Bin 0 -> 24552 bytes .../lib/libwinapi_hrtfapo.a | Bin 0 -> 4930 bytes .../lib/libwinapi_httpapi.a | Bin 0 -> 36898 bytes .../lib/libwinapi_iashlpr.a | Bin 0 -> 10954 bytes .../lib/libwinapi_icm32.a | Bin 0 -> 18430 bytes .../lib/libwinapi_icmui.a | Bin 0 -> 3300 bytes .../lib/libwinapi_icuin.a | Bin 0 -> 476094 bytes .../lib/libwinapi_icuuc.a | Bin 0 -> 677872 bytes .../lib/libwinapi_imagehlp.a | Bin 0 -> 117826 bytes .../lib/libwinapi_imgutil.a | Bin 0 -> 8714 bytes .../lib/libwinapi_imm32.a | Bin 0 -> 66990 bytes .../lib/libwinapi_infocardapi.a | Bin 0 -> 14872 bytes .../lib/libwinapi_inkobjcore.a | Bin 0 -> 25196 bytes .../lib/libwinapi_inseng.a | Bin 0 -> 7242 bytes .../lib/libwinapi_iphlpapi.a | Bin 0 -> 230434 bytes .../lib/libwinapi_iprop.a | Bin 0 -> 8032 bytes .../lib/libwinapi_irprops.a | Bin 0 -> 31054 bytes .../lib/libwinapi_iscsidsc.a | Bin 0 -> 67730 bytes .../lib/libwinapi_jsrt.a | Bin 0 -> 74600 bytes .../lib/libwinapi_kernel32.a | Bin 0 -> 1074054 bytes .../lib/libwinapi_ksproxy.a | Bin 0 -> 6626 bytes .../lib/libwinapi_ksuser.a | Bin 0 -> 7980 bytes .../lib/libwinapi_ktmw32.a | Bin 0 -> 37672 bytes .../lib/libwinapi_loadperf.a | Bin 0 -> 13266 bytes .../lib/libwinapi_lz32.a | Bin 0 -> 12176 bytes .../lib/libwinapi_magnification.a | Bin 0 -> 17314 bytes .../lib/libwinapi_mapi32.a | Bin 0 -> 107688 bytes .../lib/libwinapi_mciole32.a | Bin 0 -> 10362 bytes .../lib/libwinapi_mdmlocalmanagement.a | Bin 0 -> 4398 bytes .../lib/libwinapi_mdmregistration.a | Bin 0 -> 10366 bytes .../lib/libwinapi_mf.a | Bin 0 -> 63314 bytes .../lib/libwinapi_mfcore.a | Bin 0 -> 31188 bytes .../lib/libwinapi_mfplat.a | Bin 0 -> 125608 bytes .../lib/libwinapi_mfplay.a | Bin 0 -> 2506 bytes .../lib/libwinapi_mfreadwrite.a | Bin 0 -> 6054 bytes .../lib/libwinapi_mfsensorgroup.a | Bin 0 -> 4226 bytes .../lib/libwinapi_mfsrcsnk.a | Bin 0 -> 3334 bytes .../lib/libwinapi_mgmtapi.a | Bin 0 -> 8706 bytes .../lib/libwinapi_mi.a | Bin 0 -> 2514 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68068 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3556 bytes ...inapi_mincore-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3476 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 65846 bytes ...napi_mincore-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16330 bytes ...napi_mincore-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2662 bytes ...i_mincore-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13320 bytes ...i_mincore-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34208 bytes ..._mincore-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5138 bytes ..._mincore-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3522 bytes ..._mincore-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2726 bytes ...api_mincore-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5138 bytes ...api_mincore-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6066 bytes ...api_mincore-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2706 bytes ...mincore-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2738 bytes ...mincore-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3602 bytes ...ore-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7698 bytes ...ore-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6286 bytes ...ore-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2778 bytes ...ore-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6126 bytes ...pi_mincore-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5002 bytes ...pi_mincore-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2690 bytes ...napi_mincore-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63222 bytes ...napi_mincore-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5250 bytes ...napi_mincore-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4418 bytes ...napi_mincore-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10042 bytes ...napi_mincore-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10842 bytes ...napi_mincore-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2662 bytes ...napi_mincore-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3458 bytes ...napi_mincore-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2718 bytes ..._mincore-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5490 bytes ...pi_mincore-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6002 bytes ...napi_mincore-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13742 bytes ...napi_mincore-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7382 bytes ...ncore-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 6138 bytes ...ncore-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2782 bytes ...winapi_mincore-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7722 bytes ...winapi_mincore-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4288 bytes ...inapi_mincore-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2666 bytes ...ore-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 25994 bytes ...ore-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4338 bytes ...ore-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2758 bytes ...ore-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3642 bytes ...core-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 50704 bytes ...core-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2754 bytes ...core-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3614 bytes ...core-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 11926 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 14864 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15368 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11326 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5276 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2762 bytes ...pi_mincore-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3528 bytes ...mincore-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10230 bytes ...mincore-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3578 bytes ...mincore-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2710 bytes ...mincore-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7038 bytes ...napi_mincore-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20070 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19774 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4570 bytes ...e-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10376 bytes ...re-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 42680 bytes ...re-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 13900 bytes ...re-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9534 bytes ...re-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12256 bytes ...e-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4510 bytes ...i_mincore-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3600 bytes ...api_mincore-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19610 bytes ...pi_mincore-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8496 bytes ...pi_mincore-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3604 bytes ..._mincore-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6206 bytes ..._mincore-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4490 bytes ..._mincore-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4694 bytes ..._mincore-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 36898 bytes ..._mincore-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5186 bytes ..._mincore-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3602 bytes ...incore-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 12742 bytes ...incore-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4518 bytes ..._mincore-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3594 bytes ..._mincore-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2714 bytes ...pi_mincore-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8432 bytes ...pi_mincore-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9872 bytes ...pi_mincore-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2718 bytes ...api_mincore-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35706 bytes ...api_mincore-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16164 bytes ...api_mincore-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4374 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20164 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9414 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6230 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2758 bytes ...i_mincore-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6058 bytes ...re-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3672 bytes ...re-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2786 bytes ...incore-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33874 bytes ..._mincore-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13374 bytes ...napi_mincore-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5880 bytes ...napi_mincore-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3530 bytes ...i_mincore-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5196 bytes ...i_mincore-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3572 bytes ...ncore-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11282 bytes ...ncore-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8828 bytes ...api_mincore-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9546 bytes ...core-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 24978 bytes ...core-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2762 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4450 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7018 bytes ...api_mincore-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2750 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-0.a | Bin 0 -> 8812 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-1.a | Bin 0 -> 2690 bytes ...pi_mincore-api-ms-win-core-xstate-l1-1-2.a | Bin 0 -> 2742 bytes ...pi_mincore-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6872 bytes ...mincore-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35386 bytes ...mincore-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14170 bytes ...ncore-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7766 bytes ...ncore-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3584 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8628 bytes ...core-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4310 bytes ...core-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2790 bytes ...re-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11014 bytes ...core-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10146 bytes ...api_mincore-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6290 bytes ..._mincore-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8726 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2838 bytes ..._mincore-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 82212 bytes ..._mincore-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7798 bytes ..._mincore-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2694 bytes ..._mincore-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2770 bytes ...e-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26114 bytes ...ore-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7034 bytes ...ore-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2782 bytes ..._mincore-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5594 bytes ...i_mincore-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4458 bytes ...i_mincore-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4466 bytes ...i_mincore-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3564 bytes ...ore-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7638 bytes ...ore-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8758 bytes ...mincore-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15338 bytes .../lib/libwinapi_mincore-authz.a | Bin 0 -> 32456 bytes .../lib/libwinapi_mincore-bcrypt.a | Bin 0 -> 46236 bytes .../lib/libwinapi_mincore-cabinet.a | Bin 0 -> 22288 bytes .../lib/libwinapi_mincore-crypt32.a | Bin 0 -> 202142 bytes .../lib/libwinapi_mincore-cryptbase.a | Bin 0 -> 10582 bytes .../lib/libwinapi_mincore-cryptnet.a | Bin 0 -> 5946 bytes .../lib/libwinapi_mincore-dfscli.a | Bin 0 -> 22856 bytes .../lib/libwinapi_mincore-dnsapi.a | Bin 0 -> 222890 bytes .../lib/libwinapi_mincore-dsparse.a | Bin 0 -> 17574 bytes .../lib/libwinapi_mincore-dsrole.a | Bin 0 -> 3412 bytes .../lib/libwinapi_mincore-iphlpapi.a | Bin 0 -> 232706 bytes .../lib/libwinapi_mincore-logoncli.a | Bin 0 -> 29514 bytes .../lib/libwinapi_mincore-mpr.a | Bin 0 -> 36666 bytes .../lib/libwinapi_mincore-mswsock.a | Bin 0 -> 23650 bytes .../lib/libwinapi_mincore-ncrypt.a | Bin 0 -> 64630 bytes .../lib/libwinapi_mincore-netutils.a | Bin 0 -> 5830 bytes .../lib/libwinapi_mincore-oleaut32.a | Bin 0 -> 325186 bytes .../lib/libwinapi_mincore-rpcrt4.a | Bin 0 -> 433960 bytes .../lib/libwinapi_mincore-samcli.a | Bin 0 -> 30740 bytes .../lib/libwinapi_mincore-schedcli.a | Bin 0 -> 4982 bytes .../lib/libwinapi_mincore-srvcli.a | Bin 0 -> 39936 bytes .../lib/libwinapi_mincore-sspicli.a | Bin 0 -> 77882 bytes .../lib/libwinapi_mincore-userenv.a | Bin 0 -> 61150 bytes .../lib/libwinapi_mincore-websocket.a | Bin 0 -> 12614 bytes .../lib/libwinapi_mincore-winhttp.a | Bin 0 -> 53690 bytes .../lib/libwinapi_mincore-wkscli.a | Bin 0 -> 20258 bytes .../lib/libwinapi_mincore-wldap32.a | Bin 0 -> 196972 bytes .../lib/libwinapi_mincore-ws2_32.a | Bin 0 -> 156730 bytes .../lib/libwinapi_mincore.a | 167 + ...vel-api-ms-win-downlevel-advapi32-l1-1-0.a | Bin 0 -> 124774 bytes ...vel-api-ms-win-downlevel-advapi32-l2-1-0.a | Bin 0 -> 13856 bytes ...vel-api-ms-win-downlevel-normaliz-l1-1-0.a | Bin 0 -> 3592 bytes ...nlevel-api-ms-win-downlevel-ole32-l1-1-0.a | Bin 0 -> 42478 bytes ...evel-api-ms-win-downlevel-shell32-l1-1-0.a | Bin 0 -> 4710 bytes ...evel-api-ms-win-downlevel-shlwapi-l1-1-0.a | Bin 0 -> 128962 bytes ...evel-api-ms-win-downlevel-shlwapi-l2-1-0.a | Bin 0 -> 48284 bytes ...level-api-ms-win-downlevel-user32-l1-1-0.a | Bin 0 -> 19838 bytes ...evel-api-ms-win-downlevel-version-l1-1-0.a | Bin 0 -> 6980 bytes .../lib/libwinapi_mincore_downlevel.a | 11 + .../lib/libwinapi_mmdevapi.a | Bin 0 -> 26266 bytes .../lib/libwinapi_mpr.a | Bin 0 -> 36282 bytes .../lib/libwinapi_mprapi.a | Bin 0 -> 134836 bytes .../lib/libwinapi_mprsnap.a | Bin 0 -> 38164 bytes .../lib/libwinapi_mqrt.a | Bin 0 -> 38126 bytes .../lib/libwinapi_mrmsupport.a | Bin 0 -> 4948 bytes .../lib/libwinapi_msacm32.a | Bin 0 -> 34774 bytes .../lib/libwinapi_msajapi.a | Bin 0 -> 496202 bytes .../lib/libwinapi_mscms.a | Bin 0 -> 94094 bytes .../lib/libwinapi_msctfmonitor.a | Bin 0 -> 4166 bytes .../lib/libwinapi_msdelta.a | Bin 0 -> 13398 bytes .../lib/libwinapi_msdmo.a | Bin 0 -> 13294 bytes .../lib/libwinapi_msdrm.a | Bin 0 -> 70394 bytes .../lib/libwinapi_msi.a | Bin 0 -> 235986 bytes .../lib/libwinapi_msimg32.a | Bin 0 -> 4014 bytes .../lib/libwinapi_mspatcha.a | Bin 0 -> 14946 bytes .../lib/libwinapi_mspatchc.a | Bin 0 -> 13298 bytes .../lib/libwinapi_msports.a | Bin 0 -> 10582 bytes .../lib/libwinapi_msrating.a | Bin 0 -> 27722 bytes .../lib/libwinapi_mstask.a | Bin 0 -> 10598 bytes .../lib/libwinapi_msv1_0.a | Bin 0 -> 14552 bytes .../lib/libwinapi_msvfw32.a | Bin 0 -> 38326 bytes .../lib/libwinapi_mswsock.a | Bin 0 -> 23386 bytes .../lib/libwinapi_mtx.a | Bin 0 -> 3990 bytes .../lib/libwinapi_mtxdm.a | Bin 0 -> 2498 bytes ..._nanosrv-api-ms-win-net-isolation-l1-1-0.a | Bin 0 -> 9422 bytes ..._nanosrv-api-ms-win-net-isolation-l1-1-1.a | Bin 0 -> 2822 bytes .../lib/libwinapi_nanosrv-clfsw32.a | Bin 0 -> 51420 bytes .../lib/libwinapi_nanosrv-clusapi.a | Bin 0 -> 229746 bytes .../lib/libwinapi_nanosrv-cryptxml.a | Bin 0 -> 17266 bytes .../lib/libwinapi_nanosrv-dbgeng.a | Bin 0 -> 4856 bytes .../lib/libwinapi_nanosrv-dbghelp.a | Bin 0 -> 187580 bytes .../lib/libwinapi_nanosrv-dnsperf.a | Bin 0 -> 4246 bytes .../lib/libwinapi_nanosrv-esent.a | Bin 0 -> 298284 bytes .../lib/libwinapi_nanosrv-faultrep.a | Bin 0 -> 9822 bytes .../lib/libwinapi_nanosrv-framedynos.a | Bin 0 -> 2500 bytes .../lib/libwinapi_nanosrv-fwpuclnt.a | Bin 0 -> 231006 bytes .../lib/libwinapi_nanosrv-hbaapi.a | Bin 0 -> 78950 bytes .../lib/libwinapi_nanosrv-httpapi.a | Bin 0 -> 37282 bytes .../lib/libwinapi_nanosrv-iscsidsc.a | Bin 0 -> 67666 bytes .../lib/libwinapi_nanosrv-ktmw32.a | Bin 0 -> 38064 bytes .../lib/libwinapi_nanosrv-loadperf.a | Bin 0 -> 13418 bytes .../lib/libwinapi_nanosrv-mprapi.a | Bin 0 -> 136156 bytes .../lib/libwinapi_nanosrv-netsh.a | Bin 0 -> 19890 bytes .../lib/libwinapi_nanosrv-ntdsapi.a | Bin 0 -> 97814 bytes .../lib/libwinapi_nanosrv-ntlanman.a | Bin 0 -> 16274 bytes .../lib/libwinapi_nanosrv-pdh.a | Bin 0 -> 91026 bytes .../lib/libwinapi_nanosrv-resutils.a | Bin 0 -> 107718 bytes .../lib/libwinapi_nanosrv-snmpapi.a | Bin 0 -> 32270 bytes .../lib/libwinapi_nanosrv-tbs.a | Bin 0 -> 15494 bytes .../lib/libwinapi_nanosrv-traffic.a | Bin 0 -> 19074 bytes .../lib/libwinapi_nanosrv-virtdisk.a | Bin 0 -> 23978 bytes .../lib/libwinapi_nanosrv-vssapi.a | Bin 0 -> 11118 bytes .../lib/libwinapi_nanosrv-webservices.a | Bin 0 -> 157534 bytes .../lib/libwinapi_nanosrv-wer.a | Bin 0 -> 40846 bytes .../lib/libwinapi_nanosrv-wevtapi.a | Bin 0 -> 37522 bytes .../lib/libwinapi_nanosrv-wintrust.a | Bin 0 -> 113630 bytes .../lib/libwinapi_nanosrv-wnvapi.a | Bin 0 -> 3308 bytes .../lib/libwinapi_nanosrv-wsmsvc.a | Bin 0 -> 121238 bytes .../lib/libwinapi_nanosrv.a | 36 + .../lib/libwinapi_ncrypt.a | Bin 0 -> 106382 bytes .../lib/libwinapi_nddeapi.a | Bin 0 -> 24122 bytes .../lib/libwinapi_ndfapi.a | Bin 0 -> 16300 bytes .../lib/libwinapi_netapi32.a | Bin 0 -> 171302 bytes .../lib/libwinapi_netsh.a | Bin 0 -> 19666 bytes .../lib/libwinapi_newdev.a | Bin 0 -> 20542 bytes .../lib/libwinapi_ninput.a | Bin 0 -> 21822 bytes .../lib/libwinapi_normaliz.a | Bin 0 -> 5634 bytes .../lib/libwinapi_ntdll.a | Bin 0 -> 1670630 bytes .../lib/libwinapi_ntdsa.a | Bin 0 -> 118096 bytes .../lib/libwinapi_ntdsapi.a | Bin 0 -> 96814 bytes .../lib/libwinapi_ntdsatq.a | Bin 0 -> 37458 bytes .../lib/libwinapi_ntdsetup.a | Bin 0 -> 21162 bytes .../lib/libwinapi_ntfrsapi.a | Bin 0 -> 29498 bytes .../lib/libwinapi_ntlanman.a | Bin 0 -> 16090 bytes .../lib/libwinapi_ntmarta.a | Bin 0 -> 36654 bytes .../lib/libwinapi_ntquery.a | Bin 0 -> 12202 bytes .../lib/libwinapi_odbc32.a | Bin 0 -> 138234 bytes .../lib/libwinapi_odbcbcp.a | Bin 0 -> 23184 bytes .../lib/libwinapi_oemlicense.a | Bin 0 -> 3328 bytes .../lib/libwinapi_ole32.a | Bin 0 -> 384260 bytes .../lib/libwinapi_oleacc.a | Bin 0 -> 17964 bytes .../lib/libwinapi_oleaut32.a | Bin 0 -> 321850 bytes .../lib/libwinapi_olecli32.a | Bin 0 -> 139110 bytes .../lib/libwinapi_oledlg.a | Bin 0 -> 19890 bytes .../lib/libwinapi_olesvr32.a | Bin 0 -> 19698 bytes .../lib/libwinapi_ondemandconnroutehelper.a | Bin 0 -> 8682 bytes ...api_onecore-api-ms-win-core-atoms-l1-1-0.a | Bin 0 -> 15494 bytes ..._onecore-api-ms-win-core-calendar-l1-1-0.a | Bin 0 -> 7934 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68068 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3556 bytes ...inapi_onecore-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3476 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 65846 bytes ...napi_onecore-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16330 bytes ...napi_onecore-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2662 bytes ...core-api-ms-win-core-console-ansi-l2-1-0.a | Bin 0 -> 2738 bytes ...i_onecore-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13320 bytes ...i_onecore-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34208 bytes ...i_onecore-api-ms-win-core-console-l3-1-0.a | Bin 0 -> 2726 bytes ..._onecore-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5138 bytes ..._onecore-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3522 bytes ..._onecore-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2726 bytes ...api_onecore-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5138 bytes ...api_onecore-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6066 bytes ...api_onecore-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2706 bytes ...onecore-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2738 bytes ...onecore-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3602 bytes ...i_onecore-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5172 bytes ...i_onecore-api-ms-win-core-enclave-l1-1-1.a | Bin 0 -> 5942 bytes ...ore-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7698 bytes ...ore-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6286 bytes ...ore-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2778 bytes ...ore-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6126 bytes ...re-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6354 bytes ...re-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2758 bytes ...pi_onecore-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5002 bytes ...pi_onecore-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2690 bytes ...pi_onecore-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 5946 bytes ...pi_onecore-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3532 bytes ...onecore-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 9518 bytes ...onecore-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 6006 bytes ...napi_onecore-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63222 bytes ...napi_onecore-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5250 bytes ...napi_onecore-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4418 bytes ...napi_onecore-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10042 bytes ...napi_onecore-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10842 bytes ...napi_onecore-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2662 bytes ...napi_onecore-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3458 bytes ...napi_onecore-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2718 bytes ..._onecore-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5490 bytes ...pi_onecore-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6002 bytes ...napi_onecore-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13742 bytes ...napi_onecore-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7382 bytes ...ore-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 8314 bytes ...ecore-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 6138 bytes ...ecore-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2782 bytes ...winapi_onecore-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7722 bytes ...winapi_onecore-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4288 bytes ...inapi_onecore-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2666 bytes ...inapi_onecore-api-ms-win-core-job-l2-1-0.a | Bin 0 -> 6868 bytes ...inapi_onecore-api-ms-win-core-job-l2-1-1.a | Bin 0 -> 4530 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 11406 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 34538 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-1.a | Bin 0 -> 13868 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-2.a | Bin 0 -> 8524 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-3.a | Bin 0 -> 14036 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-4.a | Bin 0 -> 2754 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-5.a | Bin 0 -> 3620 bytes ...e-api-ms-win-core-kernel32-legacy-l1-1-6.a | Bin 0 -> 2798 bytes ...core-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2682 bytes ...ore-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 25994 bytes ...ore-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4338 bytes ...ore-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2758 bytes ...ore-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3642 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 16926 bytes ...core-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 50704 bytes ...core-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2754 bytes ...core-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3614 bytes ...core-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 11926 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 8790 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 14864 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15368 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11326 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5276 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2762 bytes ...pi_onecore-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3528 bytes ...re-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4514 bytes ...re-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2746 bytes ...onecore-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10230 bytes ...onecore-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3578 bytes ...onecore-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2710 bytes ...re-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4510 bytes ...onecore-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7038 bytes ...ore-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6054 bytes ...napi_onecore-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20070 bytes ...core-api-ms-win-core-perfcounters-l1-1-0.a | Bin 0 -> 13982 bytes ...re-api-ms-win-core-privateprofile-l1-1-0.a | Bin 0 -> 13840 bytes ...re-api-ms-win-core-privateprofile-l1-1-1.a | Bin 0 -> 3680 bytes ...-win-core-processenvironment-ansi-l1-1-0.a | Bin 0 -> 2846 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19774 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4570 bytes ...e-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10376 bytes ...re-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 42680 bytes ...re-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 13900 bytes ...re-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9534 bytes ...re-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12256 bytes ...e-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4510 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 6310 bytes ...win-core-processtopology-obsolete-l1-1-1.a | Bin 0 -> 2882 bytes ...i_onecore-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3600 bytes ...necore-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 8788 bytes ...api_onecore-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19610 bytes ...pi_onecore-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8496 bytes ...pi_onecore-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3604 bytes ..._onecore-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6206 bytes ..._onecore-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4490 bytes ..._onecore-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4694 bytes ..._onecore-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 36898 bytes ..._onecore-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5186 bytes ..._onecore-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3602 bytes ..._onecore-api-ms-win-core-registry-l2-1-0.a | Bin 0 -> 24018 bytes ...necore-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 12742 bytes ...necore-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4518 bytes ...ore-api-ms-win-core-shutdown-ansi-l1-1-0.a | Bin 0 -> 4494 bytes ..._onecore-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3594 bytes ..._onecore-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2714 bytes ...e-api-ms-win-core-sidebyside-ansi-l1-1-0.a | Bin 0 -> 3608 bytes ...necore-api-ms-win-core-sidebyside-l1-1-0.a | Bin 0 -> 10934 bytes ...pi_onecore-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8432 bytes ...pi_onecore-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9872 bytes ...pi_onecore-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2718 bytes ...e-api-ms-win-core-string-obsolete-l1-1-0.a | Bin 0 -> 9760 bytes ...e-api-ms-win-core-string-obsolete-l1-1-1.a | Bin 0 -> 3488 bytes ...necore-api-ms-win-core-stringansi-l1-1-0.a | Bin 0 -> 11532 bytes ...necore-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 7698 bytes ...api_onecore-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35706 bytes ...api_onecore-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16164 bytes ...api_onecore-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4374 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20164 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9414 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6230 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2758 bytes ...i_onecore-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6058 bytes ...re-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3672 bytes ...re-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2786 bytes ...necore-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33874 bytes ...api-ms-win-core-threadpool-legacy-l1-1-0.a | Bin 0 -> 7830 bytes ..._onecore-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13374 bytes ..._onecore-api-ms-win-core-toolhelp-l1-1-0.a | Bin 0 -> 7598 bytes ..._onecore-api-ms-win-core-toolhelp-l1-1-1.a | Bin 0 -> 5106 bytes ...inapi_onecore-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 32204 bytes ...napi_onecore-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5880 bytes ...napi_onecore-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3530 bytes ...i_onecore-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5196 bytes ...i_onecore-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3572 bytes ...ecore-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 5236 bytes ...ecore-api-ms-win-core-versionansi-l1-1-1.a | Bin 0 -> 3604 bytes ...ecore-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2714 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 12410 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7346 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3714 bytes ...ecore-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11282 bytes ...ecore-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8828 bytes ...api_onecore-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9546 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3760 bytes ...re-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2774 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4758 bytes ...core-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 24978 bytes ...core-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2762 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4450 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7018 bytes ...api_onecore-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2750 bytes ...pi_onecore-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6872 bytes ...onecore-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35386 bytes ...onecore-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14170 bytes ...ecore-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7766 bytes ...ecore-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3584 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8628 bytes ...core-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4310 bytes ...core-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2790 bytes ...re-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11014 bytes ...necore-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 13152 bytes ...core-api-ms-win-eventing-obsolete-l1-1-0.a | Bin 0 -> 4418 bytes ...core-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10146 bytes ...i_onecore-api-ms-win-eventing-tdh-l1-1-0.a | Bin 0 -> 12152 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2862 bytes ...winapi_onecore-api-ms-win-mm-time-l1-1-0.a | Bin 0 -> 5878 bytes ...core-api-ms-win-oobe-notification-l1-1-0.a | Bin 0 -> 4518 bytes ...pi_onecore-api-ms-win-perf-legacy-l1-1-0.a | Bin 0 -> 9538 bytes ...api_onecore-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6290 bytes ...api-ms-win-power-limitsmanagement-l1-1-0.a | Bin 0 -> 10886 bytes ..._onecore-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8726 bytes ...core-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4398 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2838 bytes ...ore-api-ms-win-security-base-ansi-l1-1-0.a | Bin 0 -> 3570 bytes ..._onecore-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 82212 bytes ..._onecore-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7798 bytes ..._onecore-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2694 bytes ..._onecore-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2770 bytes ...e-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26114 bytes ...ore-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 34306 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2862 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6218 bytes ...ore-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7034 bytes ...ore-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2782 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5358 bytes ...core-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 6950 bytes ...ore-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3634 bytes ..._onecore-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5594 bytes ...i-ms-win-security-systemfunctions-l1-1-0.a | Bin 0 -> 4458 bytes ...core-api-ms-win-service-core-ansi-l1-1-0.a | Bin 0 -> 4454 bytes ...core-api-ms-win-service-core-ansi-l1-1-1.a | Bin 0 -> 2770 bytes ...i_onecore-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4458 bytes ...i_onecore-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4466 bytes ...i_onecore-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3564 bytes ...ore-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7638 bytes ...ore-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8758 bytes ...onecore-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15338 bytes ...pi_onecore-api-ms-win-shcore-path-l1-1-0.a | Bin 0 -> 5160 bytes ...necore-api-ms-win-shcore-registry-l1-1-0.a | Bin 0 -> 24536 bytes ...necore-api-ms-win-shcore-registry-l1-1-1.a | Bin 0 -> 2770 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4546 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7014 bytes ...onecore-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2762 bytes ...re-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4662 bytes ...onecore-api-ms-win-shcore-sysinfo-l1-1-0.a | Bin 0 -> 4526 bytes ...ore-api-ms-win-shcore-unicodeansi-l1-1-0.a | Bin 0 -> 5202 bytes ...core-api-ms-win-shell-shdirectory-l1-1-0.a | Bin 0 -> 4430 bytes .../lib/libwinapi_onecore-authz.a | Bin 0 -> 32456 bytes .../lib/libwinapi_onecore-bcrypt.a | Bin 0 -> 46236 bytes .../lib/libwinapi_onecore-cabinet.a | Bin 0 -> 22288 bytes .../lib/libwinapi_onecore-crypt32.a | Bin 0 -> 202142 bytes .../lib/libwinapi_onecore-cryptbase.a | Bin 0 -> 8176 bytes .../lib/libwinapi_onecore-cryptnet.a | Bin 0 -> 5946 bytes .../lib/libwinapi_onecore-dfscli.a | Bin 0 -> 22856 bytes .../lib/libwinapi_onecore-dnsapi.a | Bin 0 -> 222890 bytes .../lib/libwinapi_onecore-dsparse.a | Bin 0 -> 17574 bytes .../lib/libwinapi_onecore-dsrole.a | Bin 0 -> 3412 bytes .../lib/libwinapi_onecore-fltlib.a | Bin 0 -> 25218 bytes .../lib/libwinapi_onecore-iphlpapi.a | Bin 0 -> 232706 bytes .../lib/libwinapi_onecore-logoncli.a | Bin 0 -> 29514 bytes .../lib/libwinapi_onecore-mpr.a | Bin 0 -> 36666 bytes .../lib/libwinapi_onecore-mswsock.a | Bin 0 -> 23650 bytes .../lib/libwinapi_onecore-ncrypt.a | Bin 0 -> 64630 bytes .../lib/libwinapi_onecore-netutils.a | Bin 0 -> 5830 bytes .../lib/libwinapi_onecore-ntdll.a | Bin 0 -> 18480 bytes .../lib/libwinapi_onecore-oleaut32.a | Bin 0 -> 325186 bytes .../lib/libwinapi_onecore-powrprof.a | Bin 0 -> 58994 bytes .../lib/libwinapi_onecore-profapi.a | Bin 0 -> 15158 bytes .../lib/libwinapi_onecore-rpcrt4.a | Bin 0 -> 433960 bytes .../lib/libwinapi_onecore-samcli.a | Bin 0 -> 30740 bytes .../lib/libwinapi_onecore-schedcli.a | Bin 0 -> 4982 bytes .../lib/libwinapi_onecore-srvcli.a | Bin 0 -> 39936 bytes .../lib/libwinapi_onecore-sspicli.a | Bin 0 -> 77882 bytes .../lib/libwinapi_onecore-tokenbinding.a | Bin 0 -> 8602 bytes .../lib/libwinapi_onecore-userenv.a | Bin 0 -> 61150 bytes .../lib/libwinapi_onecore-websocket.a | Bin 0 -> 12614 bytes .../lib/libwinapi_onecore-winhttp.a | Bin 0 -> 53690 bytes .../lib/libwinapi_onecore-wkscli.a | Bin 0 -> 20258 bytes .../lib/libwinapi_onecore-wldap32.a | Bin 0 -> 196972 bytes .../lib/libwinapi_onecore-ws2_32.a | Bin 0 -> 156730 bytes .../lib/libwinapi_onecore-xmllite.a | Bin 0 -> 6962 bytes .../lib/libwinapi_onecore.a | 257 + .../libwinapi_onecore_downlevel-advapi32.a | Bin 0 -> 510800 bytes .../lib/libwinapi_onecore_downlevel-apphelp.a | Bin 0 -> 8224 bytes .../libwinapi_onecore_downlevel-comctl32.a | Bin 0 -> 60678 bytes .../libwinapi_onecore_downlevel-comdlg32.a | Bin 0 -> 16802 bytes .../lib/libwinapi_onecore_downlevel-d3d10.a | Bin 0 -> 5138 bytes .../lib/libwinapi_onecore_downlevel-d3d9.a | Bin 0 -> 5806 bytes .../libwinapi_onecore_downlevel-d3dx10_47.a | Bin 0 -> 6182 bytes .../lib/libwinapi_onecore_downlevel-difxapi.a | Bin 0 -> 3468 bytes .../lib/libwinapi_onecore_downlevel-gdi32.a | Bin 0 -> 176080 bytes .../lib/libwinapi_onecore_downlevel-input.a | Bin 0 -> 11074 bytes .../libwinapi_onecore_downlevel-kernel32.a | Bin 0 -> 972840 bytes .../lib/libwinapi_onecore_downlevel-msi.a | Bin 0 -> 34500 bytes .../lib/libwinapi_onecore_downlevel-newdev.a | Bin 0 -> 10334 bytes .../lib/libwinapi_onecore_downlevel-ole32.a | Bin 0 -> 317130 bytes .../lib/libwinapi_onecore_downlevel-oleacc.a | Bin 0 -> 11838 bytes .../libwinapi_onecore_downlevel-oleaut32.a | Bin 0 -> 329356 bytes .../lib/libwinapi_onecore_downlevel-oledlg.a | Bin 0 -> 17926 bytes .../lib/libwinapi_onecore_downlevel-pdh.a | Bin 0 -> 13922 bytes .../lib/libwinapi_onecore_downlevel-psapi.a | Bin 0 -> 23902 bytes .../libwinapi_onecore_downlevel-resutils.a | Bin 0 -> 10360 bytes .../libwinapi_onecore_downlevel-rstrtmgr.a | Bin 0 -> 6528 bytes .../lib/libwinapi_onecore_downlevel-secur32.a | Bin 0 -> 76282 bytes .../libwinapi_onecore_downlevel-setupapi.a | Bin 0 -> 156366 bytes .../lib/libwinapi_onecore_downlevel-shell32.a | Bin 0 -> 135696 bytes .../lib/libwinapi_onecore_downlevel-shlwapi.a | Bin 0 -> 313754 bytes .../lib/libwinapi_onecore_downlevel-tdh.a | Bin 0 -> 11848 bytes .../lib/libwinapi_onecore_downlevel-twinapi.a | Bin 0 -> 2582 bytes .../lib/libwinapi_onecore_downlevel-user32.a | Bin 0 -> 507550 bytes .../lib/libwinapi_onecore_downlevel-uxtheme.a | Bin 0 -> 39082 bytes .../lib/libwinapi_onecore_downlevel-version.a | Bin 0 -> 9972 bytes .../lib/libwinapi_onecore_downlevel-winmm.a | Bin 0 -> 5758 bytes .../libwinapi_onecore_downlevel-winspool.a | Bin 0 -> 34746 bytes .../libwinapi_onecore_downlevel-wtsapi32.a | Bin 0 -> 15172 bytes .../libwinapi_onecore_downlevel-xinput1_4.a | Bin 0 -> 8314 bytes .../lib/libwinapi_onecore_downlevel.a | 36 + ...reuap-api-ms-win-appmodel-runtime-l1-1-0.a | Bin 0 -> 19088 bytes ...reuap-api-ms-win-appmodel-runtime-l1-1-1.a | Bin 0 -> 15996 bytes ...reuap-api-ms-win-appmodel-runtime-l1-1-2.a | Bin 0 -> 9156 bytes ..._onecoreuap-api-ms-win-core-atoms-l1-1-0.a | Bin 0 -> 15574 bytes ...ecoreuap-api-ms-win-core-calendar-l1-1-0.a | Bin 0 -> 7962 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 68404 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 3580 bytes ...pi_onecoreuap-api-ms-win-core-com-l1-1-2.a | Bin 0 -> 3500 bytes ...pi_onecoreuap-api-ms-win-core-com-l2-1-1.a | Bin 0 -> 19206 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66154 bytes ...i_onecoreuap-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16380 bytes ...i_onecoreuap-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2678 bytes ...euap-api-ms-win-core-console-ansi-l2-1-0.a | Bin 0 -> 2754 bytes ...necoreuap-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 13392 bytes ...necoreuap-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 34376 bytes ...necoreuap-api-ms-win-core-console-l3-1-0.a | Bin 0 -> 2746 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-0.a | Bin 0 -> 5160 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3540 bytes ...ecoreuap-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2742 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 5170 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-1.a | Bin 0 -> 6102 bytes ..._onecoreuap-api-ms-win-core-debug-l1-1-2.a | Bin 0 -> 2726 bytes ...coreuap-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2758 bytes ...coreuap-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3626 bytes ...necoreuap-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5204 bytes ...necoreuap-api-ms-win-core-enclave-l1-1-1.a | Bin 0 -> 5978 bytes ...uap-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 7742 bytes ...uap-api-ms-win-core-errorhandling-l1-1-1.a | Bin 0 -> 6322 bytes ...uap-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2798 bytes ...uap-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 6162 bytes ...ap-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6378 bytes ...ap-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2774 bytes ...onecoreuap-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5026 bytes ...onecoreuap-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2706 bytes ...onecoreuap-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 5970 bytes ...onecoreuap-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3550 bytes ...coreuap-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 9570 bytes ...coreuap-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 6042 bytes ...i_onecoreuap-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 63390 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 5272 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-1.a | Bin 0 -> 4438 bytes ...i_onecoreuap-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 10076 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 10878 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-1.a | Bin 0 -> 2678 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 3476 bytes ...i_onecoreuap-api-ms-win-core-file-l2-1-3.a | Bin 0 -> 2734 bytes ...ecoreuap-api-ms-win-core-firmware-l1-1-0.a | Bin 0 -> 5512 bytes ...onecoreuap-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 6026 bytes ...i_onecoreuap-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 13794 bytes ...i_onecoreuap-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 7410 bytes ...uap-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 8362 bytes ...reuap-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 6174 bytes ...reuap-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2802 bytes ...api_onecoreuap-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 7750 bytes ...api_onecoreuap-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 4310 bytes ...pi_onecoreuap-api-ms-win-core-job-l1-1-0.a | Bin 0 -> 2686 bytes ...pi_onecoreuap-api-ms-win-core-job-l2-1-0.a | Bin 0 -> 6908 bytes ...pi_onecoreuap-api-ms-win-core-job-l2-1-1.a | Bin 0 -> 4558 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 11442 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 34708 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-1.a | Bin 0 -> 13940 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-2.a | Bin 0 -> 8572 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-3.a | Bin 0 -> 14108 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-4.a | Bin 0 -> 2774 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-5.a | Bin 0 -> 3644 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-6.a | Bin 0 -> 2818 bytes ...euap-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2700 bytes ...uap-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 26126 bytes ...uap-api-ms-win-core-libraryloader-l1-2-1.a | Bin 0 -> 4366 bytes ...uap-api-ms-win-core-libraryloader-l1-2-2.a | Bin 0 -> 2778 bytes ...uap-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3666 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 17014 bytes ...euap-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 50840 bytes ...euap-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2770 bytes ...euap-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3632 bytes ...euap-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 11964 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 8838 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 14910 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 15414 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 11362 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5298 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-4.a | Bin 0 -> 2778 bytes ...onecoreuap-api-ms-win-core-memory-l1-1-5.a | Bin 0 -> 3546 bytes ...ap-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4534 bytes ...ap-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2762 bytes ...coreuap-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10286 bytes ...coreuap-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3602 bytes ...coreuap-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2730 bytes ...ap-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4530 bytes ...coreuap-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7078 bytes ...uap-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6090 bytes ...i_onecoreuap-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20128 bytes ...euap-api-ms-win-core-perfcounters-l1-1-0.a | Bin 0 -> 14024 bytes ...ap-api-ms-win-core-privateprofile-l1-1-0.a | Bin 0 -> 13882 bytes ...ap-api-ms-win-core-privateprofile-l1-1-1.a | Bin 0 -> 3698 bytes ...-win-core-processenvironment-ansi-l1-1-0.a | Bin 0 -> 2866 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 19830 bytes ...pi-ms-win-core-processenvironment-l1-2-0.a | Bin 0 -> 4590 bytes ...p-api-ms-win-core-processsnapshot-l1-1-0.a | Bin 0 -> 10432 bytes ...ap-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 42794 bytes ...ap-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 13942 bytes ...ap-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 9566 bytes ...ap-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 12294 bytes ...p-api-ms-win-core-processtopology-l1-1-0.a | Bin 0 -> 4538 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 6334 bytes ...win-core-processtopology-obsolete-l1-1-1.a | Bin 0 -> 2898 bytes ...necoreuap-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3624 bytes ...oreuap-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 8818 bytes ..._onecoreuap-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 19710 bytes ...uap-api-ms-win-core-psm-appnotify-l1-1-0.a | Bin 0 -> 3786 bytes ...onecoreuap-api-ms-win-core-quirks-l1-1-0.a | Bin 0 -> 8526 bytes ...onecoreuap-api-ms-win-core-quirks-l1-1-1.a | Bin 0 -> 3622 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 6230 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4510 bytes ...ecoreuap-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4714 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-0.a | Bin 0 -> 36998 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-1.a | Bin 0 -> 5208 bytes ...ecoreuap-api-ms-win-core-registry-l1-1-2.a | Bin 0 -> 3620 bytes ...ecoreuap-api-ms-win-core-registry-l2-1-0.a | Bin 0 -> 24086 bytes ...oreuap-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 12782 bytes ...oreuap-api-ms-win-core-rtlsupport-l1-2-0.a | Bin 0 -> 4538 bytes ...uap-api-ms-win-core-shutdown-ansi-l1-1-0.a | Bin 0 -> 4522 bytes ...ecoreuap-api-ms-win-core-shutdown-l1-1-0.a | Bin 0 -> 3612 bytes ...ecoreuap-api-ms-win-core-shutdown-l1-1-1.a | Bin 0 -> 2730 bytes ...p-api-ms-win-core-sidebyside-ansi-l1-1-0.a | Bin 0 -> 3632 bytes ...oreuap-api-ms-win-core-sidebyside-l1-1-0.a | Bin 0 -> 10970 bytes ..._onecoreuap-api-ms-win-core-slapi-l1-1-0.a | Bin 0 -> 3638 bytes ...onecoreuap-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 8462 bytes ...onecoreuap-api-ms-win-core-string-l2-1-0.a | Bin 0 -> 9906 bytes ...onecoreuap-api-ms-win-core-string-l2-1-1.a | Bin 0 -> 2734 bytes ...p-api-ms-win-core-string-obsolete-l1-1-0.a | Bin 0 -> 9804 bytes ...p-api-ms-win-core-string-obsolete-l1-1-1.a | Bin 0 -> 3508 bytes ...oreuap-api-ms-win-core-stringansi-l1-1-0.a | Bin 0 -> 11570 bytes ...oreuap-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 7726 bytes ..._onecoreuap-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35884 bytes ..._onecoreuap-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 16248 bytes ..._onecoreuap-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4402 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 20268 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 9466 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-1.a | Bin 0 -> 6266 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-2.a | Bin 0 -> 2778 bytes ...necoreuap-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 6094 bytes ...ap-api-ms-win-core-systemtopology-l1-1-0.a | Bin 0 -> 3690 bytes ...ap-api-ms-win-core-systemtopology-l1-1-1.a | Bin 0 -> 2802 bytes ...oreuap-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33962 bytes ...api-ms-win-core-threadpool-legacy-l1-1-0.a | Bin 0 -> 7874 bytes ...ecoreuap-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 13414 bytes ...ecoreuap-api-ms-win-core-toolhelp-l1-1-0.a | Bin 0 -> 7626 bytes ...ecoreuap-api-ms-win-core-toolhelp-l1-1-1.a | Bin 0 -> 5128 bytes ...pi_onecoreuap-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 32362 bytes ...i_onecoreuap-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 5906 bytes ...i_onecoreuap-api-ms-win-core-util-l1-1-1.a | Bin 0 -> 3548 bytes ...necoreuap-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 5228 bytes ...necoreuap-api-ms-win-core-version-l1-1-1.a | Bin 0 -> 3596 bytes ...reuap-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 5268 bytes ...reuap-api-ms-win-core-versionansi-l1-1-1.a | Bin 0 -> 3628 bytes ...reuap-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2734 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 12474 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7386 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3738 bytes ...reuap-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11342 bytes ...reuap-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8876 bytes ..._onecoreuap-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9598 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3778 bytes ...ap-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2790 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4778 bytes ...euap-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 25046 bytes ...euap-api-ms-win-core-winrt-string-l1-1-1.a | Bin 0 -> 2778 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 4478 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-1.a | Bin 0 -> 7058 bytes ..._onecoreuap-api-ms-win-core-wow64-l1-1-2.a | Bin 0 -> 2770 bytes ...onecoreuap-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 6898 bytes ...coreuap-api-ms-win-devices-config-l1-1-1.a | Bin 0 -> 35558 bytes ...coreuap-api-ms-win-devices-config-l1-1-2.a | Bin 0 -> 14242 bytes ...reuap-api-ms-win-devices-swdevice-l1-1-0.a | Bin 0 -> 7810 bytes ...reuap-api-ms-win-devices-swdevice-l1-1-1.a | Bin 0 -> 3608 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-0.a | Bin 0 -> 86760 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-1.a | Bin 0 -> 41878 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-2.a | Bin 0 -> 20026 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-3.a | Bin 0 -> 14348 bytes ...i_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-4.a | Bin 0 -> 19504 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 8676 bytes ...euap-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4330 bytes ...euap-api-ms-win-eventing-consumer-l1-1-1.a | Bin 0 -> 2806 bytes ...ap-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 11050 bytes ...oreuap-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 13194 bytes ...euap-api-ms-win-eventing-obsolete-l1-1-0.a | Bin 0 -> 4438 bytes ...euap-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 10180 bytes ...necoreuap-api-ms-win-eventing-tdh-l1-1-0.a | Bin 0 -> 12216 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2882 bytes ...i-ms-win-gaming-expandedresources-l1-1-0.a | Bin 0 -> 4630 bytes ...uap-api-ms-win-gaming-gamemonitor-l1-1-0.a | Bin 0 -> 4546 bytes ...uap-api-ms-win-gaming-gamemonitor-l1-1-1.a | Bin 0 -> 2846 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-0.a | Bin 0 -> 7810 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-1.a | Bin 0 -> 3646 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-2.a | Bin 0 -> 8110 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-3.a | Bin 0 -> 3682 bytes ...onecoreuap-api-ms-win-gaming-tcui-l1-1-4.a | Bin 0 -> 8706 bytes ...api_onecoreuap-api-ms-win-mm-misc-l1-1-0.a | Bin 0 -> 25062 bytes ...api_onecoreuap-api-ms-win-mm-misc-l1-1-1.a | Bin 0 -> 2666 bytes ...napi_onecoreuap-api-ms-win-mm-mme-l1-1-0.a | Bin 0 -> 84946 bytes ...necoreuap-api-ms-win-mm-playsound-l1-1-0.a | Bin 0 -> 5100 bytes ...api_onecoreuap-api-ms-win-mm-time-l1-1-0.a | Bin 0 -> 5902 bytes ...reuap-api-ms-win-ntuser-sysparams-l1-1-0.a | Bin 0 -> 12152 bytes ...euap-api-ms-win-oobe-notification-l1-1-0.a | Bin 0 -> 4538 bytes ...onecoreuap-api-ms-win-perf-legacy-l1-1-0.a | Bin 0 -> 9570 bytes ..._onecoreuap-api-ms-win-power-base-l1-1-0.a | Bin 0 -> 6326 bytes ...api-ms-win-power-limitsmanagement-l1-1-0.a | Bin 0 -> 10942 bytes ...ecoreuap-api-ms-win-power-setting-l1-1-0.a | Bin 0 -> 8756 bytes ...euap-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4418 bytes ...-api-ms-win-security-appcontainer-l1-1-0.a | Bin 0 -> 2854 bytes ...uap-api-ms-win-security-base-ansi-l1-1-0.a | Bin 0 -> 3594 bytes ...ecoreuap-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 82422 bytes ...ecoreuap-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 7826 bytes ...ecoreuap-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2710 bytes ...ecoreuap-api-ms-win-security-base-l1-2-2.a | Bin 0 -> 2786 bytes ...p-api-ms-win-security-credentials-l1-1-0.a | Bin 0 -> 26244 bytes ...uap-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 34478 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2882 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6242 bytes ...uap-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 7074 bytes ...uap-api-ms-win-security-lsalookup-l2-1-1.a | Bin 0 -> 2802 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5390 bytes ...euap-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 6976 bytes ...uap-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3658 bytes ...ecoreuap-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5616 bytes ...i-ms-win-security-systemfunctions-l1-1-0.a | Bin 0 -> 4486 bytes ...euap-api-ms-win-service-core-ansi-l1-1-0.a | Bin 0 -> 4474 bytes ...euap-api-ms-win-service-core-ansi-l1-1-1.a | Bin 0 -> 2786 bytes ...necoreuap-api-ms-win-service-core-l1-1-0.a | Bin 0 -> 4486 bytes ...necoreuap-api-ms-win-service-core-l1-1-1.a | Bin 0 -> 4494 bytes ...necoreuap-api-ms-win-service-core-l1-1-2.a | Bin 0 -> 3588 bytes ...uap-api-ms-win-service-management-l1-1-0.a | Bin 0 -> 7682 bytes ...uap-api-ms-win-service-management-l2-1-0.a | Bin 0 -> 8806 bytes ...coreuap-api-ms-win-service-winsvc-l1-1-0.a | Bin 0 -> 15418 bytes ...onecoreuap-api-ms-win-shcore-path-l1-1-0.a | Bin 0 -> 5182 bytes ...oreuap-api-ms-win-shcore-registry-l1-1-0.a | Bin 0 -> 24606 bytes ...oreuap-api-ms-win-shcore-registry-l1-1-1.a | Bin 0 -> 2786 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4574 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7054 bytes ...coreuap-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2782 bytes ...ap-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4682 bytes ...coreuap-api-ms-win-shcore-sysinfo-l1-1-0.a | Bin 0 -> 4552 bytes ...uap-api-ms-win-shcore-unicodeansi-l1-1-0.a | Bin 0 -> 5234 bytes ...oreuap-api-ms-win-shell-namespace-l1-1-0.a | Bin 0 -> 19936 bytes ...euap-api-ms-win-shell-shdirectory-l1-1-0.a | Bin 0 -> 4450 bytes .../lib/libwinapi_onecoreuap-authz.a | Bin 0 -> 32542 bytes .../lib/libwinapi_onecoreuap-bcrypt.a | Bin 0 -> 46468 bytes .../lib/libwinapi_onecoreuap-cabinet.a | Bin 0 -> 22356 bytes .../lib/libwinapi_onecoreuap-chakra.a | Bin 0 -> 98518 bytes .../lib/libwinapi_onecoreuap-coremessaging.a | Bin 0 -> 24390 bytes .../lib/libwinapi_onecoreuap-crypt32.a | Bin 0 -> 202636 bytes .../lib/libwinapi_onecoreuap-cryptbase.a | Bin 0 -> 8206 bytes .../lib/libwinapi_onecoreuap-cryptnet.a | Bin 0 -> 5982 bytes .../lib/libwinapi_onecoreuap-d2d1.a | Bin 0 -> 12354 bytes .../lib/libwinapi_onecoreuap-d3d11.a | Bin 0 -> 9402 bytes .../lib/libwinapi_onecoreuap-d3d12.a | Bin 0 -> 10382 bytes .../lib/libwinapi_onecoreuap-d3dcompiler_47.a | Bin 0 -> 23838 bytes .../lib/libwinapi_onecoreuap-deviceaccess.a | Bin 0 -> 4330 bytes .../lib/libwinapi_onecoreuap-dfscli.a | Bin 0 -> 22976 bytes .../lib/libwinapi_onecoreuap-dhcpcsvc.a | Bin 0 -> 54686 bytes .../lib/libwinapi_onecoreuap-dhcpcsvc6.a | Bin 0 -> 19790 bytes .../lib/libwinapi_onecoreuap-dnsapi.a | Bin 0 -> 223982 bytes .../lib/libwinapi_onecoreuap-dsparse.a | Bin 0 -> 17628 bytes .../lib/libwinapi_onecoreuap-dsrole.a | Bin 0 -> 3436 bytes .../lib/libwinapi_onecoreuap-dwrite.a | Bin 0 -> 2570 bytes .../lib/libwinapi_onecoreuap-dxgi.a | Bin 0 -> 9226 bytes .../lib/libwinapi_onecoreuap-esent.a | Bin 0 -> 299046 bytes ...i_onecoreuap-ext-ms-win-core-iuri-l1-1-0.a | Bin 0 -> 4326 bytes ...ecoreuap-ext-ms-win-gaming-xinput-l1-1-0.a | Bin 0 -> 7750 bytes ...uap-ext-ms-win-networking-wlanapi-l1-1-0.a | Bin 0 -> 20594 bytes ...p-ext-ms-win-shell32-shellfolders-l1-1-0.a | Bin 0 -> 12898 bytes ...p-ext-ms-win-shell32-shellfolders-l1-1-1.a | Bin 0 -> 3612 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-0.a | Bin 0 -> 3594 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-1.a | Bin 0 -> 8802 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-2.a | Bin 0 -> 3626 bytes ...api_onecoreuap-ext-ms-win-uiacore-l1-1-3.a | Bin 0 -> 2706 bytes .../lib/libwinapi_onecoreuap-fltlib.a | Bin 0 -> 25350 bytes .../lib/libwinapi_onecoreuap-hid.a | Bin 0 -> 37680 bytes .../lib/libwinapi_onecoreuap-hrtfapo.a | Bin 0 -> 5024 bytes .../lib/libwinapi_onecoreuap-inkobjcore.a | Bin 0 -> 25608 bytes .../lib/libwinapi_onecoreuap-iphlpapi.a | Bin 0 -> 233836 bytes .../lib/libwinapi_onecoreuap-logoncli.a | Bin 0 -> 29666 bytes .../lib/libwinapi_onecoreuap-mf.a | Bin 0 -> 64270 bytes .../lib/libwinapi_onecoreuap-mfplat.a | Bin 0 -> 127462 bytes .../lib/libwinapi_onecoreuap-mfreadwrite.a | Bin 0 -> 6158 bytes .../lib/libwinapi_onecoreuap-mfsensorgroup.a | Bin 0 -> 4310 bytes .../lib/libwinapi_onecoreuap-mmdevapi.a | Bin 0 -> 26670 bytes .../lib/libwinapi_onecoreuap-mpr.a | Bin 0 -> 36766 bytes .../lib/libwinapi_onecoreuap-msajapi.a | Bin 0 -> 501836 bytes .../lib/libwinapi_onecoreuap-mswsock.a | Bin 0 -> 23726 bytes .../lib/libwinapi_onecoreuap-ncrypt.a | Bin 0 -> 64954 bytes .../lib/libwinapi_onecoreuap-netutils.a | Bin 0 -> 5866 bytes .../lib/libwinapi_onecoreuap-ntdll.a | Bin 0 -> 18534 bytes .../lib/libwinapi_onecoreuap-oleaut32.a | Bin 0 -> 326796 bytes .../lib/libwinapi_onecoreuap-powrprof.a | Bin 0 -> 59286 bytes .../lib/libwinapi_onecoreuap-profapi.a | Bin 0 -> 15204 bytes .../lib/libwinapi_onecoreuap-propsys.a | Bin 0 -> 185814 bytes .../lib/libwinapi_onecoreuap-rometadata.a | Bin 0 -> 2602 bytes .../lib/libwinapi_onecoreuap-rpcrt4.a | Bin 0 -> 436062 bytes .../lib/libwinapi_onecoreuap-samcli.a | Bin 0 -> 30900 bytes .../lib/libwinapi_onecoreuap-schedcli.a | Bin 0 -> 5014 bytes .../lib/libwinapi_onecoreuap-srvcli.a | Bin 0 -> 40144 bytes .../lib/libwinapi_onecoreuap-sspicli.a | Bin 0 -> 78080 bytes .../lib/libwinapi_onecoreuap-tokenbinding.a | Bin 0 -> 8650 bytes .../libwinapi_onecoreuap-uiautomationcore.a | Bin 0 -> 75794 bytes .../lib/libwinapi_onecoreuap-urlmon.a | Bin 0 -> 55948 bytes .../lib/libwinapi_onecoreuap-userenv.a | Bin 0 -> 61306 bytes .../lib/libwinapi_onecoreuap-webservices.a | Bin 0 -> 157936 bytes .../lib/libwinapi_onecoreuap-websocket.a | Bin 0 -> 12654 bytes .../libwinapi_onecoreuap-windows.data.pdf.a | Bin 0 -> 2630 bytes .../libwinapi_onecoreuap-windows.networking.a | Bin 0 -> 2694 bytes .../lib/libwinapi_onecoreuap-windowscodecs.a | Bin 0 -> 106210 bytes .../lib/libwinapi_onecoreuap-winhttp.a | Bin 0 -> 53828 bytes .../lib/libwinapi_onecoreuap-wintrust.a | Bin 0 -> 2562 bytes .../lib/libwinapi_onecoreuap-wkscli.a | Bin 0 -> 20366 bytes .../lib/libwinapi_onecoreuap-wlanapi.a | Bin 0 -> 40862 bytes .../lib/libwinapi_onecoreuap-wldap32.a | Bin 0 -> 197482 bytes .../lib/libwinapi_onecoreuap-wpprecorderum.a | Bin 0 -> 5050 bytes .../lib/libwinapi_onecoreuap-ws2_32.a | Bin 0 -> 157492 bytes .../lib/libwinapi_onecoreuap-xaudio2_9.a | Bin 0 -> 7386 bytes .../lib/libwinapi_onecoreuap-xmllite.a | Bin 0 -> 6988 bytes .../lib/libwinapi_onecoreuap.a | 324 + .../libwinapi_onecoreuap_downlevel-advapi32.a | Bin 0 -> 513278 bytes .../libwinapi_onecoreuap_downlevel-apphelp.a | Bin 0 -> 8254 bytes .../libwinapi_onecoreuap_downlevel-comctl32.a | Bin 0 -> 60980 bytes .../libwinapi_onecoreuap_downlevel-comdlg32.a | Bin 0 -> 16894 bytes .../libwinapi_onecoreuap_downlevel-d3d10.a | Bin 0 -> 5160 bytes .../lib/libwinapi_onecoreuap_downlevel-d3d9.a | Bin 0 -> 5842 bytes ...libwinapi_onecoreuap_downlevel-d3dx10_47.a | Bin 0 -> 6206 bytes .../libwinapi_onecoreuap_downlevel-difxapi.a | Bin 0 -> 3486 bytes .../libwinapi_onecoreuap_downlevel-gdi32.a | Bin 0 -> 176572 bytes .../libwinapi_onecoreuap_downlevel-input.a | Bin 0 -> 11110 bytes .../libwinapi_onecoreuap_downlevel-kernel32.a | Bin 0 -> 977524 bytes .../lib/libwinapi_onecoreuap_downlevel-msi.a | Bin 0 -> 34594 bytes .../libwinapi_onecoreuap_downlevel-newdev.a | Bin 0 -> 10390 bytes .../libwinapi_onecoreuap_downlevel-ole32.a | Bin 0 -> 317912 bytes .../libwinapi_onecoreuap_downlevel-oleacc.a | Bin 0 -> 11902 bytes .../libwinapi_onecoreuap_downlevel-oleaut32.a | Bin 0 -> 330966 bytes .../libwinapi_onecoreuap_downlevel-oledlg.a | Bin 0 -> 18022 bytes .../lib/libwinapi_onecoreuap_downlevel-pdh.a | Bin 0 -> 13966 bytes .../libwinapi_onecoreuap_downlevel-psapi.a | Bin 0 -> 23970 bytes .../libwinapi_onecoreuap_downlevel-resutils.a | Bin 0 -> 10416 bytes .../libwinapi_onecoreuap_downlevel-rstrtmgr.a | Bin 0 -> 6568 bytes .../libwinapi_onecoreuap_downlevel-secur32.a | Bin 0 -> 76474 bytes .../libwinapi_onecoreuap_downlevel-setupapi.a | Bin 0 -> 157106 bytes .../libwinapi_onecoreuap_downlevel-shell32.a | Bin 0 -> 136038 bytes .../libwinapi_onecoreuap_downlevel-shlwapi.a | Bin 0 -> 314598 bytes .../lib/libwinapi_onecoreuap_downlevel-tdh.a | Bin 0 -> 11886 bytes .../libwinapi_onecoreuap_downlevel-twinapi.a | Bin 0 -> 2598 bytes .../libwinapi_onecoreuap_downlevel-user32.a | Bin 0 -> 510034 bytes .../libwinapi_onecoreuap_downlevel-uxtheme.a | Bin 0 -> 39186 bytes .../libwinapi_onecoreuap_downlevel-version.a | Bin 0 -> 10006 bytes .../libwinapi_onecoreuap_downlevel-winmm.a | Bin 0 -> 5782 bytes .../libwinapi_onecoreuap_downlevel-winspool.a | Bin 0 -> 34924 bytes .../libwinapi_onecoreuap_downlevel-wtsapi32.a | Bin 0 -> 15252 bytes ...libwinapi_onecoreuap_downlevel-xinput1_4.a | Bin 0 -> 8344 bytes .../lib/libwinapi_onecoreuap_downlevel.a | 36 + .../lib/libwinapi_opengl32.a | Bin 0 -> 284674 bytes .../lib/libwinapi_opmxbox.a | Bin 0 -> 4150 bytes .../lib/libwinapi_p2p.a | Bin 0 -> 92242 bytes .../lib/libwinapi_p2pgraph.a | Bin 0 -> 32634 bytes .../lib/libwinapi_pathcch.a | Bin 0 -> 19314 bytes .../lib/libwinapi_pdh.a | Bin 0 -> 90106 bytes .../lib/libwinapi_peerdist.a | Bin 0 -> 25802 bytes .../lib/libwinapi_powrprof.a | Bin 0 -> 92186 bytes .../lib/libwinapi_prntvpt.a | Bin 0 -> 25926 bytes .../lib/libwinapi_propsys.a | Bin 0 -> 183570 bytes .../lib/libwinapi_psapi.a | Bin 0 -> 23326 bytes .../lib/libwinapi_quartz.a | Bin 0 -> 4804 bytes .../lib/libwinapi_query.a | Bin 0 -> 12166 bytes .../lib/libwinapi_qwave.a | Bin 0 -> 12724 bytes .../lib/libwinapi_rasapi32.a | Bin 0 -> 116618 bytes .../lib/libwinapi_rasdlg.a | Bin 0 -> 20098 bytes .../lib/libwinapi_resutils.a | Bin 0 -> 106678 bytes .../lib/libwinapi_rometadata.a | Bin 0 -> 2534 bytes .../lib/libwinapi_rpcexts.a | Bin 0 -> 45048 bytes .../lib/libwinapi_rpcns4.a | Bin 0 -> 52100 bytes .../lib/libwinapi_rpcproxy.a | Bin 0 -> 4878 bytes .../lib/libwinapi_rpcrt4.a | Bin 0 -> 429744 bytes .../lib/libwinapi_rstrtmgr.a | Bin 0 -> 11006 bytes .../lib/libwinapi_rtm.a | Bin 0 -> 94818 bytes .../lib/libwinapi_rtutils.a | Bin 0 -> 34034 bytes .../lib/libwinapi_rtworkq.a | Bin 0 -> 29630 bytes ...bject-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 11378 bytes ...bject-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 8906 bytes ...ntimeobject-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9630 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3802 bytes ...ct-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2810 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4806 bytes ...ject-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 25170 bytes ...ject-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4446 bytes .../lib/libwinapi_runtimeobject.a | 10 + .../lib/libwinapi_samlib.a | Bin 0 -> 58936 bytes .../lib/libwinapi_samsrv.a | Bin 0 -> 271130 bytes .../lib/libwinapi_sas.a | Bin 0 -> 2414 bytes .../lib/libwinapi_scarddlg.a | Bin 0 -> 5726 bytes .../lib/libwinapi_scecli.a | Bin 0 -> 52152 bytes .../lib/libwinapi_scesrv.a | Bin 0 -> 3328 bytes .../lib/libwinapi_schannel.a | Bin 0 -> 29250 bytes .../lib/libwinapi_secur32.a | Bin 0 -> 77790 bytes .../lib/libwinapi_security.a | Bin 0 -> 31026 bytes .../lib/libwinapi_sens.a | Bin 0 -> 4114 bytes .../lib/libwinapi_sensapi.a | Bin 0 -> 4134 bytes .../lib/libwinapi_sensorsutils.a | Bin 0 -> 51638 bytes .../lib/libwinapi_setupapi.a | Bin 0 -> 465930 bytes .../lib/libwinapi_sfc.a | Bin 0 -> 14312 bytes ...re-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6338 bytes ...re-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2750 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-0.a | Bin 0 -> 4542 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-1.a | Bin 0 -> 7010 bytes ..._shcore-api-ms-win-shcore-scaling-l1-1-2.a | Bin 0 -> 2758 bytes ...re-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4650 bytes .../lib/libwinapi_shcore.a | 8 + .../lib/libwinapi_shdocvw.a | Bin 0 -> 16738 bytes .../lib/libwinapi_shell32.a | Bin 0 -> 330758 bytes .../lib/libwinapi_shfolder.a | Bin 0 -> 3290 bytes .../lib/libwinapi_shlwapi.a | Bin 0 -> 286724 bytes .../lib/libwinapi_slc.a | Bin 0 -> 31662 bytes .../lib/libwinapi_slcext.a | Bin 0 -> 8934 bytes .../lib/libwinapi_slwga.a | Bin 0 -> 2482 bytes .../lib/libwinapi_snmpapi.a | Bin 0 -> 31926 bytes .../lib/libwinapi_spoolss.a | Bin 0 -> 158774 bytes .../lib/libwinapi_sporder.a | Bin 0 -> 3338 bytes .../lib/libwinapi_srpapi.a | Bin 0 -> 19126 bytes .../lib/libwinapi_ssdpapi.a | Bin 0 -> 25002 bytes .../lib/libwinapi_sti.a | Bin 0 -> 4950 bytes .../lib/libwinapi_swdevice.a | Bin 0 -> 8942 bytes .../lib/libwinapi_synchronization.a | Bin 0 -> 4158 bytes .../lib/libwinapi_t2embed.a | Bin 0 -> 12990 bytes .../lib/libwinapi_tapi32.a | Bin 0 -> 221324 bytes .../lib/libwinapi_tbs.a | Bin 0 -> 15318 bytes .../lib/libwinapi_tdh.a | Bin 0 -> 21410 bytes .../lib/libwinapi_tokenbinding.a | Bin 0 -> 8498 bytes .../lib/libwinapi_traffic.a | Bin 0 -> 18858 bytes .../lib/libwinapi_tsec.a | Bin 0 -> 24182 bytes .../lib/libwinapi_txfw32.a | Bin 0 -> 9198 bytes .../lib/libwinapi_ualapi.a | Bin 0 -> 7198 bytes .../lib/libwinapi_uiautomationcore.a | Bin 0 -> 85682 bytes .../lib/libwinapi_umpdddi.a | Bin 0 -> 64584 bytes .../lib/libwinapi_urlmon.a | Bin 0 -> 73398 bytes .../lib/libwinapi_user32.a | Bin 0 -> 608188 bytes .../lib/libwinapi_userenv.a | Bin 0 -> 60542 bytes .../lib/libwinapi_usp10.a | Bin 0 -> 33748 bytes .../lib/libwinapi_uxtheme.a | Bin 0 -> 61866 bytes .../lib/libwinapi_version.a | Bin 0 -> 11270 bytes .../lib/libwinapi_vertdll.a | Bin 0 -> 73598 bytes .../lib/libwinapi_vfw32-avicap32.a | Bin 0 -> 6612 bytes .../lib/libwinapi_vfw32-avifil32.a | Bin 0 -> 60488 bytes .../lib/libwinapi_vfw32-msvfw32.a | Bin 0 -> 38638 bytes .../lib/libwinapi_vfw32.a | 5 + .../lib/libwinapi_virtdisk.a | Bin 0 -> 23722 bytes .../lib/libwinapi_vssapi.a | Bin 0 -> 10990 bytes .../lib/libwinapi_wcmapi.a | Bin 0 -> 31874 bytes .../lib/libwinapi_wdsbp.a | Bin 0 -> 7258 bytes .../lib/libwinapi_wdsclientapi.a | Bin 0 -> 49914 bytes .../lib/libwinapi_wdsmc.a | Bin 0 -> 6792 bytes .../lib/libwinapi_wdspxe.a | Bin 0 -> 26530 bytes .../lib/libwinapi_wdstptc.a | Bin 0 -> 12946 bytes .../lib/libwinapi_webservices.a | Bin 0 -> 155950 bytes .../lib/libwinapi_websocket.a | Bin 0 -> 12470 bytes .../lib/libwinapi_wecapi.a | Bin 0 -> 13926 bytes .../lib/libwinapi_wer.a | Bin 0 -> 40422 bytes .../lib/libwinapi_wevtapi.a | Bin 0 -> 37130 bytes .../lib/libwinapi_wiaservc.a | Bin 0 -> 45134 bytes .../lib/libwinapi_winbio.a | Bin 0 -> 50712 bytes .../lib/libwinapi_windows.data.pdf.a | Bin 0 -> 2562 bytes .../lib/libwinapi_windows.networking.a | Bin 0 -> 2626 bytes .../lib/libwinapi_windows.ui.a | Bin 0 -> 3336 bytes ...wsapp-api-ms-win-appmodel-runtime-l1-1-0.a | Bin 0 -> 6318 bytes ...wsapp-api-ms-win-appmodel-runtime-l1-1-1.a | Bin 0 -> 8030 bytes ...pi_windowsapp-api-ms-win-core-com-l1-1-0.a | Bin 0 -> 33556 bytes ...pi_windowsapp-api-ms-win-core-com-l1-1-1.a | Bin 0 -> 2710 bytes ...pi_windowsapp-api-ms-win-core-com-l2-1-1.a | Bin 0 -> 19206 bytes ...api-ms-win-core-com-midlproxystub-l1-1-0.a | Bin 0 -> 66154 bytes ...i_windowsapp-api-ms-win-core-comm-l1-1-0.a | Bin 0 -> 16380 bytes ...i_windowsapp-api-ms-win-core-comm-l1-1-1.a | Bin 0 -> 2678 bytes ...indowsapp-api-ms-win-core-console-l1-1-0.a | Bin 0 -> 8444 bytes ...indowsapp-api-ms-win-core-console-l2-1-0.a | Bin 0 -> 16302 bytes ...ndowsapp-api-ms-win-core-datetime-l1-1-1.a | Bin 0 -> 3540 bytes ...ndowsapp-api-ms-win-core-datetime-l1-1-2.a | Bin 0 -> 2742 bytes ..._windowsapp-api-ms-win-core-debug-l1-1-0.a | Bin 0 -> 4378 bytes ...dowsapp-api-ms-win-core-delayload-l1-1-0.a | Bin 0 -> 2758 bytes ...dowsapp-api-ms-win-core-delayload-l1-1-1.a | Bin 0 -> 3626 bytes ...indowsapp-api-ms-win-core-enclave-l1-1-0.a | Bin 0 -> 5204 bytes ...app-api-ms-win-core-errorhandling-l1-1-0.a | Bin 0 -> 6066 bytes ...app-api-ms-win-core-errorhandling-l1-1-2.a | Bin 0 -> 2798 bytes ...app-api-ms-win-core-errorhandling-l1-1-3.a | Bin 0 -> 3618 bytes ...pp-api-ms-win-core-featurestaging-l1-1-0.a | Bin 0 -> 6378 bytes ...pp-api-ms-win-core-featurestaging-l1-1-1.a | Bin 0 -> 2774 bytes ...windowsapp-api-ms-win-core-fibers-l1-1-0.a | Bin 0 -> 5026 bytes ...windowsapp-api-ms-win-core-fibers-l1-1-1.a | Bin 0 -> 2706 bytes ...windowsapp-api-ms-win-core-fibers-l2-1-0.a | Bin 0 -> 4334 bytes ...windowsapp-api-ms-win-core-fibers-l2-1-1.a | Bin 0 -> 3550 bytes ...dowsapp-api-ms-win-core-file-ansi-l1-1-0.a | Bin 0 -> 2774 bytes ...dowsapp-api-ms-win-core-file-ansi-l2-1-0.a | Bin 0 -> 3518 bytes ...i_windowsapp-api-ms-win-core-file-l1-1-0.a | Bin 0 -> 45908 bytes ...i_windowsapp-api-ms-win-core-file-l1-2-0.a | Bin 0 -> 3472 bytes ...i_windowsapp-api-ms-win-core-file-l1-2-2.a | Bin 0 -> 4338 bytes ...i_windowsapp-api-ms-win-core-file-l2-1-0.a | Bin 0 -> 6768 bytes ...i_windowsapp-api-ms-win-core-file-l2-1-2.a | Bin 0 -> 2662 bytes ...windowsapp-api-ms-win-core-handle-l1-1-0.a | Bin 0 -> 4346 bytes ...i_windowsapp-api-ms-win-core-heap-l1-1-0.a | Bin 0 -> 9014 bytes ...i_windowsapp-api-ms-win-core-heap-l2-1-0.a | Bin 0 -> 5834 bytes ...app-api-ms-win-core-heap-obsolete-l1-1-0.a | Bin 0 -> 5158 bytes ...wsapp-api-ms-win-core-interlocked-l1-1-0.a | Bin 0 -> 6174 bytes ...wsapp-api-ms-win-core-interlocked-l1-2-0.a | Bin 0 -> 2802 bytes ...api_windowsapp-api-ms-win-core-io-l1-1-0.a | Bin 0 -> 6938 bytes ...api_windowsapp-api-ms-win-core-io-l1-1-1.a | Bin 0 -> 3478 bytes ...-ms-win-core-kernel32-legacy-ansi-l1-1-0.a | Bin 0 -> 2806 bytes ...p-api-ms-win-core-kernel32-legacy-l1-1-0.a | Bin 0 -> 8636 bytes ...sapp-api-ms-win-core-largeinteger-l1-1-0.a | Bin 0 -> 2700 bytes ...app-api-ms-win-core-libraryloader-l1-2-0.a | Bin 0 -> 7814 bytes ...app-api-ms-win-core-libraryloader-l2-1-0.a | Bin 0 -> 3666 bytes ...api-ms-win-core-localization-ansi-l1-1-0.a | Bin 0 -> 3626 bytes ...sapp-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 25692 bytes ...sapp-api-ms-win-core-localization-l1-2-1.a | Bin 0 -> 2770 bytes ...sapp-api-ms-win-core-localization-l1-2-2.a | Bin 0 -> 3632 bytes ...sapp-api-ms-win-core-localization-l2-1-0.a | Bin 0 -> 6964 bytes ...ms-win-core-localization-obsolete-l1-2-0.a | Bin 0 -> 3698 bytes ...windowsapp-api-ms-win-core-memory-l1-1-0.a | Bin 0 -> 5122 bytes ...windowsapp-api-ms-win-core-memory-l1-1-1.a | Bin 0 -> 8618 bytes ...windowsapp-api-ms-win-core-memory-l1-1-2.a | Bin 0 -> 4406 bytes ...windowsapp-api-ms-win-core-memory-l1-1-3.a | Bin 0 -> 5298 bytes ...pp-api-ms-win-core-namedpipe-ansi-l1-1-0.a | Bin 0 -> 4534 bytes ...pp-api-ms-win-core-namedpipe-ansi-l1-1-1.a | Bin 0 -> 2762 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-1-0.a | Bin 0 -> 10286 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-2-1.a | Bin 0 -> 3602 bytes ...dowsapp-api-ms-win-core-namedpipe-l1-2-2.a | Bin 0 -> 2730 bytes ...pp-api-ms-win-core-namespace-ansi-l1-1-0.a | Bin 0 -> 4530 bytes ...dowsapp-api-ms-win-core-namespace-l1-1-0.a | Bin 0 -> 7078 bytes ...app-api-ms-win-core-normalization-l1-1-0.a | Bin 0 -> 6090 bytes ...i_windowsapp-api-ms-win-core-path-l1-1-0.a | Bin 0 -> 20128 bytes ...pi-ms-win-core-processenvironment-l1-1-0.a | Bin 0 -> 16454 bytes ...pp-api-ms-win-core-processthreads-l1-1-0.a | Bin 0 -> 29062 bytes ...pp-api-ms-win-core-processthreads-l1-1-1.a | Bin 0 -> 11382 bytes ...pp-api-ms-win-core-processthreads-l1-1-2.a | Bin 0 -> 3670 bytes ...pp-api-ms-win-core-processthreads-l1-1-3.a | Bin 0 -> 10558 bytes ...win-core-processtopology-obsolete-l1-1-0.a | Bin 0 -> 4602 bytes ...indowsapp-api-ms-win-core-profile-l1-1-0.a | Bin 0 -> 3624 bytes ...owsapp-api-ms-win-core-psapi-ansi-l1-1-0.a | Bin 0 -> 3626 bytes ..._windowsapp-api-ms-win-core-psapi-l1-1-0.a | Bin 0 -> 6122 bytes ...app-api-ms-win-core-psm-appnotify-l1-1-0.a | Bin 0 -> 3786 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-0.a | Bin 0 -> 2778 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-1.a | Bin 0 -> 4510 bytes ...ndowsapp-api-ms-win-core-realtime-l1-1-2.a | Bin 0 -> 4714 bytes ...owsapp-api-ms-win-core-rtlsupport-l1-1-0.a | Bin 0 -> 6054 bytes ..._windowsapp-api-ms-win-core-slapi-l1-1-0.a | Bin 0 -> 3638 bytes ...windowsapp-api-ms-win-core-string-l1-1-0.a | Bin 0 -> 6854 bytes ...owsapp-api-ms-win-core-synch-ansi-l1-1-0.a | Bin 0 -> 6910 bytes ..._windowsapp-api-ms-win-core-synch-l1-1-0.a | Bin 0 -> 35884 bytes ..._windowsapp-api-ms-win-core-synch-l1-2-0.a | Bin 0 -> 13592 bytes ..._windowsapp-api-ms-win-core-synch-l1-2-1.a | Bin 0 -> 4402 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-1-0.a | Bin 0 -> 12714 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-2-0.a | Bin 0 -> 3632 bytes ...indowsapp-api-ms-win-core-sysinfo-l1-2-3.a | Bin 0 -> 2762 bytes ...owsapp-api-ms-win-core-threadpool-l1-2-0.a | Bin 0 -> 33962 bytes ...ndowsapp-api-ms-win-core-timezone-l1-1-0.a | Bin 0 -> 11674 bytes ...pi_windowsapp-api-ms-win-core-url-l1-1-0.a | Bin 0 -> 3544 bytes ...i_windowsapp-api-ms-win-core-util-l1-1-0.a | Bin 0 -> 4238 bytes ...indowsapp-api-ms-win-core-version-l1-1-0.a | Bin 0 -> 4426 bytes ...wsapp-api-ms-win-core-versionansi-l1-1-0.a | Bin 0 -> 4462 bytes ...wsapp-api-ms-win-core-windowsceip-l1-1-0.a | Bin 0 -> 2734 bytes ...ms-win-core-windowserrorreporting-l1-1-0.a | Bin 0 -> 5402 bytes ...ms-win-core-windowserrorreporting-l1-1-1.a | Bin 0 -> 7386 bytes ...ms-win-core-windowserrorreporting-l1-1-2.a | Bin 0 -> 3738 bytes ...wsapp-api-ms-win-core-winrt-error-l1-1-0.a | Bin 0 -> 10412 bytes ...wsapp-api-ms-win-core-winrt-error-l1-1-1.a | Bin 0 -> 3668 bytes ..._windowsapp-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9598 bytes ...pi-ms-win-core-winrt-registration-l1-1-0.a | Bin 0 -> 3778 bytes ...pp-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2790 bytes ...win-core-winrt-roparameterizediid-l1-1-0.a | Bin 0 -> 4778 bytes ...sapp-api-ms-win-core-winrt-string-l1-1-0.a | Bin 0 -> 24200 bytes ..._windowsapp-api-ms-win-core-wow64-l1-1-0.a | Bin 0 -> 2702 bytes ...windowsapp-api-ms-win-core-xstate-l2-1-0.a | Bin 0 -> 5258 bytes ...i-ms-win-eventing-classicprovider-l1-1-0.a | Bin 0 -> 7044 bytes ...sapp-api-ms-win-eventing-consumer-l1-1-0.a | Bin 0 -> 4330 bytes ...pp-api-ms-win-eventing-controller-l1-1-0.a | Bin 0 -> 6030 bytes ...owsapp-api-ms-win-eventing-legacy-l1-1-0.a | Bin 0 -> 5126 bytes ...sapp-api-ms-win-eventing-provider-l1-1-0.a | Bin 0 -> 8528 bytes ...i-ms-win-gaming-deviceinformation-l1-1-0.a | Bin 0 -> 2882 bytes ...i-ms-win-gaming-expandedresources-l1-1-0.a | Bin 0 -> 4630 bytes ...app-api-ms-win-gaming-gamemonitor-l1-1-0.a | Bin 0 -> 4546 bytes ...app-api-ms-win-gaming-gamemonitor-l1-1-1.a | Bin 0 -> 2846 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-0.a | Bin 0 -> 7810 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-1.a | Bin 0 -> 3646 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-2.a | Bin 0 -> 8110 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-3.a | Bin 0 -> 3682 bytes ...windowsapp-api-ms-win-gaming-tcui-l1-1-4.a | Bin 0 -> 8706 bytes ...sapp-api-ms-win-ro-typeresolution-l1-1-0.a | Bin 0 -> 4418 bytes ...ndowsapp-api-ms-win-security-base-l1-1-0.a | Bin 0 -> 45540 bytes ...ndowsapp-api-ms-win-security-base-l1-2-0.a | Bin 0 -> 2758 bytes ...ndowsapp-api-ms-win-security-base-l1-2-1.a | Bin 0 -> 2710 bytes ...app-api-ms-win-security-cryptoapi-l1-1-0.a | Bin 0 -> 23534 bytes ...ms-win-security-isolatedcontainer-l1-1-0.a | Bin 0 -> 2882 bytes ...pi-ms-win-security-lsalookup-ansi-l2-1-0.a | Bin 0 -> 6242 bytes ...app-api-ms-win-security-lsalookup-l2-1-0.a | Bin 0 -> 6194 bytes ...api-ms-win-security-provider-ansi-l1-1-0.a | Bin 0 -> 5390 bytes ...sapp-api-ms-win-security-provider-l1-1-0.a | Bin 0 -> 6976 bytes ...app-api-ms-win-security-sddl-ansi-l1-1-0.a | Bin 0 -> 3658 bytes ...ndowsapp-api-ms-win-security-sddl-l1-1-0.a | Bin 0 -> 5616 bytes ...pp-api-ms-win-shcore-stream-winrt-l1-1-0.a | Bin 0 -> 4682 bytes .../lib/libwinapi_windowsapp-bcrypt.a | Bin 0 -> 30158 bytes .../lib/libwinapi_windowsapp-cabinet.a | Bin 0 -> 14532 bytes .../lib/libwinapi_windowsapp-chakra.a | Bin 0 -> 92114 bytes .../lib/libwinapi_windowsapp-coremessaging.a | Bin 0 -> 2678 bytes .../lib/libwinapi_windowsapp-crypt32.a | Bin 0 -> 115056 bytes .../lib/libwinapi_windowsapp-d2d1.a | Bin 0 -> 12354 bytes .../lib/libwinapi_windowsapp-d3d11.a | Bin 0 -> 5174 bytes .../lib/libwinapi_windowsapp-d3d12.a | Bin 0 -> 7006 bytes .../lib/libwinapi_windowsapp-d3dcompiler_47.a | Bin 0 -> 22190 bytes .../lib/libwinapi_windowsapp-deviceaccess.a | Bin 0 -> 2650 bytes .../lib/libwinapi_windowsapp-dhcpcsvc.a | Bin 0 -> 4182 bytes .../lib/libwinapi_windowsapp-dhcpcsvc6.a | Bin 0 -> 4214 bytes .../lib/libwinapi_windowsapp-dwrite.a | Bin 0 -> 2570 bytes .../lib/libwinapi_windowsapp-dxgi.a | Bin 0 -> 3362 bytes .../lib/libwinapi_windowsapp-esent.a | Bin 0 -> 88346 bytes ...i_windowsapp-ext-ms-win-core-iuri-l1-1-0.a | Bin 0 -> 3504 bytes ...ndowsapp-ext-ms-win-gaming-xinput-l1-1-0.a | Bin 0 -> 7750 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-0.a | Bin 0 -> 3594 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-1.a | Bin 0 -> 8010 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-2.a | Bin 0 -> 3626 bytes ...api_windowsapp-ext-ms-win-uiacore-l1-1-3.a | Bin 0 -> 2706 bytes .../lib/libwinapi_windowsapp-hrtfapo.a | Bin 0 -> 2542 bytes .../lib/libwinapi_windowsapp-inkobjcore.a | Bin 0 -> 23222 bytes .../lib/libwinapi_windowsapp-iphlpapi.a | Bin 0 -> 21954 bytes .../lib/libwinapi_windowsapp-mf.a | Bin 0 -> 14014 bytes .../lib/libwinapi_windowsapp-mfplat.a | Bin 0 -> 48966 bytes .../lib/libwinapi_windowsapp-mfreadwrite.a | Bin 0 -> 6158 bytes .../lib/libwinapi_windowsapp-mfsensorgroup.a | Bin 0 -> 3442 bytes .../lib/libwinapi_windowsapp-mmdevapi.a | Bin 0 -> 2626 bytes .../lib/libwinapi_windowsapp-msajapi.a | Bin 0 -> 492032 bytes .../lib/libwinapi_windowsapp-mswsock.a | Bin 0 -> 4106 bytes .../lib/libwinapi_windowsapp-ncrypt.a | Bin 0 -> 20238 bytes .../lib/libwinapi_windowsapp-ntdll.a | Bin 0 -> 18534 bytes .../lib/libwinapi_windowsapp-oleaut32.a | Bin 0 -> 283012 bytes .../lib/libwinapi_windowsapp-propsys.a | Bin 0 -> 16816 bytes .../lib/libwinapi_windowsapp-rometadata.a | Bin 0 -> 2602 bytes .../lib/libwinapi_windowsapp-rpcrt4.a | Bin 0 -> 224198 bytes .../lib/libwinapi_windowsapp-sspicli.a | Bin 0 -> 19892 bytes .../libwinapi_windowsapp-uiautomationcore.a | Bin 0 -> 4406 bytes .../lib/libwinapi_windowsapp-urlmon.a | Bin 0 -> 3400 bytes .../lib/libwinapi_windowsapp-webservices.a | Bin 0 -> 141508 bytes .../libwinapi_windowsapp-windows.data.pdf.a | Bin 0 -> 2630 bytes .../libwinapi_windowsapp-windows.networking.a | Bin 0 -> 2694 bytes .../lib/libwinapi_windowsapp-windowscodecs.a | Bin 0 -> 9374 bytes .../lib/libwinapi_windowsapp-ws2_32.a | Bin 0 -> 81592 bytes .../lib/libwinapi_windowsapp-xaudio2_9.a | Bin 0 -> 6562 bytes .../lib/libwinapi_windowsapp-xmllite.a | Bin 0 -> 6988 bytes .../lib/libwinapi_windowsapp.a | 182 + .../libwinapi_windowsapp_downlevel-advapi32.a | Bin 0 -> 113940 bytes ...evel-api-ms-win-core-localization-l1-2-0.a | Bin 0 -> 3602 bytes ...p_downlevel-api-ms-win-core-winrt-l1-1-0.a | Bin 0 -> 9738 bytes ...el-api-ms-win-core-winrt-robuffer-l1-1-0.a | Bin 0 -> 2850 bytes .../libwinapi_windowsapp_downlevel-cabinet.a | Bin 0 -> 14742 bytes .../lib/libwinapi_windowsapp_downlevel-d2d1.a | Bin 0 -> 12534 bytes .../libwinapi_windowsapp_downlevel-d3d11.a | Bin 0 -> 5264 bytes ...napi_windowsapp_downlevel-d3dcompiler_47.a | Bin 0 -> 22490 bytes ...winapi_windowsapp_downlevel-deviceaccess.a | Bin 0 -> 2710 bytes .../libwinapi_windowsapp_downlevel-dhcpcsvc.a | Bin 0 -> 4262 bytes ...libwinapi_windowsapp_downlevel-dhcpcsvc6.a | Bin 0 -> 4294 bytes .../libwinapi_windowsapp_downlevel-dwrite.a | Bin 0 -> 2630 bytes .../lib/libwinapi_windowsapp_downlevel-dxgi.a | Bin 0 -> 3432 bytes .../libwinapi_windowsapp_downlevel-esent.a | Bin 0 -> 89476 bytes .../libwinapi_windowsapp_downlevel-kernel32.a | Bin 0 -> 427758 bytes .../lib/libwinapi_windowsapp_downlevel-mf.a | Bin 0 -> 14214 bytes .../libwinapi_windowsapp_downlevel-mfplat.a | Bin 0 -> 49586 bytes ...bwinapi_windowsapp_downlevel-mfreadwrite.a | Bin 0 -> 6258 bytes .../libwinapi_windowsapp_downlevel-mmdevapi.a | Bin 0 -> 2686 bytes .../libwinapi_windowsapp_downlevel-msajapi.a | Bin 0 -> 497542 bytes .../libwinapi_windowsapp_downlevel-mscoree.a | Bin 0 -> 2638 bytes .../libwinapi_windowsapp_downlevel-mswsock.a | Bin 0 -> 4186 bytes .../libwinapi_windowsapp_downlevel-ole32.a | Bin 0 -> 106722 bytes .../libwinapi_windowsapp_downlevel-oleaut32.a | Bin 0 -> 286642 bytes .../libwinapi_windowsapp_downlevel-propsys.a | Bin 0 -> 17046 bytes .../libwinapi_windowsapp_downlevel-rpcrt4.a | Bin 0 -> 226928 bytes ...pi_windowsapp_downlevel-uiautomationcore.a | Bin 0 -> 14966 bytes .../libwinapi_windowsapp_downlevel-urlmon.a | Bin 0 -> 5074 bytes ...bwinapi_windowsapp_downlevel-webservices.a | Bin 0 -> 143288 bytes ...pi_windowsapp_downlevel-windows.data.pdf.a | Bin 0 -> 2690 bytes ..._windowsapp_downlevel-windows.networking.a | Bin 0 -> 2754 bytes ...inapi_windowsapp_downlevel-windowscodecs.a | Bin 0 -> 9514 bytes .../libwinapi_windowsapp_downlevel-ws2_32.a | Bin 0 -> 82662 bytes ...libwinapi_windowsapp_downlevel-xaudio2_8.a | Bin 0 -> 6672 bytes ...libwinapi_windowsapp_downlevel-xinput1_4.a | Bin 0 -> 7586 bytes .../libwinapi_windowsapp_downlevel-xmllite.a | Bin 0 -> 7098 bytes .../lib/libwinapi_windowsapp_downlevel.a | 38 + .../lib/libwinapi_windowscodecs.a | Bin 0 -> 105016 bytes .../lib/libwinapi_winfax.a | Bin 0 -> 46364 bytes .../lib/libwinapi_winhttp.a | Bin 0 -> 53986 bytes .../lib/libwinapi_wininet.a | Bin 0 -> 260434 bytes .../lib/libwinapi_winmm.a | Bin 0 -> 140700 bytes .../lib/libwinapi_winscard.a | Bin 0 -> 58330 bytes .../lib/libwinapi_winspool.a | Bin 0 -> 166614 bytes .../lib/libwinapi_winsqlite3.a | Bin 0 -> 192422 bytes .../lib/libwinapi_winsta.a | Bin 0 -> 141860 bytes .../lib/libwinapi_wintrust.a | Bin 0 -> 112526 bytes .../lib/libwinapi_winusb.a | Bin 0 -> 32218 bytes .../lib/libwinapi_wlanapi.a | Bin 0 -> 54228 bytes .../lib/libwinapi_wlanui.a | Bin 0 -> 4046 bytes .../lib/libwinapi_wldap32.a | Bin 0 -> 194972 bytes .../lib/libwinapi_wmip.a | Bin 0 -> 37418 bytes .../lib/libwinapi_wmvcore.a | Bin 0 -> 12150 bytes .../lib/libwinapi_wnvapi.a | Bin 0 -> 3252 bytes .../lib/libwinapi_wofutil.a | Bin 0 -> 10470 bytes .../lib/libwinapi_ws2_32.a | Bin 0 -> 155138 bytes .../lib/libwinapi_wscapi.a | Bin 0 -> 32066 bytes .../lib/libwinapi_wsclient.a | Bin 0 -> 25750 bytes .../lib/libwinapi_wsdapi.a | Bin 0 -> 33498 bytes .../lib/libwinapi_wsmsvc.a | Bin 0 -> 120038 bytes .../lib/libwinapi_wsnmp32.a | Bin 0 -> 41340 bytes .../lib/libwinapi_wsock32.a | Bin 0 -> 58416 bytes .../lib/libwinapi_wtsapi32.a | Bin 0 -> 54714 bytes .../lib/libwinapi_xaudio2.a | Bin 0 -> 7236 bytes .../lib/libwinapi_xaudio2_8.a | Bin 0 -> 6446 bytes .../lib/libwinapi_xinput.a | Bin 0 -> 8032 bytes .../lib/libwinapi_xinput9_1_0.a | Bin 0 -> 5722 bytes .../lib/libwinapi_xinputuap.a | Bin 0 -> 8080 bytes .../lib/libwinapi_xmllite.a | Bin 0 -> 6874 bytes .../lib/libwinapi_xolehlp.a | Bin 0 -> 5894 bytes .../lib/libwinapi_xpsdocumenttargetprint.a | Bin 0 -> 2546 bytes .../lib/libwinapi_xpsprint.a | Bin 0 -> 3294 bytes .../winapi-x86_64-pc-windows-gnu/src/lib.rs | 7 + anneal/v2/vendor/winapi/.cargo-checksum.json | 1 + anneal/v2/vendor/winapi/.cargo_vcs_info.json | 5 + anneal/v2/vendor/winapi/Cargo.toml | 434 + anneal/v2/vendor/winapi/Cargo.toml.orig | 431 + anneal/v2/vendor/winapi/LICENSE-APACHE | 201 + anneal/v2/vendor/winapi/LICENSE-MIT | 19 + anneal/v2/vendor/winapi/README.md | 90 + anneal/v2/vendor/winapi/build.rs | 527 + anneal/v2/vendor/winapi/src/km/d3dkmthk.rs | 312 + anneal/v2/vendor/winapi/src/km/mod.rs | 7 + anneal/v2/vendor/winapi/src/lib.rs | 71 + anneal/v2/vendor/winapi/src/macros.rs | 440 + anneal/v2/vendor/winapi/src/shared/basetsd.rs | 70 + anneal/v2/vendor/winapi/src/shared/bcrypt.rs | 1001 + anneal/v2/vendor/winapi/src/shared/bthdef.rs | 1103 + .../v2/vendor/winapi/src/shared/bthioctl.rs | 151 + .../v2/vendor/winapi/src/shared/bthsdpdef.rs | 68 + .../v2/vendor/winapi/src/shared/bugcodes.rs | 456 + anneal/v2/vendor/winapi/src/shared/cderr.rs | 44 + anneal/v2/vendor/winapi/src/shared/cfg.rs | 138 + anneal/v2/vendor/winapi/src/shared/d3d9.rs | 1268 + .../v2/vendor/winapi/src/shared/d3d9caps.rs | 366 + .../v2/vendor/winapi/src/shared/d3d9types.rs | 1487 + anneal/v2/vendor/winapi/src/shared/d3dkmdt.rs | 45 + .../v2/vendor/winapi/src/shared/d3dukmdt.rs | 413 + .../v2/vendor/winapi/src/shared/dcomptypes.rs | 50 + anneal/v2/vendor/winapi/src/shared/devguid.rs | 178 + anneal/v2/vendor/winapi/src/shared/devpkey.rs | 401 + .../v2/vendor/winapi/src/shared/devpropdef.rs | 83 + anneal/v2/vendor/winapi/src/shared/dinputd.rs | 21 + anneal/v2/vendor/winapi/src/shared/dxgi.rs | 411 + anneal/v2/vendor/winapi/src/shared/dxgi1_2.rs | 355 + anneal/v2/vendor/winapi/src/shared/dxgi1_3.rs | 190 + anneal/v2/vendor/winapi/src/shared/dxgi1_4.rs | 112 + anneal/v2/vendor/winapi/src/shared/dxgi1_5.rs | 92 + anneal/v2/vendor/winapi/src/shared/dxgi1_6.rs | 98 + .../v2/vendor/winapi/src/shared/dxgiformat.rs | 127 + .../v2/vendor/winapi/src/shared/dxgitype.rs | 109 + .../v2/vendor/winapi/src/shared/evntprov.rs | 309 + .../v2/vendor/winapi/src/shared/evntrace.rs | 990 + anneal/v2/vendor/winapi/src/shared/guiddef.rs | 36 + .../v2/vendor/winapi/src/shared/hidclass.rs | 68 + anneal/v2/vendor/winapi/src/shared/hidpi.rs | 393 + anneal/v2/vendor/winapi/src/shared/hidsdi.rs | 110 + .../v2/vendor/winapi/src/shared/hidusage.rs | 274 + anneal/v2/vendor/winapi/src/shared/ifdef.rs | 208 + anneal/v2/vendor/winapi/src/shared/ifmib.rs | 53 + anneal/v2/vendor/winapi/src/shared/in6addr.rs | 18 + anneal/v2/vendor/winapi/src/shared/inaddr.rs | 29 + anneal/v2/vendor/winapi/src/shared/intsafe.rs | 5 + .../v2/vendor/winapi/src/shared/ipifcons.rs | 244 + anneal/v2/vendor/winapi/src/shared/ipmib.rs | 381 + .../v2/vendor/winapi/src/shared/iprtrmib.rs | 125 + anneal/v2/vendor/winapi/src/shared/ks.rs | 63 + anneal/v2/vendor/winapi/src/shared/ksmedia.rs | 110 + .../v2/vendor/winapi/src/shared/ktmtypes.rs | 138 + anneal/v2/vendor/winapi/src/shared/lmcons.rs | 60 + .../v2/vendor/winapi/src/shared/minwindef.rs | 102 + anneal/v2/vendor/winapi/src/shared/mmreg.rs | 309 + anneal/v2/vendor/winapi/src/shared/mod.rs | 92 + .../v2/vendor/winapi/src/shared/mprapidef.rs | 14 + anneal/v2/vendor/winapi/src/shared/mstcpip.rs | 492 + .../v2/vendor/winapi/src/shared/mswsockdef.rs | 48 + .../v2/vendor/winapi/src/shared/netioapi.rs | 702 + anneal/v2/vendor/winapi/src/shared/nldef.rs | 204 + .../v2/vendor/winapi/src/shared/ntddndis.rs | 75 + .../v2/vendor/winapi/src/shared/ntddscsi.rs | 834 + anneal/v2/vendor/winapi/src/shared/ntddser.rs | 17 + anneal/v2/vendor/winapi/src/shared/ntdef.rs | 1083 + .../v2/vendor/winapi/src/shared/ntstatus.rs | 2574 ++ anneal/v2/vendor/winapi/src/shared/qos.rs | 20 + anneal/v2/vendor/winapi/src/shared/rpc.rs | 9 + anneal/v2/vendor/winapi/src/shared/rpcdce.rs | 563 + anneal/v2/vendor/winapi/src/shared/rpcndr.rs | 25 + anneal/v2/vendor/winapi/src/shared/sddl.rs | 217 + anneal/v2/vendor/winapi/src/shared/sspi.rs | 1074 + .../v2/vendor/winapi/src/shared/stralign.rs | 40 + .../v2/vendor/winapi/src/shared/tcpestats.rs | 211 + anneal/v2/vendor/winapi/src/shared/tcpmib.rs | 244 + .../src/shared/transportsettingcommon.rs | 10 + anneal/v2/vendor/winapi/src/shared/tvout.rs | 72 + anneal/v2/vendor/winapi/src/shared/udpmib.rs | 130 + anneal/v2/vendor/winapi/src/shared/usb.rs | 523 + .../v2/vendor/winapi/src/shared/usbioctl.rs | 705 + .../v2/vendor/winapi/src/shared/usbiodef.rs | 120 + anneal/v2/vendor/winapi/src/shared/usbscan.rs | 21 + anneal/v2/vendor/winapi/src/shared/usbspec.rs | 860 + anneal/v2/vendor/winapi/src/shared/windef.rs | 125 + .../v2/vendor/winapi/src/shared/windot11.rs | 2853 ++ .../v2/vendor/winapi/src/shared/windowsx.rs | 17 + .../v2/vendor/winapi/src/shared/winerror.rs | 6150 +++++ .../v2/vendor/winapi/src/shared/winusbio.rs | 38 + .../v2/vendor/winapi/src/shared/wlantypes.rs | 78 + anneal/v2/vendor/winapi/src/shared/wmistr.rs | 199 + anneal/v2/vendor/winapi/src/shared/wnnc.rs | 77 + anneal/v2/vendor/winapi/src/shared/ws2def.rs | 556 + .../v2/vendor/winapi/src/shared/ws2ipdef.rs | 112 + anneal/v2/vendor/winapi/src/shared/wtypes.rs | 344 + .../v2/vendor/winapi/src/shared/wtypesbase.rs | 161 + anneal/v2/vendor/winapi/src/ucrt/corecrt.rs | 11 + anneal/v2/vendor/winapi/src/ucrt/mod.rs | 7 + anneal/v2/vendor/winapi/src/um/accctrl.rs | 371 + anneal/v2/vendor/winapi/src/um/aclapi.rs | 362 + anneal/v2/vendor/winapi/src/um/adhoc.rs | 220 + anneal/v2/vendor/winapi/src/um/appmgmt.rs | 122 + anneal/v2/vendor/winapi/src/um/audioclient.rs | 172 + .../vendor/winapi/src/um/audiosessiontypes.rs | 37 + anneal/v2/vendor/winapi/src/um/avrt.rs | 82 + anneal/v2/vendor/winapi/src/um/bits.rs | 295 + anneal/v2/vendor/winapi/src/um/bits10_1.rs | 37 + anneal/v2/vendor/winapi/src/um/bits1_5.rs | 70 + anneal/v2/vendor/winapi/src/um/bits2_0.rs | 51 + anneal/v2/vendor/winapi/src/um/bits2_5.rs | 64 + anneal/v2/vendor/winapi/src/um/bits3_0.rs | 179 + anneal/v2/vendor/winapi/src/um/bits4_0.rs | 32 + anneal/v2/vendor/winapi/src/um/bits5_0.rs | 95 + anneal/v2/vendor/winapi/src/um/bitscfg.rs | 70 + anneal/v2/vendor/winapi/src/um/bitsmsg.rs | 142 + .../v2/vendor/winapi/src/um/bluetoothapis.rs | 414 + .../vendor/winapi/src/um/bluetoothleapis.rs | 104 + anneal/v2/vendor/winapi/src/um/bthledef.rs | 280 + anneal/v2/vendor/winapi/src/um/cfgmgr32.rs | 2077 ++ anneal/v2/vendor/winapi/src/um/cguid.rs | 134 + anneal/v2/vendor/winapi/src/um/combaseapi.rs | 477 + anneal/v2/vendor/winapi/src/um/coml2api.rs | 10 + anneal/v2/vendor/winapi/src/um/commapi.rs | 87 + anneal/v2/vendor/winapi/src/um/commctrl.rs | 4135 +++ anneal/v2/vendor/winapi/src/um/commdlg.rs | 712 + .../v2/vendor/winapi/src/um/commoncontrols.rs | 232 + anneal/v2/vendor/winapi/src/um/consoleapi.rs | 91 + anneal/v2/vendor/winapi/src/um/corsym.rs | 89 + anneal/v2/vendor/winapi/src/um/d2d1.rs | 982 + anneal/v2/vendor/winapi/src/um/d2d1_1.rs | 847 + anneal/v2/vendor/winapi/src/um/d2d1_2.rs | 68 + anneal/v2/vendor/winapi/src/um/d2d1_3.rs | 698 + .../vendor/winapi/src/um/d2d1effectauthor.rs | 516 + anneal/v2/vendor/winapi/src/um/d2d1effects.rs | 617 + .../v2/vendor/winapi/src/um/d2d1effects_1.rs | 31 + .../v2/vendor/winapi/src/um/d2d1effects_2.rs | 40 + anneal/v2/vendor/winapi/src/um/d2d1svg.rs | 411 + .../v2/vendor/winapi/src/um/d2dbasetypes.rs | 15 + anneal/v2/vendor/winapi/src/um/d3d.rs | 61 + anneal/v2/vendor/winapi/src/um/d3d10.rs | 57 + anneal/v2/vendor/winapi/src/um/d3d10_1.rs | 11 + .../v2/vendor/winapi/src/um/d3d10_1shader.rs | 7 + anneal/v2/vendor/winapi/src/um/d3d10effect.rs | 45 + anneal/v2/vendor/winapi/src/um/d3d10misc.rs | 7 + .../v2/vendor/winapi/src/um/d3d10sdklayers.rs | 13 + anneal/v2/vendor/winapi/src/um/d3d10shader.rs | 206 + anneal/v2/vendor/winapi/src/um/d3d11.rs | 3421 +++ anneal/v2/vendor/winapi/src/um/d3d11_1.rs | 484 + anneal/v2/vendor/winapi/src/um/d3d11_2.rs | 146 + anneal/v2/vendor/winapi/src/um/d3d11_3.rs | 23 + anneal/v2/vendor/winapi/src/um/d3d11_4.rs | 7 + anneal/v2/vendor/winapi/src/um/d3d11on12.rs | 67 + .../v2/vendor/winapi/src/um/d3d11sdklayers.rs | 2679 ++ anneal/v2/vendor/winapi/src/um/d3d11shader.rs | 477 + .../src/um/d3d11tokenizedprogramformat.rs | 1335 + anneal/v2/vendor/winapi/src/um/d3d12.rs | 2722 ++ .../v2/vendor/winapi/src/um/d3d12sdklayers.rs | 1364 + anneal/v2/vendor/winapi/src/um/d3d12shader.rs | 347 + anneal/v2/vendor/winapi/src/um/d3dcommon.rs | 744 + anneal/v2/vendor/winapi/src/um/d3dcompiler.rs | 274 + anneal/v2/vendor/winapi/src/um/d3dcsx.rs | 11 + anneal/v2/vendor/winapi/src/um/d3dx10core.rs | 11 + anneal/v2/vendor/winapi/src/um/d3dx10math.rs | 7 + anneal/v2/vendor/winapi/src/um/d3dx10mesh.rs | 19 + anneal/v2/vendor/winapi/src/um/datetimeapi.rs | 60 + anneal/v2/vendor/winapi/src/um/davclnt.rs | 104 + anneal/v2/vendor/winapi/src/um/dbghelp.rs | 750 + anneal/v2/vendor/winapi/src/um/dbt.rs | 192 + anneal/v2/vendor/winapi/src/um/dcommon.rs | 114 + anneal/v2/vendor/winapi/src/um/dcomp.rs | 1159 + .../v2/vendor/winapi/src/um/dcompanimation.rs | 38 + anneal/v2/vendor/winapi/src/um/dde.rs | 20 + anneal/v2/vendor/winapi/src/um/ddraw.rs | 37 + anneal/v2/vendor/winapi/src/um/ddrawi.rs | 13 + anneal/v2/vendor/winapi/src/um/ddrawint.rs | 41 + anneal/v2/vendor/winapi/src/um/debugapi.rs | 41 + .../v2/vendor/winapi/src/um/devicetopology.rs | 462 + anneal/v2/vendor/winapi/src/um/dinput.rs | 107 + anneal/v2/vendor/winapi/src/um/dispex.rs | 221 + anneal/v2/vendor/winapi/src/um/dmksctl.rs | 11 + anneal/v2/vendor/winapi/src/um/dmusicc.rs | 71 + anneal/v2/vendor/winapi/src/um/docobj.rs | 136 + .../v2/vendor/winapi/src/um/documenttarget.rs | 24 + anneal/v2/vendor/winapi/src/um/dot1x.rs | 151 + anneal/v2/vendor/winapi/src/um/dpa_dsa.rs | 283 + anneal/v2/vendor/winapi/src/um/dpapi.rs | 100 + anneal/v2/vendor/winapi/src/um/dsgetdc.rs | 267 + anneal/v2/vendor/winapi/src/um/dsound.rs | 342 + anneal/v2/vendor/winapi/src/um/dsrole.rs | 66 + anneal/v2/vendor/winapi/src/um/dvp.rs | 25 + anneal/v2/vendor/winapi/src/um/dwmapi.rs | 295 + anneal/v2/vendor/winapi/src/um/dwrite.rs | 1477 + anneal/v2/vendor/winapi/src/um/dwrite_1.rs | 746 + anneal/v2/vendor/winapi/src/um/dwrite_2.rs | 293 + anneal/v2/vendor/winapi/src/um/dwrite_3.rs | 578 + anneal/v2/vendor/winapi/src/um/dxdiag.rs | 11 + anneal/v2/vendor/winapi/src/um/dxfile.rs | 23 + anneal/v2/vendor/winapi/src/um/dxgidebug.rs | 235 + anneal/v2/vendor/winapi/src/um/dxva2api.rs | 706 + anneal/v2/vendor/winapi/src/um/dxvahd.rs | 555 + anneal/v2/vendor/winapi/src/um/eaptypes.rs | 403 + anneal/v2/vendor/winapi/src/um/enclaveapi.rs | 64 + .../v2/vendor/winapi/src/um/endpointvolume.rs | 123 + .../v2/vendor/winapi/src/um/errhandlingapi.rs | 75 + anneal/v2/vendor/winapi/src/um/evntcons.rs | 229 + anneal/v2/vendor/winapi/src/um/exdisp.rs | 220 + anneal/v2/vendor/winapi/src/um/fibersapi.rs | 23 + anneal/v2/vendor/winapi/src/um/fileapi.rs | 639 + .../src/um/functiondiscoverykeys_devpkey.rs | 117 + anneal/v2/vendor/winapi/src/um/gl/gl.rs | 52 + anneal/v2/vendor/winapi/src/um/gl/mod.rs | 7 + anneal/v2/vendor/winapi/src/um/handleapi.rs | 36 + anneal/v2/vendor/winapi/src/um/heapapi.rs | 92 + .../um/highlevelmonitorconfigurationapi.rs | 171 + anneal/v2/vendor/winapi/src/um/http.rs | 1096 + anneal/v2/vendor/winapi/src/um/imm.rs | 42 + .../v2/vendor/winapi/src/um/interlockedapi.rs | 31 + anneal/v2/vendor/winapi/src/um/ioapiset.rs | 71 + anneal/v2/vendor/winapi/src/um/ipexport.rs | 174 + anneal/v2/vendor/winapi/src/um/iphlpapi.rs | 521 + anneal/v2/vendor/winapi/src/um/iptypes.rs | 372 + anneal/v2/vendor/winapi/src/um/jobapi.rs | 14 + anneal/v2/vendor/winapi/src/um/jobapi2.rs | 63 + .../v2/vendor/winapi/src/um/knownfolders.rs | 287 + anneal/v2/vendor/winapi/src/um/ktmw32.rs | 63 + anneal/v2/vendor/winapi/src/um/l2cmn.rs | 55 + .../v2/vendor/winapi/src/um/libloaderapi.rs | 236 + anneal/v2/vendor/winapi/src/um/lmaccess.rs | 1215 + anneal/v2/vendor/winapi/src/um/lmalert.rs | 75 + anneal/v2/vendor/winapi/src/um/lmapibuf.rs | 30 + anneal/v2/vendor/winapi/src/um/lmat.rs | 62 + anneal/v2/vendor/winapi/src/um/lmdfs.rs | 483 + anneal/v2/vendor/winapi/src/um/lmerrlog.rs | 268 + anneal/v2/vendor/winapi/src/um/lmjoin.rs | 232 + anneal/v2/vendor/winapi/src/um/lmmsg.rs | 56 + anneal/v2/vendor/winapi/src/um/lmremutl.rs | 61 + anneal/v2/vendor/winapi/src/um/lmrepl.rs | 200 + anneal/v2/vendor/winapi/src/um/lmserver.rs | 1255 + anneal/v2/vendor/winapi/src/um/lmshare.rs | 379 + anneal/v2/vendor/winapi/src/um/lmstats.rs | 85 + anneal/v2/vendor/winapi/src/um/lmsvc.rs | 180 + anneal/v2/vendor/winapi/src/um/lmuse.rs | 101 + anneal/v2/vendor/winapi/src/um/lmwksta.rs | 421 + .../src/um/lowlevelmonitorconfigurationapi.rs | 49 + anneal/v2/vendor/winapi/src/um/lsalookup.rs | 109 + anneal/v2/vendor/winapi/src/um/memoryapi.rs | 390 + anneal/v2/vendor/winapi/src/um/minschannel.rs | 58 + anneal/v2/vendor/winapi/src/um/minwinbase.rs | 337 + anneal/v2/vendor/winapi/src/um/mmdeviceapi.rs | 220 + anneal/v2/vendor/winapi/src/um/mmeapi.rs | 336 + anneal/v2/vendor/winapi/src/um/mmsystem.rs | 266 + anneal/v2/vendor/winapi/src/um/mod.rs | 302 + anneal/v2/vendor/winapi/src/um/msaatext.rs | 59 + anneal/v2/vendor/winapi/src/um/mscat.rs | 36 + anneal/v2/vendor/winapi/src/um/mschapp.rs | 48 + anneal/v2/vendor/winapi/src/um/mssip.rs | 255 + anneal/v2/vendor/winapi/src/um/mswsock.rs | 413 + .../v2/vendor/winapi/src/um/namedpipeapi.rs | 93 + .../v2/vendor/winapi/src/um/namespaceapi.rs | 36 + anneal/v2/vendor/winapi/src/um/nb30.rs | 214 + anneal/v2/vendor/winapi/src/um/ncrypt.rs | 88 + anneal/v2/vendor/winapi/src/um/ntlsa.rs | 1530 ++ anneal/v2/vendor/winapi/src/um/ntsecapi.rs | 1728 ++ anneal/v2/vendor/winapi/src/um/oaidl.rs | 915 + anneal/v2/vendor/winapi/src/um/objbase.rs | 64 + anneal/v2/vendor/winapi/src/um/objidl.rs | 525 + anneal/v2/vendor/winapi/src/um/objidlbase.rs | 952 + anneal/v2/vendor/winapi/src/um/ocidl.rs | 68 + anneal/v2/vendor/winapi/src/um/ole2.rs | 21 + anneal/v2/vendor/winapi/src/um/oleauto.rs | 849 + anneal/v2/vendor/winapi/src/um/olectl.rs | 14 + anneal/v2/vendor/winapi/src/um/oleidl.rs | 43 + anneal/v2/vendor/winapi/src/um/opmapi.rs | 362 + anneal/v2/vendor/winapi/src/um/pdh.rs | 806 + anneal/v2/vendor/winapi/src/um/perflib.rs | 331 + .../src/um/physicalmonitorenumerationapi.rs | 43 + .../v2/vendor/winapi/src/um/playsoundapi.rs | 46 + .../v2/vendor/winapi/src/um/portabledevice.rs | 163 + .../vendor/winapi/src/um/portabledeviceapi.rs | 288 + .../winapi/src/um/portabledevicetypes.rs | 255 + anneal/v2/vendor/winapi/src/um/powerbase.rs | 35 + .../v2/vendor/winapi/src/um/powersetting.rs | 60 + anneal/v2/vendor/winapi/src/um/powrprof.rs | 550 + anneal/v2/vendor/winapi/src/um/processenv.rs | 98 + .../vendor/winapi/src/um/processsnapshot.rs | 120 + .../vendor/winapi/src/um/processthreadsapi.rs | 441 + .../winapi/src/um/processtopologyapi.rs | 23 + anneal/v2/vendor/winapi/src/um/profileapi.rs | 15 + anneal/v2/vendor/winapi/src/um/propidl.rs | 392 + anneal/v2/vendor/winapi/src/um/propkey.rs | 2300 ++ anneal/v2/vendor/winapi/src/um/propkeydef.rs | 13 + anneal/v2/vendor/winapi/src/um/propsys.rs | 46 + anneal/v2/vendor/winapi/src/um/prsht.rs | 361 + anneal/v2/vendor/winapi/src/um/psapi.rs | 422 + .../v2/vendor/winapi/src/um/realtimeapiset.rs | 30 + anneal/v2/vendor/winapi/src/um/reason.rs | 60 + .../v2/vendor/winapi/src/um/restartmanager.rs | 150 + .../winapi/src/um/restrictederrorinfo.rs | 20 + anneal/v2/vendor/winapi/src/um/rmxfguid.rs | 67 + anneal/v2/vendor/winapi/src/um/rtinfo.rs | 7 + anneal/v2/vendor/winapi/src/um/sapi.rs | 1388 + anneal/v2/vendor/winapi/src/um/sapi51.rs | 3726 +++ anneal/v2/vendor/winapi/src/um/sapi53.rs | 1823 ++ anneal/v2/vendor/winapi/src/um/sapiddk.rs | 238 + anneal/v2/vendor/winapi/src/um/sapiddk51.rs | 651 + anneal/v2/vendor/winapi/src/um/schannel.rs | 339 + .../winapi/src/um/securityappcontainer.rs | 16 + .../vendor/winapi/src/um/securitybaseapi.rs | 690 + anneal/v2/vendor/winapi/src/um/servprov.rs | 23 + anneal/v2/vendor/winapi/src/um/setupapi.rs | 3571 +++ anneal/v2/vendor/winapi/src/um/shellapi.rs | 923 + .../vendor/winapi/src/um/shellscalingapi.rs | 44 + anneal/v2/vendor/winapi/src/um/shlobj.rs | 260 + anneal/v2/vendor/winapi/src/um/shobjidl.rs | 329 + .../v2/vendor/winapi/src/um/shobjidl_core.rs | 576 + anneal/v2/vendor/winapi/src/um/shtypes.rs | 44 + anneal/v2/vendor/winapi/src/um/softpub.rs | 3 + anneal/v2/vendor/winapi/src/um/spapidef.rs | 53 + anneal/v2/vendor/winapi/src/um/spellcheck.rs | 146 + anneal/v2/vendor/winapi/src/um/sporder.rs | 41 + anneal/v2/vendor/winapi/src/um/sql.rs | 108 + anneal/v2/vendor/winapi/src/um/sqlext.rs | 95 + anneal/v2/vendor/winapi/src/um/sqltypes.rs | 142 + anneal/v2/vendor/winapi/src/um/sqlucode.rs | 106 + anneal/v2/vendor/winapi/src/um/sspi.rs | 7 + .../v2/vendor/winapi/src/um/stringapiset.rs | 75 + anneal/v2/vendor/winapi/src/um/strmif.rs | 7 + anneal/v2/vendor/winapi/src/um/subauth.rs | 204 + anneal/v2/vendor/winapi/src/um/synchapi.rs | 349 + anneal/v2/vendor/winapi/src/um/sysinfoapi.rs | 217 + .../vendor/winapi/src/um/systemtopologyapi.rs | 20 + anneal/v2/vendor/winapi/src/um/taskschd.rs | 1233 + anneal/v2/vendor/winapi/src/um/textstor.rs | 11 + .../vendor/winapi/src/um/threadpoolapiset.rs | 171 + .../winapi/src/um/threadpoollegacyapiset.rs | 44 + anneal/v2/vendor/winapi/src/um/timeapi.rs | 20 + anneal/v2/vendor/winapi/src/um/timezoneapi.rs | 89 + anneal/v2/vendor/winapi/src/um/tlhelp32.rs | 194 + anneal/v2/vendor/winapi/src/um/unknwnbase.rs | 43 + anneal/v2/vendor/winapi/src/um/urlhist.rs | 97 + anneal/v2/vendor/winapi/src/um/urlmon.rs | 21 + anneal/v2/vendor/winapi/src/um/userenv.rs | 159 + anneal/v2/vendor/winapi/src/um/usp10.rs | 560 + anneal/v2/vendor/winapi/src/um/utilapiset.rs | 25 + anneal/v2/vendor/winapi/src/um/uxtheme.rs | 772 + anneal/v2/vendor/winapi/src/um/vsbackup.rs | 520 + anneal/v2/vendor/winapi/src/um/vss.rs | 284 + anneal/v2/vendor/winapi/src/um/vsserror.rs | 89 + anneal/v2/vendor/winapi/src/um/vswriter.rs | 397 + anneal/v2/vendor/winapi/src/um/wbemads.rs | 41 + anneal/v2/vendor/winapi/src/um/wbemcli.rs | 1174 + anneal/v2/vendor/winapi/src/um/wbemdisp.rs | 1344 + anneal/v2/vendor/winapi/src/um/wbemprov.rs | 302 + anneal/v2/vendor/winapi/src/um/wbemtran.rs | 184 + anneal/v2/vendor/winapi/src/um/wct.rs | 114 + anneal/v2/vendor/winapi/src/um/werapi.rs | 64 + anneal/v2/vendor/winapi/src/um/winbase.rs | 2854 ++ anneal/v2/vendor/winapi/src/um/wincodec.rs | 1861 ++ anneal/v2/vendor/winapi/src/um/wincodecsdk.rs | 564 + anneal/v2/vendor/winapi/src/um/wincon.rs | 459 + anneal/v2/vendor/winapi/src/um/wincontypes.rs | 114 + anneal/v2/vendor/winapi/src/um/wincred.rs | 532 + anneal/v2/vendor/winapi/src/um/wincrypt.rs | 7365 +++++ anneal/v2/vendor/winapi/src/um/windowsceip.rs | 9 + anneal/v2/vendor/winapi/src/um/winefs.rs | 178 + anneal/v2/vendor/winapi/src/um/winevt.rs | 543 + anneal/v2/vendor/winapi/src/um/wingdi.rs | 5591 ++++ anneal/v2/vendor/winapi/src/um/winhttp.rs | 658 + anneal/v2/vendor/winapi/src/um/wininet.rs | 2364 ++ anneal/v2/vendor/winapi/src/um/winineti.rs | 142 + anneal/v2/vendor/winapi/src/um/winioctl.rs | 1091 + anneal/v2/vendor/winapi/src/um/winnetwk.rs | 446 + anneal/v2/vendor/winapi/src/um/winnls.rs | 817 + anneal/v2/vendor/winapi/src/um/winnt.rs | 8648 ++++++ anneal/v2/vendor/winapi/src/um/winreg.rs | 684 + anneal/v2/vendor/winapi/src/um/winsafer.rs | 228 + anneal/v2/vendor/winapi/src/um/winscard.rs | 709 + anneal/v2/vendor/winapi/src/um/winsmcrd.rs | 166 + anneal/v2/vendor/winapi/src/um/winsock2.rs | 1450 + anneal/v2/vendor/winapi/src/um/winspool.rs | 2433 ++ anneal/v2/vendor/winapi/src/um/winsvc.rs | 695 + anneal/v2/vendor/winapi/src/um/wintrust.rs | 123 + anneal/v2/vendor/winapi/src/um/winusb.rs | 224 + anneal/v2/vendor/winapi/src/um/winuser.rs | 7251 +++++ anneal/v2/vendor/winapi/src/um/winver.rs | 53 + anneal/v2/vendor/winapi/src/um/wlanapi.rs | 1459 + anneal/v2/vendor/winapi/src/um/wlanihv.rs | 410 + .../v2/vendor/winapi/src/um/wlanihvtypes.rs | 41 + anneal/v2/vendor/winapi/src/um/wlclient.rs | 33 + anneal/v2/vendor/winapi/src/um/wow64apiset.rs | 32 + .../vendor/winapi/src/um/wpdmtpextensions.rs | 60 + anneal/v2/vendor/winapi/src/um/ws2bth.rs | 211 + anneal/v2/vendor/winapi/src/um/ws2spi.rs | 909 + anneal/v2/vendor/winapi/src/um/ws2tcpip.rs | 346 + anneal/v2/vendor/winapi/src/um/wtsapi32.rs | 6 + anneal/v2/vendor/winapi/src/um/xinput.rs | 173 + anneal/v2/vendor/winapi/src/vc/excpt.rs | 18 + anneal/v2/vendor/winapi/src/vc/limits.rs | 7 + anneal/v2/vendor/winapi/src/vc/mod.rs | 10 + anneal/v2/vendor/winapi/src/vc/vadefs.rs | 8 + anneal/v2/vendor/winapi/src/vc/vcruntime.rs | 9 + .../v2/vendor/winapi/src/winrt/activation.rs | 13 + anneal/v2/vendor/winapi/src/winrt/hstring.rs | 25 + .../v2/vendor/winapi/src/winrt/inspectable.rs | 29 + anneal/v2/vendor/winapi/src/winrt/mod.rs | 12 + anneal/v2/vendor/winapi/src/winrt/roapi.rs | 60 + anneal/v2/vendor/winapi/src/winrt/robuffer.rs | 12 + .../v2/vendor/winapi/src/winrt/roerrorapi.rs | 103 + .../v2/vendor/winapi/src/winrt/winstring.rs | 150 + 4818 files changed, 628911 insertions(+), 5 deletions(-) create mode 100644 anneal/v2/vendor/addr2line/.cargo-checksum.json create mode 100644 anneal/v2/vendor/addr2line/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/addr2line/CHANGELOG.md create mode 100644 anneal/v2/vendor/addr2line/Cargo.lock create mode 100644 anneal/v2/vendor/addr2line/Cargo.toml create mode 100644 anneal/v2/vendor/addr2line/Cargo.toml.orig create mode 100644 anneal/v2/vendor/addr2line/LICENSE-APACHE create mode 100644 anneal/v2/vendor/addr2line/LICENSE-MIT create mode 100644 anneal/v2/vendor/addr2line/README.md create mode 100644 anneal/v2/vendor/addr2line/src/bin/addr2line.rs create mode 100644 anneal/v2/vendor/addr2line/src/frame.rs create mode 100644 anneal/v2/vendor/addr2line/src/function.rs create mode 100644 anneal/v2/vendor/addr2line/src/lib.rs create mode 100644 anneal/v2/vendor/addr2line/src/line.rs create mode 100644 anneal/v2/vendor/addr2line/src/loader.rs create mode 100644 anneal/v2/vendor/addr2line/src/lookup.rs create mode 100644 anneal/v2/vendor/addr2line/src/unit.rs create mode 100644 anneal/v2/vendor/backtrace-ext/.cargo-checksum.json create mode 100644 anneal/v2/vendor/backtrace-ext/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/backtrace-ext/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/backtrace-ext/Cargo.lock create mode 100644 anneal/v2/vendor/backtrace-ext/Cargo.toml create mode 100644 anneal/v2/vendor/backtrace-ext/Cargo.toml.orig create mode 100644 anneal/v2/vendor/backtrace-ext/README.md create mode 100644 anneal/v2/vendor/backtrace-ext/examples/miette.rs create mode 100644 anneal/v2/vendor/backtrace-ext/src/lib.rs create mode 100644 anneal/v2/vendor/backtrace-ext/src/test.rs create mode 100644 anneal/v2/vendor/backtrace/.cargo-checksum.json create mode 100644 anneal/v2/vendor/backtrace/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/backtrace/.github/workflows/main.yml create mode 100644 anneal/v2/vendor/backtrace/.github/workflows/publish.yml create mode 100644 anneal/v2/vendor/backtrace/CHANGELOG.md create mode 100644 anneal/v2/vendor/backtrace/Cargo.lock create mode 100644 anneal/v2/vendor/backtrace/Cargo.toml create mode 100644 anneal/v2/vendor/backtrace/Cargo.toml.orig create mode 100644 anneal/v2/vendor/backtrace/LICENSE-APACHE create mode 100644 anneal/v2/vendor/backtrace/LICENSE-MIT create mode 100644 anneal/v2/vendor/backtrace/README.md create mode 100644 anneal/v2/vendor/backtrace/benches/benchmarks.rs create mode 100644 anneal/v2/vendor/backtrace/bindings.txt create mode 100644 anneal/v2/vendor/backtrace/examples/backtrace.rs create mode 100644 anneal/v2/vendor/backtrace/examples/raw.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/libunwind.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/miri.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/mod.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/noop.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/win32.rs create mode 100644 anneal/v2/vendor/backtrace/src/backtrace/win64.rs create mode 100644 anneal/v2/vendor/backtrace/src/capture.rs create mode 100644 anneal/v2/vendor/backtrace/src/dbghelp.rs create mode 100644 anneal/v2/vendor/backtrace/src/lib.rs create mode 100644 anneal/v2/vendor/backtrace/src/print.rs create mode 100644 anneal/v2/vendor/backtrace/src/print/fuchsia.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/dbghelp.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/coff.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/elf.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_aix.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_macos.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_windows.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/lru.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/macho.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/stash.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/gimli/xcoff.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/miri.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/mod.rs create mode 100644 anneal/v2/vendor/backtrace/src/symbolize/noop.rs create mode 100644 anneal/v2/vendor/backtrace/src/types.rs create mode 100644 anneal/v2/vendor/backtrace/src/windows_sys.rs create mode 100644 anneal/v2/vendor/backtrace/src/windows_sys_arm32_shim.rs create mode 100644 anneal/v2/vendor/backtrace/tests/accuracy/auxiliary.rs create mode 100644 anneal/v2/vendor/backtrace/tests/accuracy/main.rs create mode 100644 anneal/v2/vendor/backtrace/tests/common/mod.rs create mode 100644 anneal/v2/vendor/backtrace/tests/concurrent-panics.rs create mode 100644 anneal/v2/vendor/backtrace/tests/current-exe-mismatch.rs create mode 100644 anneal/v2/vendor/backtrace/tests/long_fn_name.rs create mode 100644 anneal/v2/vendor/backtrace/tests/sgx-image-base.rs create mode 100644 anneal/v2/vendor/backtrace/tests/skip_inner_frames.rs create mode 100644 anneal/v2/vendor/backtrace/tests/smoke.rs create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/.cargo-checksum.json create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/CHANGELOG.md create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml.orig create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/LICENSE-APACHE create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/LICENSE-MIT create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/README.md create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/src/lib.rs create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/src/sealed.rs create mode 100644 anneal/v2/vendor/block-buffer-0.10.4/tests/mod.rs create mode 100644 anneal/v2/vendor/bumpalo/.cargo-checksum.json create mode 100644 anneal/v2/vendor/bumpalo/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/bumpalo/CHANGELOG.md create mode 100644 anneal/v2/vendor/bumpalo/Cargo.lock create mode 100644 anneal/v2/vendor/bumpalo/Cargo.toml create mode 100644 anneal/v2/vendor/bumpalo/Cargo.toml.orig create mode 100644 anneal/v2/vendor/bumpalo/LICENSE-APACHE create mode 100644 anneal/v2/vendor/bumpalo/LICENSE-MIT create mode 100644 anneal/v2/vendor/bumpalo/README.md create mode 100644 anneal/v2/vendor/bumpalo/rustfmt.toml create mode 100644 anneal/v2/vendor/bumpalo/src/alloc.rs create mode 100644 anneal/v2/vendor/bumpalo/src/boxed.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/collect_in.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/mod.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/raw_vec.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/str/lossy.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/str/mod.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/string.rs create mode 100644 anneal/v2/vendor/bumpalo/src/collections/vec.rs create mode 100644 anneal/v2/vendor/bumpalo/src/lib.rs create mode 100644 anneal/v2/vendor/camino/.cargo-checksum.json create mode 100644 anneal/v2/vendor/camino/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/camino/.claude/settings.json create mode 100644 anneal/v2/vendor/camino/CHANGELOG.md create mode 100644 anneal/v2/vendor/camino/Cargo.lock create mode 100644 anneal/v2/vendor/camino/Cargo.lock.rust161 create mode 100644 anneal/v2/vendor/camino/Cargo.toml create mode 100644 anneal/v2/vendor/camino/Cargo.toml.orig create mode 100644 anneal/v2/vendor/camino/LICENSE-APACHE create mode 100644 anneal/v2/vendor/camino/LICENSE-MIT create mode 100644 anneal/v2/vendor/camino/README.md create mode 100644 anneal/v2/vendor/camino/build.rs create mode 100644 anneal/v2/vendor/camino/clippy.toml create mode 100644 anneal/v2/vendor/camino/release.toml create mode 100644 anneal/v2/vendor/camino/rustfmt.toml create mode 100644 anneal/v2/vendor/camino/src/lib.rs create mode 100644 anneal/v2/vendor/camino/src/proptest_impls.rs create mode 100644 anneal/v2/vendor/camino/src/serde_impls.rs create mode 100644 anneal/v2/vendor/camino/src/tests.rs create mode 100644 anneal/v2/vendor/camino/tests/integration_tests.rs create mode 100644 anneal/v2/vendor/cargo-platform/.cargo-checksum.json create mode 100644 anneal/v2/vendor/cargo-platform/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/cargo-platform/Cargo.lock create mode 100644 anneal/v2/vendor/cargo-platform/Cargo.toml create mode 100644 anneal/v2/vendor/cargo-platform/Cargo.toml.orig create mode 100644 anneal/v2/vendor/cargo-platform/LICENSE-APACHE create mode 100644 anneal/v2/vendor/cargo-platform/LICENSE-MIT create mode 100644 anneal/v2/vendor/cargo-platform/README.md create mode 100644 anneal/v2/vendor/cargo-platform/examples/matches.rs create mode 100644 anneal/v2/vendor/cargo-platform/src/cfg.rs create mode 100644 anneal/v2/vendor/cargo-platform/src/error.rs create mode 100644 anneal/v2/vendor/cargo-platform/src/lib.rs create mode 100644 anneal/v2/vendor/cargo-platform/tests/test_cfg.rs create mode 100644 anneal/v2/vendor/cargo_metadata/.cargo-checksum.json create mode 100644 anneal/v2/vendor/cargo_metadata/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/cargo_metadata/.github/workflows/main.yml create mode 100644 anneal/v2/vendor/cargo_metadata/.github/workflows/release.yml create mode 100644 anneal/v2/vendor/cargo_metadata/CHANGELOG.md create mode 100644 anneal/v2/vendor/cargo_metadata/Cargo.lock create mode 100644 anneal/v2/vendor/cargo_metadata/Cargo.toml create mode 100644 anneal/v2/vendor/cargo_metadata/Cargo.toml.orig create mode 100644 anneal/v2/vendor/cargo_metadata/LICENSE-MIT create mode 100644 anneal/v2/vendor/cargo_metadata/README.md create mode 100644 anneal/v2/vendor/cargo_metadata/clippy.toml create mode 100644 anneal/v2/vendor/cargo_metadata/src/dependency.rs create mode 100644 anneal/v2/vendor/cargo_metadata/src/diagnostic.rs create mode 100644 anneal/v2/vendor/cargo_metadata/src/errors.rs create mode 100644 anneal/v2/vendor/cargo_metadata/src/lib.rs create mode 100644 anneal/v2/vendor/cargo_metadata/src/libtest.rs create mode 100644 anneal/v2/vendor/cargo_metadata/src/messages.rs create mode 100644 anneal/v2/vendor/cargo_metadata/tests/selftest.rs create mode 100644 anneal/v2/vendor/cargo_metadata/tests/test_samples.rs create mode 100644 anneal/v2/vendor/clap-cargo/.cargo-checksum.json create mode 100644 anneal/v2/vendor/clap-cargo/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/clap-cargo/Cargo.lock create mode 100644 anneal/v2/vendor/clap-cargo/Cargo.toml create mode 100644 anneal/v2/vendor/clap-cargo/Cargo.toml.orig create mode 100644 anneal/v2/vendor/clap-cargo/LICENSE-APACHE create mode 100644 anneal/v2/vendor/clap-cargo/LICENSE-MIT create mode 100644 anneal/v2/vendor/clap-cargo/README.md create mode 100644 anneal/v2/vendor/clap-cargo/examples/flags.rs create mode 100644 anneal/v2/vendor/clap-cargo/src/features.rs create mode 100644 anneal/v2/vendor/clap-cargo/src/lib.rs create mode 100644 anneal/v2/vendor/clap-cargo/src/manifest.rs create mode 100644 anneal/v2/vendor/clap-cargo/src/style.rs create mode 100644 anneal/v2/vendor/clap-cargo/src/workspace.rs create mode 100644 anneal/v2/vendor/console/.cargo-checksum.json create mode 100644 anneal/v2/vendor/console/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/console/CHANGELOG.md create mode 100644 anneal/v2/vendor/console/Cargo.lock create mode 100644 anneal/v2/vendor/console/Cargo.toml create mode 100644 anneal/v2/vendor/console/Cargo.toml.orig create mode 100644 anneal/v2/vendor/console/LICENSE create mode 100644 anneal/v2/vendor/console/README.md create mode 100644 anneal/v2/vendor/console/src/ansi.rs create mode 100644 anneal/v2/vendor/console/src/common_term.rs create mode 100644 anneal/v2/vendor/console/src/kb.rs create mode 100644 anneal/v2/vendor/console/src/lib.rs create mode 100644 anneal/v2/vendor/console/src/term.rs create mode 100644 anneal/v2/vendor/console/src/unix_term.rs create mode 100644 anneal/v2/vendor/console/src/utils.rs create mode 100644 anneal/v2/vendor/console/src/wasm_term.rs create mode 100644 anneal/v2/vendor/console/src/windows_term/colors.rs create mode 100644 anneal/v2/vendor/console/src/windows_term/mod.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/.cargo-checksum.json create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/CHANGELOG.md create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/Cargo.lock create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml.orig create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-APACHE create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-MIT create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/README.md create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/src/aarch64.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/src/lib.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/src/loongarch64.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/src/miri.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/src/x86.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/tests/aarch64.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/tests/loongarch64.rs create mode 100644 anneal/v2/vendor/cpufeatures-0.2.17/tests/x86.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/.cargo-checksum.json create mode 100644 anneal/v2/vendor/crossbeam-deque/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/crossbeam-deque/CHANGELOG.md create mode 100644 anneal/v2/vendor/crossbeam-deque/Cargo.toml create mode 100644 anneal/v2/vendor/crossbeam-deque/Cargo.toml.orig create mode 100644 anneal/v2/vendor/crossbeam-deque/LICENSE-APACHE create mode 100644 anneal/v2/vendor/crossbeam-deque/LICENSE-MIT create mode 100644 anneal/v2/vendor/crossbeam-deque/README.md create mode 100644 anneal/v2/vendor/crossbeam-deque/src/deque.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/src/lib.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/tests/fifo.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/tests/injector.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/tests/lifo.rs create mode 100644 anneal/v2/vendor/crossbeam-deque/tests/steal.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/.cargo-checksum.json create mode 100644 anneal/v2/vendor/crossbeam-epoch/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/crossbeam-epoch/CHANGELOG.md create mode 100644 anneal/v2/vendor/crossbeam-epoch/Cargo.lock create mode 100644 anneal/v2/vendor/crossbeam-epoch/Cargo.toml create mode 100644 anneal/v2/vendor/crossbeam-epoch/Cargo.toml.orig create mode 100644 anneal/v2/vendor/crossbeam-epoch/LICENSE-APACHE create mode 100644 anneal/v2/vendor/crossbeam-epoch/LICENSE-MIT create mode 100644 anneal/v2/vendor/crossbeam-epoch/README.md create mode 100644 anneal/v2/vendor/crossbeam-epoch/benches/defer.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/benches/flush.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/benches/pin.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/examples/sanitize.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/atomic.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/collector.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/default.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/deferred.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/epoch.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/guard.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/internal.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/lib.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/sync/list.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/sync/mod.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/sync/once_lock.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/src/sync/queue.rs create mode 100644 anneal/v2/vendor/crossbeam-epoch/tests/loom.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/.cargo-checksum.json create mode 100644 anneal/v2/vendor/crossbeam-utils/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/crossbeam-utils/CHANGELOG.md create mode 100644 anneal/v2/vendor/crossbeam-utils/Cargo.toml create mode 100644 anneal/v2/vendor/crossbeam-utils/Cargo.toml.orig create mode 100644 anneal/v2/vendor/crossbeam-utils/LICENSE-APACHE create mode 100644 anneal/v2/vendor/crossbeam-utils/LICENSE-MIT create mode 100644 anneal/v2/vendor/crossbeam-utils/README.md create mode 100644 anneal/v2/vendor/crossbeam-utils/benches/atomic_cell.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/build-common.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/build.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/no_atomic.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/atomic/atomic_cell.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/atomic/consume.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/atomic/mod.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock_wide.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/backoff.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/cache_padded.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/lib.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/sync/mod.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/sync/once_lock.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/sync/parker.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/sync/sharded_lock.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/sync/wait_group.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/src/thread.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/atomic_cell.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/cache_padded.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/parker.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/sharded_lock.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/thread.rs create mode 100644 anneal/v2/vendor/crossbeam-utils/tests/wait_group.rs create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/.cargo-checksum.json create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/CHANGELOG.md create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/Cargo.lock create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml.orig create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/LICENSE-APACHE create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/LICENSE-MIT create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/README.md create mode 100644 anneal/v2/vendor/crypto-common-0.1.7/src/lib.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/.cargo-checksum.json create mode 100644 anneal/v2/vendor/digest-0.10.7/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/digest-0.10.7/CHANGELOG.md create mode 100644 anneal/v2/vendor/digest-0.10.7/Cargo.toml create mode 100644 anneal/v2/vendor/digest-0.10.7/Cargo.toml.orig create mode 100644 anneal/v2/vendor/digest-0.10.7/LICENSE-APACHE create mode 100644 anneal/v2/vendor/digest-0.10.7/LICENSE-MIT create mode 100644 anneal/v2/vendor/digest-0.10.7/README.md create mode 100644 anneal/v2/vendor/digest-0.10.7/src/core_api.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/core_api/ct_variable.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/core_api/rt_variable.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/core_api/wrapper.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/core_api/xof_reader.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev/fixed.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev/mac.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev/rng.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev/variable.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/dev/xof.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/digest.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/lib.rs create mode 100644 anneal/v2/vendor/digest-0.10.7/src/mac.rs create mode 100644 anneal/v2/vendor/either/.cargo-checksum.json create mode 100644 anneal/v2/vendor/either/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/either/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/either/Cargo.lock create mode 100644 anneal/v2/vendor/either/Cargo.toml create mode 100644 anneal/v2/vendor/either/Cargo.toml.orig create mode 100644 anneal/v2/vendor/either/LICENSE-APACHE create mode 100644 anneal/v2/vendor/either/LICENSE-MIT create mode 100644 anneal/v2/vendor/either/README-crates.io.md create mode 100644 anneal/v2/vendor/either/README.rst create mode 100644 anneal/v2/vendor/either/src/into_either.rs create mode 100644 anneal/v2/vendor/either/src/iterator.rs create mode 100644 anneal/v2/vendor/either/src/lib.rs create mode 100644 anneal/v2/vendor/either/src/serde_untagged.rs create mode 100644 anneal/v2/vendor/either/src/serde_untagged_optional.rs create mode 100644 anneal/v2/vendor/encode_unicode/.cargo-checksum.json create mode 100644 anneal/v2/vendor/encode_unicode/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/encode_unicode/.cirrus.yml create mode 100644 anneal/v2/vendor/encode_unicode/AUTHORS.md create mode 100644 anneal/v2/vendor/encode_unicode/Cargo.lock create mode 100644 anneal/v2/vendor/encode_unicode/Cargo.toml create mode 100644 anneal/v2/vendor/encode_unicode/Cargo.toml.orig create mode 100644 anneal/v2/vendor/encode_unicode/LICENSE-APACHE create mode 100644 anneal/v2/vendor/encode_unicode/LICENSE-MIT create mode 100644 anneal/v2/vendor/encode_unicode/README.md create mode 100644 anneal/v2/vendor/encode_unicode/RELEASES.md create mode 100644 anneal/v2/vendor/encode_unicode/benches/length.rs create mode 100644 anneal/v2/vendor/encode_unicode/benches/multiiterators.rs create mode 100755 anneal/v2/vendor/encode_unicode/do.sh create mode 100644 anneal/v2/vendor/encode_unicode/examples/length_distribution.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/decoding_iterators.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/errors.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/lib.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/traits.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/utf16_char.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/utf16_iterators.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/utf8_char.rs create mode 100644 anneal/v2/vendor/encode_unicode/src/utf8_iterators.rs create mode 100644 anneal/v2/vendor/encode_unicode/tests/errs.rs create mode 100644 anneal/v2/vendor/encode_unicode/tests/exhaustive.rs create mode 100644 anneal/v2/vendor/encode_unicode/tests/iterators.rs create mode 100644 anneal/v2/vendor/encode_unicode/tests/oks.rs create mode 100644 anneal/v2/vendor/fs2/.appveyor.yml create mode 100644 anneal/v2/vendor/fs2/.cargo-checksum.json create mode 100644 anneal/v2/vendor/fs2/.travis.yml create mode 100644 anneal/v2/vendor/fs2/Cargo.toml create mode 100644 anneal/v2/vendor/fs2/Cargo.toml.orig create mode 100644 anneal/v2/vendor/fs2/LICENSE-APACHE create mode 100644 anneal/v2/vendor/fs2/LICENSE-MIT create mode 100644 anneal/v2/vendor/fs2/README.md create mode 100644 anneal/v2/vendor/fs2/src/lib.rs create mode 100644 anneal/v2/vendor/fs2/src/unix.rs create mode 100644 anneal/v2/vendor/fs2/src/windows.rs create mode 100644 anneal/v2/vendor/futures-core/.cargo-checksum.json create mode 100644 anneal/v2/vendor/futures-core/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/futures-core/Cargo.lock create mode 100644 anneal/v2/vendor/futures-core/Cargo.toml create mode 100644 anneal/v2/vendor/futures-core/Cargo.toml.orig create mode 100644 anneal/v2/vendor/futures-core/LICENSE-APACHE create mode 100644 anneal/v2/vendor/futures-core/LICENSE-MIT create mode 100644 anneal/v2/vendor/futures-core/README.md create mode 100644 anneal/v2/vendor/futures-core/src/future.rs create mode 100644 anneal/v2/vendor/futures-core/src/lib.rs create mode 100644 anneal/v2/vendor/futures-core/src/stream.rs create mode 100644 anneal/v2/vendor/futures-core/src/task/__internal/atomic_waker.rs create mode 100644 anneal/v2/vendor/futures-core/src/task/__internal/mod.rs create mode 100644 anneal/v2/vendor/futures-core/src/task/mod.rs create mode 100644 anneal/v2/vendor/futures-core/src/task/poll.rs create mode 100644 anneal/v2/vendor/futures-task/.cargo-checksum.json create mode 100644 anneal/v2/vendor/futures-task/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/futures-task/Cargo.lock create mode 100644 anneal/v2/vendor/futures-task/Cargo.toml create mode 100644 anneal/v2/vendor/futures-task/Cargo.toml.orig create mode 100644 anneal/v2/vendor/futures-task/LICENSE-APACHE create mode 100644 anneal/v2/vendor/futures-task/LICENSE-MIT create mode 100644 anneal/v2/vendor/futures-task/README.md create mode 100644 anneal/v2/vendor/futures-task/src/arc_wake.rs create mode 100644 anneal/v2/vendor/futures-task/src/future_obj.rs create mode 100644 anneal/v2/vendor/futures-task/src/lib.rs create mode 100644 anneal/v2/vendor/futures-task/src/noop_waker.rs create mode 100644 anneal/v2/vendor/futures-task/src/spawn.rs create mode 100644 anneal/v2/vendor/futures-task/src/waker.rs create mode 100644 anneal/v2/vendor/futures-task/src/waker_ref.rs create mode 100644 anneal/v2/vendor/futures-util/.cargo-checksum.json create mode 100644 anneal/v2/vendor/futures-util/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/futures-util/Cargo.lock create mode 100644 anneal/v2/vendor/futures-util/Cargo.toml create mode 100644 anneal/v2/vendor/futures-util/Cargo.toml.orig create mode 100644 anneal/v2/vendor/futures-util/LICENSE-APACHE create mode 100644 anneal/v2/vendor/futures-util/LICENSE-MIT create mode 100644 anneal/v2/vendor/futures-util/README.md create mode 100644 anneal/v2/vendor/futures-util/benches/bilock.rs create mode 100644 anneal/v2/vendor/futures-util/benches/flatten_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/benches/futures_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/benches/select.rs create mode 100644 anneal/v2/vendor/futures-util/src/abortable.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/join_mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/pending.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/poll.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/random.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/select_mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/async_await/stream_select_mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/compat/compat01as03.rs create mode 100644 anneal/v2/vendor/futures-util/src/compat/compat03as01.rs create mode 100644 anneal/v2/vendor/futures-util/src/compat/executor.rs create mode 100644 anneal/v2/vendor/futures-util/src/compat/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/fns.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/abortable.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/always_ready.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/either.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/catch_unwind.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/flatten.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/fuse.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/map.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/remote_handle.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/future/shared.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/join.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/join_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/lazy.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/maybe_done.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/option.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/pending.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/poll_fn.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/poll_immediate.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/ready.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/select.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/select_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/select_ok.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_future/into_future.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_future/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_future/try_flatten.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_future/try_flatten_err.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_join.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_join_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_maybe_done.rs create mode 100644 anneal/v2/vendor/futures-util/src/future/try_select.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/allow_std.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/buf_reader.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/buf_writer.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/chain.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/close.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/copy.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/copy_buf.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/copy_buf_abortable.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/cursor.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/empty.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/fill_buf.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/flush.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/into_sink.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/line_writer.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/lines.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_exact.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_line.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_to_end.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_to_string.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_until.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/read_vectored.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/repeat.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/seek.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/sink.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/split.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/take.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/window.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/write.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/write_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/write_all_vectored.rs create mode 100644 anneal/v2/vendor/futures-util/src/io/write_vectored.rs create mode 100644 anneal/v2/vendor/futures-util/src/lib.rs create mode 100644 anneal/v2/vendor/futures-util/src/lock/bilock.rs create mode 100644 anneal/v2/vendor/futures-util/src/lock/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/lock/mutex.rs create mode 100644 anneal/v2/vendor/futures-util/src/macros.rs create mode 100644 anneal/v2/vendor/futures-util/src/never.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/buffer.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/close.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/drain.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/err_into.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/fanout.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/feed.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/flush.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/map_err.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/send.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/send_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/unfold.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/with.rs create mode 100644 anneal/v2/vendor/futures-util/src/sink/with_flat_map.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/abortable.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/empty.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_ordered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_unordered/abort.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_unordered/iter.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_unordered/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/futures_unordered/task.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/iter.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/once.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/pending.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/poll_fn.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/poll_immediate.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/repeat.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/repeat_with.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/select.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/select_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/select_with_strategy.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/all.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/any.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/buffer_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/buffered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/catch_unwind.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/chain.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/chunks.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/collect.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/concat.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/count.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/cycle.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/enumerate.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/filter.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/filter_map.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/flatten.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/flatten_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/fold.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/for_each.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/for_each_concurrent.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/forward.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/fuse.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/into_future.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/map.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/next.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/peek.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/ready_chunks.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/scan.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/select_next_some.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/skip.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/skip_while.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/split.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/take.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/take_until.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/take_while.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/then.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/unzip.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/stream/zip.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/and_then.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/into_async_read.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/into_stream.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/or_else.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_all.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_any.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffer_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_chunks.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_collect.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_concat.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter_map.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten_unordered.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_fold.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each_concurrent.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_next.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_ready_chunks.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_skip_while.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_take_while.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/try_stream/try_unfold.rs create mode 100644 anneal/v2/vendor/futures-util/src/stream/unfold.rs create mode 100644 anneal/v2/vendor/futures-util/src/task/mod.rs create mode 100644 anneal/v2/vendor/futures-util/src/task/spawn.rs create mode 100644 anneal/v2/vendor/futures-util/src/unfold_state.rs create mode 100644 anneal/v2/vendor/generic-array/.cargo-checksum.json create mode 100644 anneal/v2/vendor/generic-array/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/generic-array/CHANGELOG.md create mode 100644 anneal/v2/vendor/generic-array/Cargo.toml create mode 100644 anneal/v2/vendor/generic-array/Cargo.toml.orig create mode 100644 anneal/v2/vendor/generic-array/LICENSE create mode 100644 anneal/v2/vendor/generic-array/README.md create mode 100644 anneal/v2/vendor/generic-array/build.rs create mode 100644 anneal/v2/vendor/generic-array/src/arr.rs create mode 100644 anneal/v2/vendor/generic-array/src/functional.rs create mode 100644 anneal/v2/vendor/generic-array/src/hex.rs create mode 100644 anneal/v2/vendor/generic-array/src/impl_serde.rs create mode 100644 anneal/v2/vendor/generic-array/src/impl_zeroize.rs create mode 100644 anneal/v2/vendor/generic-array/src/impls.rs create mode 100644 anneal/v2/vendor/generic-array/src/iter.rs create mode 100644 anneal/v2/vendor/generic-array/src/lib.rs create mode 100644 anneal/v2/vendor/generic-array/src/sequence.rs create mode 100644 anneal/v2/vendor/gimli/.cargo-checksum.json create mode 100644 anneal/v2/vendor/gimli/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/gimli/CHANGELOG.md create mode 100644 anneal/v2/vendor/gimli/Cargo.lock create mode 100644 anneal/v2/vendor/gimli/Cargo.toml create mode 100644 anneal/v2/vendor/gimli/Cargo.toml.orig create mode 100644 anneal/v2/vendor/gimli/LICENSE-APACHE create mode 100644 anneal/v2/vendor/gimli/LICENSE-MIT create mode 100644 anneal/v2/vendor/gimli/README.md create mode 100644 anneal/v2/vendor/gimli/src/arch.rs create mode 100644 anneal/v2/vendor/gimli/src/common.rs create mode 100644 anneal/v2/vendor/gimli/src/constants.rs create mode 100644 anneal/v2/vendor/gimli/src/endianity.rs create mode 100644 anneal/v2/vendor/gimli/src/leb128.rs create mode 100644 anneal/v2/vendor/gimli/src/lib.rs create mode 100644 anneal/v2/vendor/gimli/src/read/abbrev.rs create mode 100644 anneal/v2/vendor/gimli/src/read/addr.rs create mode 100644 anneal/v2/vendor/gimli/src/read/aranges.rs create mode 100644 anneal/v2/vendor/gimli/src/read/cfi.rs create mode 100644 anneal/v2/vendor/gimli/src/read/dwarf.rs create mode 100644 anneal/v2/vendor/gimli/src/read/endian_reader.rs create mode 100644 anneal/v2/vendor/gimli/src/read/endian_slice.rs create mode 100644 anneal/v2/vendor/gimli/src/read/index.rs create mode 100644 anneal/v2/vendor/gimli/src/read/line.rs create mode 100644 anneal/v2/vendor/gimli/src/read/lists.rs create mode 100644 anneal/v2/vendor/gimli/src/read/loclists.rs create mode 100644 anneal/v2/vendor/gimli/src/read/lookup.rs create mode 100644 anneal/v2/vendor/gimli/src/read/macros.rs create mode 100644 anneal/v2/vendor/gimli/src/read/mod.rs create mode 100644 anneal/v2/vendor/gimli/src/read/op.rs create mode 100644 anneal/v2/vendor/gimli/src/read/pubnames.rs create mode 100644 anneal/v2/vendor/gimli/src/read/pubtypes.rs create mode 100644 anneal/v2/vendor/gimli/src/read/reader.rs create mode 100644 anneal/v2/vendor/gimli/src/read/relocate.rs create mode 100644 anneal/v2/vendor/gimli/src/read/rnglists.rs create mode 100644 anneal/v2/vendor/gimli/src/read/str.rs create mode 100644 anneal/v2/vendor/gimli/src/read/unit.rs create mode 100644 anneal/v2/vendor/gimli/src/read/util.rs create mode 100644 anneal/v2/vendor/gimli/src/read/value.rs create mode 100644 anneal/v2/vendor/gimli/src/test_util.rs create mode 100644 anneal/v2/vendor/gimli/src/write/abbrev.rs create mode 100644 anneal/v2/vendor/gimli/src/write/cfi.rs create mode 100644 anneal/v2/vendor/gimli/src/write/dwarf.rs create mode 100644 anneal/v2/vendor/gimli/src/write/endian_vec.rs create mode 100644 anneal/v2/vendor/gimli/src/write/line.rs create mode 100644 anneal/v2/vendor/gimli/src/write/loc.rs create mode 100644 anneal/v2/vendor/gimli/src/write/mod.rs create mode 100644 anneal/v2/vendor/gimli/src/write/op.rs create mode 100644 anneal/v2/vendor/gimli/src/write/range.rs create mode 100644 anneal/v2/vendor/gimli/src/write/relocate.rs create mode 100644 anneal/v2/vendor/gimli/src/write/section.rs create mode 100644 anneal/v2/vendor/gimli/src/write/str.rs create mode 100644 anneal/v2/vendor/gimli/src/write/unit.rs create mode 100644 anneal/v2/vendor/gimli/src/write/writer.rs create mode 100644 anneal/v2/vendor/indicatif/.cargo-checksum.json create mode 100644 anneal/v2/vendor/indicatif/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/indicatif/.github/dependabot.yml create mode 100644 anneal/v2/vendor/indicatif/.github/workflows/rust.yml create mode 100644 anneal/v2/vendor/indicatif/Cargo.lock create mode 100644 anneal/v2/vendor/indicatif/Cargo.toml create mode 100644 anneal/v2/vendor/indicatif/Cargo.toml.orig create mode 100644 anneal/v2/vendor/indicatif/LICENSE create mode 100644 anneal/v2/vendor/indicatif/README.md create mode 100644 anneal/v2/vendor/indicatif/deny.toml create mode 100644 anneal/v2/vendor/indicatif/examples/cargo.rs create mode 100644 anneal/v2/vendor/indicatif/examples/cargowrap.rs create mode 100644 anneal/v2/vendor/indicatif/examples/download-continued.rs create mode 100644 anneal/v2/vendor/indicatif/examples/download-speed.rs create mode 100644 anneal/v2/vendor/indicatif/examples/download.rs create mode 100644 anneal/v2/vendor/indicatif/examples/fastbar.rs create mode 100644 anneal/v2/vendor/indicatif/examples/finebars.rs create mode 100644 anneal/v2/vendor/indicatif/examples/iterator.rs create mode 100644 anneal/v2/vendor/indicatif/examples/log.rs create mode 100644 anneal/v2/vendor/indicatif/examples/long-spinner.rs create mode 100644 anneal/v2/vendor/indicatif/examples/message.rs create mode 100644 anneal/v2/vendor/indicatif/examples/morebars.rs create mode 100644 anneal/v2/vendor/indicatif/examples/multi-tree-ext.rs create mode 100644 anneal/v2/vendor/indicatif/examples/multi-tree.rs create mode 100644 anneal/v2/vendor/indicatif/examples/multi.rs create mode 100644 anneal/v2/vendor/indicatif/examples/single.rs create mode 100644 anneal/v2/vendor/indicatif/examples/slow.rs create mode 100644 anneal/v2/vendor/indicatif/examples/spinner-loop.rs create mode 100644 anneal/v2/vendor/indicatif/examples/steady.rs create mode 100644 anneal/v2/vendor/indicatif/examples/tokio.rs create mode 100644 anneal/v2/vendor/indicatif/examples/yarnish.rs create mode 100644 anneal/v2/vendor/indicatif/src/draw_target.rs create mode 100644 anneal/v2/vendor/indicatif/src/format.rs create mode 100644 anneal/v2/vendor/indicatif/src/in_memory.rs create mode 100644 anneal/v2/vendor/indicatif/src/iter.rs create mode 100644 anneal/v2/vendor/indicatif/src/lib.rs create mode 100644 anneal/v2/vendor/indicatif/src/multi.rs create mode 100644 anneal/v2/vendor/indicatif/src/progress_bar.rs create mode 100644 anneal/v2/vendor/indicatif/src/rayon.rs create mode 100644 anneal/v2/vendor/indicatif/src/state.rs create mode 100644 anneal/v2/vendor/indicatif/src/style.rs create mode 100644 anneal/v2/vendor/indicatif/src/term_like.rs create mode 100644 anneal/v2/vendor/indicatif/tests/multi-autodrop.rs create mode 100644 anneal/v2/vendor/indicatif/tests/render.rs create mode 100644 anneal/v2/vendor/is_ci/.cargo-checksum.json create mode 100644 anneal/v2/vendor/is_ci/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/is_ci/.editorconfig create mode 100644 anneal/v2/vendor/is_ci/CHANGELOG.md create mode 100644 anneal/v2/vendor/is_ci/Cargo.lock create mode 100644 anneal/v2/vendor/is_ci/Cargo.toml create mode 100644 anneal/v2/vendor/is_ci/Cargo.toml.orig create mode 100644 anneal/v2/vendor/is_ci/LICENSE create mode 100644 anneal/v2/vendor/is_ci/Makefile.toml create mode 100644 anneal/v2/vendor/is_ci/README.md create mode 100644 anneal/v2/vendor/is_ci/cliff.toml create mode 100644 anneal/v2/vendor/is_ci/src/lib.rs create mode 100644 anneal/v2/vendor/is_ci/src/main.rs create mode 100644 anneal/v2/vendor/js-sys/.cargo-checksum.json create mode 100644 anneal/v2/vendor/js-sys/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/js-sys/Cargo.lock create mode 100644 anneal/v2/vendor/js-sys/Cargo.toml create mode 100644 anneal/v2/vendor/js-sys/Cargo.toml.orig create mode 100644 anneal/v2/vendor/js-sys/LICENSE-APACHE create mode 100644 anneal/v2/vendor/js-sys/LICENSE-MIT create mode 100644 anneal/v2/vendor/js-sys/README.md create mode 100644 anneal/v2/vendor/js-sys/src/Temporal.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/mod.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/queue.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/stream.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/task/mod.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/task/multithread.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/task/singlethread.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/task/wait_async_polyfill.rs create mode 100644 anneal/v2/vendor/js-sys/src/futures/task/worker.js create mode 100644 anneal/v2/vendor/js-sys/src/lib.rs create mode 100644 anneal/v2/vendor/miette-derive/.cargo-checksum.json create mode 100644 anneal/v2/vendor/miette-derive/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/miette-derive/Cargo.lock create mode 100644 anneal/v2/vendor/miette-derive/Cargo.toml create mode 100644 anneal/v2/vendor/miette-derive/Cargo.toml.orig create mode 100644 anneal/v2/vendor/miette-derive/LICENSE create mode 100644 anneal/v2/vendor/miette-derive/src/code.rs create mode 100644 anneal/v2/vendor/miette-derive/src/diagnostic.rs create mode 100644 anneal/v2/vendor/miette-derive/src/diagnostic_arg.rs create mode 100644 anneal/v2/vendor/miette-derive/src/diagnostic_source.rs create mode 100644 anneal/v2/vendor/miette-derive/src/fmt.rs create mode 100644 anneal/v2/vendor/miette-derive/src/forward.rs create mode 100644 anneal/v2/vendor/miette-derive/src/help.rs create mode 100644 anneal/v2/vendor/miette-derive/src/label.rs create mode 100644 anneal/v2/vendor/miette-derive/src/lib.rs create mode 100644 anneal/v2/vendor/miette-derive/src/related.rs create mode 100644 anneal/v2/vendor/miette-derive/src/severity.rs create mode 100644 anneal/v2/vendor/miette-derive/src/source_code.rs create mode 100644 anneal/v2/vendor/miette-derive/src/url.rs create mode 100644 anneal/v2/vendor/miette-derive/src/utils.rs create mode 100644 anneal/v2/vendor/miette/.cargo-checksum.json create mode 100644 anneal/v2/vendor/miette/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/miette/.editorconfig create mode 100644 anneal/v2/vendor/miette/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/miette/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/miette/CHANGELOG.md create mode 100644 anneal/v2/vendor/miette/CODE_OF_CONDUCT.md create mode 100644 anneal/v2/vendor/miette/CONTRIBUTING.md create mode 100644 anneal/v2/vendor/miette/Cargo.lock create mode 100644 anneal/v2/vendor/miette/Cargo.toml create mode 100644 anneal/v2/vendor/miette/Cargo.toml.orig create mode 100644 anneal/v2/vendor/miette/LICENSE create mode 100644 anneal/v2/vendor/miette/Makefile.toml create mode 100644 anneal/v2/vendor/miette/README.md create mode 100644 anneal/v2/vendor/miette/README.tpl create mode 100644 anneal/v2/vendor/miette/cliff.toml create mode 100644 anneal/v2/vendor/miette/clippy.toml create mode 100644 anneal/v2/vendor/miette/examples/serde_json.rs create mode 100644 anneal/v2/vendor/miette/rustfmt.toml create mode 100644 anneal/v2/vendor/miette/src/chain.rs create mode 100644 anneal/v2/vendor/miette/src/diagnostic_chain.rs create mode 100644 anneal/v2/vendor/miette/src/diagnostic_impls.rs create mode 100644 anneal/v2/vendor/miette/src/error.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/context.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/error.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/fmt.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/into_diagnostic.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/kind.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/macros.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/mod.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/ptr.rs create mode 100644 anneal/v2/vendor/miette/src/eyreish/wrapper.rs create mode 100644 anneal/v2/vendor/miette/src/handler.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/debug.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/graphical.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/json.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/mod.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/narratable.rs create mode 100644 anneal/v2/vendor/miette/src/handlers/theme.rs create mode 100644 anneal/v2/vendor/miette/src/highlighters/blank.rs create mode 100644 anneal/v2/vendor/miette/src/highlighters/mod.rs create mode 100644 anneal/v2/vendor/miette/src/highlighters/syntect.rs create mode 100644 anneal/v2/vendor/miette/src/lib.rs create mode 100644 anneal/v2/vendor/miette/src/macro_helpers.rs create mode 100644 anneal/v2/vendor/miette/src/miette_diagnostic.rs create mode 100644 anneal/v2/vendor/miette/src/named_source.rs create mode 100644 anneal/v2/vendor/miette/src/panic.rs create mode 100644 anneal/v2/vendor/miette/src/protocol.rs create mode 100644 anneal/v2/vendor/miette/src/source_impls.rs create mode 100644 anneal/v2/vendor/object/.cargo-checksum.json create mode 100644 anneal/v2/vendor/object/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/object/CHANGELOG.md create mode 100644 anneal/v2/vendor/object/Cargo.lock create mode 100644 anneal/v2/vendor/object/Cargo.toml create mode 100644 anneal/v2/vendor/object/Cargo.toml.orig create mode 100644 anneal/v2/vendor/object/LICENSE-APACHE create mode 100644 anneal/v2/vendor/object/LICENSE-MIT create mode 100644 anneal/v2/vendor/object/README.md create mode 100644 anneal/v2/vendor/object/build.rs create mode 100644 anneal/v2/vendor/object/src/archive.rs create mode 100644 anneal/v2/vendor/object/src/build/bytes.rs create mode 100644 anneal/v2/vendor/object/src/build/elf.rs create mode 100644 anneal/v2/vendor/object/src/build/error.rs create mode 100644 anneal/v2/vendor/object/src/build/mod.rs create mode 100644 anneal/v2/vendor/object/src/build/table.rs create mode 100644 anneal/v2/vendor/object/src/common.rs create mode 100644 anneal/v2/vendor/object/src/elf.rs create mode 100644 anneal/v2/vendor/object/src/endian.rs create mode 100644 anneal/v2/vendor/object/src/lib.rs create mode 100644 anneal/v2/vendor/object/src/macho.rs create mode 100644 anneal/v2/vendor/object/src/pe.rs create mode 100644 anneal/v2/vendor/object/src/pod.rs create mode 100644 anneal/v2/vendor/object/src/read/any.rs create mode 100644 anneal/v2/vendor/object/src/read/archive.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/comdat.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/file.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/import.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/relocation.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/section.rs create mode 100644 anneal/v2/vendor/object/src/read/coff/symbol.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/attributes.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/comdat.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/compression.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/dynamic.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/file.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/hash.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/note.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/relocation.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/section.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/segment.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/symbol.rs create mode 100644 anneal/v2/vendor/object/src/read/elf/version.rs create mode 100644 anneal/v2/vendor/object/src/read/gnu_compression.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/dyld_cache.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/fat.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/file.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/load_command.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/relocation.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/section.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/segment.rs create mode 100644 anneal/v2/vendor/object/src/read/macho/symbol.rs create mode 100644 anneal/v2/vendor/object/src/read/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/data_directory.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/export.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/file.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/import.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/relocation.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/resource.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/rich.rs create mode 100644 anneal/v2/vendor/object/src/read/pe/section.rs create mode 100644 anneal/v2/vendor/object/src/read/read_cache.rs create mode 100644 anneal/v2/vendor/object/src/read/read_ref.rs create mode 100644 anneal/v2/vendor/object/src/read/traits.rs create mode 100644 anneal/v2/vendor/object/src/read/util.rs create mode 100644 anneal/v2/vendor/object/src/read/wasm.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/comdat.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/file.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/mod.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/relocation.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/section.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/segment.rs create mode 100644 anneal/v2/vendor/object/src/read/xcoff/symbol.rs create mode 100644 anneal/v2/vendor/object/src/write/coff/mod.rs create mode 100644 anneal/v2/vendor/object/src/write/coff/object.rs create mode 100644 anneal/v2/vendor/object/src/write/coff/writer.rs create mode 100644 anneal/v2/vendor/object/src/write/elf/mod.rs create mode 100644 anneal/v2/vendor/object/src/write/elf/object.rs create mode 100644 anneal/v2/vendor/object/src/write/elf/writer.rs create mode 100644 anneal/v2/vendor/object/src/write/macho.rs create mode 100644 anneal/v2/vendor/object/src/write/mod.rs create mode 100644 anneal/v2/vendor/object/src/write/pe.rs create mode 100644 anneal/v2/vendor/object/src/write/string.rs create mode 100644 anneal/v2/vendor/object/src/write/util.rs create mode 100644 anneal/v2/vendor/object/src/write/xcoff.rs create mode 100644 anneal/v2/vendor/object/src/xcoff.rs create mode 100644 anneal/v2/vendor/object/tests/build/elf.rs create mode 100644 anneal/v2/vendor/object/tests/build/mod.rs create mode 100644 anneal/v2/vendor/object/tests/integration.rs create mode 100644 anneal/v2/vendor/object/tests/parse_self.rs create mode 100644 anneal/v2/vendor/object/tests/read/coff.rs create mode 100644 anneal/v2/vendor/object/tests/read/elf.rs create mode 100644 anneal/v2/vendor/object/tests/read/macho.rs create mode 100644 anneal/v2/vendor/object/tests/read/mod.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/bss.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/coff.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/comdat.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/common.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/elf.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/macho.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/mod.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/section_flags.rs create mode 100644 anneal/v2/vendor/object/tests/round_trip/tls.rs create mode 100644 anneal/v2/vendor/owo-colors/.cargo-checksum.json create mode 100644 anneal/v2/vendor/owo-colors/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/owo-colors/CHANGELOG.md create mode 100644 anneal/v2/vendor/owo-colors/Cargo.lock create mode 100644 anneal/v2/vendor/owo-colors/Cargo.toml create mode 100644 anneal/v2/vendor/owo-colors/Cargo.toml.orig create mode 100644 anneal/v2/vendor/owo-colors/LICENSE create mode 100644 anneal/v2/vendor/owo-colors/README.md create mode 100644 anneal/v2/vendor/owo-colors/build.rs create mode 100644 anneal/v2/vendor/owo-colors/src/colors.rs create mode 100644 anneal/v2/vendor/owo-colors/src/colors/css.rs create mode 100644 anneal/v2/vendor/owo-colors/src/colors/custom.rs create mode 100644 anneal/v2/vendor/owo-colors/src/colors/dynamic.rs create mode 100644 anneal/v2/vendor/owo-colors/src/colors/xterm.rs create mode 100644 anneal/v2/vendor/owo-colors/src/combo.rs create mode 100644 anneal/v2/vendor/owo-colors/src/dyn_colors.rs create mode 100644 anneal/v2/vendor/owo-colors/src/dyn_styles.rs create mode 100644 anneal/v2/vendor/owo-colors/src/lib.rs create mode 100644 anneal/v2/vendor/owo-colors/src/overrides.rs create mode 100644 anneal/v2/vendor/owo-colors/src/styled_list.rs create mode 100644 anneal/v2/vendor/owo-colors/src/styles.rs create mode 100644 anneal/v2/vendor/owo-colors/src/supports_colors.rs create mode 100644 anneal/v2/vendor/owo-colors/src/tests.rs create mode 100644 anneal/v2/vendor/pin-project-lite/.cargo-checksum.json create mode 100644 anneal/v2/vendor/pin-project-lite/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/pin-project-lite/CHANGELOG.md create mode 100644 anneal/v2/vendor/pin-project-lite/Cargo.lock create mode 100644 anneal/v2/vendor/pin-project-lite/Cargo.toml create mode 100644 anneal/v2/vendor/pin-project-lite/Cargo.toml.orig create mode 100644 anneal/v2/vendor/pin-project-lite/LICENSE-APACHE create mode 100644 anneal/v2/vendor/pin-project-lite/LICENSE-MIT create mode 100644 anneal/v2/vendor/pin-project-lite/README.md create mode 100644 anneal/v2/vendor/pin-project-lite/src/lib.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/auxiliary/mod.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/compiletest.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/drop_order.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/.rustfmt.toml create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/default/enum.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/default/enum.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/default/struct.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/default/struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/multifields/enum.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/multifields/enum.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/multifields/struct.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/multifields/struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-all.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-all.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-mut.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-mut.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-none.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-none.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-ref.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/enum-ref.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-all.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-all.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-mut.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-mut.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-none.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-none.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-ref.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/naming/struct-ref.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/not_unpin/enum.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/not_unpin/enum.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/not_unpin/struct.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/not_unpin/struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pinned_drop/enum.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pinned_drop/enum.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pinned_drop/struct.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pinned_drop/struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pub/enum.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pub/enum.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pub/struct.expanded.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expand/pub/struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/expandtest.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/include/basic.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/proper_unpin.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/test.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/not_unpin/conflict-unpin.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/not_unpin/conflict-unpin.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/not_unpin/negative_impls_stable.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/not_unpin/negative_impls_stable.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/conflict-drop.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/conflict-drop.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/conflict-unpin.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/conflict-unpin.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/invalid-bounds.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/invalid-bounds.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/invalid.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/invalid.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/negative_impls_stable.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/negative_impls_stable.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/overlapping_lifetime_names.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/overlapping_lifetime_names.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/overlapping_unpin_struct.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/overlapping_unpin_struct.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/packed.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/packed.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/unpin_sneaky.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/unpin_sneaky.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/unsupported.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pin_project/unsupported.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.stderr create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.rs create mode 100644 anneal/v2/vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.stderr create mode 100644 anneal/v2/vendor/rayon-core/.cargo-checksum.json create mode 100644 anneal/v2/vendor/rayon-core/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/rayon-core/Cargo.lock create mode 100644 anneal/v2/vendor/rayon-core/Cargo.toml create mode 100644 anneal/v2/vendor/rayon-core/Cargo.toml.orig create mode 100644 anneal/v2/vendor/rayon-core/LICENSE-APACHE create mode 100644 anneal/v2/vendor/rayon-core/LICENSE-MIT create mode 100644 anneal/v2/vendor/rayon-core/README.md create mode 100644 anneal/v2/vendor/rayon-core/build.rs create mode 100644 anneal/v2/vendor/rayon-core/src/broadcast/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/broadcast/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/quicksort_race1.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/quicksort_race2.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/quicksort_race3.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/rc_return.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/rc_upvar.rs create mode 100644 anneal/v2/vendor/rayon-core/src/compile_fail/scope_join_bad.rs create mode 100644 anneal/v2/vendor/rayon-core/src/job.rs create mode 100644 anneal/v2/vendor/rayon-core/src/join/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/join/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/latch.rs create mode 100644 anneal/v2/vendor/rayon-core/src/lib.rs create mode 100644 anneal/v2/vendor/rayon-core/src/private.rs create mode 100644 anneal/v2/vendor/rayon-core/src/registry.rs create mode 100644 anneal/v2/vendor/rayon-core/src/scope/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/scope/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/sleep/README.md create mode 100644 anneal/v2/vendor/rayon-core/src/sleep/counters.rs create mode 100644 anneal/v2/vendor/rayon-core/src/sleep/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/spawn/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/spawn/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/thread_pool/mod.rs create mode 100644 anneal/v2/vendor/rayon-core/src/thread_pool/test.rs create mode 100644 anneal/v2/vendor/rayon-core/src/unwind.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/double_init_fail.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/init_zero_threads.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/scope_join.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/scoped_threadpool.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/simple_panic.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/stack_overflow_crash.rs create mode 100644 anneal/v2/vendor/rayon-core/tests/use_current_thread.rs create mode 100644 anneal/v2/vendor/rayon/.cargo-checksum.json create mode 100644 anneal/v2/vendor/rayon/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/rayon/Cargo.lock create mode 100644 anneal/v2/vendor/rayon/Cargo.toml create mode 100644 anneal/v2/vendor/rayon/Cargo.toml.orig create mode 100644 anneal/v2/vendor/rayon/FAQ.md create mode 100644 anneal/v2/vendor/rayon/LICENSE-APACHE create mode 100644 anneal/v2/vendor/rayon/LICENSE-MIT create mode 100644 anneal/v2/vendor/rayon/README.md create mode 100644 anneal/v2/vendor/rayon/RELEASES.md create mode 100644 anneal/v2/vendor/rayon/src/array.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/binary_heap.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/btree_map.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/btree_set.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/hash_map.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/hash_set.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/linked_list.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/collections/vec_deque.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/cannot_collect_filtermap_data.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/cannot_zip_filtered_data.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/cell_par_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/must_use.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/no_send_par_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/compile_fail/rc_par_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/delegate.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/blocks.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/chain.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/chunks.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/cloned.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/collect/consumer.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/collect/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/collect/test.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/copied.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/empty.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/enumerate.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/extend.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/filter.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/filter_map.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/find.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/find_first_last/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/find_first_last/test.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/flat_map.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/flat_map_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/flatten.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/flatten_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/fold.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/fold_chunks.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/fold_chunks_with.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/for_each.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/from_par_iter.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/inspect.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/interleave.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/interleave_shortest.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/intersperse.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/len.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/map.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/map_with.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/multizip.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/noop.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/once.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/panic_fuse.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/par_bridge.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/plumbing/README.md create mode 100644 anneal/v2/vendor/rayon/src/iter/plumbing/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/positions.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/product.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/reduce.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/repeat.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/rev.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/skip.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/skip_any.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/skip_any_while.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/splitter.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/step_by.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/sum.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/take.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/take_any.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/take_any_while.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/test.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/try_fold.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/try_reduce.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/try_reduce_with.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/unzip.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/update.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/walk_tree.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/while_some.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/zip.rs create mode 100644 anneal/v2/vendor/rayon/src/iter/zip_eq.rs create mode 100644 anneal/v2/vendor/rayon/src/lib.rs create mode 100644 anneal/v2/vendor/rayon/src/math.rs create mode 100644 anneal/v2/vendor/rayon/src/option.rs create mode 100644 anneal/v2/vendor/rayon/src/par_either.rs create mode 100644 anneal/v2/vendor/rayon/src/prelude.rs create mode 100644 anneal/v2/vendor/rayon/src/private.rs create mode 100644 anneal/v2/vendor/rayon/src/range.rs create mode 100644 anneal/v2/vendor/rayon/src/range_inclusive.rs create mode 100644 anneal/v2/vendor/rayon/src/result.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/chunk_by.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/chunks.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/mod.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/rchunks.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/sort.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/test.rs create mode 100644 anneal/v2/vendor/rayon/src/slice/windows.rs create mode 100644 anneal/v2/vendor/rayon/src/split_producer.rs create mode 100644 anneal/v2/vendor/rayon/src/str.rs create mode 100644 anneal/v2/vendor/rayon/src/string.rs create mode 100644 anneal/v2/vendor/rayon/src/vec.rs create mode 100644 anneal/v2/vendor/rayon/tests/chars.rs create mode 100644 anneal/v2/vendor/rayon/tests/clones.rs create mode 100644 anneal/v2/vendor/rayon/tests/collect.rs create mode 100644 anneal/v2/vendor/rayon/tests/cross-pool.rs create mode 100644 anneal/v2/vendor/rayon/tests/debug.rs create mode 100644 anneal/v2/vendor/rayon/tests/drain_vec.rs create mode 100644 anneal/v2/vendor/rayon/tests/intersperse.rs create mode 100644 anneal/v2/vendor/rayon/tests/issue671-unzip.rs create mode 100644 anneal/v2/vendor/rayon/tests/issue671.rs create mode 100644 anneal/v2/vendor/rayon/tests/iter_panic.rs create mode 100644 anneal/v2/vendor/rayon/tests/named-threads.rs create mode 100644 anneal/v2/vendor/rayon/tests/octillion.rs create mode 100644 anneal/v2/vendor/rayon/tests/par_bridge_recursion.rs create mode 100644 anneal/v2/vendor/rayon/tests/producer_split_at.rs create mode 100644 anneal/v2/vendor/rayon/tests/sort-panic-safe.rs create mode 100644 anneal/v2/vendor/rayon/tests/str.rs create mode 100644 anneal/v2/vendor/rustc-demangle/.cargo-checksum.json create mode 100644 anneal/v2/vendor/rustc-demangle/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/rustc-demangle/.github/dependabot.yml create mode 100644 anneal/v2/vendor/rustc-demangle/.github/workflows/main.yml create mode 100644 anneal/v2/vendor/rustc-demangle/.github/workflows/release.yml create mode 100644 anneal/v2/vendor/rustc-demangle/CHANGELOG.md create mode 100644 anneal/v2/vendor/rustc-demangle/Cargo.lock create mode 100644 anneal/v2/vendor/rustc-demangle/Cargo.toml create mode 100644 anneal/v2/vendor/rustc-demangle/Cargo.toml.orig create mode 100644 anneal/v2/vendor/rustc-demangle/LICENSE-APACHE create mode 100644 anneal/v2/vendor/rustc-demangle/LICENSE-MIT create mode 100644 anneal/v2/vendor/rustc-demangle/README.md create mode 100644 anneal/v2/vendor/rustc-demangle/src/legacy.rs create mode 100644 anneal/v2/vendor/rustc-demangle/src/lib.rs create mode 100644 anneal/v2/vendor/rustc-demangle/src/v0-large-test-symbols/early-recursion-limit create mode 100644 anneal/v2/vendor/rustc-demangle/src/v0.rs create mode 100644 anneal/v2/vendor/rustversion/.cargo-checksum.json create mode 100644 anneal/v2/vendor/rustversion/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/rustversion/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/rustversion/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/rustversion/Cargo.lock create mode 100644 anneal/v2/vendor/rustversion/Cargo.toml create mode 100644 anneal/v2/vendor/rustversion/Cargo.toml.orig create mode 100644 anneal/v2/vendor/rustversion/LICENSE-APACHE create mode 100644 anneal/v2/vendor/rustversion/LICENSE-MIT create mode 100644 anneal/v2/vendor/rustversion/README.md create mode 100644 anneal/v2/vendor/rustversion/build/build.rs create mode 100644 anneal/v2/vendor/rustversion/build/rustc.rs create mode 100644 anneal/v2/vendor/rustversion/src/attr.rs create mode 100644 anneal/v2/vendor/rustversion/src/bound.rs create mode 100644 anneal/v2/vendor/rustversion/src/constfn.rs create mode 100644 anneal/v2/vendor/rustversion/src/date.rs create mode 100644 anneal/v2/vendor/rustversion/src/error.rs create mode 100644 anneal/v2/vendor/rustversion/src/expand.rs create mode 100644 anneal/v2/vendor/rustversion/src/expr.rs create mode 100644 anneal/v2/vendor/rustversion/src/iter.rs create mode 100644 anneal/v2/vendor/rustversion/src/lib.rs create mode 100644 anneal/v2/vendor/rustversion/src/release.rs create mode 100644 anneal/v2/vendor/rustversion/src/time.rs create mode 100644 anneal/v2/vendor/rustversion/src/token.rs create mode 100644 anneal/v2/vendor/rustversion/src/version.rs create mode 100644 anneal/v2/vendor/rustversion/tests/compiletest.rs create mode 100644 anneal/v2/vendor/rustversion/tests/test_const.rs create mode 100644 anneal/v2/vendor/rustversion/tests/test_eval.rs create mode 100644 anneal/v2/vendor/rustversion/tests/test_parse.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-bound.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-bound.stderr create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-date.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-date.stderr create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-not.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-not.stderr create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-version.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/bad-version.stderr create mode 100644 anneal/v2/vendor/rustversion/tests/ui/const-not-fn.rs create mode 100644 anneal/v2/vendor/rustversion/tests/ui/const-not-fn.stderr create mode 100644 anneal/v2/vendor/same-file/.cargo-checksum.json create mode 100644 anneal/v2/vendor/same-file/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/same-file/COPYING create mode 100644 anneal/v2/vendor/same-file/Cargo.lock create mode 100644 anneal/v2/vendor/same-file/Cargo.toml create mode 100644 anneal/v2/vendor/same-file/Cargo.toml.orig create mode 100644 anneal/v2/vendor/same-file/LICENSE-MIT create mode 100644 anneal/v2/vendor/same-file/README.md create mode 100644 anneal/v2/vendor/same-file/UNLICENSE create mode 100644 anneal/v2/vendor/same-file/examples/is_same_file.rs create mode 100644 anneal/v2/vendor/same-file/examples/is_stderr.rs create mode 100644 anneal/v2/vendor/same-file/rustfmt.toml create mode 100644 anneal/v2/vendor/same-file/src/lib.rs create mode 100644 anneal/v2/vendor/same-file/src/unix.rs create mode 100644 anneal/v2/vendor/same-file/src/unknown.rs create mode 100644 anneal/v2/vendor/same-file/src/win.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/.cargo-checksum.json create mode 100644 anneal/v2/vendor/sha2-0.10.9/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/sha2-0.10.9/CHANGELOG.md create mode 100644 anneal/v2/vendor/sha2-0.10.9/Cargo.lock create mode 100644 anneal/v2/vendor/sha2-0.10.9/Cargo.toml create mode 100644 anneal/v2/vendor/sha2-0.10.9/Cargo.toml.orig create mode 100644 anneal/v2/vendor/sha2-0.10.9/LICENSE-APACHE create mode 100644 anneal/v2/vendor/sha2-0.10.9/LICENSE-MIT create mode 100644 anneal/v2/vendor/sha2-0.10.9/README.md create mode 100644 anneal/v2/vendor/sha2-0.10.9/benches/mod.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/consts.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/core_api.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/lib.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256/aarch64.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256/loongarch64_asm.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256/soft.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256/soft_compact.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha256/x86.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512/aarch64.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512/loongarch64_asm.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512/soft.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512/soft_compact.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/src/sha512/x86.rs create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha224.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha256.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha384.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha512.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha512_224.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/data/sha512_256.blb create mode 100644 anneal/v2/vendor/sha2-0.10.9/tests/mod.rs create mode 100644 anneal/v2/vendor/slab/.cargo-checksum.json create mode 100644 anneal/v2/vendor/slab/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/slab/CHANGELOG.md create mode 100644 anneal/v2/vendor/slab/Cargo.lock create mode 100644 anneal/v2/vendor/slab/Cargo.toml create mode 100644 anneal/v2/vendor/slab/Cargo.toml.orig create mode 100644 anneal/v2/vendor/slab/LICENSE create mode 100644 anneal/v2/vendor/slab/README.md create mode 100644 anneal/v2/vendor/slab/SECURITY.md create mode 100644 anneal/v2/vendor/slab/src/builder.rs create mode 100644 anneal/v2/vendor/slab/src/lib.rs create mode 100644 anneal/v2/vendor/slab/src/serde.rs create mode 100644 anneal/v2/vendor/slab/tests/serde.rs create mode 100644 anneal/v2/vendor/slab/tests/slab.rs create mode 100644 anneal/v2/vendor/supports-color/.cargo-checksum.json create mode 100644 anneal/v2/vendor/supports-color/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/supports-color/.editorconfig create mode 100644 anneal/v2/vendor/supports-color/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/supports-color/.github/workflows/miri.yml create mode 100644 anneal/v2/vendor/supports-color/CHANGELOG.md create mode 100644 anneal/v2/vendor/supports-color/Cargo.toml create mode 100644 anneal/v2/vendor/supports-color/Cargo.toml.orig create mode 100644 anneal/v2/vendor/supports-color/LICENSE create mode 100644 anneal/v2/vendor/supports-color/Makefile.toml create mode 100644 anneal/v2/vendor/supports-color/README.md create mode 100644 anneal/v2/vendor/supports-color/cliff.toml create mode 100644 anneal/v2/vendor/supports-color/src/lib.rs create mode 100644 anneal/v2/vendor/supports-color/tests/cached.rs create mode 100644 anneal/v2/vendor/supports-hyperlinks/.cargo-checksum.json create mode 100644 anneal/v2/vendor/supports-hyperlinks/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/supports-hyperlinks/.editorconfig create mode 100644 anneal/v2/vendor/supports-hyperlinks/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/supports-hyperlinks/CHANGELOG.md create mode 100644 anneal/v2/vendor/supports-hyperlinks/Cargo.lock create mode 100644 anneal/v2/vendor/supports-hyperlinks/Cargo.toml create mode 100644 anneal/v2/vendor/supports-hyperlinks/Cargo.toml.orig create mode 100644 anneal/v2/vendor/supports-hyperlinks/LICENSE create mode 100644 anneal/v2/vendor/supports-hyperlinks/Makefile.toml create mode 100644 anneal/v2/vendor/supports-hyperlinks/README.md create mode 100644 anneal/v2/vendor/supports-hyperlinks/cliff.toml create mode 100644 anneal/v2/vendor/supports-hyperlinks/src/lib.rs create mode 100644 anneal/v2/vendor/supports-unicode/.cargo-checksum.json create mode 100644 anneal/v2/vendor/supports-unicode/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/supports-unicode/.editorconfig create mode 100644 anneal/v2/vendor/supports-unicode/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/supports-unicode/CHANGELOG.md create mode 100644 anneal/v2/vendor/supports-unicode/Cargo.toml create mode 100644 anneal/v2/vendor/supports-unicode/Cargo.toml.orig create mode 100644 anneal/v2/vendor/supports-unicode/LICENSE create mode 100644 anneal/v2/vendor/supports-unicode/Makefile.toml create mode 100644 anneal/v2/vendor/supports-unicode/README.md create mode 100644 anneal/v2/vendor/supports-unicode/cliff.toml create mode 100644 anneal/v2/vendor/supports-unicode/src/lib.rs create mode 100644 anneal/v2/vendor/terminal_size/.cargo-checksum.json create mode 100644 anneal/v2/vendor/terminal_size/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/terminal_size/.github/dependabot.yml create mode 100644 anneal/v2/vendor/terminal_size/.github/workflows/main.yml create mode 100644 anneal/v2/vendor/terminal_size/Cargo.lock create mode 100644 anneal/v2/vendor/terminal_size/Cargo.toml create mode 100644 anneal/v2/vendor/terminal_size/Cargo.toml.orig create mode 100644 anneal/v2/vendor/terminal_size/LICENSE-APACHE create mode 100644 anneal/v2/vendor/terminal_size/LICENSE-MIT create mode 100644 anneal/v2/vendor/terminal_size/README.md create mode 100644 anneal/v2/vendor/terminal_size/examples/get_size.rs create mode 100644 anneal/v2/vendor/terminal_size/src/lib.rs create mode 100644 anneal/v2/vendor/terminal_size/src/unix.rs create mode 100644 anneal/v2/vendor/terminal_size/src/windows.rs create mode 100644 anneal/v2/vendor/textwrap/.cargo-checksum.json create mode 100644 anneal/v2/vendor/textwrap/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/textwrap/CHANGELOG.md create mode 100644 anneal/v2/vendor/textwrap/Cargo.lock create mode 100644 anneal/v2/vendor/textwrap/Cargo.toml create mode 100644 anneal/v2/vendor/textwrap/Cargo.toml.orig create mode 100644 anneal/v2/vendor/textwrap/LICENSE create mode 100644 anneal/v2/vendor/textwrap/README.md create mode 100644 anneal/v2/vendor/textwrap/dprint.json create mode 100644 anneal/v2/vendor/textwrap/rustfmt.toml create mode 100644 anneal/v2/vendor/textwrap/src/columns.rs create mode 100644 anneal/v2/vendor/textwrap/src/core.rs create mode 100644 anneal/v2/vendor/textwrap/src/fill.rs create mode 100644 anneal/v2/vendor/textwrap/src/fuzzing.rs create mode 100644 anneal/v2/vendor/textwrap/src/indentation.rs create mode 100644 anneal/v2/vendor/textwrap/src/lib.rs create mode 100644 anneal/v2/vendor/textwrap/src/line_ending.rs create mode 100644 anneal/v2/vendor/textwrap/src/options.rs create mode 100644 anneal/v2/vendor/textwrap/src/refill.rs create mode 100644 anneal/v2/vendor/textwrap/src/termwidth.rs create mode 100644 anneal/v2/vendor/textwrap/src/word_separators.rs create mode 100644 anneal/v2/vendor/textwrap/src/word_splitters.rs create mode 100644 anneal/v2/vendor/textwrap/src/wrap.rs create mode 100644 anneal/v2/vendor/textwrap/src/wrap_algorithms.rs create mode 100644 anneal/v2/vendor/textwrap/src/wrap_algorithms/optimal_fit.rs create mode 100644 anneal/v2/vendor/textwrap/tests/indent.rs create mode 100644 anneal/v2/vendor/textwrap/tests/version-numbers.rs create mode 100644 anneal/v2/vendor/unicode-linebreak/.cargo-checksum.json create mode 100644 anneal/v2/vendor/unicode-linebreak/Cargo.toml create mode 100644 anneal/v2/vendor/unicode-linebreak/Cargo.toml.orig create mode 100644 anneal/v2/vendor/unicode-linebreak/LICENSE create mode 100644 anneal/v2/vendor/unicode-linebreak/README.md create mode 100644 anneal/v2/vendor/unicode-linebreak/src/lib.rs create mode 100644 anneal/v2/vendor/unicode-linebreak/src/shared.rs create mode 100644 anneal/v2/vendor/unicode-linebreak/src/tables.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/.cargo-checksum.json create mode 100644 anneal/v2/vendor/unicode-segmentation/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/unicode-segmentation/COPYRIGHT create mode 100644 anneal/v2/vendor/unicode-segmentation/Cargo.lock create mode 100644 anneal/v2/vendor/unicode-segmentation/Cargo.toml create mode 100644 anneal/v2/vendor/unicode-segmentation/Cargo.toml.orig create mode 100644 anneal/v2/vendor/unicode-segmentation/LICENSE-APACHE create mode 100644 anneal/v2/vendor/unicode-segmentation/LICENSE-MIT create mode 100644 anneal/v2/vendor/unicode-segmentation/README.md create mode 100644 anneal/v2/vendor/unicode-segmentation/benches/chars.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/benches/unicode_word_indices.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/benches/word_bounds.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/benches/words.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/src/grapheme.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/src/lib.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/src/sentence.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/src/tables.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/src/word.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/tests/test.rs create mode 100644 anneal/v2/vendor/unicode-segmentation/tests/testdata/mod.rs create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/.cargo-checksum.json create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/COPYRIGHT create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/Cargo.toml create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/Cargo.toml.orig create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/LICENSE-APACHE create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/LICENSE-MIT create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/README.md create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/benches/benches.rs create mode 100755 anneal/v2/vendor/unicode-width-0.1.14/scripts/unicode.py create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/src/lib.rs create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/src/tables.rs create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/tests/emoji-test.txt create mode 100644 anneal/v2/vendor/unicode-width-0.1.14/tests/tests.rs create mode 100644 anneal/v2/vendor/unicode-width/.cargo-checksum.json create mode 100644 anneal/v2/vendor/unicode-width/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/unicode-width/COPYRIGHT create mode 100644 anneal/v2/vendor/unicode-width/Cargo.lock create mode 100644 anneal/v2/vendor/unicode-width/Cargo.toml create mode 100644 anneal/v2/vendor/unicode-width/Cargo.toml.orig create mode 100644 anneal/v2/vendor/unicode-width/LICENSE-APACHE create mode 100644 anneal/v2/vendor/unicode-width/LICENSE-MIT create mode 100644 anneal/v2/vendor/unicode-width/README.md create mode 100644 anneal/v2/vendor/unicode-width/benches/benches.rs create mode 100755 anneal/v2/vendor/unicode-width/scripts/unicode.py create mode 100644 anneal/v2/vendor/unicode-width/src/lib.rs create mode 100644 anneal/v2/vendor/unicode-width/src/tables.rs create mode 100644 anneal/v2/vendor/unicode-width/tests/emoji-test.txt create mode 100644 anneal/v2/vendor/unicode-width/tests/tests.rs create mode 100644 anneal/v2/vendor/unit-prefix/.cargo-checksum.json create mode 100644 anneal/v2/vendor/unit-prefix/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/unit-prefix/.forgejo/workflows/ci.yaml create mode 100644 anneal/v2/vendor/unit-prefix/Cargo.lock create mode 100644 anneal/v2/vendor/unit-prefix/Cargo.toml create mode 100644 anneal/v2/vendor/unit-prefix/Cargo.toml.orig create mode 100644 anneal/v2/vendor/unit-prefix/LICENSE create mode 100644 anneal/v2/vendor/unit-prefix/README.md create mode 100644 anneal/v2/vendor/unit-prefix/examples/conversions.rs create mode 100644 anneal/v2/vendor/unit-prefix/src/lib.rs create mode 100644 anneal/v2/vendor/unit-prefix/src/parse.rs create mode 100644 anneal/v2/vendor/version_check/.cargo-checksum.json create mode 100644 anneal/v2/vendor/version_check/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/version_check/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/version_check/.travis.yml create mode 100644 anneal/v2/vendor/version_check/Cargo.toml create mode 100644 anneal/v2/vendor/version_check/Cargo.toml.orig create mode 100644 anneal/v2/vendor/version_check/LICENSE-APACHE create mode 100644 anneal/v2/vendor/version_check/LICENSE-MIT create mode 100644 anneal/v2/vendor/version_check/README.md create mode 100644 anneal/v2/vendor/version_check/src/channel.rs create mode 100644 anneal/v2/vendor/version_check/src/date.rs create mode 100644 anneal/v2/vendor/version_check/src/lib.rs create mode 100644 anneal/v2/vendor/version_check/src/version.rs create mode 100644 anneal/v2/vendor/walkdir/.cargo-checksum.json create mode 100644 anneal/v2/vendor/walkdir/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/walkdir/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/walkdir/COPYING create mode 100644 anneal/v2/vendor/walkdir/Cargo.toml create mode 100644 anneal/v2/vendor/walkdir/Cargo.toml.orig create mode 100644 anneal/v2/vendor/walkdir/LICENSE-MIT create mode 100644 anneal/v2/vendor/walkdir/README.md create mode 100644 anneal/v2/vendor/walkdir/UNLICENSE create mode 100644 anneal/v2/vendor/walkdir/compare/nftw.c create mode 100644 anneal/v2/vendor/walkdir/compare/walk.py create mode 100644 anneal/v2/vendor/walkdir/rustfmt.toml create mode 100644 anneal/v2/vendor/walkdir/src/dent.rs create mode 100644 anneal/v2/vendor/walkdir/src/error.rs create mode 100644 anneal/v2/vendor/walkdir/src/lib.rs create mode 100644 anneal/v2/vendor/walkdir/src/tests/mod.rs create mode 100644 anneal/v2/vendor/walkdir/src/tests/recursive.rs create mode 100644 anneal/v2/vendor/walkdir/src/tests/util.rs create mode 100644 anneal/v2/vendor/walkdir/src/util.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/.cargo-checksum.json create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/Cargo.lock create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/Cargo.toml create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/Cargo.toml.orig create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/LICENSE-APACHE create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/LICENSE-MIT create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/ast.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/codegen.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/encode.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/error.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/generics.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/hash.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/lib.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro-support/src/parser.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/.cargo-checksum.json create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/Cargo.lock create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/Cargo.toml create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/Cargo.toml.orig create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/LICENSE-APACHE create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/LICENSE-MIT create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/README.md create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/src/lib.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-macro/src/worker.js create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/.cargo-checksum.json create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/Cargo.lock create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/Cargo.toml create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/Cargo.toml.orig create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/LICENSE-APACHE create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/LICENSE-MIT create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/build.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/src/identifier.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/src/lib.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/src/schema_hash_approval.rs create mode 100644 anneal/v2/vendor/wasm-bindgen-shared/src/tys.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/.cargo-checksum.json create mode 100644 anneal/v2/vendor/wasm-bindgen/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/wasm-bindgen/Cargo.lock create mode 100644 anneal/v2/vendor/wasm-bindgen/Cargo.toml create mode 100644 anneal/v2/vendor/wasm-bindgen/Cargo.toml.orig create mode 100644 anneal/v2/vendor/wasm-bindgen/LICENSE-APACHE create mode 100644 anneal/v2/vendor/wasm-bindgen/LICENSE-MIT create mode 100644 anneal/v2/vendor/wasm-bindgen/README.md create mode 100644 anneal/v2/vendor/wasm-bindgen/build.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/cache/intern.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/cache/mod.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/cast.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/closure.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/convert/closures.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/convert/impls.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/convert/mod.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/convert/slices.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/convert/traits.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/describe.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/externref.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/handler.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/lib.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/link.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/parent.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/rt/marker.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/rt/mod.rs create mode 100644 anneal/v2/vendor/wasm-bindgen/src/sys.rs create mode 100644 anneal/v2/vendor/web-time/.cargo-checksum.json create mode 100644 anneal/v2/vendor/web-time/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/web-time/CHANGELOG.md create mode 100644 anneal/v2/vendor/web-time/Cargo.lock create mode 100644 anneal/v2/vendor/web-time/Cargo.toml create mode 100644 anneal/v2/vendor/web-time/Cargo.toml.orig create mode 100644 anneal/v2/vendor/web-time/LICENSE-APACHE create mode 100644 anneal/v2/vendor/web-time/LICENSE-MIT create mode 100644 anneal/v2/vendor/web-time/README.md create mode 100644 anneal/v2/vendor/web-time/src/lib.rs create mode 100644 anneal/v2/vendor/web-time/src/time/instant.rs create mode 100644 anneal/v2/vendor/web-time/src/time/js.rs create mode 100644 anneal/v2/vendor/web-time/src/time/mod.rs create mode 100644 anneal/v2/vendor/web-time/src/time/serde.rs create mode 100644 anneal/v2/vendor/web-time/src/time/system_time.rs create mode 100644 anneal/v2/vendor/web-time/src/web.rs create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/.cargo-checksum.json create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/Cargo.toml create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/Cargo.toml.orig create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/build.rs create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_aclui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_activeds.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_advapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_advpack.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_amsi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_api-ms-win-net-isolation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_apidll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_appmgmts.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_appnotify.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_asycfilt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_audioeng.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_authz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_avifil32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_avrt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_basesrv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_bcrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_bluetoothapis.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_bthprops.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_certadm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_certpoleng.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cfgmgr32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_chakrart.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cldapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_clfsw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_clusapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_comctl32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_comdlg32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_comppkgsup.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_compstui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_comsvcs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_coremessaging.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_credui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_crypt32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cryptdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cryptnet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cryptui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cryptxml.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cscapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_cscdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d2d1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3d10.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3d10_1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3d11.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3d12.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3d9.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3dcompiler.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3dcsx.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_d3dcsxd.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_davclnt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dbgeng.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dbghelp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dciman32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dcomp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ddraw.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_devmgr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dflayout.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dhcpsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_difxapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dinput8.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dmprocessxmlfiltered.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dnsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dnsperf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dnsrslvr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dpx.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_drt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_drtprov.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_drttransport.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dsound.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dsprop.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dssec.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dststlog.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dsuiext.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dwmapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dxgi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_dxva2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_eappcfg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_eappprxy.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_easregprov.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_efswrt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_elscore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_esent.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_evr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_faultrep.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_feclient.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_fhsvcctl.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_fltlib.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_fontsub.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_framedyd.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_framedyn.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_fwpuclnt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_fxsutility.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_gdi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_gdiplus.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_glmf32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_glu32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_gpedit.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_hbaapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_hid.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_hlink.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_httpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_iashlpr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_icm32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_icmui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_icuin.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_icuuc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_imagehlp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_imgutil.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_imm32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_infocardapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_inseng.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_iprop.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_irprops.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_iscsidsc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_jsrt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_kernel32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ksproxy.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ksuser.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ktmw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_loadperf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_lz32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_magnification.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mciole32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mdmlocalmanagement.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mdmregistration.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfplat.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfplay.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mfsrcsnk.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mgmtapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-authz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-crypt32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-dfscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-dsparse.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-dsrole.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-logoncli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-mpr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-netutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-samcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-schedcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-srvcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-sspicli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-userenv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-websocket.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-winhttp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-wkscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-wldap32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-advapi32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-advapi32-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-normaliz-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-ole32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shell32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shlwapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shlwapi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-user32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mincore_downlevel.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mpr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mprapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mprsnap.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mqrt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mrmsupport.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msacm32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msajapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mscms.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msctfmonitor.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msdelta.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msdmo.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msdrm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msimg32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mspatcha.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mspatchc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msports.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msrating.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mstask.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msv1_0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_msvfw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mtx.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_mtxdm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ncrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_nddeapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ndfapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_netapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_netsh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_newdev.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ninput.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_normaliz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntdsa.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntdsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntdsatq.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntdsetup.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntfrsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntlanman.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntmarta.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntquery.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ntvdm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_odbc32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_odbcbcp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_oemlicense.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ole32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_oleacc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_olecli32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_oledlg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_olepro32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_olesvr32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ondemandconnroutehelper.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-atoms-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-calendar-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l3-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-enclave-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-perfcounters-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-privateprofile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-privateprofile-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sidebyside-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sidebyside-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-stringansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-threadpool-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-toolhelp-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-toolhelp-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-versionansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-tdh-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-mm-time-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-oobe-notification-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-perf-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-limitsmanagement-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-systemfunctions-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-unicodeansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shell-shdirectory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-authz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-crypt32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-dfscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-dsparse.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-dsrole.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-fltlib.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-logoncli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-mpr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-netutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-ntdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-powrprof.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-profapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-samcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-schedcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-srvcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-sspicli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-userenv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-websocket.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-winhttp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-wkscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-wldap32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore-xmllite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-apphelp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-comctl32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-comdlg32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3d10.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3d9.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3dx10_47.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-difxapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-gdi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-input.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-msi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-newdev.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oleacc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oledlg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-pdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-psapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-resutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-secur32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-setupapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-shell32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-shlwapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-tdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-twinapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-user32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-uxtheme.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-version.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-winmm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-winspool.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecore_downlevel.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-atoms-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-calendar-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l3-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-enclave-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-perfcounters-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-privateprofile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-privateprofile-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psm-appnotify-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sidebyside-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sidebyside-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-slapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-stringansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-threadpool-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-toolhelp-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-toolhelp-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-versionansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-tdh-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-expandedresources-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-gamemonitor-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-gamemonitor-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-misc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-misc-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-mme-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-playsound-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-time-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-ntuser-sysparams-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-oobe-notification-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-perf-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-limitsmanagement-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-systemfunctions-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-unicodeansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shell-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shell-shdirectory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-authz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-chakra.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-coremessaging.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-crypt32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-d2d1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-d3d11.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-d3d12.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dfscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dsparse.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dsrole.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-dxgi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-esent.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-core-iuri-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-gaming-xinput-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-networking-wlanapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-shell32-shellfolders-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-shell32-shellfolders-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-fltlib.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-hid.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-logoncli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mfplat.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mpr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-msajapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-netutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ntdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-powrprof.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-profapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-propsys.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-rometadata.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-samcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-schedcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-srvcli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-sspicli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-urlmon.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-userenv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-webservices.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-websocket.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-winhttp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-wintrust.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-wkscli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-wlanapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-wldap32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-wpprecorderum.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-xaudio2_9.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap-xmllite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-apphelp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-comctl32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-comdlg32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3d10.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3d9.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3dx10_47.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-difxapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-gdi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-input.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-msi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-newdev.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oleacc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oledlg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-pdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-psapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-resutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-secur32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-setupapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-shell32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-shlwapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-tdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-twinapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-user32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-uxtheme.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-version.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-winmm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-winspool.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_opengl32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_p2p.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_p2pgraph.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_pathcch.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_pdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_peerdist.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_powrprof.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_prntvpt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_propsys.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_psapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_quartz.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_query.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_qwave.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rasapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rasdlg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_resutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rometadata.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rpcexts.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rpcns4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rpcproxy.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rtm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rtutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_rtworkq.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_runtimeobject.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_samlib.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_samsrv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sas.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_scarddlg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_scecli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_scesrv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_schannel.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_secur32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_security.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sens.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sensapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sensorsutils.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_setupapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sfc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shdocvw.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shell32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shfolder.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_shlwapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_slc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_slcext.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_slwga.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_snmpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_spoolss.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sporder.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_srpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ssdpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_sti.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_swdevice.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_synchronization.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_t2embed.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_tapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_tbs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_tdh.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_thunk32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_traffic.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_tsec.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_twain_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_txfw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ualapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_umpdddi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_urlmon.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_user32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_userenv.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_usp10.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_uxtheme.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vdmdbg.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_version.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vfw32-avicap32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vfw32-avifil32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vfw32-msvfw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vfw32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_virtdisk.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_vssapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wcmapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wdsbp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wdsclientapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wdsmc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wdspxe.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wdstptc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_webservices.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_websocket.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wecapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wer.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wevtapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wiaservc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winbio.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windows.networking.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windows.ui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-appmodel-runtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-appmodel-runtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psm-appnotify-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-slapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-expandedresources-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-gamemonitor-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-gamemonitor-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-chakra.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-coremessaging.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-crypt32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-d2d1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-d3d11.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-d3d12.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-dwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-dxgi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-esent.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-core-iuri-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-gaming-xinput-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mfplat.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-msajapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ntdll.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-propsys.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-rometadata.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-sspicli.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-urlmon.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-webservices.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-xaudio2_9.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp-xmllite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-cabinet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d2d1.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d3d11.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dxgi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-esent.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mfplat.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-msajapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mscoree.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mswsock.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-propsys.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-urlmon.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-webservices.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xaudio2_8.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xmllite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winfax.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winhttp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wininet.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winmm.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winscard.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winspool.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winsqlite3.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winsta.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wintrust.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_winusb.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wlanapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wlanui.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wldap32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wmip.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wmvcore.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wofutil.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wow32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_ws2_32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wscapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wsclient.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wsdapi.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wsmsvc.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wsnmp32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wsock32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xaudio2.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xaudio2_8.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xinput.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xinput9_1_0.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xinputuap.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xmllite.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xolehlp.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xpsdocumenttargetprint.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/lib/libwinapi_xpsprint.a create mode 100644 anneal/v2/vendor/winapi-i686-pc-windows-gnu/src/lib.rs create mode 100644 anneal/v2/vendor/winapi-util/.cargo-checksum.json create mode 100644 anneal/v2/vendor/winapi-util/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/winapi-util/.github/FUNDING.yml create mode 100644 anneal/v2/vendor/winapi-util/.github/workflows/ci.yml create mode 100644 anneal/v2/vendor/winapi-util/COPYING create mode 100644 anneal/v2/vendor/winapi-util/Cargo.lock create mode 100644 anneal/v2/vendor/winapi-util/Cargo.toml create mode 100644 anneal/v2/vendor/winapi-util/Cargo.toml.orig create mode 100644 anneal/v2/vendor/winapi-util/LICENSE-MIT create mode 100644 anneal/v2/vendor/winapi-util/README.md create mode 100644 anneal/v2/vendor/winapi-util/UNLICENSE create mode 100644 anneal/v2/vendor/winapi-util/rustfmt.toml create mode 100644 anneal/v2/vendor/winapi-util/src/console.rs create mode 100644 anneal/v2/vendor/winapi-util/src/file.rs create mode 100644 anneal/v2/vendor/winapi-util/src/lib.rs create mode 100644 anneal/v2/vendor/winapi-util/src/sysinfo.rs create mode 100644 anneal/v2/vendor/winapi-util/src/win.rs create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/.cargo-checksum.json create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/Cargo.toml create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/Cargo.toml.orig create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/build.rs create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_aclui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_activeds.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_advapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_advpack.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_amsi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_api-ms-win-net-isolation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_appmgmts.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_appnotify.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_audioeng.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_authz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_avifil32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_avrt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_basesrv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_bcrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_bluetoothapis.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_bthprops.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_certadm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_certpoleng.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cfgmgr32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_chakrart.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cldapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_clfsw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_clusapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_comctl32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_comdlg32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_comppkgsup.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_compstui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_comsvcs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_coremessaging.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_credui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_crypt32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cryptdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cryptnet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cryptui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cryptxml.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cscapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_cscdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d2d1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3d10.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3d10_1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3d11.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3d12.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3d9.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3dcompiler.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3dcsx.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_d3dcsxd.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_davclnt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dbgeng.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dbghelp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dciman32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dcomp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ddraw.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_devmgr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dflayout.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dhcpsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_difxapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dinput8.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dmprocessxmlfiltered.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dnsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dnsperf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dnsrslvr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dpx.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_drt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_drtprov.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_drttransport.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dsound.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dsprop.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dssec.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dststlog.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dsuiext.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dwmapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dxgi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_dxva2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_eappcfg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_eappprxy.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_easregprov.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_efswrt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_elscore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_esent.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_evr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_faultrep.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_feclient.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_fhsvcctl.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_fltlib.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_fontsub.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_framedyd.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_framedyn.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_fwpuclnt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_fxsutility.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_gdi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_gdiplus.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_glmf32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_glu32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_gpedit.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_hbaapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_hid.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_hlink.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_httpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_iashlpr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_icm32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_icmui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_icuin.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_icuuc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_imagehlp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_imgutil.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_imm32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_infocardapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_inseng.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_iprop.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_irprops.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_iscsidsc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_jsrt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_kernel32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ksproxy.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ksuser.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ktmw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_loadperf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_lz32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_magnification.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mciole32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mdmlocalmanagement.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mdmregistration.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfplat.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfplay.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mfsrcsnk.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mgmtapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-authz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-crypt32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-dfscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-dsparse.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-dsrole.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-logoncli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-mpr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-netutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-samcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-schedcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-srvcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-sspicli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-userenv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-websocket.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-winhttp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-wkscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-wldap32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-advapi32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-advapi32-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-normaliz-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-ole32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shell32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shlwapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-shlwapi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-user32-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel-api-ms-win-downlevel-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mincore_downlevel.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mpr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mprapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mprsnap.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mqrt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mrmsupport.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msacm32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msajapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mscms.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msctfmonitor.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msdelta.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msdmo.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msdrm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msimg32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mspatcha.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mspatchc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msports.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msrating.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mstask.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msv1_0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_msvfw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mtx.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_mtxdm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-api-ms-win-net-isolation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-api-ms-win-net-isolation-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-clfsw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-clusapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-cryptxml.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-dbgeng.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-dbghelp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-dnsperf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-esent.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-faultrep.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-framedynos.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-fwpuclnt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-hbaapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-httpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-iscsidsc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-ktmw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-loadperf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-mprapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-netsh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-ntdsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-ntlanman.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-pdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-resutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-snmpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-tbs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-traffic.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-virtdisk.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-vssapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-webservices.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-wer.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-wevtapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-wintrust.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-wnvapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv-wsmsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nanosrv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ncrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_nddeapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ndfapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_netapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_netsh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_newdev.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ninput.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_normaliz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntdsa.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntdsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntdsatq.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntdsetup.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntfrsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntlanman.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntmarta.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ntquery.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_odbc32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_odbcbcp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_oemlicense.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ole32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_oleacc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_olecli32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_oledlg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_olesvr32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ondemandconnroutehelper.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-atoms-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-calendar-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-console-l3-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-enclave-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-job-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-kernel32-legacy-l1-1-6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-perfcounters-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-privateprofile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-privateprofile-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-processtopology-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-registry-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sidebyside-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sidebyside-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-string-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-stringansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-threadpool-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-toolhelp-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-toolhelp-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-versionansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-eventing-tdh-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-mm-time-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-oobe-notification-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-perf-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-limitsmanagement-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-security-systemfunctions-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shcore-unicodeansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-api-ms-win-shell-shdirectory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-authz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-crypt32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-dfscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-dsparse.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-dsrole.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-fltlib.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-logoncli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-mpr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-netutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-ntdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-powrprof.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-profapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-samcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-schedcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-srvcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-sspicli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-userenv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-websocket.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-winhttp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-wkscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-wldap32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore-xmllite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-apphelp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-comctl32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-comdlg32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3d10.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3d9.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-d3dx10_47.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-difxapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-gdi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-input.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-msi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-newdev.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oleacc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-oledlg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-pdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-psapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-resutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-secur32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-setupapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-shell32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-shlwapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-tdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-twinapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-user32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-uxtheme.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-version.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-winmm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-winspool.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecore_downlevel.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-appmodel-runtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-atoms-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-calendar-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-console-l3-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-debug-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-enclave-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-file-l2-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-firmware-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-job-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-kernel32-legacy-l1-1-6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-memory-l1-1-5.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-perfcounters-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-privateprofile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-privateprofile-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processenvironment-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processsnapshot-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-processtopology-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-psm-appnotify-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-quirks-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-quirks-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-registry-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-rtlsupport-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-shutdown-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sidebyside-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sidebyside-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-slapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-string-obsolete-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-stringansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-systemtopology-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-systemtopology-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-threadpool-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-toolhelp-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-toolhelp-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-util-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-version-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-versionansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-winrt-string-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-wow64-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-config-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-config-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-swdevice-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-devices-swdevice-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-dx-d3dkmt-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-consumer-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-eventing-tdh-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-expandedresources-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-gamemonitor-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-gamemonitor-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-gaming-tcui-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-misc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-misc-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-mme-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-playsound-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-mm-time-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-ntuser-sysparams-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-oobe-notification-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-perf-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-limitsmanagement-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-power-setting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-appcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-base-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-credentials-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-lsalookup-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-security-systemfunctions-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-core-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-management-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-management-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-service-winsvc-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-registry-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-registry-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shcore-unicodeansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shell-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-api-ms-win-shell-shdirectory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-authz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-chakra.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-coremessaging.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-crypt32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-cryptbase.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-cryptnet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-d2d1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-d3d11.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-d3d12.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dfscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dnsapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dsparse.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dsrole.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-dxgi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-esent.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-core-iuri-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-gaming-xinput-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-networking-wlanapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-shell32-shellfolders-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-shell32-shellfolders-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ext-ms-win-uiacore-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-fltlib.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-hid.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-logoncli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mfplat.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mpr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-msajapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-netutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ntdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-powrprof.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-profapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-propsys.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-rometadata.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-samcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-schedcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-srvcli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-sspicli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-urlmon.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-userenv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-webservices.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-websocket.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-winhttp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-wintrust.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-wkscli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-wlanapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-wldap32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-wpprecorderum.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-xaudio2_9.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap-xmllite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-apphelp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-comctl32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-comdlg32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3d10.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3d9.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-d3dx10_47.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-difxapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-gdi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-input.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-msi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-newdev.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oleacc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-oledlg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-pdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-psapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-resutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-secur32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-setupapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-shell32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-shlwapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-tdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-twinapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-user32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-uxtheme.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-version.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-winmm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-winspool.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_onecoreuap_downlevel.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_opengl32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_opmxbox.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_p2p.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_p2pgraph.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_pathcch.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_pdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_peerdist.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_powrprof.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_prntvpt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_propsys.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_psapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_quartz.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_query.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_qwave.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rasapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rasdlg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_resutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rometadata.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rpcexts.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rpcns4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rpcproxy.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rstrtmgr.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rtm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rtutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_rtworkq.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_runtimeobject.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_samlib.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_samsrv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sas.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_scarddlg.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_scecli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_scesrv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_schannel.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_secur32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_security.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sens.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sensapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sensorsutils.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_setupapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sfc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-scaling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shdocvw.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shell32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shfolder.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_shlwapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_slc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_slcext.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_slwga.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_snmpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_spoolss.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sporder.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_srpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ssdpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_sti.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_swdevice.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_synchronization.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_t2embed.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_tapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_tbs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_tdh.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_tokenbinding.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_traffic.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_tsec.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_txfw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ualapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_umpdddi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_urlmon.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_user32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_userenv.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_usp10.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_uxtheme.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_version.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vertdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vfw32-avicap32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vfw32-avifil32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vfw32-msvfw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vfw32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_virtdisk.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_vssapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wcmapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wdsbp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wdsclientapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wdsmc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wdspxe.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wdstptc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_webservices.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_websocket.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wecapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wer.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wevtapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wiaservc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winbio.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windows.networking.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windows.ui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-appmodel-runtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-appmodel-runtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-com-midlproxystub-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-comm-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-comm-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-console-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-console-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-datetime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-datetime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-debug-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-delayload-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-delayload-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-enclave-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-errorhandling-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-featurestaging-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-featurestaging-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-fibers-l2-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-file-l2-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-handle-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-heap-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-interlocked-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-interlocked-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-io-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-io-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-kernel32-legacy-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-kernel32-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-largeinteger-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-libraryloader-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-libraryloader-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-localization-obsolete-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-memory-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-ansi-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namedpipe-l1-2-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namespace-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-namespace-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-normalization-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-path-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processenvironment-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processthreads-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-processtopology-obsolete-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-profile-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psapi-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-psm-appnotify-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-realtime-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-rtlsupport-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-slapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-synch-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-sysinfo-l1-2-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-threadpool-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-timezone-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-url-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-util-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-version-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-versionansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowsceip-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-windowserrorreporting-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-error-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-error-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-registration-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-roparameterizediid-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-winrt-string-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-wow64-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-core-xstate-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-classicprovider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-consumer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-controller-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-legacy-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-eventing-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-deviceinformation-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-expandedresources-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-gamemonitor-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-gamemonitor-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-gaming-tcui-l1-1-4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-ro-typeresolution-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-base-l1-2-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-cryptoapi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-isolatedcontainer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-lsalookup-ansi-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-lsalookup-l2-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-provider-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-provider-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-sddl-ansi-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-security-sddl-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-api-ms-win-shcore-stream-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-bcrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-chakra.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-coremessaging.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-crypt32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-d2d1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-d3d11.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-d3d12.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-dwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-dxgi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-esent.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-core-iuri-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-gaming-xinput-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ext-ms-win-uiacore-l1-1-3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-hrtfapo.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-inkobjcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-iphlpapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mfplat.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mfsensorgroup.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-msajapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ncrypt.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ntdll.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-propsys.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-rometadata.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-sspicli.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-urlmon.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-webservices.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-xaudio2_9.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp-xmllite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-advapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-localization-l1-2-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-winrt-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-api-ms-win-core-winrt-robuffer-l1-1-0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-cabinet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d2d1.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d3d11.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-d3dcompiler_47.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-deviceaccess.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dhcpcsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dhcpcsvc6.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-dxgi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-esent.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-kernel32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mfplat.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mfreadwrite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mmdevapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-msajapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mscoree.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-mswsock.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-ole32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-oleaut32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-propsys.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-rpcrt4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-uiautomationcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-urlmon.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-webservices.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windows.data.pdf.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windows.networking.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xaudio2_8.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xinput1_4.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel-xmllite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowsapp_downlevel.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_windowscodecs.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winfax.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winhttp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wininet.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winmm.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winscard.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winspool.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winsqlite3.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winsta.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wintrust.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_winusb.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wlanapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wlanui.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wldap32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wmip.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wmvcore.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wnvapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wofutil.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_ws2_32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wscapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wsclient.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wsdapi.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wsmsvc.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wsnmp32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wsock32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_wtsapi32.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xaudio2.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xaudio2_8.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xinput.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xinput9_1_0.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xinputuap.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xmllite.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xolehlp.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xpsdocumenttargetprint.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/lib/libwinapi_xpsprint.a create mode 100644 anneal/v2/vendor/winapi-x86_64-pc-windows-gnu/src/lib.rs create mode 100644 anneal/v2/vendor/winapi/.cargo-checksum.json create mode 100644 anneal/v2/vendor/winapi/.cargo_vcs_info.json create mode 100644 anneal/v2/vendor/winapi/Cargo.toml create mode 100644 anneal/v2/vendor/winapi/Cargo.toml.orig create mode 100644 anneal/v2/vendor/winapi/LICENSE-APACHE create mode 100644 anneal/v2/vendor/winapi/LICENSE-MIT create mode 100644 anneal/v2/vendor/winapi/README.md create mode 100644 anneal/v2/vendor/winapi/build.rs create mode 100644 anneal/v2/vendor/winapi/src/km/d3dkmthk.rs create mode 100644 anneal/v2/vendor/winapi/src/km/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/lib.rs create mode 100644 anneal/v2/vendor/winapi/src/macros.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/basetsd.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/bcrypt.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/bthdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/bthioctl.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/bthsdpdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/bugcodes.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/cderr.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/cfg.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/d3d9.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/d3d9caps.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/d3d9types.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/d3dkmdt.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/d3dukmdt.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dcomptypes.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/devguid.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/devpkey.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/devpropdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dinputd.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi1_2.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi1_3.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi1_4.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi1_5.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgi1_6.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgiformat.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/dxgitype.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/evntprov.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/evntrace.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/guiddef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/hidclass.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/hidpi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/hidsdi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/hidusage.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ifdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ifmib.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/in6addr.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/inaddr.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/intsafe.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ipifcons.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ipmib.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/iprtrmib.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ks.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ksmedia.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ktmtypes.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/lmcons.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/minwindef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/mmreg.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/mprapidef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/mstcpip.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/mswsockdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/netioapi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/nldef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ntddndis.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ntddscsi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ntddser.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ntdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ntstatus.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/qos.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/rpc.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/rpcdce.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/rpcndr.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/sddl.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/sspi.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/stralign.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/tcpestats.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/tcpmib.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/transportsettingcommon.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/tvout.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/udpmib.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/usb.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/usbioctl.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/usbiodef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/usbscan.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/usbspec.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/windef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/windot11.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/windowsx.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/winerror.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/winusbio.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/wlantypes.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/wmistr.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/wnnc.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ws2def.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/ws2ipdef.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/wtypes.rs create mode 100644 anneal/v2/vendor/winapi/src/shared/wtypesbase.rs create mode 100644 anneal/v2/vendor/winapi/src/ucrt/corecrt.rs create mode 100644 anneal/v2/vendor/winapi/src/ucrt/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/um/accctrl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/aclapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/adhoc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/appmgmt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/audioclient.rs create mode 100644 anneal/v2/vendor/winapi/src/um/audiosessiontypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/avrt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits10_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits1_5.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits2_0.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits2_5.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits3_0.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits4_0.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bits5_0.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bitscfg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bitsmsg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bluetoothapis.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bluetoothleapis.rs create mode 100644 anneal/v2/vendor/winapi/src/um/bthledef.rs create mode 100644 anneal/v2/vendor/winapi/src/um/cfgmgr32.rs create mode 100644 anneal/v2/vendor/winapi/src/um/cguid.rs create mode 100644 anneal/v2/vendor/winapi/src/um/combaseapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/coml2api.rs create mode 100644 anneal/v2/vendor/winapi/src/um/commapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/commctrl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/commdlg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/commoncontrols.rs create mode 100644 anneal/v2/vendor/winapi/src/um/consoleapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/corsym.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1_2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1_3.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1effectauthor.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1effects.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1effects_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1effects_2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2d1svg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d2dbasetypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10_1shader.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10effect.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10misc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10sdklayers.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d10shader.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11_2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11_3.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11_4.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11on12.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11sdklayers.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11shader.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d11tokenizedprogramformat.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d12.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d12sdklayers.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3d12shader.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dcommon.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dcompiler.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dcsx.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dx10core.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dx10math.rs create mode 100644 anneal/v2/vendor/winapi/src/um/d3dx10mesh.rs create mode 100644 anneal/v2/vendor/winapi/src/um/datetimeapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/davclnt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dbghelp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dbt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dcommon.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dcomp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dcompanimation.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dde.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ddraw.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ddrawi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ddrawint.rs create mode 100644 anneal/v2/vendor/winapi/src/um/debugapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/devicetopology.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dinput.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dispex.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dmksctl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dmusicc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/docobj.rs create mode 100644 anneal/v2/vendor/winapi/src/um/documenttarget.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dot1x.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dpa_dsa.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dpapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dsgetdc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dsound.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dsrole.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dvp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dwmapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dwrite.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dwrite_1.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dwrite_2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dwrite_3.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dxdiag.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dxfile.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dxgidebug.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dxva2api.rs create mode 100644 anneal/v2/vendor/winapi/src/um/dxvahd.rs create mode 100644 anneal/v2/vendor/winapi/src/um/eaptypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/enclaveapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/endpointvolume.rs create mode 100644 anneal/v2/vendor/winapi/src/um/errhandlingapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/evntcons.rs create mode 100644 anneal/v2/vendor/winapi/src/um/exdisp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/fibersapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/fileapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/functiondiscoverykeys_devpkey.rs create mode 100644 anneal/v2/vendor/winapi/src/um/gl/gl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/gl/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/um/handleapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/heapapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/highlevelmonitorconfigurationapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/http.rs create mode 100644 anneal/v2/vendor/winapi/src/um/imm.rs create mode 100644 anneal/v2/vendor/winapi/src/um/interlockedapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ioapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ipexport.rs create mode 100644 anneal/v2/vendor/winapi/src/um/iphlpapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/iptypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/jobapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/jobapi2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/knownfolders.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ktmw32.rs create mode 100644 anneal/v2/vendor/winapi/src/um/l2cmn.rs create mode 100644 anneal/v2/vendor/winapi/src/um/libloaderapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmaccess.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmalert.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmapibuf.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmat.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmdfs.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmerrlog.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmjoin.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmmsg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmremutl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmrepl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmserver.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmshare.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmstats.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmsvc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmuse.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lmwksta.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lowlevelmonitorconfigurationapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/lsalookup.rs create mode 100644 anneal/v2/vendor/winapi/src/um/memoryapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/minschannel.rs create mode 100644 anneal/v2/vendor/winapi/src/um/minwinbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mmdeviceapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mmeapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mmsystem.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/um/msaatext.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mscat.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mschapp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mssip.rs create mode 100644 anneal/v2/vendor/winapi/src/um/mswsock.rs create mode 100644 anneal/v2/vendor/winapi/src/um/namedpipeapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/namespaceapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/nb30.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ncrypt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ntlsa.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ntsecapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/oaidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/objbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/objidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/objidlbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ocidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ole2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/oleauto.rs create mode 100644 anneal/v2/vendor/winapi/src/um/olectl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/oleidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/opmapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/pdh.rs create mode 100644 anneal/v2/vendor/winapi/src/um/perflib.rs create mode 100644 anneal/v2/vendor/winapi/src/um/physicalmonitorenumerationapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/playsoundapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/portabledevice.rs create mode 100644 anneal/v2/vendor/winapi/src/um/portabledeviceapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/portabledevicetypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/powerbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/powersetting.rs create mode 100644 anneal/v2/vendor/winapi/src/um/powrprof.rs create mode 100644 anneal/v2/vendor/winapi/src/um/processenv.rs create mode 100644 anneal/v2/vendor/winapi/src/um/processsnapshot.rs create mode 100644 anneal/v2/vendor/winapi/src/um/processthreadsapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/processtopologyapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/profileapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/propidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/propkey.rs create mode 100644 anneal/v2/vendor/winapi/src/um/propkeydef.rs create mode 100644 anneal/v2/vendor/winapi/src/um/propsys.rs create mode 100644 anneal/v2/vendor/winapi/src/um/prsht.rs create mode 100644 anneal/v2/vendor/winapi/src/um/psapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/realtimeapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/reason.rs create mode 100644 anneal/v2/vendor/winapi/src/um/restartmanager.rs create mode 100644 anneal/v2/vendor/winapi/src/um/restrictederrorinfo.rs create mode 100644 anneal/v2/vendor/winapi/src/um/rmxfguid.rs create mode 100644 anneal/v2/vendor/winapi/src/um/rtinfo.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sapi51.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sapi53.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sapiddk.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sapiddk51.rs create mode 100644 anneal/v2/vendor/winapi/src/um/schannel.rs create mode 100644 anneal/v2/vendor/winapi/src/um/securityappcontainer.rs create mode 100644 anneal/v2/vendor/winapi/src/um/securitybaseapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/servprov.rs create mode 100644 anneal/v2/vendor/winapi/src/um/setupapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shellapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shellscalingapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shlobj.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shobjidl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shobjidl_core.rs create mode 100644 anneal/v2/vendor/winapi/src/um/shtypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/softpub.rs create mode 100644 anneal/v2/vendor/winapi/src/um/spapidef.rs create mode 100644 anneal/v2/vendor/winapi/src/um/spellcheck.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sporder.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sql.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sqlext.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sqltypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sqlucode.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sspi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/stringapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/strmif.rs create mode 100644 anneal/v2/vendor/winapi/src/um/subauth.rs create mode 100644 anneal/v2/vendor/winapi/src/um/synchapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/sysinfoapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/systemtopologyapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/taskschd.rs create mode 100644 anneal/v2/vendor/winapi/src/um/textstor.rs create mode 100644 anneal/v2/vendor/winapi/src/um/threadpoolapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/threadpoollegacyapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/timeapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/timezoneapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/tlhelp32.rs create mode 100644 anneal/v2/vendor/winapi/src/um/unknwnbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/urlhist.rs create mode 100644 anneal/v2/vendor/winapi/src/um/urlmon.rs create mode 100644 anneal/v2/vendor/winapi/src/um/userenv.rs create mode 100644 anneal/v2/vendor/winapi/src/um/usp10.rs create mode 100644 anneal/v2/vendor/winapi/src/um/utilapiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/uxtheme.rs create mode 100644 anneal/v2/vendor/winapi/src/um/vsbackup.rs create mode 100644 anneal/v2/vendor/winapi/src/um/vss.rs create mode 100644 anneal/v2/vendor/winapi/src/um/vsserror.rs create mode 100644 anneal/v2/vendor/winapi/src/um/vswriter.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wbemads.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wbemcli.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wbemdisp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wbemprov.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wbemtran.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wct.rs create mode 100644 anneal/v2/vendor/winapi/src/um/werapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winbase.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincodec.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincodecsdk.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincon.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincontypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincred.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wincrypt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/windowsceip.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winefs.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winevt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wingdi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winhttp.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wininet.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winineti.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winioctl.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winnetwk.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winnls.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winnt.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winreg.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winsafer.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winscard.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winsmcrd.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winsock2.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winspool.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winsvc.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wintrust.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winusb.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winuser.rs create mode 100644 anneal/v2/vendor/winapi/src/um/winver.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wlanapi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wlanihv.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wlanihvtypes.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wlclient.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wow64apiset.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wpdmtpextensions.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ws2bth.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ws2spi.rs create mode 100644 anneal/v2/vendor/winapi/src/um/ws2tcpip.rs create mode 100644 anneal/v2/vendor/winapi/src/um/wtsapi32.rs create mode 100644 anneal/v2/vendor/winapi/src/um/xinput.rs create mode 100644 anneal/v2/vendor/winapi/src/vc/excpt.rs create mode 100644 anneal/v2/vendor/winapi/src/vc/limits.rs create mode 100644 anneal/v2/vendor/winapi/src/vc/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/vc/vadefs.rs create mode 100644 anneal/v2/vendor/winapi/src/vc/vcruntime.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/activation.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/hstring.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/inspectable.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/mod.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/roapi.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/robuffer.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/roerrorapi.rs create mode 100644 anneal/v2/vendor/winapi/src/winrt/winstring.rs diff --git a/anneal/v2/Cargo.lock b/anneal/v2/Cargo.lock index d540fbaf9c..619fc5e919 100644 --- a/anneal/v2/Cargo.lock +++ b/anneal/v2/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + [[package]] name = "adler2" version = "2.0.1" @@ -73,6 +82,30 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + [[package]] name = "base64" version = "0.22.1" @@ -85,6 +118,15 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.12.0" @@ -94,21 +136,73 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + [[package]] name = "cargo-anneal" version = "0.1.0-alpha.22" dependencies = [ + "anyhow", + "cargo_metadata", "clap", + "clap-cargo", "env_logger", "exocrate", + "fs2", + "indicatif", "log", + "miette", + "rayon", + "serde", + "serde_json", + "sha2 0.10.9", + "tempfile", + "thiserror", "toml_const", + "walkdir", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", ] [[package]] @@ -139,6 +233,19 @@ dependencies = [ "clap_derive", ] +[[package]] +name = "clap-cargo" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936551935c8258754bb8216aec040957d261f977303754b9bf1a213518388006" +dependencies = [ + "anstyle", + "cargo_metadata", + "clap", + "serde", + "serde_json", +] + [[package]] name = "clap_builder" version = "4.6.0" @@ -175,12 +282,33 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "console" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width 0.2.2", + "windows-sys 0.61.2", +] + [[package]] name = "const-oid" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "cpufeatures" version = "0.3.0" @@ -199,6 +327,41 @@ dependencies = [ "cfg-if", ] +[[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 = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "crypto-common" version = "0.2.2" @@ -208,15 +371,25 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + [[package]] name = "digest" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer", + "block-buffer 0.12.0", "const-oid", - "crypto-common", + "crypto-common 0.2.2", ] [[package]] @@ -240,6 +413,18 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "env_filter" version = "1.0.1" @@ -287,7 +472,7 @@ dependencies = [ "fs4", "libc", "log", - "sha2", + "sha2 0.11.0", "sha2-const", "tar", "tempfile", @@ -335,6 +520,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "fs4" version = "1.1.0" @@ -345,6 +540,40 @@ dependencies = [ "windows-sys 0.61.2", ] +[[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 = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -381,6 +610,12 @@ dependencies = [ "wasip3", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + [[package]] name = "hashbrown" version = "0.15.5" @@ -445,6 +680,26 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indicatif" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" +dependencies = [ + "console", + "portable-atomic", + "unicode-segmentation", + "unicode-width 0.2.2", + "unit-prefix", + "web-time", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -491,6 +746,18 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + [[package]] name = "leb128fmt" version = "0.1.0" @@ -530,6 +797,36 @@ version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -540,6 +837,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -558,6 +864,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -607,6 +919,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "pkg-config" version = "0.3.33" @@ -668,6 +986,26 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -722,6 +1060,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + [[package]] name = "rustix" version = "1.1.4" @@ -770,11 +1114,30 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "serde" @@ -783,6 +1146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -827,6 +1191,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.11.0" @@ -834,8 +1209,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -862,6 +1237,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "strsim" version = "0.11.1" @@ -874,6 +1255,27 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + [[package]] name = "syn" version = "2.0.117" @@ -909,6 +1311,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.2.2", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -1004,12 +1426,42 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "untrusted" version = "0.9.0" @@ -1057,6 +1509,22 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1081,6 +1549,51 @@ dependencies = [ "wit-bindgen 0.51.0", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + [[package]] name = "wasm-encoder" version = "0.244.0" @@ -1115,6 +1628,16 @@ dependencies = [ "semver", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "1.0.7" @@ -1124,6 +1647,37 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +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 0.61.2", +] + +[[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" diff --git a/anneal/v2/Cargo.toml b/anneal/v2/Cargo.toml index a379165b4c..9a5f8ce0b0 100644 --- a/anneal/v2/Cargo.toml +++ b/anneal/v2/Cargo.toml @@ -45,5 +45,18 @@ url = "https://example.com/macos-aarch64.tar.zst" exocrate = { path = "./exocrate" } toml_const = "1.3.0" clap = { version = "4.5", features = ["derive"] } +clap-cargo = { version = "0.18.3", features = ["cargo_metadata"] } env_logger = "0.11" log = "0.4" +anyhow = "1.0.102" +cargo_metadata = "0.23.1" +miette = { version = "7.6.0", features = ["derive", "fancy"] } +thiserror = "2.0.18" +serde_json = "1.0.149" +serde = { version = "1.0.228", features = ["derive"] } +indicatif = { version = "0.18.4", features = ["improved_unicode"] } +fs2 = "0.4" +walkdir = "2.5.0" +sha2 = "0.10" +tempfile = "3.27.0" +rayon = "1.11.0" diff --git a/anneal/v2/vendor/addr2line/.cargo-checksum.json b/anneal/v2/vendor/addr2line/.cargo-checksum.json new file mode 100644 index 0000000000..e3bcc6a06a --- /dev/null +++ b/anneal/v2/vendor/addr2line/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"70f22e279a4a1b2697dfc1b53ead965a913faa3d2604545c439b28a24bf5eaf5","CHANGELOG.md":"2bfe37c8240577170e3e9122c2e17942e8b2aba73fee100eeeede47b1107f8b8","Cargo.lock":"c9e56108c9a0cadb122774fbe24b2085a521ac1252686dc3cb70ae165af6bdf2","Cargo.toml":"6c371cb14bed07740324acb5b126bd58cf87771be72d4d88366b000f138b8001","Cargo.toml.orig":"1ce22b0b31c6bd077501c96cd568a95ee894042d651b0db9245a2f4395d12872","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"c635ed91d7b0c87ff2f0f311cd1a31336d2cbc4d011965d3b58afaca073538d9","src/bin/addr2line.rs":"147c07d761c845c5faf3e1e3904c33374bc84bc79b2b95ae892b1def5ce6ced6","src/frame.rs":"de3b23388c36a0874db5569d1f49ce6cc52ef2006b9ae9b9a3eba7654b201e2b","src/function.rs":"6e0aceeb826db8fcec78376ee72b5dca098ae3e409e9defc5f1af9bfb2c7f173","src/lib.rs":"79fea2e8912719a0a4e30207839e7689e66f6c801a80dde3e81f0fed9c7fd3e8","src/line.rs":"374afffcd11e38dc1b093d38b16b42d33c2a5fa9e7dbb759ecf15c1f6c58a7a0","src/loader.rs":"d94f6ca760382a2f3260fa8e6382196eaba07aaced308f088e8957f94cd21479","src/lookup.rs":"0d28a2fd00f0696f8fb50cdc88cb7d55a910df8bf3052b7c74ae50a387346e67","src/unit.rs":"ec201e91333dc8919ab64f0144025521c46ac897679538432a84788af5244667"},"package":"1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"} \ No newline at end of file diff --git a/anneal/v2/vendor/addr2line/.cargo_vcs_info.json b/anneal/v2/vendor/addr2line/.cargo_vcs_info.json new file mode 100644 index 0000000000..1c33eaf6da --- /dev/null +++ b/anneal/v2/vendor/addr2line/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f02db009deb9b441818afa49cb1b17453c1e4243" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/addr2line/CHANGELOG.md b/anneal/v2/vendor/addr2line/CHANGELOG.md new file mode 100644 index 0000000000..5c2cc45194 --- /dev/null +++ b/anneal/v2/vendor/addr2line/CHANGELOG.md @@ -0,0 +1,485 @@ +# `addr2line` Change Log + +-------------------------------------------------------------------------------- + +## 0.25.1 (2025/09/13) + +### Changed + +* Fixed line parsing for split DWARF. + [#353](https://github.com/gimli-rs/addr2line/pull/353) + +* Changed `.debug_aranges` parsing to skip invalid entries instead of failing. + [#355](https://github.com/gimli-rs/addr2line/pull/355) + +-------------------------------------------------------------------------------- + +## 0.25.0 (2025/06/11) + +### Breaking changes + +* Updated `gimli` dependency. + +### Added + +* Added `Loader::find_symbol`. + [#341](https://github.com/gimli-rs/addr2line/pull/341) + [#349](https://github.com/gimli-rs/addr2line/pull/349) + +* Added `Loader::get_section_range`. + Added `--section` option to `addr2line` binary. + [#343](https://github.com/gimli-rs/addr2line/pull/343) + +* Added `wasm` feature. + [#348](https://github.com/gimli-rs/addr2line/pull/348) + +### Changed + +* Fixed handling of Windows paths that use forward slashes. + [#342](https://github.com/gimli-rs/addr2line/pull/342) + +* Removed `compiler-builtins` from `rustc-dep-of-std` dependencies. + [#345](https://github.com/gimli-rs/addr2line/pull/345) + +-------------------------------------------------------------------------------- + +## 0.24.2 (2024/10/04) + +### Changed + +* Enabled caching of DWARF abbreviations. + [#318](https://github.com/gimli-rs/addr2line/pull/318) + +* Changed the `addr2line` binary to prefer symbol names over DWARF names. + [#332](https://github.com/gimli-rs/addr2line/pull/332) + +* Updated `gimli` dependency. + +### Added + +* Added `Context::from_arc_dwarf`. + [#327](https://github.com/gimli-rs/addr2line/pull/327) + +* Added benchmark comparison. + [#315](https://github.com/gimli-rs/addr2line/pull/315) + [#321](https://github.com/gimli-rs/addr2line/pull/321) + [#322](https://github.com/gimli-rs/addr2line/pull/322) + [#325](https://github.com/gimli-rs/addr2line/pull/325) + +* Added more tests. + [#328](https://github.com/gimli-rs/addr2line/pull/328) + [#330](https://github.com/gimli-rs/addr2line/pull/330) + [#331](https://github.com/gimli-rs/addr2line/pull/331) + [#333](https://github.com/gimli-rs/addr2line/pull/333) + +-------------------------------------------------------------------------------- + +## 0.24.1 (2024/07/26) + +### Changed + +* Fixed parsing of partial units, which are found in supplementary object files. + [#313](https://github.com/gimli-rs/addr2line/pull/313) + +-------------------------------------------------------------------------------- + +## 0.24.0 (2024/07/16) + +### Breaking changes + +* Updated `gimli` dependency. + +### Changed + +* Changed the order of ranges returned by `Context::find_location_range`, and + fixed handling in rare situations. + [#303](https://github.com/gimli-rs/addr2line/pull/303) + [#304](https://github.com/gimli-rs/addr2line/pull/304) + [#306](https://github.com/gimli-rs/addr2line/pull/306) + +* Improved the performance of `Context::find_location`. + [#305](https://github.com/gimli-rs/addr2line/pull/305) + +### Added + +* Added `LoaderReader`. + [#307](https://github.com/gimli-rs/addr2line/pull/307) + +* Added `--all` option to `addr2line`. + [#307](https://github.com/gimli-rs/addr2line/pull/307) + +-------------------------------------------------------------------------------- + +## 0.23.0 (2024/05/26) + +### Breaking changes + +* Updated `gimli` dependency. + +* Deleted `Context::new`, `Context::new_with_sup`, and `builtin_split_dwarf_loader`. + Use `Context::from_dwarf` or `Loader::new` instead. + This removes `object` from the public API. + [#296](https://github.com/gimli-rs/addr2line/pull/296) + +### Changed + +* Fixed handling of column 0 in the line table. + [#290](https://github.com/gimli-rs/addr2line/pull/290) + +* Moved `addr2line` from `examples` to `bin`. Requires the `bin` feature. + [#291](https://github.com/gimli-rs/addr2line/pull/291) + +* Split up `lib.rs` into smaller modules. + [#292](https://github.com/gimli-rs/addr2line/pull/292) + +### Added + +* Added `Loader`. Requires the `loader` feature. + [#296](https://github.com/gimli-rs/addr2line/pull/296) + [#297](https://github.com/gimli-rs/addr2line/pull/297) + +* Added unpacked Mach-O support to `Loader`. + [#298](https://github.com/gimli-rs/addr2line/pull/298) + +-------------------------------------------------------------------------------- + +## 0.22.0 (2024/04/11) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +-------------------------------------------------------------------------------- + +## 0.21.0 (2023/08/12) + +### Breaking changes + +* Updated `gimli`, `object`, and `fallible-iterator` dependencies. + +### Changed + +* The minimum supported rust version is 1.65.0. + +* Store boxed slices instead of `Vec` objects in `Context`. + [#278](https://github.com/gimli-rs/addr2line/pull/278) + +-------------------------------------------------------------------------------- + +## 0.20.0 (2023/04/15) + +### Breaking changes + +* The minimum supported rust version is 1.58.0. + +* Changed `Context::find_frames` to return `LookupResult`. + Use `LookupResult::skip_all_loads` to obtain the result without loading split DWARF. + [#260](https://github.com/gimli-rs/addr2line/pull/260) + +* Replaced `Context::find_dwarf_unit` with `Context::find_dwarf_and_unit`. + [#260](https://github.com/gimli-rs/addr2line/pull/260) + +* Updated `object` dependency. + +### Changed + +* Fix handling of file index 0 for DWARF 5. + [#264](https://github.com/gimli-rs/addr2line/pull/264) + +### Added + +* Added types and methods to support loading split DWARF: + `LookupResult`, `SplitDwarfLoad`, `SplitDwarfLoader`, `Context::preload_units`. + [#260](https://github.com/gimli-rs/addr2line/pull/260) + [#262](https://github.com/gimli-rs/addr2line/pull/262) + [#263](https://github.com/gimli-rs/addr2line/pull/263) + +-------------------------------------------------------------------------------- + +## 0.19.0 (2022/11/24) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +-------------------------------------------------------------------------------- + +## 0.18.0 (2022/07/16) + +### Breaking changes + +* Updated `object` dependency. + +### Changed + +* Fixed handling of relative path for `DW_AT_comp_dir`. + [#239](https://github.com/gimli-rs/addr2line/pull/239) + +* Fixed handling of `DW_FORM_addrx` for DWARF 5 support. + [#243](https://github.com/gimli-rs/addr2line/pull/243) + +* Fixed handling of units that are missing range information. + [#249](https://github.com/gimli-rs/addr2line/pull/249) + +-------------------------------------------------------------------------------- + +## 0.17.0 (2021/10/24) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +### Changed + +* Use `skip_attributes` to improve performance. + [#236](https://github.com/gimli-rs/addr2line/pull/236) + +-------------------------------------------------------------------------------- + +## 0.16.0 (2021/07/26) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +-------------------------------------------------------------------------------- + +## 0.15.2 (2021/06/04) + +### Fixed + +* Allow `Context` to be `Send`. + [#219](https://github.com/gimli-rs/addr2line/pull/219) + +-------------------------------------------------------------------------------- + +## 0.15.1 (2021/05/02) + +### Fixed + +* Don't ignore aranges with address 0. + [#217](https://github.com/gimli-rs/addr2line/pull/217) + +-------------------------------------------------------------------------------- + +## 0.15.0 (2021/05/02) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + [#215](https://github.com/gimli-rs/addr2line/pull/215) + +* Added `debug_aranges` parameter to `Context::from_sections`. + [#200](https://github.com/gimli-rs/addr2line/pull/200) + +### Added + +* Added `.debug_aranges` support. + [#200](https://github.com/gimli-rs/addr2line/pull/200) + +* Added supplementary object file support. + [#208](https://github.com/gimli-rs/addr2line/pull/208) + +### Fixed + +* Fixed handling of Windows paths in locations. + [#209](https://github.com/gimli-rs/addr2line/pull/209) + +* examples/addr2line: Flush stdout after each response. + [#210](https://github.com/gimli-rs/addr2line/pull/210) + +* examples/addr2line: Avoid copying every section. + [#213](https://github.com/gimli-rs/addr2line/pull/213) + +-------------------------------------------------------------------------------- + +## 0.14.1 (2020/12/31) + +### Fixed + +* Fix location lookup for skeleton units. + [#201](https://github.com/gimli-rs/addr2line/pull/201) + +### Added + +* Added `Context::find_location_range`. + [#196](https://github.com/gimli-rs/addr2line/pull/196) + [#199](https://github.com/gimli-rs/addr2line/pull/199) + +-------------------------------------------------------------------------------- + +## 0.14.0 (2020/10/27) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +### Fixed + +* Handle units that only have line information. + [#188](https://github.com/gimli-rs/addr2line/pull/188) + +* Handle DWARF units with version <= 4 and no `DW_AT_name`. + [#191](https://github.com/gimli-rs/addr2line/pull/191) + +* Fix handling of `DW_FORM_ref_addr`. + [#193](https://github.com/gimli-rs/addr2line/pull/193) + +-------------------------------------------------------------------------------- + +## 0.13.0 (2020/07/07) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +* Added `rustc-dep-of-std` feature. + [#166](https://github.com/gimli-rs/addr2line/pull/166) + +### Changed + +* Improve performance by parsing function contents lazily. + [#178](https://github.com/gimli-rs/addr2line/pull/178) + +* Don't skip `.debug_info` and `.debug_line` entries with a zero address. + [#182](https://github.com/gimli-rs/addr2line/pull/182) + +-------------------------------------------------------------------------------- + +## 0.12.2 (2020/06/21) + +### Fixed + +* Avoid linear search for `DW_FORM_ref_addr`. + [#175](https://github.com/gimli-rs/addr2line/pull/175) + +-------------------------------------------------------------------------------- + +## 0.12.1 (2020/05/19) + +### Fixed + +* Handle units with overlapping address ranges. + [#163](https://github.com/gimli-rs/addr2line/pull/163) + +* Don't assert for functions with overlapping address ranges. + [#168](https://github.com/gimli-rs/addr2line/pull/168) + +-------------------------------------------------------------------------------- + +## 0.12.0 (2020/05/12) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +* Added more optional features: `smallvec` and `fallible-iterator`. + [#160](https://github.com/gimli-rs/addr2line/pull/160) + +### Added + +* Added `Context::dwarf` and `Context::find_dwarf_unit`. + [#159](https://github.com/gimli-rs/addr2line/pull/159) + +### Changed + +* Removed `lazycell` dependency. + [#160](https://github.com/gimli-rs/addr2line/pull/160) + +-------------------------------------------------------------------------------- + +## 0.11.0 (2020/01/11) + +### Breaking changes + +* Updated `gimli` and `object` dependencies. + +* [#130](https://github.com/gimli-rs/addr2line/pull/130) + Changed `Location::file` from `Option` to `Option<&str>`. + This required adding lifetime parameters to `Location` and other structs that + contain it. + +* [#152](https://github.com/gimli-rs/addr2line/pull/152) + Changed `Location::line` and `Location::column` from `Option`to `Option`. + +* [#156](https://github.com/gimli-rs/addr2line/pull/156) + Deleted `alloc` feature, and fixed `no-std` builds with stable rust. + Removed default `Reader` parameter for `Context`, and added `ObjectContext` instead. + +### Added + +* [#134](https://github.com/gimli-rs/addr2line/pull/134) + Added `Context::from_dwarf`. + +### Changed + +* [#133](https://github.com/gimli-rs/addr2line/pull/133) + Fixed handling of units that can't be parsed. + +* [#155](https://github.com/gimli-rs/addr2line/pull/155) + Fixed `addr2line` output to match binutils. + +* [#130](https://github.com/gimli-rs/addr2line/pull/130) + Improved `.debug_line` parsing performance. + +* [#148](https://github.com/gimli-rs/addr2line/pull/148) + [#150](https://github.com/gimli-rs/addr2line/pull/150) + [#151](https://github.com/gimli-rs/addr2line/pull/151) + [#152](https://github.com/gimli-rs/addr2line/pull/152) + Improved `.debug_info` parsing performance. + +* [#137](https://github.com/gimli-rs/addr2line/pull/137) + [#138](https://github.com/gimli-rs/addr2line/pull/138) + [#139](https://github.com/gimli-rs/addr2line/pull/139) + [#140](https://github.com/gimli-rs/addr2line/pull/140) + [#146](https://github.com/gimli-rs/addr2line/pull/146) + Improved benchmarks. + +-------------------------------------------------------------------------------- + +## 0.10.0 (2019/07/07) + +### Breaking changes + +* [#127](https://github.com/gimli-rs/addr2line/pull/127) + Update `gimli`. + +-------------------------------------------------------------------------------- + +## 0.9.0 (2019/05/02) + +### Breaking changes + +* [#121](https://github.com/gimli-rs/addr2line/pull/121) + Update `gimli`, `object`, and `fallible-iterator` dependencies. + +### Added + +* [#121](https://github.com/gimli-rs/addr2line/pull/121) + Reexport `gimli`, `object`, and `fallible-iterator`. + +-------------------------------------------------------------------------------- + +## 0.8.0 (2019/02/06) + +### Breaking changes + +* [#107](https://github.com/gimli-rs/addr2line/pull/107) + Update `object` dependency to 0.11. This is part of the public API. + +### Added + +* [#101](https://github.com/gimli-rs/addr2line/pull/101) + Add `object` feature (enabled by default). Disable this feature to remove + the `object` dependency and `Context::new` API. + +* [#102](https://github.com/gimli-rs/addr2line/pull/102) + Add `std` (enabled by default) and `alloc` features. + +### Changed + +* [#108](https://github.com/gimli-rs/addr2line/issues/108) + `demangle` no longer outputs the hash for rust symbols. + +* [#109](https://github.com/gimli-rs/addr2line/issues/109) + Set default `R` for `Context`. diff --git a/anneal/v2/vendor/addr2line/Cargo.lock b/anneal/v2/vendor/addr2line/Cargo.lock new file mode 100644 index 0000000000..47feaae49e --- /dev/null +++ b/anneal/v2/vendor/addr2line/Cargo.lock @@ -0,0 +1,1089 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli 0.31.1", +] + +[[package]] +name = "addr2line" +version = "0.25.1" +dependencies = [ + "backtrace", + "clap", + "cpp_demangle", + "criterion", + "fallible-iterator", + "findshlibs", + "gimli 0.32.3", + "libtest-mimic", + "memmap2", + "object 0.37.3", + "rustc-demangle", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "smallvec", + "typed-arena", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line 0.24.2", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.36.7", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "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.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "cpp_demangle" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +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 = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.0", +] + +[[package]] +name = "escape8259" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +dependencies = [ + "fallible-iterator", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "stable_deref_trait", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libtest-mimic" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5297962ef19edda4ce33aaa484386e0a5b3d7f2f4e037cbeee00503ef6b29d33" +dependencies = [ + "anstream", + "anstyle", + "clap", + "escape8259", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" +dependencies = [ + "libc", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "flate2", + "memchr", + "ruzstd", + "wasmparser", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[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 = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d441c3b2ebf55cebf796bfdc265d67fa09db17b7bb6bd4be75c509e1e8fec3" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9c45b374136f52f2d6311062c7146bff20fec063c3f5d46a410bd937746955" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.0", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ruzstd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +dependencies = [ + "rustix", + "windows-sys 0.60.2", +] + +[[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 = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasmparser" +version = "0.236.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7" +dependencies = [ + "bitflags", +] + +[[package]] +name = "web-sys" +version = "0.3.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +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 0.61.0", +] + +[[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.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link 0.1.3", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/anneal/v2/vendor/addr2line/Cargo.toml b/anneal/v2/vendor/addr2line/Cargo.toml new file mode 100644 index 0000000000..c734b4c67f --- /dev/null +++ b/anneal/v2/vendor/addr2line/Cargo.toml @@ -0,0 +1,164 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.81" +name = "addr2line" +version = "0.25.1" +build = false +include = [ + "/CHANGELOG.md", + "/Cargo.lock", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A cross-platform symbolication library written in Rust, using `gimli`" +documentation = "https://docs.rs/addr2line" +readme = "README.md" +keywords = [ + "DWARF", + "debug", + "elf", + "symbolicate", + "atos", +] +categories = ["development-tools::debugging"] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/gimli-rs/addr2line" + +[features] +all = [ + "bin", + "wasm", +] +bin = [ + "loader", + "rustc-demangle", + "cpp_demangle", + "fallible-iterator", + "smallvec", + "dep:clap", +] +cargo-all = [] +default = [ + "rustc-demangle", + "cpp_demangle", + "loader", + "fallible-iterator", + "smallvec", +] +loader = [ + "std", + "dep:object", + "dep:memmap2", + "dep:typed-arena", +] +rustc-dep-of-std = [ + "core", + "alloc", + "gimli/rustc-dep-of-std", +] +std = ["gimli/std"] +wasm = ["object/wasm"] + +[lib] +name = "addr2line" +path = "src/lib.rs" + +[[bin]] +name = "addr2line" +path = "src/bin/addr2line.rs" +required-features = ["bin"] + +[dependencies.alloc] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-alloc" + +[dependencies.clap] +version = "4.3.21" +features = ["wrap_help"] +optional = true + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.cpp_demangle] +version = "0.4" +features = ["alloc"] +optional = true +default-features = false + +[dependencies.fallible-iterator] +version = "0.3.0" +optional = true +default-features = false + +[dependencies.gimli] +version = "0.32.0" +features = ["read"] +default-features = false + +[dependencies.memmap2] +version = "0.9.4" +optional = true + +[dependencies.object] +version = "0.37.0" +features = [ + "read", + "compression", +] +optional = true +default-features = false + +[dependencies.rustc-demangle] +version = "0.1" +optional = true + +[dependencies.smallvec] +version = "1" +optional = true +default-features = false + +[dependencies.typed-arena] +version = "2" +optional = true + +[dev-dependencies.backtrace] +version = "0.3.13" + +[dev-dependencies.criterion] +version = "0.7.0" + +[dev-dependencies.findshlibs] +version = "0.10" + +[dev-dependencies.libtest-mimic] +version = "0.8.1" + +[profile.bench] +codegen-units = 1 +debug = 2 + +[profile.release] +debug = 2 diff --git a/anneal/v2/vendor/addr2line/Cargo.toml.orig b/anneal/v2/vendor/addr2line/Cargo.toml.orig new file mode 100644 index 0000000000..d155a15926 --- /dev/null +++ b/anneal/v2/vendor/addr2line/Cargo.toml.orig @@ -0,0 +1,92 @@ +[package] +name = "addr2line" +version = "0.25.1" +description = "A cross-platform symbolication library written in Rust, using `gimli`" +documentation = "https://docs.rs/addr2line" +keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"] +categories = ["development-tools::debugging"] +license = "Apache-2.0 OR MIT" +readme = "./README.md" +repository = "https://github.com/gimli-rs/addr2line" +edition = "2018" +rust-version = "1.81" +include = [ + "/CHANGELOG.md", + "/Cargo.lock", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src", +] + +[dependencies] +gimli = { version = "0.32.0", default-features = false, features = ["read"] } +fallible-iterator = { version = "0.3.0", default-features = false, optional = true } +smallvec = { version = "1", default-features = false, optional = true } +rustc-demangle = { version = "0.1", optional = true } +cpp_demangle = { version = "0.4", default-features = false, features = ["alloc"], optional = true } + +# loader dependencies +object = { version = "0.37.0", default-features = false, features = ["read", "compression"], optional = true } +memmap2 = { version = "0.9.4", optional = true } +typed-arena = { version = "2", optional = true } + +# bin dependencies +clap = { version = "4.3.21", features = ["wrap_help"], optional = true } + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +alloc = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-alloc' } + +[dev-dependencies] +backtrace = "0.3.13" +criterion = "0.7.0" +findshlibs = "0.10" +libtest-mimic = "0.8.1" +auxiliary = { path = "tests/auxiliary" } + +[profile.release] +debug = true + +[profile.bench] +debug = true +codegen-units = 1 + +[features] +default = ["rustc-demangle", "cpp_demangle", "loader", "fallible-iterator", "smallvec"] +std = ["gimli/std"] +wasm = ["object/wasm"] +loader = ["std", "dep:object", "dep:memmap2", "dep:typed-arena"] +bin = ["loader", "rustc-demangle", "cpp_demangle", "fallible-iterator", "smallvec", "dep:clap"] +all = ["bin", "wasm"] + +# Use of --all-features is not supported. +# This is a dummy feature to detect when --all-features is used. +cargo-all = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core', 'alloc', 'gimli/rustc-dep-of-std'] + +[[test]] +name = "testinput" +harness = false +required-features = ["bin"] + +[[test]] +name = "correctness" +required-features = ["loader", "fallible-iterator"] + +[[test]] +name = "parse" +required-features = ["loader"] + +[[bin]] +name = "addr2line" +required-features = ["bin"] + +[[bench]] +name = "bench" +harness = false diff --git a/anneal/v2/vendor/addr2line/LICENSE-APACHE b/anneal/v2/vendor/addr2line/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/addr2line/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/addr2line/LICENSE-MIT b/anneal/v2/vendor/addr2line/LICENSE-MIT new file mode 100644 index 0000000000..3a03f1f850 --- /dev/null +++ b/anneal/v2/vendor/addr2line/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016-2018 The gimli Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/addr2line/README.md b/anneal/v2/vendor/addr2line/README.md new file mode 100644 index 0000000000..74cf3336c8 --- /dev/null +++ b/anneal/v2/vendor/addr2line/README.md @@ -0,0 +1,50 @@ +# addr2line + +[![](https://img.shields.io/crates/v/addr2line.svg)](https://crates.io/crates/addr2line) +[![](https://img.shields.io/docsrs/addr2line.svg)](https://docs.rs/addr2line) +[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/addr2line/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/addr2line?branch=master) + +`addr2line` provides a cross-platform library for retrieving per-address debug information +from files with DWARF debug information. Given an address, it can return the file name, +line number, and function name associated with that address, as well as the inline call +stack leading to that address. + +The crate has a CLI wrapper around the library which provides some of +the functionality of the `addr2line` command line tool distributed with +[GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html). + +# Quickstart + - Add the [`addr2line` crate](https://crates.io/crates/addr2line) to your `Cargo.toml`. + - Call [`addr2line::Loader::new`](https://docs.rs/addr2line/*/addr2line/struct.Loader.html#method.new) with the file path. + - Use [`addr2line::Loader::find_location`](https://docs.rs/addr2line/*/addr2line/struct.Loader.html#method.find_location) + or [`addr2line::Loader::find_frames`](https://docs.rs/addr2line/*/addr2line/struct.Loader.html#method.find_frames) + to look up debug information for an address. + +If you want to provide your own file loading and memory management, use +[`addr2line::Context`](https://docs.rs/addr2line/*/addr2line/struct.Context.html) +instead of `addr2line::Loader`. + +# Performance + +`addr2line` optimizes for speed over memory by caching parsed information. +The DWARF information is parsed lazily where possible. + +The library aims to perform similarly to equivalent existing tools such +as `addr2line` from binutils, `eu-addr2line` from elfutils, and +`llvm-addr2line` from the llvm project. Current benchmarks show a performance +improvement in all cases: + +![addr2line runtime](benchmark-time.svg) + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT) + +at your option. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/addr2line/src/bin/addr2line.rs b/anneal/v2/vendor/addr2line/src/bin/addr2line.rs new file mode 100644 index 0000000000..150ee9ab3d --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/bin/addr2line.rs @@ -0,0 +1,313 @@ +use fallible_iterator::FallibleIterator; +use std::borrow::Cow; +use std::io::{BufRead, Lines, StdinLock, Write}; +use std::path::{Path, PathBuf}; + +use clap::{Arg, ArgAction, Command}; + +use addr2line::{Loader, LoaderReader, Location}; + +fn parse_uint_from_hex_string(string: &str) -> Option { + if string.len() > 2 && string.starts_with("0x") { + u64::from_str_radix(&string[2..], 16).ok() + } else { + u64::from_str_radix(string, 16).ok() + } +} + +enum Addrs<'a> { + Args(clap::parser::ValuesRef<'a, String>), + Stdin(Lines>), + All { + iter: addr2line::LocationRangeIter<'a, LoaderReader<'a>>, + max: u64, + }, +} + +impl<'a> Iterator for Addrs<'a> { + type Item = Option; + + fn next(&mut self) -> Option> { + let text = match self { + Addrs::Args(vals) => vals.next().map(Cow::from), + Addrs::Stdin(lines) => lines.next().map(Result::unwrap).map(Cow::from), + Addrs::All { iter, max } => { + for (addr, _len, _loc) in iter { + if addr >= *max { + *max = addr + 1; + return Some(Some(addr)); + } + } + return None; + } + }; + text.as_ref() + .map(Cow::as_ref) + .map(parse_uint_from_hex_string) + } +} + +fn print_loc(loc: Option<&Location<'_>>, basenames: bool, llvm: bool) { + if let Some(loc) = loc { + if let Some(ref file) = loc.file.as_ref() { + let path = if basenames { + Path::new(Path::new(file).file_name().unwrap()) + } else { + Path::new(file) + }; + print!("{}:", path.display()); + } else { + print!("??:"); + } + if llvm { + print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0)); + } else if let Some(line) = loc.line { + print!("{}", line); + } else { + print!("?"); + } + println!(); + } else if llvm { + println!("??:0:0"); + } else { + println!("??:0"); + } +} + +fn print_function(name: Option<&str>, language: Option, demangle: bool) { + if let Some(name) = name { + if demangle { + print!("{}", addr2line::demangle_auto(Cow::from(name), language)); + } else { + print!("{}", name); + } + } else { + print!("??"); + } +} + +struct Options<'a> { + do_functions: bool, + do_inlines: bool, + pretty: bool, + print_addrs: bool, + basenames: bool, + demangle: bool, + llvm: bool, + exe: &'a PathBuf, + sup: Option<&'a PathBuf>, + section: Option<&'a String>, +} + +fn main() { + let matches = Command::new("addr2line") + .version(env!("CARGO_PKG_VERSION")) + .about("A fast addr2line Rust port") + .max_term_width(100) + .args(&[ + Arg::new("exe") + .short('e') + .long("exe") + .value_name("filename") + .value_parser(clap::value_parser!(PathBuf)) + .help( + "Specify the name of the executable for which addresses should be translated.", + ) + .required(true), + Arg::new("sup") + .long("sup") + .value_name("filename") + .value_parser(clap::value_parser!(PathBuf)) + .help("Path to supplementary object file."), + Arg::new("section") + .short('j') + .long("section") + .value_name("name") + .help( + "Read offsets relative to the specified section instead of absolute addresses.", + ), + Arg::new("all") + .long("all") + .action(ArgAction::SetTrue) + .conflicts_with("addrs") + .help("Display all addresses that have line number information."), + Arg::new("functions") + .short('f') + .long("functions") + .action(ArgAction::SetTrue) + .help("Display function names as well as file and line number information."), + Arg::new("pretty").short('p').long("pretty-print") + .action(ArgAction::SetTrue) + .help( + "Make the output more human friendly: each location are printed on one line.", + ), + Arg::new("inlines").short('i').long("inlines") + .action(ArgAction::SetTrue) + .help( + "If the address belongs to a function that was inlined, the source information for \ + all enclosing scopes back to the first non-inlined function will also be printed.", + ), + Arg::new("addresses").short('a').long("addresses") + .action(ArgAction::SetTrue) + .help( + "Display the address before the function name, file and line number information.", + ), + Arg::new("basenames") + .short('s') + .long("basenames") + .action(ArgAction::SetTrue) + .help("Display only the base of each file name."), + Arg::new("demangle").short('C').long("demangle") + .action(ArgAction::SetTrue) + .help( + "Demangle function names. \ + Specifying a specific demangling style (like GNU addr2line) is not supported. \ + (TODO)" + ), + Arg::new("llvm") + .long("llvm") + .action(ArgAction::SetTrue) + .help("Display output in the same format as llvm-symbolizer."), + Arg::new("addrs") + .action(ArgAction::Append) + .help("Addresses to use instead of reading from stdin."), + ]) + .get_matches(); + + let opts = Options { + do_functions: matches.get_flag("functions"), + do_inlines: matches.get_flag("inlines"), + pretty: matches.get_flag("pretty"), + print_addrs: matches.get_flag("addresses"), + basenames: matches.get_flag("basenames"), + demangle: matches.get_flag("demangle"), + llvm: matches.get_flag("llvm"), + exe: matches.get_one::("exe").unwrap(), + sup: matches.get_one::("sup"), + section: matches.get_one::("section"), + }; + + let ctx = Loader::new_with_sup(opts.exe, opts.sup).unwrap(); + + let section_range = opts.section.map(|section_name| { + ctx.get_section_range(section_name.as_bytes()) + .unwrap_or_else(|| panic!("cannot find section {}", section_name)) + }); + + let stdin = std::io::stdin(); + let addrs = if matches.get_flag("all") { + Addrs::All { + iter: ctx.find_location_range(0, !0).unwrap(), + max: 0, + } + } else { + matches + .get_many::("addrs") + .map(Addrs::Args) + .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines())) + }; + + for probe in addrs { + if opts.print_addrs { + let addr = probe.unwrap_or(0); + if opts.llvm { + print!("0x{:x}", addr); + } else { + print!("0x{:016x}", addr); + } + if opts.pretty { + print!(": "); + } else { + println!(); + } + } + + // If --section is given, add the section address to probe. + let probe = probe.and_then(|probe| { + if let Some(section_range) = section_range { + if probe < (section_range.end - section_range.begin) { + Some(probe + section_range.begin) + } else { + // If addr >= section size, treat it as if no line number information was found. + None + } + } else { + Some(probe) + } + }); + + if opts.do_functions || opts.do_inlines { + let mut printed_anything = false; + if let Some(probe) = probe { + let mut frames = ctx.find_frames(probe).unwrap().peekable(); + let mut first = true; + while let Some(frame) = frames.next().unwrap() { + if opts.pretty && !first { + print!(" (inlined by) "); + } + first = false; + + if opts.do_functions { + // Only use the symbol table if this isn't an inlined function. + let symbol = if matches!(frames.peek(), Ok(None)) { + ctx.find_symbol(probe) + } else { + None + }; + if symbol.is_some() { + // Prefer the symbol table over the DWARF name because: + // - the symbol can include a clone suffix + // - llvm may omit the linkage name in the DWARF with -g1 + print_function(symbol, None, opts.demangle); + } else if let Some(func) = frame.function { + print_function( + func.raw_name().ok().as_deref(), + func.language, + opts.demangle, + ); + } else { + print_function(None, None, opts.demangle); + } + + if opts.pretty { + print!(" at "); + } else { + println!(); + } + } + + print_loc(frame.location.as_ref(), opts.basenames, opts.llvm); + + printed_anything = true; + + if !opts.do_inlines { + break; + } + } + } + + if !printed_anything { + if opts.do_functions { + let name = probe.and_then(|probe| ctx.find_symbol(probe)); + print_function(name, None, opts.demangle); + + if opts.pretty { + print!(" at "); + } else { + println!(); + } + } + + print_loc(None, opts.basenames, opts.llvm); + } + } else { + let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap()); + print_loc(loc.as_ref(), opts.basenames, opts.llvm); + } + + if opts.llvm { + println!(); + } + std::io::stdout().flush().unwrap(); + } +} diff --git a/anneal/v2/vendor/addr2line/src/frame.rs b/anneal/v2/vendor/addr2line/src/frame.rs new file mode 100644 index 0000000000..f665eeb8e5 --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/frame.rs @@ -0,0 +1,221 @@ +use alloc::borrow::Cow; +use alloc::string::String; +use core::iter; + +use crate::{maybe_small, Error, Function, InlinedFunction, ResUnit}; + +/// A source location. +pub struct Location<'a> { + /// The file name. + pub file: Option<&'a str>, + /// The line number. + pub line: Option, + /// The column number. + /// + /// A value of `Some(0)` indicates the left edge. + pub column: Option, +} + +/// A function frame. +pub struct Frame<'ctx, R: gimli::Reader> { + /// The DWARF unit offset corresponding to the DIE of the function. + pub dw_die_offset: Option>, + /// The name of the function. + pub function: Option>, + /// The source location corresponding to this frame. + pub location: Option>, +} + +/// An iterator over function frames. +pub struct FrameIter<'ctx, R>(FrameIterState<'ctx, R>) +where + R: gimli::Reader; + +enum FrameIterState<'ctx, R> +where + R: gimli::Reader, +{ + Empty, + Location(Option>), + Frames(FrameIterFrames<'ctx, R>), +} + +struct FrameIterFrames<'ctx, R> +where + R: gimli::Reader, +{ + unit: &'ctx ResUnit, + sections: &'ctx gimli::Dwarf, + function: &'ctx Function, + inlined_functions: iter::Rev>>, + next: Option>, +} + +impl<'ctx, R> FrameIter<'ctx, R> +where + R: gimli::Reader + 'ctx, +{ + pub(crate) fn new_empty() -> Self { + FrameIter(FrameIterState::Empty) + } + + pub(crate) fn new_location(location: Location<'ctx>) -> Self { + FrameIter(FrameIterState::Location(Some(location))) + } + + pub(crate) fn new_frames( + unit: &'ctx ResUnit, + sections: &'ctx gimli::Dwarf, + function: &'ctx Function, + inlined_functions: maybe_small::Vec<&'ctx InlinedFunction>, + location: Option>, + ) -> Self { + FrameIter(FrameIterState::Frames(FrameIterFrames { + unit, + sections, + function, + inlined_functions: inlined_functions.into_iter().rev(), + next: location, + })) + } + + /// Advances the iterator and returns the next frame. + #[allow(clippy::should_implement_trait)] + pub fn next(&mut self) -> Result>, Error> { + let frames = match &mut self.0 { + FrameIterState::Empty => return Ok(None), + FrameIterState::Location(location) => { + // We can't move out of a mutable reference, so use `take` instead. + let location = location.take(); + self.0 = FrameIterState::Empty; + return Ok(Some(Frame { + dw_die_offset: None, + function: None, + location, + })); + } + FrameIterState::Frames(frames) => frames, + }; + + let loc = frames.next.take(); + let func = match frames.inlined_functions.next() { + Some(func) => func, + None => { + let frame = Frame { + dw_die_offset: Some(frames.function.dw_die_offset), + function: frames.function.name.clone().map(|name| FunctionName { + name, + language: frames.unit.lang, + }), + location: loc, + }; + self.0 = FrameIterState::Empty; + return Ok(Some(frame)); + } + }; + + let mut next = Location { + file: None, + line: if func.call_line != 0 { + Some(func.call_line) + } else { + None + }, + column: if func.call_column != 0 { + Some(func.call_column) + } else { + None + }, + }; + if let Some(call_file) = func.call_file { + if let Some(lines) = frames.unit.parse_lines(frames.sections)? { + next.file = lines.file(call_file); + } + } + frames.next = Some(next); + + Ok(Some(Frame { + dw_die_offset: Some(func.dw_die_offset), + function: func.name.clone().map(|name| FunctionName { + name, + language: frames.unit.lang, + }), + location: loc, + })) + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'ctx, R> fallible_iterator::FallibleIterator for FrameIter<'ctx, R> +where + R: gimli::Reader + 'ctx, +{ + type Item = Frame<'ctx, R>; + type Error = Error; + + #[inline] + fn next(&mut self) -> Result>, Error> { + self.next() + } +} + +/// A function name. +pub struct FunctionName { + /// The name of the function. + pub name: R, + /// The language of the compilation unit containing this function. + pub language: Option, +} + +impl FunctionName { + /// The raw name of this function before demangling. + pub fn raw_name(&self) -> Result, Error> { + self.name.to_string_lossy() + } + + /// The name of this function after demangling (if applicable). + pub fn demangle(&self) -> Result, Error> { + self.raw_name().map(|x| demangle_auto(x, self.language)) + } +} + +/// Demangle a symbol name using the demangling scheme for the given language. +/// +/// Returns `None` if demangling failed or is not required. +#[allow(unused_variables)] +pub fn demangle(name: &str, language: gimli::DwLang) -> Option { + match language { + #[cfg(feature = "rustc-demangle")] + gimli::DW_LANG_Rust => rustc_demangle::try_demangle(name) + .ok() + .as_ref() + .map(|x| format!("{:#}", x)), + #[cfg(feature = "cpp_demangle")] + gimli::DW_LANG_C_plus_plus + | gimli::DW_LANG_C_plus_plus_03 + | gimli::DW_LANG_C_plus_plus_11 + | gimli::DW_LANG_C_plus_plus_14 => cpp_demangle::Symbol::new(name) + .ok() + .and_then(|x| x.demangle(&Default::default()).ok()), + _ => None, + } +} + +/// Apply 'best effort' demangling of a symbol name. +/// +/// If `language` is given, then only the demangling scheme for that language +/// is used. +/// +/// If `language` is `None`, then heuristics are used to determine how to +/// demangle the name. Currently, these heuristics are very basic. +/// +/// If demangling fails or is not required, then `name` is returned unchanged. +pub fn demangle_auto(name: Cow<'_, str>, language: Option) -> Cow<'_, str> { + match language { + Some(language) => demangle(name.as_ref(), language), + None => demangle(name.as_ref(), gimli::DW_LANG_Rust) + .or_else(|| demangle(name.as_ref(), gimli::DW_LANG_C_plus_plus)), + } + .map(Cow::from) + .unwrap_or(name) +} diff --git a/anneal/v2/vendor/addr2line/src/function.rs b/anneal/v2/vendor/addr2line/src/function.rs new file mode 100644 index 0000000000..e84c80f1dd --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/function.rs @@ -0,0 +1,563 @@ +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::cmp::Ordering; + +use crate::maybe_small; +use crate::{Context, DebugFile, Error, LazyResult, RangeAttributes}; + +pub(crate) struct LazyFunctions(LazyResult>); + +impl LazyFunctions { + pub(crate) fn new() -> Self { + LazyFunctions(LazyResult::new()) + } + + pub(crate) fn borrow(&self, unit: gimli::UnitRef) -> Result<&Functions, Error> { + self.0 + .get_or_init(|| Functions::parse(unit)) + .as_ref() + .map_err(Error::clone) + } +} + +pub(crate) struct Functions { + /// List of all `DW_TAG_subprogram` details in the unit. + pub(crate) functions: Box<[LazyFunction]>, + /// List of `DW_TAG_subprogram` address ranges in the unit. + pub(crate) addresses: Box<[FunctionAddress]>, +} + +/// A single address range for a function. +/// +/// It is possible for a function to have multiple address ranges; this +/// is handled by having multiple `FunctionAddress` entries with the same +/// `function` field. +pub(crate) struct FunctionAddress { + range: gimli::Range, + /// An index into `Functions::functions`. + pub(crate) function: usize, +} + +pub(crate) struct LazyFunction { + dw_die_offset: gimli::UnitOffset, + lazy: LazyResult>, +} + +impl LazyFunction { + fn new(dw_die_offset: gimli::UnitOffset) -> Self { + LazyFunction { + dw_die_offset, + lazy: LazyResult::new(), + } + } + + pub(crate) fn borrow( + &self, + file: DebugFile, + unit: gimli::UnitRef, + ctx: &Context, + ) -> Result<&Function, Error> { + self.lazy + .get_or_init(|| Function::parse(self.dw_die_offset, file, unit, ctx)) + .as_ref() + .map_err(Error::clone) + } +} + +pub(crate) struct Function { + pub(crate) dw_die_offset: gimli::UnitOffset, + pub(crate) name: Option, + /// List of all `DW_TAG_inlined_subroutine` details in this function. + inlined_functions: Box<[InlinedFunction]>, + /// List of `DW_TAG_inlined_subroutine` address ranges in this function. + inlined_addresses: Box<[InlinedFunctionAddress]>, +} + +pub(crate) struct InlinedFunctionAddress { + range: gimli::Range, + call_depth: usize, + /// An index into `Function::inlined_functions`. + function: usize, +} + +pub(crate) struct InlinedFunction { + pub(crate) dw_die_offset: gimli::UnitOffset, + pub(crate) name: Option, + pub(crate) call_file: Option, + pub(crate) call_line: u32, + pub(crate) call_column: u32, +} + +impl Functions { + fn parse(unit: gimli::UnitRef) -> Result, Error> { + let mut functions = Vec::new(); + let mut addresses = Vec::new(); + let mut entries = unit.entries_raw(None)?; + while !entries.is_empty() { + let dw_die_offset = entries.next_offset(); + if let Some(abbrev) = entries.read_abbreviation()? { + if abbrev.tag() == gimli::DW_TAG_subprogram { + let mut ranges = RangeAttributes::default(); + for spec in abbrev.attributes() { + match entries.read_attribute(*spec) { + Ok(ref attr) => { + match attr.name() { + gimli::DW_AT_low_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => { + ranges.low_pc = Some(val) + } + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.low_pc = Some(unit.address(index)?); + } + _ => {} + }, + gimli::DW_AT_high_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => { + ranges.high_pc = Some(val) + } + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.high_pc = Some(unit.address(index)?); + } + gimli::AttributeValue::Udata(val) => { + ranges.size = Some(val) + } + _ => {} + }, + gimli::DW_AT_ranges => { + ranges.ranges_offset = + unit.attr_ranges_offset(attr.value())?; + } + _ => {} + }; + } + Err(e) => return Err(e), + } + } + + let function_index = functions.len(); + let has_address = ranges.for_each_range(unit, |range| { + addresses.push(FunctionAddress { + range, + function: function_index, + }); + })?; + if has_address { + functions.push(LazyFunction::new(dw_die_offset)); + } + } else { + entries.skip_attributes(abbrev.attributes())?; + } + } + } + + // The binary search requires the addresses to be sorted. + // + // It also requires them to be non-overlapping. In practice, overlapping + // function ranges are unlikely, so we don't try to handle that yet. + // + // It's possible for multiple functions to have the same address range if the + // compiler can detect and remove functions with identical code. In that case + // we'll nondeterministically return one of them. + addresses.sort_by_key(|x| x.range.begin); + + Ok(Functions { + functions: functions.into_boxed_slice(), + addresses: addresses.into_boxed_slice(), + }) + } + + pub(crate) fn find_address(&self, probe: u64) -> Option { + self.addresses + .binary_search_by(|address| { + if probe < address.range.begin { + Ordering::Greater + } else if probe >= address.range.end { + Ordering::Less + } else { + Ordering::Equal + } + }) + .ok() + } + + pub(crate) fn parse_inlined_functions( + &self, + file: DebugFile, + unit: gimli::UnitRef, + ctx: &Context, + ) -> Result<(), Error> { + for function in &*self.functions { + function.borrow(file, unit, ctx)?; + } + Ok(()) + } +} + +impl Function { + fn parse( + dw_die_offset: gimli::UnitOffset, + file: DebugFile, + unit: gimli::UnitRef, + ctx: &Context, + ) -> Result { + let mut entries = unit.entries_raw(Some(dw_die_offset))?; + let depth = entries.next_depth(); + let abbrev = entries.read_abbreviation()?.unwrap(); + debug_assert_eq!(abbrev.tag(), gimli::DW_TAG_subprogram); + + let mut name = None; + for spec in abbrev.attributes() { + match entries.read_attribute(*spec) { + Ok(ref attr) => { + match attr.name() { + gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { + if let Ok(val) = unit.attr_string(attr.value()) { + name = Some(val); + } + } + gimli::DW_AT_name => { + if name.is_none() { + name = unit.attr_string(attr.value()).ok(); + } + } + gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { + if name.is_none() { + name = name_attr(attr.value(), file, unit, ctx, 16)?; + } + } + _ => {} + }; + } + Err(e) => return Err(e), + } + } + + let mut state = InlinedState { + entries, + functions: Vec::new(), + addresses: Vec::new(), + file, + unit, + ctx, + }; + Function::parse_children(&mut state, depth, 0)?; + + // Sort ranges in "breadth-first traversal order", i.e. first by call_depth + // and then by range.begin. This allows finding the range containing an + // address at a certain depth using binary search. + // Note: Using DFS order, i.e. ordering by range.begin first and then by + // call_depth, would not work! Consider the two examples + // "[0..10 at depth 0], [0..2 at depth 1], [6..8 at depth 1]" and + // "[0..5 at depth 0], [0..2 at depth 1], [5..10 at depth 0], [6..8 at depth 1]". + // In this example, if you want to look up address 7 at depth 0, and you + // encounter [0..2 at depth 1], are you before or after the target range? + // You don't know. + state.addresses.sort_by(|r1, r2| { + if r1.call_depth < r2.call_depth { + Ordering::Less + } else if r1.call_depth > r2.call_depth { + Ordering::Greater + } else if r1.range.begin < r2.range.begin { + Ordering::Less + } else if r1.range.begin > r2.range.begin { + Ordering::Greater + } else { + Ordering::Equal + } + }); + + Ok(Function { + dw_die_offset, + name, + inlined_functions: state.functions.into_boxed_slice(), + inlined_addresses: state.addresses.into_boxed_slice(), + }) + } + + fn parse_children( + state: &mut InlinedState, + depth: isize, + inlined_depth: usize, + ) -> Result<(), Error> { + loop { + let dw_die_offset = state.entries.next_offset(); + let next_depth = state.entries.next_depth(); + if next_depth <= depth { + return Ok(()); + } + if let Some(abbrev) = state.entries.read_abbreviation()? { + match abbrev.tag() { + gimli::DW_TAG_subprogram => { + Function::skip(&mut state.entries, abbrev, next_depth)?; + } + gimli::DW_TAG_inlined_subroutine => { + InlinedFunction::parse( + state, + dw_die_offset, + abbrev, + next_depth, + inlined_depth, + )?; + } + _ => { + state.entries.skip_attributes(abbrev.attributes())?; + } + } + } + } + } + + fn skip( + entries: &mut gimli::EntriesRaw<'_, '_, R>, + abbrev: &gimli::Abbreviation, + depth: isize, + ) -> Result<(), Error> { + // TODO: use DW_AT_sibling + entries.skip_attributes(abbrev.attributes())?; + while entries.next_depth() > depth { + if let Some(abbrev) = entries.read_abbreviation()? { + entries.skip_attributes(abbrev.attributes())?; + } + } + Ok(()) + } + + /// Build the list of inlined functions that contain `probe`. + pub(crate) fn find_inlined_functions( + &self, + probe: u64, + ) -> maybe_small::Vec<&InlinedFunction> { + // `inlined_functions` is ordered from outside to inside. + let mut inlined_functions = maybe_small::Vec::new(); + let mut inlined_addresses = &self.inlined_addresses[..]; + loop { + let current_depth = inlined_functions.len(); + // Look up (probe, current_depth) in inline_ranges. + // `inlined_addresses` is sorted in "breadth-first traversal order", i.e. + // by `call_depth` first, and then by `range.begin`. See the comment at + // the sort call for more information about why. + let search = inlined_addresses.binary_search_by(|range| { + if range.call_depth > current_depth { + Ordering::Greater + } else if range.call_depth < current_depth { + Ordering::Less + } else if range.range.begin > probe { + Ordering::Greater + } else if range.range.end <= probe { + Ordering::Less + } else { + Ordering::Equal + } + }); + if let Ok(index) = search { + let function_index = inlined_addresses[index].function; + inlined_functions.push(&self.inlined_functions[function_index]); + inlined_addresses = &inlined_addresses[index + 1..]; + } else { + break; + } + } + inlined_functions + } +} + +impl InlinedFunction { + fn parse( + state: &mut InlinedState, + dw_die_offset: gimli::UnitOffset, + abbrev: &gimli::Abbreviation, + depth: isize, + inlined_depth: usize, + ) -> Result<(), Error> { + let unit = state.unit; + let mut ranges = RangeAttributes::default(); + let mut name = None; + let mut call_file = None; + let mut call_line = 0; + let mut call_column = 0; + for spec in abbrev.attributes() { + match state.entries.read_attribute(*spec) { + Ok(ref attr) => match attr.name() { + gimli::DW_AT_low_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val), + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.low_pc = Some(unit.address(index)?); + } + _ => {} + }, + gimli::DW_AT_high_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val), + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.high_pc = Some(unit.address(index)?); + } + gimli::AttributeValue::Udata(val) => ranges.size = Some(val), + _ => {} + }, + gimli::DW_AT_ranges => { + ranges.ranges_offset = unit.attr_ranges_offset(attr.value())?; + } + gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { + if let Ok(val) = unit.attr_string(attr.value()) { + name = Some(val); + } + } + gimli::DW_AT_name => { + if name.is_none() { + name = unit.attr_string(attr.value()).ok(); + } + } + gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { + if name.is_none() { + name = name_attr(attr.value(), state.file, unit, state.ctx, 16)?; + } + } + gimli::DW_AT_call_file => { + // There is a spec issue [1] with how DW_AT_call_file is specified in DWARF 5. + // Before, a file index of 0 would indicate no source file, however in + // DWARF 5 this could be a valid index into the file table. + // + // Implementations such as LLVM generates a file index of 0 when DWARF 5 is + // used. + // + // Thus, if we see a version of 5 or later, treat a file index of 0 as such. + // [1]: http://wiki.dwarfstd.org/index.php?title=DWARF5_Line_Table_File_Numbers + if let gimli::AttributeValue::FileIndex(fi) = attr.value() { + if fi > 0 || unit.header.version() >= 5 { + call_file = Some(fi); + } + } + } + gimli::DW_AT_call_line => { + call_line = attr.udata_value().unwrap_or(0) as u32; + } + gimli::DW_AT_call_column => { + call_column = attr.udata_value().unwrap_or(0) as u32; + } + _ => {} + }, + Err(e) => return Err(e), + } + } + + let function_index = state.functions.len(); + state.functions.push(InlinedFunction { + dw_die_offset, + name, + call_file, + call_line, + call_column, + }); + + ranges.for_each_range(unit, |range| { + state.addresses.push(InlinedFunctionAddress { + range, + call_depth: inlined_depth, + function: function_index, + }); + })?; + + Function::parse_children(state, depth, inlined_depth + 1) + } +} + +struct InlinedState<'a, R: gimli::Reader> { + // Mutable fields. + entries: gimli::EntriesRaw<'a, 'a, R>, + functions: Vec>, + addresses: Vec, + + // Constant fields. + file: DebugFile, + unit: gimli::UnitRef<'a, R>, + ctx: &'a Context, +} + +fn name_attr( + attr: gimli::AttributeValue, + mut file: DebugFile, + unit: gimli::UnitRef, + ctx: &Context, + recursion_limit: usize, +) -> Result, Error> +where + R: gimli::Reader, +{ + if recursion_limit == 0 { + return Ok(None); + } + + match attr { + gimli::AttributeValue::UnitRef(offset) => { + name_entry(file, unit, offset, ctx, recursion_limit) + } + gimli::AttributeValue::DebugInfoRef(dr) => { + let sections = unit.dwarf; + let (unit, offset) = ctx.find_unit(dr, file)?; + let unit = gimli::UnitRef::new(sections, unit); + name_entry(file, unit, offset, ctx, recursion_limit) + } + gimli::AttributeValue::DebugInfoRefSup(dr) => { + if let Some(sup_sections) = unit.dwarf.sup.as_ref() { + file = DebugFile::Supplementary; + let (unit, offset) = ctx.find_unit(dr, file)?; + let unit = gimli::UnitRef::new(sup_sections, unit); + name_entry(file, unit, offset, ctx, recursion_limit) + } else { + Ok(None) + } + } + _ => Ok(None), + } +} + +fn name_entry( + file: DebugFile, + unit: gimli::UnitRef, + offset: gimli::UnitOffset, + ctx: &Context, + recursion_limit: usize, +) -> Result, Error> +where + R: gimli::Reader, +{ + let mut entries = unit.entries_raw(Some(offset))?; + let abbrev = if let Some(abbrev) = entries.read_abbreviation()? { + abbrev + } else { + return Err(gimli::Error::NoEntryAtGivenOffset); + }; + + let mut name = None; + let mut next = None; + for spec in abbrev.attributes() { + match entries.read_attribute(*spec) { + Ok(ref attr) => match attr.name() { + gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => { + if let Ok(val) = unit.attr_string(attr.value()) { + return Ok(Some(val)); + } + } + gimli::DW_AT_name => { + if let Ok(val) = unit.attr_string(attr.value()) { + name = Some(val); + } + } + gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => { + next = Some(attr.value()); + } + _ => {} + }, + Err(e) => return Err(e), + } + } + + if name.is_some() { + return Ok(name); + } + + if let Some(next) = next { + return name_attr(next, file, unit, ctx, recursion_limit - 1); + } + + Ok(None) +} diff --git a/anneal/v2/vendor/addr2line/src/lib.rs b/anneal/v2/vendor/addr2line/src/lib.rs new file mode 100644 index 0000000000..ac458deac0 --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/lib.rs @@ -0,0 +1,418 @@ +//! `addr2line` provides a cross-platform library for retrieving per-address debug information +//! from files with DWARF debug information. Given an address, it can return the file name, +//! line number, and function name associated with that address, as well as the inline call +//! stack leading to that address. +//! +//! At the lowest level, the library uses a [`Context`] to cache parsed information so that +//! multiple lookups are efficient. To create a `Context`, you first need to open and parse the +//! file using an object file parser such as [`object`](https://github.com/gimli-rs/object), +//! create a [`gimli::Dwarf`], and finally call [`Context::from_dwarf`]. +//! +//! Location information is obtained with [`Context::find_location`] or +//! [`Context::find_location_range`]. Function information is obtained with +//! [`Context::find_frames`], which returns a frame for each inline function. Each frame +//! contains both name and location. +//! +//! The library also provides a [`Loader`] which internally memory maps the files, +//! uses the `object` crate to do the parsing, and creates a `Context`. +//! The `Context` is not exposed, but the `Loader` provides the same functionality +//! via [`Loader::find_location`], [`Loader::find_location_range`], and +//! [`Loader::find_frames`]. The `Loader` also provides [`Loader::find_symbol`] +//! to use the symbol table instead of DWARF debugging information. +//! The `Loader` will load Mach-O dSYM files and split DWARF files as needed. +//! +//! The crate has a CLI wrapper around the library which provides some of +//! the functionality of the `addr2line` command line tool distributed with +//! [GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html). +#![deny(missing_docs)] +#![no_std] + +#[cfg(feature = "cargo-all")] +compile_error!("'--all-features' is not supported; use '--features all' instead"); + +#[cfg(feature = "std")] +extern crate std; + +#[allow(unused_imports)] +#[macro_use] +extern crate alloc; + +#[cfg(feature = "fallible-iterator")] +pub extern crate fallible_iterator; +pub extern crate gimli; + +use alloc::sync::Arc; +use core::cell::OnceCell; +use core::ops::ControlFlow; + +use crate::function::{Function, Functions, InlinedFunction, LazyFunctions}; +use crate::line::{LazyLines, LineLocationRangeIter, Lines}; +use crate::lookup::{LoopingLookup, SimpleLookup}; +use crate::unit::{ResUnit, ResUnits, SupUnits}; + +#[cfg(feature = "smallvec")] +mod maybe_small { + pub type Vec = smallvec::SmallVec<[T; 16]>; + pub type IntoIter = smallvec::IntoIter<[T; 16]>; +} +#[cfg(not(feature = "smallvec"))] +mod maybe_small { + pub type Vec = alloc::vec::Vec; + pub type IntoIter = alloc::vec::IntoIter; +} + +mod frame; +pub use frame::{demangle, demangle_auto, Frame, FrameIter, FunctionName, Location}; + +mod function; +mod line; + +#[cfg(feature = "loader")] +mod loader; +#[cfg(feature = "loader")] +pub use loader::{Loader, LoaderReader, Symbol}; + +mod lookup; +pub use lookup::{LookupContinuation, LookupResult, SplitDwarfLoad}; + +mod unit; +pub use unit::LocationRangeIter; + +type Error = gimli::Error; +type LazyResult = OnceCell>; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum DebugFile { + Primary, + Supplementary, + Dwo, +} + +/// The state necessary to perform address to line translation. +/// +/// Constructing a `Context` is somewhat costly, so users should aim to reuse `Context`s +/// when performing lookups for many addresses in the same executable. +pub struct Context { + sections: Arc>, + units: ResUnits, + sup_units: SupUnits, +} + +impl Context { + /// Construct a new `Context` from DWARF sections. + /// + /// This method does not support using a supplementary object file. + #[allow(clippy::too_many_arguments)] + pub fn from_sections( + debug_abbrev: gimli::DebugAbbrev, + debug_addr: gimli::DebugAddr, + debug_aranges: gimli::DebugAranges, + debug_info: gimli::DebugInfo, + debug_line: gimli::DebugLine, + debug_line_str: gimli::DebugLineStr, + debug_ranges: gimli::DebugRanges, + debug_rnglists: gimli::DebugRngLists, + debug_str: gimli::DebugStr, + debug_str_offsets: gimli::DebugStrOffsets, + default_section: R, + ) -> Result { + Self::from_dwarf(gimli::Dwarf { + debug_abbrev, + debug_addr, + debug_aranges, + debug_info, + debug_line, + debug_line_str, + debug_macinfo: default_section.clone().into(), + debug_macro: default_section.clone().into(), + debug_str, + debug_str_offsets, + debug_types: default_section.clone().into(), + locations: gimli::LocationLists::new( + default_section.clone().into(), + default_section.into(), + ), + ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists), + file_type: gimli::DwarfFileType::Main, + sup: None, + abbreviations_cache: gimli::AbbreviationsCache::new(), + }) + } + + /// Construct a new `Context` from an existing [`gimli::Dwarf`] object. + #[inline] + pub fn from_dwarf(sections: gimli::Dwarf) -> Result, Error> { + Self::from_arc_dwarf(Arc::new(sections)) + } + + /// Construct a new `Context` from an existing [`gimli::Dwarf`] object. + #[inline] + pub fn from_arc_dwarf(sections: Arc>) -> Result, Error> { + let units = ResUnits::parse(§ions)?; + let sup_units = if let Some(sup) = sections.sup.as_ref() { + SupUnits::parse(sup)? + } else { + SupUnits::default() + }; + Ok(Context { + sections, + units, + sup_units, + }) + } +} + +impl Context { + /// Find the DWARF unit corresponding to the given virtual memory address. + pub fn find_dwarf_and_unit( + &self, + probe: u64, + ) -> LookupResult>, Buf = R>> + { + let mut units_iter = self.units.find(probe); + if let Some(unit) = units_iter.next() { + return LoopingLookup::new_lookup( + unit.find_function_or_location(probe, self), + move |r| { + ControlFlow::Break(match r { + Ok((Some(_), _)) | Ok((_, Some(_))) => { + let (_file, unit) = unit + .dwarf_and_unit(self) + // We've already been through both error cases here to get to this point. + .unwrap() + .unwrap(); + Some(unit) + } + _ => match units_iter.next() { + Some(next_unit) => { + return ControlFlow::Continue( + next_unit.find_function_or_location(probe, self), + ); + } + None => None, + }, + }) + }, + ); + } + + LoopingLookup::new_complete(None) + } + + /// Find the source file and line corresponding to the given virtual memory address. + pub fn find_location(&self, probe: u64) -> Result>, Error> { + for unit in self.units.find(probe) { + if let Some(location) = unit.find_location(probe, &self.sections)? { + return Ok(Some(location)); + } + } + Ok(None) + } + + /// Return source file and lines for a range of addresses. For each location it also + /// returns the address and size of the range of the underlying instructions. + pub fn find_location_range( + &self, + probe_low: u64, + probe_high: u64, + ) -> Result, Error> { + self.units + .find_location_range(probe_low, probe_high, &self.sections) + } + + /// Return an iterator for the function frames corresponding to the given virtual + /// memory address. + /// + /// If the probe address is not for an inline function then only one frame is + /// returned. + /// + /// If the probe address is for an inline function then the first frame corresponds + /// to the innermost inline function. Subsequent frames contain the caller and call + /// location, until an non-inline caller is reached. + pub fn find_frames( + &self, + probe: u64, + ) -> LookupResult, Error>, Buf = R>> + { + let mut units_iter = self.units.find(probe); + if let Some(unit) = units_iter.next() { + LoopingLookup::new_lookup(unit.find_function_or_location(probe, self), move |r| { + ControlFlow::Break(match r { + Err(e) => Err(e), + Ok((Some(function), location)) => { + let inlined_functions = function.find_inlined_functions(probe); + Ok(FrameIter::new_frames( + unit, + &self.sections, + function, + inlined_functions, + location, + )) + } + Ok((None, Some(location))) => Ok(FrameIter::new_location(location)), + Ok((None, None)) => match units_iter.next() { + Some(next_unit) => { + return ControlFlow::Continue( + next_unit.find_function_or_location(probe, self), + ); + } + None => Ok(FrameIter::new_empty()), + }, + }) + }) + } else { + LoopingLookup::new_complete(Ok(FrameIter::new_empty())) + } + } + + /// Preload units for `probe`. + /// + /// The iterator returns pairs of `SplitDwarfLoad`s containing the + /// information needed to locate and load split DWARF for `probe` and + /// a matching callback to invoke once that data is available. + /// + /// If this method is called, and all of the returned closures are invoked, + /// addr2line guarantees that any future API call for the address `probe` + /// will not require the loading of any split DWARF. + /// + /// ```no_run + /// # use addr2line::*; + /// # use std::sync::Arc; + /// # let ctx: Context> = todo!(); + /// # let do_split_dwarf_load = |load: SplitDwarfLoad>| -> Option>>> { None }; + /// const ADDRESS: u64 = 0xdeadbeef; + /// ctx.preload_units(ADDRESS).for_each(|(load, callback)| { + /// let dwo = do_split_dwarf_load(load); + /// callback(dwo); + /// }); + /// + /// let frames_iter = match ctx.find_frames(ADDRESS) { + /// LookupResult::Output(result) => result, + /// LookupResult::Load { .. } => unreachable!("addr2line promised we wouldn't get here"), + /// }; + /// + /// // ... + /// ``` + pub fn preload_units( + &'_ self, + probe: u64, + ) -> impl Iterator< + Item = ( + SplitDwarfLoad, + impl FnOnce(Option>>) -> Result<(), gimli::Error> + '_, + ), + > { + self.units + .find(probe) + .filter_map(move |unit| match unit.dwarf_and_unit(self) { + LookupResult::Output(_) => None, + LookupResult::Load { load, continuation } => Some((load, |result| { + continuation.resume(result).unwrap().map(|_| ()) + })), + }) + } + + /// Initialize all line data structures. This is used for benchmarks. + #[doc(hidden)] + pub fn parse_lines(&self) -> Result<(), Error> { + for unit in self.units.iter() { + unit.parse_lines(&self.sections)?; + } + Ok(()) + } + + /// Initialize all function data structures. This is used for benchmarks. + #[doc(hidden)] + pub fn parse_functions(&self) -> Result<(), Error> { + for unit in self.units.iter() { + unit.parse_functions(self).skip_all_loads()?; + } + Ok(()) + } + + /// Initialize all inlined function data structures. This is used for benchmarks. + #[doc(hidden)] + pub fn parse_inlined_functions(&self) -> Result<(), Error> { + for unit in self.units.iter() { + unit.parse_inlined_functions(self).skip_all_loads()?; + } + Ok(()) + } +} + +impl Context { + // Find the unit containing the given offset, and convert the offset into a unit offset. + fn find_unit( + &self, + offset: gimli::DebugInfoOffset, + file: DebugFile, + ) -> Result<(&gimli::Unit, gimli::UnitOffset), Error> { + let unit = match file { + DebugFile::Primary => self.units.find_offset(offset)?, + DebugFile::Supplementary => self.sup_units.find_offset(offset)?, + DebugFile::Dwo => return Err(gimli::Error::NoEntryAtGivenOffset), + }; + + let unit_offset = offset + .to_unit_offset(&unit.header) + .ok_or(gimli::Error::NoEntryAtGivenOffset)?; + Ok((unit, unit_offset)) + } +} + +struct RangeAttributes { + low_pc: Option, + high_pc: Option, + size: Option, + ranges_offset: Option::Offset>>, +} + +impl Default for RangeAttributes { + fn default() -> Self { + RangeAttributes { + low_pc: None, + high_pc: None, + size: None, + ranges_offset: None, + } + } +} + +impl RangeAttributes { + fn for_each_range( + &self, + unit: gimli::UnitRef, + mut f: F, + ) -> Result { + let mut added_any = false; + let mut add_range = |range: gimli::Range| { + if range.begin < range.end { + f(range); + added_any = true + } + }; + if let Some(ranges_offset) = self.ranges_offset { + let mut range_list = unit.ranges(ranges_offset)?; + while let Some(range) = range_list.next()? { + add_range(range); + } + } else if let (Some(begin), Some(end)) = (self.low_pc, self.high_pc) { + add_range(gimli::Range { begin, end }); + } else if let (Some(begin), Some(size)) = (self.low_pc, self.size) { + // If `begin` is a -1 tombstone, this will overflow and the check in + // `add_range` will ignore it. + let end = begin.wrapping_add(size); + add_range(gimli::Range { begin, end }); + } + Ok(added_any) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn context_is_send() { + fn assert_is_send() {} + assert_is_send::>>(); + } +} diff --git a/anneal/v2/vendor/addr2line/src/line.rs b/anneal/v2/vendor/addr2line/src/line.rs new file mode 100644 index 0000000000..4b1c95dc37 --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/line.rs @@ -0,0 +1,313 @@ +use alloc::boxed::Box; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::cmp::Ordering; +use core::mem; +use core::num::NonZeroU64; + +use crate::{Error, LazyResult, Location}; + +pub(crate) struct LazyLines(LazyResult); + +impl LazyLines { + pub(crate) fn new() -> Self { + LazyLines(LazyResult::new()) + } + + pub(crate) fn borrow( + &self, + dw_unit: gimli::UnitRef, + ilnp: &gimli::IncompleteLineProgram, + ) -> Result<&Lines, Error> { + self.0 + .get_or_init(|| Lines::parse(dw_unit, ilnp.clone())) + .as_ref() + .map_err(Error::clone) + } +} + +struct LineSequence { + start: u64, + end: u64, + rows: Box<[LineRow]>, +} + +struct LineRow { + address: u64, + file_index: u64, + line: u32, + column: u32, +} + +pub(crate) struct Lines { + files: Box<[String]>, + sequences: Box<[LineSequence]>, +} + +impl Lines { + fn parse( + dw_unit: gimli::UnitRef, + ilnp: gimli::IncompleteLineProgram, + ) -> Result { + let mut sequences = Vec::new(); + let mut sequence_rows = Vec::::new(); + let mut rows = ilnp.rows(); + while let Some((_, row)) = rows.next_row()? { + if row.end_sequence() { + if let Some(start) = sequence_rows.first().map(|x| x.address) { + let end = row.address(); + let mut rows = Vec::new(); + mem::swap(&mut rows, &mut sequence_rows); + sequences.push(LineSequence { + start, + end, + rows: rows.into_boxed_slice(), + }); + } + continue; + } + + let address = row.address(); + let file_index = row.file_index(); + // Convert line and column to u32 to save a little memory. + // We'll handle the special case of line 0 later, + // and return left edge as column 0 in the public API. + let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32; + let column = match row.column() { + gimli::ColumnType::LeftEdge => 0, + gimli::ColumnType::Column(x) => x.get() as u32, + }; + + if let Some(last_row) = sequence_rows.last_mut() { + if last_row.address == address { + last_row.file_index = file_index; + last_row.line = line; + last_row.column = column; + continue; + } + } + + sequence_rows.push(LineRow { + address, + file_index, + line, + column, + }); + } + sequences.sort_by_key(|x| x.start); + + let mut files = Vec::new(); + let header = rows.header(); + match header.file(0) { + Some(file) => files.push(render_file(dw_unit, file, header)?), + None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index + } + let mut index = 1; + while let Some(file) = header.file(index) { + files.push(render_file(dw_unit, file, header)?); + index += 1; + } + + Ok(Self { + files: files.into_boxed_slice(), + sequences: sequences.into_boxed_slice(), + }) + } + + pub(crate) fn file(&self, index: u64) -> Option<&str> { + self.files.get(index as usize).map(String::as_str) + } + + pub(crate) fn ranges(&self) -> impl Iterator + '_ { + self.sequences.iter().map(|sequence| gimli::Range { + begin: sequence.start, + end: sequence.end, + }) + } + + fn row_location(&self, row: &LineRow) -> Location<'_> { + let file = self.files.get(row.file_index as usize).map(String::as_str); + Location { + file, + line: if row.line != 0 { Some(row.line) } else { None }, + // If row.line is specified then row.column always has meaning. + column: if row.line != 0 { + Some(row.column) + } else { + None + }, + } + } + + pub(crate) fn find_location(&self, probe: u64) -> Result>, Error> { + let seq_idx = self.sequences.binary_search_by(|sequence| { + if probe < sequence.start { + Ordering::Greater + } else if probe >= sequence.end { + Ordering::Less + } else { + Ordering::Equal + } + }); + let seq_idx = match seq_idx { + Ok(x) => x, + Err(_) => return Ok(None), + }; + let sequence = &self.sequences[seq_idx]; + + let idx = sequence + .rows + .binary_search_by(|row| row.address.cmp(&probe)); + let idx = match idx { + Ok(x) => x, + Err(0) => return Ok(None), + Err(x) => x - 1, + }; + Ok(Some(self.row_location(&sequence.rows[idx]))) + } + + pub(crate) fn find_location_range( + &self, + probe_low: u64, + probe_high: u64, + ) -> Result, Error> { + // Find index for probe_low. + let seq_idx = self.sequences.binary_search_by(|sequence| { + if probe_low < sequence.start { + Ordering::Greater + } else if probe_low >= sequence.end { + Ordering::Less + } else { + Ordering::Equal + } + }); + let seq_idx = match seq_idx { + Ok(x) => x, + Err(x) => x, // probe below sequence, but range could overlap + }; + + let row_idx = if let Some(seq) = self.sequences.get(seq_idx) { + let idx = seq.rows.binary_search_by(|row| row.address.cmp(&probe_low)); + match idx { + Ok(x) => x, + Err(0) => 0, // probe below sequence, but range could overlap + Err(x) => x - 1, + } + } else { + 0 + }; + + Ok(LineLocationRangeIter { + lines: self, + seq_idx, + row_idx, + probe_high, + }) + } +} + +pub(crate) struct LineLocationRangeIter<'ctx> { + lines: &'ctx Lines, + seq_idx: usize, + row_idx: usize, + probe_high: u64, +} + +impl<'ctx> Iterator for LineLocationRangeIter<'ctx> { + type Item = (u64, u64, Location<'ctx>); + + fn next(&mut self) -> Option<(u64, u64, Location<'ctx>)> { + while let Some(seq) = self.lines.sequences.get(self.seq_idx) { + if seq.start >= self.probe_high { + break; + } + + match seq.rows.get(self.row_idx) { + Some(row) => { + if row.address >= self.probe_high { + break; + } + + let nextaddr = seq + .rows + .get(self.row_idx + 1) + .map(|row| row.address) + .unwrap_or(seq.end); + + let item = ( + row.address, + nextaddr - row.address, + self.lines.row_location(row), + ); + self.row_idx += 1; + + return Some(item); + } + None => { + self.seq_idx += 1; + self.row_idx = 0; + } + } + } + None + } +} + +fn render_file( + dw_unit: gimli::UnitRef, + file: &gimli::FileEntry, + header: &gimli::LineProgramHeader, +) -> Result { + let mut path = if let Some(ref comp_dir) = dw_unit.comp_dir { + comp_dir.to_string_lossy()?.into_owned() + } else { + String::new() + }; + + // The directory index 0 is defined to correspond to the compilation unit directory. + if file.directory_index() != 0 { + if let Some(directory) = file.directory(header) { + path_push( + &mut path, + dw_unit.attr_string(directory)?.to_string_lossy()?.as_ref(), + ); + } + } + + path_push( + &mut path, + dw_unit + .attr_string(file.path_name())? + .to_string_lossy()? + .as_ref(), + ); + + Ok(path) +} + +fn path_push(path: &mut String, p: &str) { + if has_forward_slash_root(p) || has_backward_slash_root(p) { + *path = p.to_string(); + } else { + let dir_separator = if has_backward_slash_root(path.as_str()) { + '\\' + } else { + '/' + }; + + if !path.is_empty() && !path.ends_with(dir_separator) { + path.push(dir_separator); + } + *path += p; + } +} + +/// Check if the path in the given string has a unix style root +fn has_forward_slash_root(p: &str) -> bool { + p.starts_with('/') || p.get(1..3) == Some(":/") +} + +/// Check if the path in the given string has a windows style root +fn has_backward_slash_root(p: &str) -> bool { + p.starts_with('\\') || p.get(1..3) == Some(":\\") +} diff --git a/anneal/v2/vendor/addr2line/src/loader.rs b/anneal/v2/vendor/addr2line/src/loader.rs new file mode 100644 index 0000000000..a006ee590b --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/loader.rs @@ -0,0 +1,499 @@ +use alloc::borrow::Cow; +use alloc::boxed::Box; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::cell::OnceCell; +use std::ffi::OsStr; +use std::fs::File; +use std::path::{Path, PathBuf}; + +use memmap2::Mmap; +use object::{Object, ObjectMapFile, ObjectSection, SymbolMap, SymbolMapName}; +use typed_arena::Arena; + +use crate::{ + Context, FrameIter, Location, LocationRangeIter, LookupContinuation, LookupResult, + SplitDwarfLoad, +}; + +/// The type used by [`Loader`] for reading DWARF data. +/// +/// This is used in the return types of the methods of [`Loader`]. +// TODO: use impl Trait when stable +pub type LoaderReader<'a> = gimli::EndianSlice<'a, gimli::RunTimeEndian>; + +type Error = Box; +type Result = std::result::Result; + +/// A loader for the DWARF data required for a `Context`. +/// +/// For performance reasons, a [`Context`] normally borrows the input data. +/// However, that means the input data must outlive the `Context`, which +/// is inconvenient for long-lived `Context`s. +/// This loader uses an arena to store the input data, together with the +/// `Context` itself. This ensures that the input data lives as long as +/// the `Context`. +/// +/// The loader performs some additional tasks: +/// - Loads the symbol table from the executable file (see [`Self::find_symbol`]). +/// - Loads Mach-O dSYM files that are located next to the executable file. +/// - Locates and loads split DWARF files (DWO and DWP). +pub struct Loader { + internal: LoaderInternal<'static>, + arena_data: Arena>, + arena_mmap: Arena, +} + +impl Loader { + /// Load the DWARF data for an executable file and create a `Context`. + #[inline] + pub fn new(path: impl AsRef) -> Result { + Self::new_with_sup(path, None::<&Path>) + } + + /// Load the DWARF data for an executable file and create a `Context`. + /// + /// Optionally also use a supplementary object file. + pub fn new_with_sup( + path: impl AsRef, + sup_path: Option>, + ) -> Result { + let arena_data = Arena::new(); + let arena_mmap = Arena::new(); + + let internal = LoaderInternal::new( + path.as_ref(), + sup_path.as_ref().map(AsRef::as_ref), + &arena_data, + &arena_mmap, + )?; + Ok(Loader { + // Convert to static lifetime to allow self-reference by `internal`. + // `internal` is only accessed through `borrow_internal`, which ensures + // that the static lifetime does not leak. + internal: unsafe { + core::mem::transmute::, LoaderInternal<'static>>(internal) + }, + arena_data, + arena_mmap, + }) + } + + fn borrow_internal<'a, F, T>(&'a self, f: F) -> T + where + F: FnOnce(&'a LoaderInternal<'a>, &'a Arena>, &'a Arena) -> T, + { + // Do not leak the static lifetime. + let internal = unsafe { + core::mem::transmute::<&LoaderInternal<'static>, &'a LoaderInternal<'a>>(&self.internal) + }; + f(internal, &self.arena_data, &self.arena_mmap) + } + + /// Get the base address used for relative virtual addresses. + /// + /// Currently this is only non-zero for PE. + pub fn relative_address_base(&self) -> u64 { + self.borrow_internal(|i, _data, _mmap| i.relative_address_base) + } + + /// Find the source file and line corresponding to the given virtual memory address. + /// + /// This calls [`Context::find_location`] with the given address. + pub fn find_location(&self, probe: u64) -> Result>> { + self.borrow_internal(|i, data, mmap| i.find_location(probe, data, mmap)) + } + + /// Return source file and lines for a range of addresses. + /// + /// This calls [`Context::find_location_range`] with the given range. + pub fn find_location_range( + &self, + probe_low: u64, + probe_high: u64, + ) -> Result>> { + self.borrow_internal(|i, data, mmap| { + i.find_location_range(probe_low, probe_high, data, mmap) + }) + } + + /// Return an iterator for the function frames corresponding to the given virtual + /// memory address. + /// + /// This calls [`Context::find_frames`] with the given address. + pub fn find_frames(&self, probe: u64) -> Result>> { + self.borrow_internal(|i, data, mmap| i.find_frames(probe, data, mmap)) + } + + /// Find the symbol table entry corresponding to the given virtual memory address. + /// Return the symbol name. + pub fn find_symbol(&self, probe: u64) -> Option<&str> { + self.find_symbol_info(probe).map(|symbol| symbol.name) + } + + /// Find the symbol table entry corresponding to the given virtual memory address. + pub fn find_symbol_info(&self, probe: u64) -> Option> { + self.borrow_internal(|i, _data, _mmap| i.find_symbol_info(probe)) + } + + /// Get the address of a section + pub fn get_section_range(&self, section_name: &[u8]) -> Option { + self.borrow_internal(|i, _data, _mmap| i.get_section_range(section_name)) + } +} + +struct LoaderInternal<'a> { + ctx: Context>, + object: object::File<'a>, + relative_address_base: u64, + symbols: SymbolMap>, + dwarf_package: Option>>, + // Map from address to Mach-O object file path. + object_map: object::ObjectMap<'a>, + // A context for each Mach-O object file. + objects: Vec>>>, +} + +impl<'a> LoaderInternal<'a> { + fn new( + path: &Path, + sup_path: Option<&Path>, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Result { + let file = File::open(path)?; + let map = arena_mmap.alloc(unsafe { Mmap::map(&file)? }); + let object = object::File::parse(&**map)?; + + let relative_address_base = object.relative_address_base(); + let symbols = object.symbol_map(); + let object_map = object.object_map(); + let mut objects = Vec::new(); + objects.resize_with(object_map.objects().len(), OnceCell::new); + + // Load supplementary object file. + // TODO: use debuglink and debugaltlink + let sup_map; + let sup_object = if let Some(sup_path) = sup_path { + let sup_file = File::open(sup_path)?; + sup_map = arena_mmap.alloc(unsafe { Mmap::map(&sup_file)? }); + Some(object::File::parse(&**sup_map)?) + } else { + None + }; + + // Load Mach-O dSYM file, ignoring errors. + let dsym = if let Some(map) = (|| { + let uuid = object.mach_uuid().ok()??; + path.parent()?.read_dir().ok()?.find_map(|candidate| { + let candidate = candidate.ok()?; + let path = candidate.path(); + if path.extension().and_then(OsStr::to_str) != Some("dSYM") { + return None; + } + let path = path.join("Contents/Resources/DWARF"); + path.read_dir().ok()?.find_map(|candidate| { + let candidate = candidate.ok()?; + let path = candidate.path(); + let file = File::open(path).ok()?; + let map = unsafe { Mmap::map(&file) }.ok()?; + let object = object::File::parse(&*map).ok()?; + if object.mach_uuid() == Ok(Some(uuid)) { + Some(map) + } else { + None + } + }) + }) + })() { + let map = arena_mmap.alloc(map); + Some(object::File::parse(&**map)?) + } else { + None + }; + let dwarf_object = dsym.as_ref().unwrap_or(&object); + + // Load the DWARF sections. + let endian = if dwarf_object.is_little_endian() { + gimli::RunTimeEndian::Little + } else { + gimli::RunTimeEndian::Big + }; + let mut dwarf = gimli::Dwarf::load(|id| { + load_section(Some(id.name()), dwarf_object, endian, arena_data) + })?; + if let Some(sup_object) = &sup_object { + dwarf.load_sup(|id| load_section(Some(id.name()), sup_object, endian, arena_data))?; + } + dwarf.populate_abbreviations_cache(gimli::AbbreviationsCacheStrategy::Duplicates); + + let ctx = Context::from_dwarf(dwarf)?; + + // Load the DWP file, ignoring errors. + let dwarf_package = (|| { + let mut dwp_path = path.to_path_buf(); + let dwp_extension = path + .extension() + .map(|previous_extension| { + let mut previous_extension = previous_extension.to_os_string(); + previous_extension.push(".dwp"); + previous_extension + }) + .unwrap_or_else(|| "dwp".into()); + dwp_path.set_extension(dwp_extension); + let dwp_file = File::open(&dwp_path).ok()?; + let map = arena_mmap.alloc(unsafe { Mmap::map(&dwp_file) }.ok()?); + let dwp_object = object::File::parse(&**map).ok()?; + + let endian = if dwp_object.is_little_endian() { + gimli::RunTimeEndian::Little + } else { + gimli::RunTimeEndian::Big + }; + let empty = gimli::EndianSlice::new(&[][..], endian); + gimli::DwarfPackage::load( + |id| load_section(id.dwo_name(), &dwp_object, endian, arena_data), + empty, + ) + .ok() + })(); + + Ok(LoaderInternal { + ctx, + object, + relative_address_base, + symbols, + dwarf_package, + object_map, + objects, + }) + } + + fn ctx( + &self, + probe: u64, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> (&Context>, u64) { + self.object_ctx(probe, arena_data, arena_mmap) + .unwrap_or((&self.ctx, probe)) + } + + fn object_ctx( + &self, + probe: u64, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Option<(&Context>, u64)> { + let symbol = self.object_map.get(probe)?; + let object_context = self.objects[symbol.object_index()] + .get_or_init(|| { + ObjectContext::new(symbol.object(&self.object_map), arena_data, arena_mmap) + }) + .as_ref()?; + object_context.ctx(symbol.name(), probe - symbol.address()) + } + + fn find_symbol_info(&self, probe: u64) -> Option> { + self.symbols.get(probe).map(|x| Symbol { + name: x.name(), + address: x.address(), + }) + } + + fn get_section_range(&self, section_name: &[u8]) -> Option { + self.object + .section_by_name_bytes(section_name) + .map(|section| { + let begin = section.address(); + let end = begin + section.size(); + gimli::Range { begin, end } + }) + } + + fn find_location( + &'a self, + probe: u64, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Result>> { + let (ctx, probe) = self.ctx(probe, arena_data, arena_mmap); + Ok(ctx.find_location(probe)?) + } + + fn find_location_range( + &self, + probe_low: u64, + probe_high: u64, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Result>> { + let (ctx, probe) = self.ctx(probe_low, arena_data, arena_mmap); + // TODO: handle ranges that cover multiple objects + let probe_high = probe + (probe_high - probe_low); + Ok(ctx.find_location_range(probe, probe_high)?) + } + + fn find_frames( + &self, + probe: u64, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Result>> { + let (ctx, probe) = self.ctx(probe, arena_data, arena_mmap); + let mut frames = ctx.find_frames(probe); + loop { + let (load, continuation) = match frames { + LookupResult::Output(output) => return Ok(output?), + LookupResult::Load { load, continuation } => (load, continuation), + }; + + let r = self.load_dwo(load, arena_data, arena_mmap)?; + frames = continuation.resume(r); + } + } + + fn load_dwo( + &self, + load: SplitDwarfLoad>, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Result>>>> { + // Load the DWO file from the DWARF package, if available. + if let Some(dwp) = self.dwarf_package.as_ref() { + if let Some(cu) = dwp.find_cu(load.dwo_id, &load.parent)? { + return Ok(Some(Arc::new(cu))); + } + } + + // Determine the path to the DWO file. + let mut path = PathBuf::new(); + if let Some(p) = load.comp_dir.as_ref() { + path.push(convert_path(p.slice())?); + } + let Some(p) = load.path.as_ref() else { + return Ok(None); + }; + path.push(convert_path(p.slice())?); + + // Load the DWO file, ignoring errors. + let dwo = (|| { + let file = File::open(&path).ok()?; + let map = arena_mmap.alloc(unsafe { Mmap::map(&file) }.ok()?); + let object = object::File::parse(&**map).ok()?; + let endian = if object.is_little_endian() { + gimli::RunTimeEndian::Little + } else { + gimli::RunTimeEndian::Big + }; + let mut dwo_dwarf = + gimli::Dwarf::load(|id| load_section(id.dwo_name(), &object, endian, arena_data)) + .ok()?; + let dwo_unit_header = dwo_dwarf.units().next().ok()??; + let dwo_unit = dwo_dwarf.unit(dwo_unit_header).ok()?; + if dwo_unit.dwo_id != Some(load.dwo_id) { + return None; + } + dwo_dwarf.make_dwo(&load.parent); + Some(Arc::new(dwo_dwarf)) + })(); + Ok(dwo) + } +} + +struct ObjectContext<'a> { + ctx: Context>, + symbols: SymbolMap>, +} + +impl<'a> ObjectContext<'a> { + fn new( + object: &ObjectMapFile<'a>, + arena_data: &'a Arena>, + arena_mmap: &'a Arena, + ) -> Option { + let file = File::open(convert_path(object.path()).ok()?).ok()?; + let map = &**arena_mmap.alloc(unsafe { Mmap::map(&file) }.ok()?); + let data = if let Some(member_name) = object.member() { + let archive = object::read::archive::ArchiveFile::parse(map).ok()?; + let member = archive.members().find_map(|member| { + let member = member.ok()?; + if member.name() == member_name { + Some(member) + } else { + None + } + })?; + member.data(map).ok()? + } else { + map + }; + let object = object::File::parse(data).ok()?; + let endian = if object.is_little_endian() { + gimli::RunTimeEndian::Little + } else { + gimli::RunTimeEndian::Big + }; + let dwarf = + gimli::Dwarf::load(|id| load_section(Some(id.name()), &object, endian, arena_data)) + .ok()?; + let ctx = Context::from_dwarf(dwarf).ok()?; + let symbols = object.symbol_map(); + Some(ObjectContext { ctx, symbols }) + } + + fn ctx(&self, symbol_name: &[u8], probe: u64) -> Option<(&Context>, u64)> { + self.symbols + .symbols() + .iter() + .find(|symbol| symbol.name().as_bytes() == symbol_name) + .map(|symbol| (&self.ctx, probe + symbol.address())) + } +} + +fn load_section<'input, Endian: gimli::Endianity>( + name: Option<&'static str>, + file: &object::File<'input>, + endian: Endian, + arena_data: &'input Arena>, +) -> Result> { + let data = match name.and_then(|name| file.section_by_name(name)) { + Some(section) => match section.uncompressed_data()? { + Cow::Borrowed(b) => b, + Cow::Owned(b) => arena_data.alloc(b), + }, + None => &[], + }; + Ok(gimli::EndianSlice::new(data, endian)) +} + +#[cfg(unix)] +fn convert_path(bytes: &[u8]) -> Result { + use std::os::unix::ffi::OsStrExt; + let s = OsStr::from_bytes(bytes); + Ok(PathBuf::from(s)) +} + +#[cfg(not(unix))] +fn convert_path(bytes: &[u8]) -> Result { + let s = std::str::from_utf8(bytes)?; + Ok(PathBuf::from(s)) +} + +/// Information from a symbol table entry. +pub struct Symbol<'a> { + name: &'a str, + address: u64, +} + +impl<'a> Symbol<'a> { + /// Get the symbol name. + pub fn name(&self) -> &'a str { + self.name + } + + /// Get the symbol address. + pub fn address(&self) -> u64 { + self.address + } +} diff --git a/anneal/v2/vendor/addr2line/src/lookup.rs b/anneal/v2/vendor/addr2line/src/lookup.rs new file mode 100644 index 0000000000..cc33dd5cb9 --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/lookup.rs @@ -0,0 +1,261 @@ +use alloc::sync::Arc; +use core::marker::PhantomData; +use core::ops::ControlFlow; + +/// This struct contains the information needed to find split DWARF data +/// and to produce a `gimli::Dwarf` for it. +pub struct SplitDwarfLoad { + /// The dwo id, for looking up in a DWARF package, or for + /// verifying an unpacked dwo found on the file system + pub dwo_id: gimli::DwoId, + /// The compilation directory `path` is relative to. + pub comp_dir: Option, + /// A path on the filesystem, relative to `comp_dir` to find this dwo. + pub path: Option, + /// Once the split DWARF data is loaded, the loader is expected + /// to call [make_dwo(parent)](gimli::read::Dwarf::make_dwo) before + /// returning the data. + pub parent: Arc>, +} + +/// Operations that consult debug information may require additional files +/// to be loaded if split DWARF is being used. This enum returns the result +/// of the operation in the `Output` variant, or information about the split +/// DWARF that is required and a continuation to invoke once it is available +/// in the `Load` variant. +/// +/// This enum is intended to be used in a loop like so: +/// ```no_run +/// # use addr2line::*; +/// # use std::sync::Arc; +/// # let ctx: Context> = todo!(); +/// # let do_split_dwarf_load = |load: SplitDwarfLoad>| -> Option>>> { None }; +/// const ADDRESS: u64 = 0xdeadbeef; +/// let mut r = ctx.find_frames(ADDRESS); +/// let result = loop { +/// match r { +/// LookupResult::Output(result) => break result, +/// LookupResult::Load { load, continuation } => { +/// let dwo = do_split_dwarf_load(load); +/// r = continuation.resume(dwo); +/// } +/// } +/// }; +/// ``` +pub enum LookupResult { + /// The lookup requires split DWARF data to be loaded. + Load { + /// The information needed to find the split DWARF data. + load: SplitDwarfLoad<::Buf>, + /// The continuation to resume with the loaded split DWARF data. + continuation: L, + }, + /// The lookup has completed and produced an output. + Output(::Output), +} + +/// This trait represents a partially complete operation that can be resumed +/// once a load of needed split DWARF data is completed or abandoned by the +/// API consumer. +pub trait LookupContinuation: Sized { + /// The final output of this operation. + type Output; + /// The type of reader used. + type Buf: gimli::Reader; + + /// Resumes the operation with the provided data. + /// + /// After the caller loads the split DWARF data required, call this + /// method to resume the operation. The return value of this method + /// indicates if the computation has completed or if further data is + /// required. + /// + /// If the additional data cannot be located, or the caller does not + /// support split DWARF, `resume(None)` can be used to continue the + /// operation with the data that is available. + fn resume(self, input: Option>>) -> LookupResult; +} + +impl LookupResult { + /// Callers that do not handle split DWARF can call `skip_all_loads` + /// to fast-forward to the end result. This result is produced with + /// the data that is available and may be less accurate than the + /// the results that would be produced if the caller did properly + /// support split DWARF. + pub fn skip_all_loads(mut self) -> L::Output { + loop { + self = match self { + LookupResult::Output(t) => return t, + LookupResult::Load { continuation, .. } => continuation.resume(None), + }; + } + } + + pub(crate) fn map T>( + self, + f: F, + ) -> LookupResult> { + match self { + LookupResult::Output(t) => LookupResult::Output(f(t)), + LookupResult::Load { load, continuation } => LookupResult::Load { + load, + continuation: MappedLookup { + original: continuation, + mutator: f, + }, + }, + } + } + + pub(crate) fn unwrap(self) -> L::Output { + match self { + LookupResult::Output(t) => t, + LookupResult::Load { .. } => unreachable!("Internal API misuse"), + } + } +} + +pub(crate) struct SimpleLookup +where + F: FnOnce(Option>>) -> T, + R: gimli::Reader, +{ + f: F, + phantom: PhantomData<(T, R)>, +} + +impl SimpleLookup +where + F: FnOnce(Option>>) -> T, + R: gimli::Reader, +{ + pub(crate) fn new_complete(t: F::Output) -> LookupResult> { + LookupResult::Output(t) + } + + pub(crate) fn new_needs_load( + load: SplitDwarfLoad, + f: F, + ) -> LookupResult> { + LookupResult::Load { + load, + continuation: SimpleLookup { + f, + phantom: PhantomData, + }, + } + } +} + +impl LookupContinuation for SimpleLookup +where + F: FnOnce(Option>>) -> T, + R: gimli::Reader, +{ + type Output = T; + type Buf = R; + + fn resume(self, v: Option>>) -> LookupResult { + LookupResult::Output((self.f)(v)) + } +} + +pub(crate) struct MappedLookup +where + L: LookupContinuation, + F: FnOnce(L::Output) -> T, +{ + original: L, + mutator: F, +} + +impl LookupContinuation for MappedLookup +where + L: LookupContinuation, + F: FnOnce(L::Output) -> T, +{ + type Output = T; + type Buf = L::Buf; + + fn resume(self, v: Option>>) -> LookupResult { + match self.original.resume(v) { + LookupResult::Output(t) => LookupResult::Output((self.mutator)(t)), + LookupResult::Load { load, continuation } => LookupResult::Load { + load, + continuation: MappedLookup { + original: continuation, + mutator: self.mutator, + }, + }, + } + } +} + +/// Some functions (e.g. `find_frames`) require considering multiple +/// compilation units, each of which might require their own split DWARF +/// lookup (and thus produce a continuation). +/// +/// We store the underlying continuation here as well as a mutator function +/// that will either a) decide that the result of this continuation is +/// what is needed and mutate it to the final result or b) produce another +/// `LookupResult`. `new_lookup` will in turn eagerly drive any non-continuation +/// `LookupResult` with successive invocations of the mutator, until a new +/// continuation or a final result is produced. And finally, the impl of +/// `LookupContinuation::resume` will call `new_lookup` each time the +/// computation is resumed. +pub(crate) struct LoopingLookup +where + L: LookupContinuation, + F: FnMut(L::Output) -> ControlFlow>, +{ + continuation: L, + mutator: F, +} + +impl LoopingLookup +where + L: LookupContinuation, + F: FnMut(L::Output) -> ControlFlow>, +{ + pub(crate) fn new_complete(t: T) -> LookupResult { + LookupResult::Output(t) + } + + pub(crate) fn new_lookup(mut r: LookupResult, mut mutator: F) -> LookupResult { + // Drive the loop eagerly so that we only ever have to represent one state + // (the r == ControlFlow::Continue state) in LoopingLookup. + loop { + match r { + LookupResult::Output(l) => match mutator(l) { + ControlFlow::Break(t) => return LookupResult::Output(t), + ControlFlow::Continue(r2) => { + r = r2; + } + }, + LookupResult::Load { load, continuation } => { + return LookupResult::Load { + load, + continuation: LoopingLookup { + continuation, + mutator, + }, + }; + } + } + } + } +} + +impl LookupContinuation for LoopingLookup +where + L: LookupContinuation, + F: FnMut(L::Output) -> ControlFlow>, +{ + type Output = T; + type Buf = L::Buf; + + fn resume(self, v: Option>>) -> LookupResult { + let r = self.continuation.resume(v); + LoopingLookup::new_lookup(r, self.mutator) + } +} diff --git a/anneal/v2/vendor/addr2line/src/unit.rs b/anneal/v2/vendor/addr2line/src/unit.rs new file mode 100644 index 0000000000..ef0bca246c --- /dev/null +++ b/anneal/v2/vendor/addr2line/src/unit.rs @@ -0,0 +1,598 @@ +use alloc::boxed::Box; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::cmp; + +use crate::{ + Context, DebugFile, Error, Function, Functions, LazyFunctions, LazyLines, LazyResult, + LineLocationRangeIter, Lines, Location, LookupContinuation, LookupResult, RangeAttributes, + SimpleLookup, SplitDwarfLoad, +}; + +pub(crate) struct UnitRange { + unit_id: usize, + min_begin: u64, + range: gimli::Range, +} + +pub(crate) struct ResUnit { + offset: gimli::DebugInfoOffset, + dw_unit: gimli::Unit, + pub(crate) lang: Option, + lines: LazyLines, + functions: LazyFunctions, + dwo: LazyResult>>>, +} + +type UnitRef<'unit, R> = (DebugFile, gimli::UnitRef<'unit, R>); + +impl ResUnit { + pub(crate) fn unit_ref<'a>(&'a self, sections: &'a gimli::Dwarf) -> gimli::UnitRef<'a, R> { + gimli::UnitRef::new(sections, &self.dw_unit) + } + + /// Returns the DWARF sections and the unit. + /// + /// Loads the DWO unit if necessary. + pub(crate) fn dwarf_and_unit<'unit, 'ctx: 'unit>( + &'unit self, + ctx: &'ctx Context, + ) -> LookupResult< + SimpleLookup< + Result, Error>, + R, + impl FnOnce(Option>>) -> Result, Error>, + >, + > { + let map_dwo = move |dwo: &'unit Result>>, Error>| match dwo { + Ok(Some(dwo)) => Ok((DebugFile::Dwo, dwo.unit_ref())), + Ok(None) => Ok((DebugFile::Primary, self.unit_ref(&*ctx.sections))), + Err(e) => Err(*e), + }; + let complete = |dwo| SimpleLookup::new_complete(map_dwo(dwo)); + + if let Some(dwo) = self.dwo.get() { + return complete(dwo); + } + + let dwo_id = match self.dw_unit.dwo_id { + None => { + return complete(self.dwo.get_or_init(|| Ok(None))); + } + Some(dwo_id) => dwo_id, + }; + + let comp_dir = self.dw_unit.comp_dir.clone(); + + let dwo_name = self.dw_unit.dwo_name().and_then(|s| { + if let Some(s) = s { + Ok(Some(ctx.sections.attr_string(&self.dw_unit, s)?)) + } else { + Ok(None) + } + }); + + let path = match dwo_name { + Ok(v) => v, + Err(e) => { + return complete(self.dwo.get_or_init(|| Err(e))); + } + }; + + let process_dwo = move |dwo_dwarf: Option>>| { + let dwo_dwarf = match dwo_dwarf { + None => return Ok(None), + Some(dwo_dwarf) => dwo_dwarf, + }; + let mut dwo_units = dwo_dwarf.units(); + let dwo_header = match dwo_units.next()? { + Some(dwo_header) => dwo_header, + None => return Ok(None), + }; + + let mut dwo_unit = dwo_dwarf.unit(dwo_header)?; + dwo_unit.copy_relocated_attributes(&self.dw_unit); + Ok(Some(Box::new(DwoUnit { + sections: dwo_dwarf, + dw_unit: dwo_unit, + }))) + }; + + SimpleLookup::new_needs_load( + SplitDwarfLoad { + dwo_id, + comp_dir, + path, + parent: ctx.sections.clone(), + }, + move |dwo_dwarf| map_dwo(self.dwo.get_or_init(|| process_dwo(dwo_dwarf))), + ) + } + + pub(crate) fn parse_lines(&self, sections: &gimli::Dwarf) -> Result, Error> { + // NB: line information is always stored in the main debug file so this does not need + // to handle DWOs. + let ilnp = match self.dw_unit.line_program { + Some(ref ilnp) => ilnp, + None => return Ok(None), + }; + self.lines.borrow(self.unit_ref(sections), ilnp).map(Some) + } + + pub(crate) fn parse_functions<'unit, 'ctx: 'unit>( + &'unit self, + ctx: &'ctx Context, + ) -> LookupResult, Error>, Buf = R>> + { + self.dwarf_and_unit(ctx).map(move |r| { + let (_file, unit) = r?; + self.functions.borrow(unit) + }) + } + + pub(crate) fn parse_inlined_functions<'unit, 'ctx: 'unit>( + &'unit self, + ctx: &'ctx Context, + ) -> LookupResult, Buf = R> + 'unit> { + self.dwarf_and_unit(ctx).map(move |r| { + let (file, unit) = r?; + self.functions + .borrow(unit)? + .parse_inlined_functions(file, unit, ctx) + }) + } + + pub(crate) fn find_location( + &self, + probe: u64, + sections: &gimli::Dwarf, + ) -> Result>, Error> { + let Some(lines) = self.parse_lines(sections)? else { + return Ok(None); + }; + lines.find_location(probe) + } + + #[inline] + pub(crate) fn find_location_range( + &self, + probe_low: u64, + probe_high: u64, + sections: &gimli::Dwarf, + ) -> Result>, Error> { + let Some(lines) = self.parse_lines(sections)? else { + return Ok(None); + }; + lines.find_location_range(probe_low, probe_high).map(Some) + } + + pub(crate) fn find_function_or_location<'unit, 'ctx: 'unit>( + &'unit self, + probe: u64, + ctx: &'ctx Context, + ) -> LookupResult< + impl LookupContinuation< + Output = Result<(Option<&'unit Function>, Option>), Error>, + Buf = R, + >, + > { + self.dwarf_and_unit(ctx).map(move |r| { + let (file, unit) = r?; + let functions = self.functions.borrow(unit)?; + let function = match functions.find_address(probe) { + Some(address) => { + let function_index = functions.addresses[address].function; + let function = &functions.functions[function_index]; + Some(function.borrow(file, unit, ctx)?) + } + None => None, + }; + let location = self.find_location(probe, &ctx.sections)?; + Ok((function, location)) + }) + } +} + +pub(crate) struct ResUnits { + ranges: Box<[UnitRange]>, + units: Box<[ResUnit]>, +} + +impl ResUnits { + pub(crate) fn parse(sections: &gimli::Dwarf) -> Result { + // Find all the references to compilation units in .debug_aranges. + // Note that we always also iterate through all of .debug_info to + // find compilation units, because .debug_aranges may be missing some. + let mut aranges = Vec::new(); + let mut headers = sections.debug_aranges.headers(); + while let Some(header) = headers.next()? { + aranges.push((header.debug_info_offset(), header.offset())); + } + aranges.sort_by_key(|i| i.0); + + let mut unit_ranges = Vec::new(); + let mut res_units = Vec::new(); + let mut units = sections.units(); + while let Some(header) = units.next()? { + let unit_id = res_units.len(); + let offset = match header.offset().as_debug_info_offset() { + Some(offset) => offset, + None => continue, + }; + // We mainly want compile units, but we may need to follow references to entries + // within other units for function names. We don't need anything from type units. + let mut need_unit_range = match header.type_() { + gimli::UnitType::Type { .. } | gimli::UnitType::SplitType { .. } => continue, + gimli::UnitType::Partial => { + // Partial units are only needed for references from other units. + // They shouldn't have any address ranges. + false + } + _ => true, + }; + let dw_unit = match sections.unit(header) { + Ok(dw_unit) => dw_unit, + Err(_) => continue, + }; + let dw_unit_ref = gimli::UnitRef::new(sections, &dw_unit); + + let mut lang = None; + if need_unit_range { + let mut entries = dw_unit_ref.entries_raw(None)?; + + let abbrev = match entries.read_abbreviation()? { + Some(abbrev) => abbrev, + None => continue, + }; + + let mut ranges = RangeAttributes::default(); + for spec in abbrev.attributes() { + let attr = entries.read_attribute(*spec)?; + match attr.name() { + gimli::DW_AT_low_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val), + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.low_pc = Some(dw_unit_ref.address(index)?); + } + _ => {} + }, + gimli::DW_AT_high_pc => match attr.value() { + gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val), + gimli::AttributeValue::DebugAddrIndex(index) => { + ranges.high_pc = Some(dw_unit_ref.address(index)?); + } + gimli::AttributeValue::Udata(val) => ranges.size = Some(val), + _ => {} + }, + gimli::DW_AT_ranges => { + ranges.ranges_offset = dw_unit_ref.attr_ranges_offset(attr.value())?; + } + gimli::DW_AT_language => { + if let gimli::AttributeValue::Language(val) = attr.value() { + lang = Some(val); + } + } + _ => {} + } + } + + // Find the address ranges for the CU, using in order of preference: + // - DW_AT_ranges + // - .debug_aranges + // - DW_AT_low_pc/DW_AT_high_pc + // + // Using DW_AT_ranges before .debug_aranges is possibly an arbitrary choice, + // but the feeling is that DW_AT_ranges is more likely to be reliable or complete + // if it is present. + // + // .debug_aranges must be used before DW_AT_low_pc/DW_AT_high_pc because + // it has been observed on macOS that DW_AT_ranges was not emitted even for + // discontiguous CUs. + let i = match ranges.ranges_offset { + Some(_) => None, + None => aranges.binary_search_by_key(&offset, |x| x.0).ok(), + }; + if let Some(mut i) = i { + // There should be only one set per CU, but in practice multiple + // sets have been observed. This is probably a compiler bug, but + // either way we need to handle it. + while i > 0 && aranges[i - 1].0 == offset { + i -= 1; + } + for (_, aranges_offset) in aranges[i..].iter().take_while(|x| x.0 == offset) { + let aranges_header = sections.debug_aranges.header(*aranges_offset)?; + let mut aranges = aranges_header.entries(); + while let Some(arange) = aranges.next().transpose() { + let Ok(arange) = arange else { + // Ignore errors. In particular, this will ignore address overflow. + // This has been seen for a unit that had a single variable + // with rustc 1.89.0. + // + // This relies on `ArangeEntryIter::next` fusing for errors that + // can't be ignored. + continue; + }; + if arange.length() != 0 { + unit_ranges.push(UnitRange { + range: arange.range(), + unit_id, + min_begin: 0, + }); + need_unit_range = false; + } + } + } + } + if need_unit_range { + need_unit_range = !ranges.for_each_range(dw_unit_ref, |range| { + unit_ranges.push(UnitRange { + range, + unit_id, + min_begin: 0, + }); + })?; + } + } + + let lines = LazyLines::new(); + if need_unit_range { + // The unit did not declare any ranges. + // Try to get some ranges from the line program sequences. + if let Some(ref ilnp) = dw_unit_ref.line_program { + if let Ok(lines) = lines.borrow(dw_unit_ref, ilnp) { + for range in lines.ranges() { + unit_ranges.push(UnitRange { + range, + unit_id, + min_begin: 0, + }) + } + } + } + } + + res_units.push(ResUnit { + offset, + dw_unit, + lang, + lines, + functions: LazyFunctions::new(), + dwo: LazyResult::new(), + }); + } + + // Sort this for faster lookup in `Self::find_range`. + unit_ranges.sort_by_key(|i| i.range.end); + + // Calculate the `min_begin` field now that we've determined the order of + // CUs. + let mut min = !0; + for i in unit_ranges.iter_mut().rev() { + min = min.min(i.range.begin); + i.min_begin = min; + } + + Ok(ResUnits { + ranges: unit_ranges.into_boxed_slice(), + units: res_units.into_boxed_slice(), + }) + } + + pub(crate) fn iter(&self) -> impl Iterator> { + self.units.iter() + } + + pub(crate) fn find_offset( + &self, + offset: gimli::DebugInfoOffset, + ) -> Result<&gimli::Unit, Error> { + match self + .units + .binary_search_by_key(&offset.0, |unit| unit.offset.0) + { + // There is never a DIE at the unit offset or before the first unit. + Ok(_) | Err(0) => Err(gimli::Error::NoEntryAtGivenOffset), + Err(i) => Ok(&self.units[i - 1].dw_unit), + } + } + + /// Finds the CUs for the function address given. + /// + /// There might be multiple CUs whose range contains this address. + /// Weak symbols have shown up in the wild which cause this to happen + /// but otherwise this can happen if the CU has non-contiguous functions + /// but only reports a single range. + /// + /// Consequently we return an iterator for all CUs which may contain the + /// address, and the caller must check if there is actually a function or + /// location in the CU for that address. + pub(crate) fn find(&self, probe: u64) -> impl Iterator> { + self.find_range(probe, probe + 1).map(|(unit, _range)| unit) + } + + /// Finds the CUs covering the range of addresses given. + /// + /// The range is [low, high) (ie, the upper bound is exclusive). This can return multiple + /// ranges for the same unit. + #[inline] + pub(crate) fn find_range( + &self, + probe_low: u64, + probe_high: u64, + ) -> impl Iterator, &gimli::Range)> { + // Find the position of the next range after a range which + // ends at `probe_low` or lower. + let pos = match self + .ranges + .binary_search_by_key(&probe_low, |i| i.range.end) + { + Ok(i) => i + 1, // Range `i` ends at exactly `probe_low`. + Err(i) => i, // Range `i - 1` ends at a lower address. + }; + + // Iterate from that position to find matching CUs. + self.ranges[pos..] + .iter() + .take_while(move |i| { + // We know that this CU's end is at least `probe_low` because + // of our sorted array. + debug_assert!(i.range.end >= probe_low); + + // Each entry keeps track of the minimum begin address for the + // remainder of the array of unit ranges. If our probe is before + // the minimum range begin of this entry, then it's guaranteed + // to not fit in any subsequent entries, so we break out. + probe_high > i.min_begin + }) + .filter_map(move |i| { + // If this CU doesn't actually contain this address, move to the + // next CU. + if probe_low >= i.range.end || probe_high <= i.range.begin { + return None; + } + Some((&self.units[i.unit_id], &i.range)) + }) + } + + pub(crate) fn find_location_range<'a>( + &'a self, + probe_low: u64, + probe_high: u64, + sections: &'a gimli::Dwarf, + ) -> Result, Error> { + let unit_iter = Box::new(self.find_range(probe_low, probe_high)); + Ok(LocationRangeIter { + unit_iter, + iter: None, + probe_low, + probe_high, + sections, + }) + } +} + +/// A DWO unit has its own DWARF sections. +struct DwoUnit { + sections: Arc>, + dw_unit: gimli::Unit, +} + +impl DwoUnit { + fn unit_ref(&self) -> gimli::UnitRef<'_, R> { + gimli::UnitRef::new(&self.sections, &self.dw_unit) + } +} + +pub(crate) struct SupUnit { + offset: gimli::DebugInfoOffset, + dw_unit: gimli::Unit, +} + +pub(crate) struct SupUnits { + units: Box<[SupUnit]>, +} + +impl Default for SupUnits { + fn default() -> Self { + SupUnits { + units: Box::default(), + } + } +} + +impl SupUnits { + pub(crate) fn parse(sections: &gimli::Dwarf) -> Result { + let mut sup_units = Vec::new(); + let mut units = sections.units(); + while let Some(header) = units.next()? { + let offset = match header.offset().as_debug_info_offset() { + Some(offset) => offset, + None => continue, + }; + let dw_unit = match sections.unit(header) { + Ok(dw_unit) => dw_unit, + Err(_) => continue, + }; + sup_units.push(SupUnit { dw_unit, offset }); + } + Ok(SupUnits { + units: sup_units.into_boxed_slice(), + }) + } + + pub(crate) fn find_offset( + &self, + offset: gimli::DebugInfoOffset, + ) -> Result<&gimli::Unit, Error> { + match self + .units + .binary_search_by_key(&offset.0, |unit| unit.offset.0) + { + // There is never a DIE at the unit offset or before the first unit. + Ok(_) | Err(0) => Err(gimli::Error::NoEntryAtGivenOffset), + Err(i) => Ok(&self.units[i - 1].dw_unit), + } + } +} + +/// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`. +pub struct LocationRangeIter<'ctx, R: gimli::Reader> { + unit_iter: Box, &'ctx gimli::Range)> + 'ctx>, + iter: Option>, + + probe_low: u64, + probe_high: u64, + sections: &'ctx gimli::Dwarf, +} + +impl<'ctx, R: gimli::Reader> LocationRangeIter<'ctx, R> { + fn next_loc(&mut self) -> Result)>, Error> { + loop { + let iter = self.iter.take(); + match iter { + None => match self.unit_iter.next() { + Some((unit, range)) => { + self.iter = unit.find_location_range( + cmp::max(self.probe_low, range.begin), + cmp::min(self.probe_high, range.end), + self.sections, + )?; + } + None => return Ok(None), + }, + Some(mut iter) => { + if let item @ Some(_) = iter.next() { + self.iter = Some(iter); + return Ok(item); + } + } + } + } + } +} + +impl<'ctx, R> Iterator for LocationRangeIter<'ctx, R> +where + R: gimli::Reader + 'ctx, +{ + type Item = (u64, u64, Location<'ctx>); + + #[inline] + fn next(&mut self) -> Option { + self.next_loc().unwrap_or_default() + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'ctx, R> fallible_iterator::FallibleIterator for LocationRangeIter<'ctx, R> +where + R: gimli::Reader + 'ctx, +{ + type Item = (u64, u64, Location<'ctx>); + type Error = Error; + + #[inline] + fn next(&mut self) -> Result, Self::Error> { + self.next_loc() + } +} diff --git a/anneal/v2/vendor/backtrace-ext/.cargo-checksum.json b/anneal/v2/vendor/backtrace-ext/.cargo-checksum.json new file mode 100644 index 0000000000..03240388bf --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"9fc4a92f2a95cea9717647e152cfeca5a571e42411b01dc6459fdd82fb87c576",".github/workflows/ci.yml":"d4b62dea116d13edebb1f936f4fd81d27b57151fc649a3fd2cccc17b7fe29728","Cargo.lock":"e6108103e5de7a31784d19ff1ce5f208f5ba926da8d49991f11f6b9f6b3a7a6a","Cargo.toml":"6c19e27c8d3f3c65ae6720d5715036faa3ab6f6187853d125e24d5ef5295d524","Cargo.toml.orig":"0205a3bf2c5eee4cf95ef2b8977629e6b748035f0ddc5de200479e6ed37eaeb3","README.md":"0545686a94177567dd9c957f137256b3d49eba77560f3b12a4b5c6c8d6546179","examples/miette.rs":"9f5e1c803a14c742f37e18b6ec965b461646a1cc156c908fa7229f4e01958220","src/lib.rs":"eb0c7d3a660108416db915d94388e384c149161fa8145e8e276add714648f01a","src/test.rs":"cca4c8198af8a71e64174ba4c587fd1f3d2f3e524520c6a99b75675607ba624c"},"package":"537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"} \ No newline at end of file diff --git a/anneal/v2/vendor/backtrace-ext/.cargo_vcs_info.json b/anneal/v2/vendor/backtrace-ext/.cargo_vcs_info.json new file mode 100644 index 0000000000..e579bab88c --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/.cargo_vcs_info.json @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "043c95350875a36be6cd755dcef21a44a52ec2cc" + } +} diff --git a/anneal/v2/vendor/backtrace-ext/.github/workflows/ci.yml b/anneal/v2/vendor/backtrace-ext/.github/workflows/ci.yml new file mode 100644 index 0000000000..439d7d6c87 --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/.github/workflows/ci.yml @@ -0,0 +1,88 @@ +# The "Normal" CI for tests and linters and whatnot +name: Rust CI + +# Ci should be run on... +on: + # Every pull request (will need approval for new contributors) + pull_request: + # Every push to... + push: + branches: + # The main branch + - main + +# We want all these checks to fail if they spit out warnings +env: + RUSTFLAGS: -Dwarnings + +jobs: + # Check that rustfmt is a no-op + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: rustfmt + override: true + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + + # Make sure the docs build without warnings + docs: + runs-on: ubuntu-latest + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@master + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: rust-docs + override: true + - uses: swatinem/rust-cache@v1 + - uses: actions-rs/cargo@v1 + with: + command: doc + args: --workspace --no-deps + + # Build and run tests/doctests/examples on all platforms + # FIXME: look into `cargo-hack` which lets you more aggressively + # probe all your features and rust versions (see tracing's ci) + test: + runs-on: ${{ matrix.os }} + strategy: + # Test the cross-product of these platforms+toolchains + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + rust: [stable, nightly, "1.56"] + feature-flags: [""] + steps: + # Setup tools + - uses: actions/checkout@master + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + - uses: swatinem/rust-cache@v1 + # Run the tests/doctests + - uses: actions-rs/cargo@v1 + env: + PWD: ${{ env.GITHUB_WORKSPACE }} + with: + command: test + args: --workspace ${{ matrix.feature-flags }} + # Test the examples + - uses: actions-rs/cargo@v1 + env: + PWD: ${{ env.GITHUB_WORKSPACE }} + with: + command: test + args: --workspace ${{ matrix.feature-flags }} --examples --bins diff --git a/anneal/v2/vendor/backtrace-ext/Cargo.lock b/anneal/v2/vendor/backtrace-ext/Cargo.lock new file mode 100644 index 0000000000..3f710742ab --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/Cargo.lock @@ -0,0 +1,515 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +dependencies = [ + "backtrace", + "miette", + "thiserror", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "is_ci" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miette" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07749fb52853e739208049fb513287c6f448de9103dfa78b05ae01f2fc5809bb" +dependencies = [ + "backtrace", + "is-terminal", + "miette-derive", + "once_cell", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a07ad93a80d1b92bb44cb42d7c49b49c9aab1778befefad49cceb5e4c5bf460" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "proc-macro2" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rustc-demangle" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + +[[package]] +name = "rustix" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "smawk" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" + +[[package]] +name = "supports-color" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" +dependencies = [ + "is-terminal", + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4806e0b03b9906e76b018a5d821ebf198c8e9dc0829ed3328eeeb5094aed60" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "supports-unicode" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.12", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-linebreak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" +dependencies = [ + "hashbrown", + "regex", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[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-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/anneal/v2/vendor/backtrace-ext/Cargo.toml b/anneal/v2/vendor/backtrace-ext/Cargo.toml new file mode 100644 index 0000000000..2195a36c6b --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/Cargo.toml @@ -0,0 +1,27 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.56" +name = "backtrace-ext" +version = "0.2.1" +description = "minor conveniences on top of the backtrace crate" +license = "MIT OR Apache-2.0" +repository = "https://github.com/gankra/backtrace-ext" +[dependencies.backtrace] +version = "0.3.61" +[dev-dependencies.miette] +version = "5.6.0" +features = ["fancy"] + +[dev-dependencies.thiserror] +version = "1.0.40" diff --git a/anneal/v2/vendor/backtrace-ext/Cargo.toml.orig b/anneal/v2/vendor/backtrace-ext/Cargo.toml.orig new file mode 100644 index 0000000000..f756c3a8d2 --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/Cargo.toml.orig @@ -0,0 +1,17 @@ +[package] +name = "backtrace-ext" +description = "minor conveniences on top of the backtrace crate" +version = "0.2.1" +edition = "2018" +license = "MIT OR Apache-2.0" +repository = "https://github.com/gankra/backtrace-ext" +rust-version = "1.56" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +backtrace = "0.3.61" + +[dev-dependencies] +miette = { version = "5.6.0", features = ["fancy"] } +thiserror = "1.0.40" diff --git a/anneal/v2/vendor/backtrace-ext/README.md b/anneal/v2/vendor/backtrace-ext/README.md new file mode 100644 index 0000000000..9432c24b02 --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/README.md @@ -0,0 +1,8 @@ +# backtrace-ext + +[![crates.io](https://img.shields.io/crates/v/backtrace-ext.svg)](https://crates.io/crates/backtrace-ext) +[![docs](https://docs.rs/backtrace-ext/badge.svg)](https://docs.rs/backtrace-ext) +[![Rust CI](https://github.com/gankra/backtrace-ext/workflows/Rust%20CI/badge.svg?branch=main)](https://github.com/gankra/backtrace-ext/actions/workflows/ci.yml) + +Minor conveniences on top of the backtrace crate, because I don't want to copy-paste this everywhere +I override a panic handler. \ No newline at end of file diff --git a/anneal/v2/vendor/backtrace-ext/examples/miette.rs b/anneal/v2/vendor/backtrace-ext/examples/miette.rs new file mode 100644 index 0000000000..ae4198256c --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/examples/miette.rs @@ -0,0 +1,99 @@ +use std::fmt::Write; + +use backtrace::Backtrace; +use miette::{Context, Diagnostic, Report}; +use thiserror::Error; + +type Result = std::result::Result; + +#[inline(never)] +fn main() { + set_panic_hook(); + do_thing(); +} + +#[inline(never)] +fn do_thing() { + panic!("ooopssie!!!"); +} + +/// Tells miette to render panics using its rendering engine. +pub fn set_panic_hook() { + std::panic::set_hook(Box::new(move |info| { + let mut message = "Something went wrong".to_string(); + let payload = info.payload(); + if let Some(msg) = payload.downcast_ref::<&str>() { + message = msg.to_string(); + } + if let Some(msg) = payload.downcast_ref::() { + message = msg.clone(); + } + let mut report: Result<()> = Err(Panic(message).into()); + if let Some(loc) = info.location() { + report = report + .with_context(|| format!("at {}:{}:{}", loc.file(), loc.line(), loc.column())); + } + if let Err(err) = report.with_context(|| "Main thread panicked.".to_string()) { + eprintln!("Error: {:?}", err); + } + })); +} + +#[derive(Debug, Error, Diagnostic)] +#[error("{0}{}", Panic::backtrace())] +#[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))] +struct Panic(String); + +impl Panic { + fn backtrace() -> String { + if let Ok(var) = std::env::var("RUST_BACKTRACE") { + if !var.is_empty() && var != "0" { + const HEX_WIDTH: usize = std::mem::size_of::() + 2; + // Padding for next lines after frame's address + const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; + let mut backtrace = String::new(); + let trace = Backtrace::new(); + let frames = backtrace_ext::short_frames_strict(&trace).enumerate(); + for (idx, (frame, sub_frames)) in frames { + let ip = frame.ip(); + let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH); + + let symbols = frame.symbols(); + if symbols.is_empty() { + let _ = write!(backtrace, " - "); + continue; + } + + for (idx, symbol) in symbols[sub_frames].iter().enumerate() { + // Print symbols from this address, + // if there are several addresses + // we need to put it on next line + if idx != 0 { + let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING); + } + + if let Some(name) = symbol.name() { + let _ = write!(backtrace, " - {}", name); + } else { + let _ = write!(backtrace, " - "); + } + + // See if there is debug information with file name and line + if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { + let _ = write!( + backtrace, + "\n{:3$}at {}:{}", + "", + file.display(), + line, + NEXT_SYMBOL_PADDING + ); + } + } + } + return backtrace; + } + } + "".into() + } +} diff --git a/anneal/v2/vendor/backtrace-ext/src/lib.rs b/anneal/v2/vendor/backtrace-ext/src/lib.rs new file mode 100644 index 0000000000..b04c59d50e --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/src/lib.rs @@ -0,0 +1,277 @@ +//! Minor conveniences on top of the backtrace crate +//! +//! See [`short_frames_strict`][] for details. +use backtrace::*; +use std::ops::Range; + +#[cfg(test)] +mod test; + +/// Gets an iterator over the frames that are part of Rust's "short backtrace" range. +/// If no such range is found, the full stack is yielded. +/// +/// Rust generally tries to include special frames on the stack called `rust_end_short_backtrace` +/// and `rust_begin_short_backtrace` which delimit the "real" stackframes from "gunk" stackframes +/// like setting up main and invoking the panic runtime. This yields all the "real" frames between +/// those two (which theoretically can be nothing with enough optimization, although that's unlikely +/// for any non-trivial program). +/// +/// If only one of the special frames is present we will only clamp one side of the stack +/// (similar to `a..` or `..a`). If the special frames are in the wrong order we will discard +/// them and produce the full stack. If multiple versions of a special frame are found +/// (I've seen it in the wild), we will pick the "innermost" ones, producing the smallest +/// possible backtrace (and excluding all special frames from the output). +/// +/// Each element of the iterator includes a Range which you should use to slice +/// the frame's `symbols()` array. This handles the theoretical situation where "real" frames +/// got inlined together with the special marker frames. I want to believe this can't happen +/// but you can never trust backtraces to be reasonable! We will never yield a Frame to you +/// with an empty Range. +/// +/// Note that some "gunk" frames may still be found within the short backtrace, as there is still some +/// platform-specific and optimization-specific glue around the edges because compilers are +/// complicated and nothing's perfect. This can include: +/// +/// * `core::ops::function::FnOnce::call_once` +/// * `std::panicking::begin_panic_handler` +/// * `core::panicking::panic_fmt` +/// * `rust_begin_unwind` +/// +/// In the future we may introduce a non-strict short_frames which heuristically filters +/// those frames out too. Until then, the strict approach is safe. +/// +/// # Example +/// +/// Here's an example simple "short backtrace" implementation. +/// Note the use of `sub_frames` for the inner loop to restrict `symbols`! +/// +/// This example is based off of code found in `miette` (Apache-2.0), which itself +/// copied the logic from `human-panic` (MIT/Apache-2.0). +/// +/// FIXME: it would be nice if this example consulted `RUST_BACKTRACE=full`, +/// and maybe other vars used by rust's builtin panic handler..? +/// +/// ``` +/// fn backtrace() -> String { +/// use std::fmt::Write; +/// if let Ok(var) = std::env::var("RUST_BACKTRACE") { +/// if !var.is_empty() && var != "0" { +/// const HEX_WIDTH: usize = std::mem::size_of::() + 2; +/// // Padding for next lines after frame's address +/// const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; +/// let mut backtrace = String::new(); +/// let trace = backtrace::Backtrace::new(); +/// let frames = backtrace_ext::short_frames_strict(&trace).enumerate(); +/// for (idx, (frame, subframes)) in frames { +/// let ip = frame.ip(); +/// let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH); +/// +/// let symbols = frame.symbols(); +/// if symbols.is_empty() { +/// let _ = write!(backtrace, " - "); +/// continue; +/// } +/// +/// for (idx, symbol) in symbols[subframes].iter().enumerate() { +/// // Print symbols from this address, +/// // if there are several addresses +/// // we need to put it on next line +/// if idx != 0 { +/// let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING); +/// } +/// +/// if let Some(name) = symbol.name() { +/// let _ = write!(backtrace, " - {}", name); +/// } else { +/// let _ = write!(backtrace, " - "); +/// } +/// +/// // See if there is debug information with file name and line +/// if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) { +/// let _ = write!( +/// backtrace, +/// "\n{:3$}at {}:{}", +/// "", +/// file.display(), +/// line, +/// NEXT_SYMBOL_PADDING +/// ); +/// } +/// } +/// } +/// return backtrace; +/// } +/// } +/// "".into() +/// } +/// ``` +pub fn short_frames_strict( + backtrace: &Backtrace, +) -> impl Iterator)> { + short_frames_strict_impl(backtrace) +} + +pub(crate) fn short_frames_strict_impl( + backtrace: &B, +) -> impl Iterator)> { + // Search for the special frames + let mut short_start = None; + let mut short_end = None; + let frames = backtrace.frames(); + for (frame_idx, frame) in frames.iter().enumerate() { + let symbols = frame.symbols(); + for (subframe_idx, frame) in symbols.iter().enumerate() { + if let Some(name) = frame.name_str() { + // Yes these ARE backwards, and that's intentional! We want to print the frames from + // "newest to oldest" (show what panicked first), and that's the order that Backtrace + // gives us, but these magic labels view the stack in the opposite order. So we just + // swap it once here and forget about that weirdness. + // + // Note that due to platform/optimization wobblyness you can end up with multiple frames + // that contain these names in sequence. If that happens we just want to pick the two + // that are closest together. For the start that means just using the last one we found, + // and for the end that means taking the first one we find. + if name.contains("rust_end_short_backtrace") { + short_start = Some((frame_idx, subframe_idx)); + } + if name.contains("rust_begin_short_backtrace") && short_end.is_none() { + short_end = Some((frame_idx, subframe_idx)); + } + } + } + } + + // Check if these are in the right order, if they aren't, discard them + // This also handles the mega-cursed case of "someone made a symbol with both names + // so actually they're the exact same subframe". + if let (Some(start), Some(end)) = (short_start, short_end) { + if start >= end { + short_start = None; + short_end = None; + } + } + + // By default we want to produce a full stack trace and now we'll try to clamp it. + let mut first_frame = 0usize; + let mut first_subframe = 0usize; + // NOTE: this is INCLUSIVE + let mut last_frame = frames.len().saturating_sub(1); + // NOTE: this is EXCLUSIVE + let mut last_subframe_excl = backtrace + .frames() + .last() + .map(|frame| frame.symbols().len()) + .unwrap_or(0); + + // This code tries to be really paranoid about boundary conditions although in practice + // most of them are impossible because there's always going to be gunk on either side + // of the short backtrace to smooth out the boundaries, and panic_fmt is basically + // impossible to optimize out. Still, don't trust backtracers!!! + // + // This library has a fuckton of tests to try to catch all the little corner cases here. + + // If we found the start bound... + if let Some((idx, sub_idx)) = short_start { + if frames[idx].symbols().len() == sub_idx + 1 { + // If it was the last subframe of this frame, we want to just + // use the whole next frame! It's ok if this takes us to `first_frame = len`, + // that will be properly handled as an empty output + first_frame = idx + 1; + first_subframe = 0; + } else { + // Otherwise use this frame, and all the subframes after it + first_frame = idx; + first_subframe = sub_idx + 1; + } + } + + // If we found the end bound... + if let Some((idx, sub_idx)) = short_end { + if sub_idx == 0 { + // If it was the first subframe of this frame, we want to just + // use the whole previous frame! + if idx == 0 { + // If we were *also* on the first frame, set subframe_excl + // to 0, indicating an empty output + last_frame = 0; + last_subframe_excl = 0; + } else { + last_frame = idx - 1; + last_subframe_excl = frames[last_frame].symbols().len(); + } + } else { + // Otherwise use this frame (no need subframe math, exclusive bound!) + last_frame = idx; + last_subframe_excl = sub_idx; + } + } + + // If the two subframes managed to perfectly line up with eachother, just + // throw everything out and yield an empty range. We don't need to fix any + // other values at this point as they won't be used for anything with an + // empty iterator + let final_frames = { + let start = (first_frame, first_subframe); + let end = (last_frame, last_subframe_excl); + if start == end { + &frames[0..0] + } else { + &frames[first_frame..=last_frame] + } + }; + + // Get the index of the last frame when starting from the first frame + let adjusted_last_frame = last_frame.saturating_sub(first_frame); + + // finally do the iteration + final_frames.iter().enumerate().map(move |(idx, frame)| { + // Default to all subframes being yielded + let mut sub_start = 0; + let mut sub_end_excl = frame.symbols().len(); + // If we're on first frame, apply its subframe clamp + if idx == 0 { + sub_start = first_subframe; + } + // If we're on the last frame, apply its subframe clamp + if idx == adjusted_last_frame { + sub_end_excl = last_subframe_excl; + } + (frame, sub_start..sub_end_excl) + }) +} + +pub(crate) trait Backtraceish { + type Frame: Frameish; + fn frames(&self) -> &[Self::Frame]; +} + +pub(crate) trait Frameish { + type Symbol: Symbolish; + fn symbols(&self) -> &[Self::Symbol]; +} + +pub(crate) trait Symbolish { + fn name_str(&self) -> Option<&str>; +} + +impl Backtraceish for Backtrace { + type Frame = BacktraceFrame; + fn frames(&self) -> &[Self::Frame] { + self.frames() + } +} + +impl Frameish for BacktraceFrame { + type Symbol = BacktraceSymbol; + fn symbols(&self) -> &[Self::Symbol] { + self.symbols() + } +} + +impl Symbolish for BacktraceSymbol { + // We need to shortcut SymbolName here because + // HRTB isn't in our msrv + fn name_str(&self) -> Option<&str> { + self.name().and_then(|n| n.as_str()) + } +} diff --git a/anneal/v2/vendor/backtrace-ext/src/test.rs b/anneal/v2/vendor/backtrace-ext/src/test.rs new file mode 100644 index 0000000000..d4d41129a7 --- /dev/null +++ b/anneal/v2/vendor/backtrace-ext/src/test.rs @@ -0,0 +1,524 @@ +use super::*; + +type BT = &'static [&'static [&'static str]]; + +impl Backtraceish for BT { + type Frame = &'static [&'static str]; + fn frames(&self) -> &[Self::Frame] { + self + } +} + +impl Frameish for &'static [&'static str] { + type Symbol = &'static str; + fn symbols(&self) -> &[Self::Symbol] { + self + } +} + +impl Symbolish for &'static str { + fn name_str(&self) -> Option<&str> { + Some(self) + } +} + +fn process(bt: BT) -> Vec<&'static str> { + let mut result = vec![]; + for (frame, subframes) in short_frames_strict_impl(&bt) { + let symbols = &frame.symbols()[subframes]; + assert!(!symbols.is_empty()); + for symbol in symbols { + result.push(*symbol); + } + } + result +} + +#[test] +fn test_full() { + let bt: BT = &[&["hello"], &["there", "simple"], &["case"]]; + let expected = vec!["hello", "there", "simple", "case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_empty() { + let bt: BT = &[]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_cursed_one_true_symbol1() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace_rust_begin_short_backtrace"], + &["there"], + ]; + let expected = vec![ + "hello", + "__rust_end_short_backtrace_rust_begin_short_backtrace", + "there", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_cursed_one_true_symbol2() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace_rust_end_short_backtrace"], + &["there"], + ]; + let expected: Vec<&str> = vec![ + "hello", + "__rust_begin_short_backtrace_rust_end_short_backtrace", + "there", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards1() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace"], + &["real"], + &["frames"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards2() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace", "real", "frames"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards3() { + let bt: BT = &[ + &["hello"], + &["__rust_begin_short_backtrace"], + &["real", "frames", "rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_backwards4() { + let bt: BT = &[ + &["hello"], + &[ + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + ], + &["case"], + ]; + let expected = vec![ + "hello", + "__rust_begin_short_backtrace", + "real", + "frames", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_simple() { + let bt: BT = &[&["hello"], &["__rust_begin_short_backtrace"], &["case"]]; + let expected = vec!["hello"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_left_edge() { + let bt: BT = &[&["__rust_begin_short_backtrace"], &["case"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_right_edge() { + let bt: BT = &[&["hello"], &["__rust_begin_short_backtrace"]]; + let expected = vec!["hello"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_empty() { + let bt: BT = &[&["__rust_begin_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_begin_clamp_sub() { + let bt: BT = &[ + &["real"], + &["frames", "core::rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_simple() { + let bt: BT = &[&["hello"], &["__rust_end_short_backtrace"], &["case"]]; + let expected = vec!["case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_left_edge() { + let bt: BT = &[&["_rust_end_short_backtrace"], &["case"]]; + let expected = vec!["case"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_right_edge() { + let bt: BT = &[&["hello"], &["__rust_end_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_empty() { + let bt: BT = &[&["__rust_end_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_end_clamp_sub() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_simple() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_various() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["core::rust_end_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["_rust_begin_short_backtrace"], + &["junk"], + &["core::rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_identical() { + let bt: BT = &[ + &["hello"], + &["rust_end_short_backtrace"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_invert1() { + let bt: BT = &[ + &["hello"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + "junk", + "rust_end_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_multiball_invert2() { + let bt: BT = &[ + &["hello"], + &["rust_begin_short_backtrace"], + &["junk"], + &["rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec![ + "hello", + "rust_begin_short_backtrace", + "junk", + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + "case", + ]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_adjacent() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_left_edge() { + let bt: BT = &[ + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + &["case"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_right_edge() { + let bt: BT = &[ + &["hello"], + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["rust_begin_short_backtrace"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_spanned() { + let bt: BT = &[ + &["__rust_end_short_backtrace"], + &["real"], + &["frames"], + &["__rust_begin_short_backtrace"], + ]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_both_spanned_empty() { + let bt: BT = &[ + &["rust_end_short_backtrace"], + &["rust_begin_short_backtrace"], + ]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_2() { + let bt: BT = &[&[ + "rust_end_short_backtrace", + "real", + "frames", + "rust_begin_short_backtrace", + ]]; + let expected = vec!["real", "frames"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_1() { + let bt: BT = &[&[ + "rust_end_short_backtrace", + "real", + "rust_begin_short_backtrace", + ]]; + let expected = vec!["real"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_one_super_frame_0() { + let bt: BT = &[&["rust_end_short_backtrace", "rust_begin_short_backtrace"]]; + let expected: Vec<&str> = vec![]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex1() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex2() { + let bt: BT = &[ + &["junk"], + &["__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace", "junk"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex3() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames"], + &["here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex4() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace"], + &["real", "frames"], + &["here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex5() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace", "real"], + &["frames", "here"], + &["__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex6() { + let bt: BT = &[ + &["junk"], + &[ + "junk", + "__rust_end_short_backtrace", + "real", + "frames", + "here", + ], + &["__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} + +#[test] +fn test_complex7() { + let bt: BT = &[ + &["junk"], + &["junk", "__rust_end_short_backtrace"], + &["real", "frames", "here", "__rust_begin_short_backtrace"], + &["junk"], + ]; + let expected = vec!["real", "frames", "here"]; + assert_eq!(process(bt), expected); +} diff --git a/anneal/v2/vendor/backtrace/.cargo-checksum.json b/anneal/v2/vendor/backtrace/.cargo-checksum.json new file mode 100644 index 0000000000..9297526fd9 --- /dev/null +++ b/anneal/v2/vendor/backtrace/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"96bb303bf1ecca8c22731ece7a5be75953f72656dd4c4695131a3ec135333388",".github/workflows/main.yml":"082109515c04f8c3974817cb1b4f288ff4230cf383de49b77c2faffb2dc1ef6a",".github/workflows/publish.yml":"e585fc84fc8dd0f7f0cd2d689963e54a64436d2ac8d2ba230d10fccfb8e03885","CHANGELOG.md":"8371b53a9eb1eee16e3e092e85ad064644ff693c6a9d23d4be750a7e27995193","Cargo.lock":"69eea14141aae967bc4ece40893e0f648ea17b0da471c5d33f4042546eb3f2ba","Cargo.toml":"cf97b237546e047f7de052801c81707ff083951d697e1781b31c4356ff7ae0bf","Cargo.toml.orig":"d37c054b037d71a60ffbf556d7861a854354afb7098d90d3598c21384246b643","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"66627f6723d9c702276ae529aaf52fc2ed0fd13204ad510d0c9a2d63e6d7d68d","benches/benchmarks.rs":"029b78bb79052ec940eecfd18067b743925189202fc16015d3c4c25b05eb6d67","bindings.txt":"292ed6429d70ea9f31724691675b9b7fcd38eba969d74e6274fce057d2dc8d0b","examples/backtrace.rs":"5da0c95ccebfaffbbe7b5a92b0e488017dc375cbb5b8fb2b7712dd65b2dfb2ba","examples/raw.rs":"eda88454164ce5ebdd99c9c70ea35a61d34f5aecfdb8fcb4efd4f9738d10b093","src/backtrace/libunwind.rs":"827c5188e2b80c2a6d06cee4b00f7cfcb38a94c5ab83f2b139cd3afe40e4662e","src/backtrace/miri.rs":"fd98e52da0acb98dc49bee28c10335426fe843790f04da30fdfeebc72d757d9c","src/backtrace/mod.rs":"666383a0bec82dbd9c7413e0fa96d62240dd20f5969b6f8b80411f7fcff2d84c","src/backtrace/noop.rs":"970db5bce5bbc129466b92409730a92f23fb9f21e13e9514187836d34e25f673","src/backtrace/win32.rs":"6b4fd32b5bd353e50eae1f2d4f1b518b2f686fd1c0088f21da33f6b34488a502","src/backtrace/win64.rs":"ff0d382dee8e0ea39c39af5ba95ce0c8c2d0f28ca370d4a71c1e120f5c8d7206","src/capture.rs":"86346735757fe182a5900e62e15b6139b8a048060b676805ddbb0924cfb6331a","src/dbghelp.rs":"830f8f5eef091eb26d59ce3bb62f8df5a331044181412ae316089bd56b39f076","src/lib.rs":"7cd7def4664c750bfbd71051b506f1461518aa08e904394cc0bc7df879fae0b6","src/print.rs":"5cc1d102e75cc2aa3c0a84cb75e33438edfac88505acbd3463ad90e104a02c93","src/print/fuchsia.rs":"a950eab722daea4e093cfb909d842839b278a0125b55f27a8179bec8e82572df","src/symbolize/dbghelp.rs":"a9ed3a3b48be42dc42b15034e7f2e816bffc1e7b6cee627e825a6ec58a5f8611","src/symbolize/gimli.rs":"1ab60499975ca48666ee0659876d55b8b3b6ee9094c44e207d33c32947263afe","src/symbolize/gimli/coff.rs":"e9f3062252f6750d376575b4fc39484647b46038245c6af9e84556cb67b7543d","src/symbolize/gimli/elf.rs":"d635a4fa2c39456395c3e4f425857d87e1999ba8f66d7631e695f9e448ff6fe9","src/symbolize/gimli/libs_aix.rs":"8ec6ce735671fe2c42458454d49b4333997c4e441b7ed48313054ca37491c821","src/symbolize/gimli/libs_dl_iterate_phdr.rs":"f2453be9c182f243774f8fd502f7165fd90b8bb27d22819e574f5c5104ef5e73","src/symbolize/gimli/libs_haiku.rs":"b21476fc5787aa4758a66a8ef7200780a09814b17e2863c9db9cdf1a218f6af4","src/symbolize/gimli/libs_illumos.rs":"4fb8c252d437d0f9b74eefc72cdf00af5a51db679f4cc0cbd67ca457b0cfe4e8","src/symbolize/gimli/libs_libnx.rs":"f0f4e2d0c9ee34d7c6da2f749df56aa6dffcd78c4cd52037799a6b5d5c82582e","src/symbolize/gimli/libs_macos.rs":"d24a2a571ddcdbfc70f73fba07a47413649ef97ca79d38e28cb4fc9713691a5c","src/symbolize/gimli/libs_windows.rs":"acdfe1ea48d2cc1fba6c304f3f161128a90d6328c5b91ea8c7fae52a62672c43","src/symbolize/gimli/lru.rs":"2ca20aacc9b1ac71fb5bedc3a85b82fc12e7d283ae68136df0316c07735b6b5c","src/symbolize/gimli/macho.rs":"cdd5bfe7a4dd981d6b7d2f7f68c2581d507cef068aa7d9ce4d53b33310004baf","src/symbolize/gimli/mmap_fake.rs":"adec262cfda1d047f4c6b3bed61c256bccfac6e10f0b47d589dd76c82675303c","src/symbolize/gimli/mmap_unix.rs":"486809e3e6c2f621fc615d347a774f30683c74a61748dcbd923c81ec52b91e17","src/symbolize/gimli/mmap_windows.rs":"8631f82b71bf65b800a842fec53903daf94e7e91f7f5b663b94f2860424ace88","src/symbolize/gimli/parse_running_mmaps_unix.rs":"c23ee114ab05f8d1a37d8c47746f26a4b6741dae63e1393e2659e7c66d44c18e","src/symbolize/gimli/stash.rs":"e9b4c8b5849fda70c25a40be2f9a16473b601926cf96909087cfff25a8ab42b5","src/symbolize/gimli/xcoff.rs":"59c4f145f79225791a7075a971fc2b190e9ccabd147120de320880fa3ac4a198","src/symbolize/miri.rs":"f5201cc8a7de24ad3424d2472cb0af59cd28563d09cc0c21e998f4cee4367ade","src/symbolize/mod.rs":"c5a9100ceb34fec87e2dcf20604620a61611720d16d844b56d882b0ed20b88a9","src/symbolize/noop.rs":"5d4432079b8ae2b9382945a57ae43df57bb4b7ed2e5956d4167e051a44567388","src/types.rs":"20cc0d35c3862f705d4ae1f2eb0564ea0afb140d444ecb17a5d5d18c6a4b1f92","src/windows_sys.rs":"f2696de4432b529542a05bbcc7132886faac0d3e6af9dd89accc5aa431412e9a","src/windows_sys_arm32_shim.rs":"8453195e374cde8ffbba82dd1543c8eedeeae9a94195197cdffe995119bf9567","tests/accuracy/auxiliary.rs":"71d2238da401042e007ef5ee20336d6834724bae96d93c8c52d11a5a332d7d34","tests/accuracy/main.rs":"851778c046bc5b51f91777716ffe9896e0f872197d069e2dcd9a8b5ef4c98b01","tests/common/mod.rs":"733101288a48cf94d5a87a1957724deaf2650c3e4e8aa0190a4a7db62aa90d01","tests/concurrent-panics.rs":"d2b958cd2147f456e10193f874290e721915c78735ac83ef975565c2deb00a0d","tests/current-exe-mismatch.rs":"0e27d53ba66997dcf06583f3000f7e1ddb824bdbe05b3862e712f454b88014f2","tests/long_fn_name.rs":"12af8bcef41f2d4f9e2711cbe2a605e15ed47b571fd871f4da1fd159494d779a","tests/sgx-image-base.rs":"564d799ce613569b9d8b65ecf027e01719409fcf3d07c9179f3c7935e364bb41","tests/skip_inner_frames.rs":"7e6af1d71df6f5793900cef01a7c56fd684a3dceebbd2b03015d2f5c1dcd92f0","tests/smoke.rs":"70d6e7852d76f21190c8b176087f49af6137099197ae9bbb59e835128211c125"},"package":"bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"} \ No newline at end of file diff --git a/anneal/v2/vendor/backtrace/.cargo_vcs_info.json b/anneal/v2/vendor/backtrace/.cargo_vcs_info.json new file mode 100644 index 0000000000..ad76f0df75 --- /dev/null +++ b/anneal/v2/vendor/backtrace/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "775f6a1ba62e7d35a1fac76e64c61d9d4687b5f2" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/backtrace/.github/workflows/main.yml b/anneal/v2/vendor/backtrace/.github/workflows/main.yml new file mode 100644 index 0000000000..9b70e41af0 --- /dev/null +++ b/anneal/v2/vendor/backtrace/.github/workflows/main.yml @@ -0,0 +1,283 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + rust: stable + - os: ubuntu-24.04 + rust: beta + - os: ubuntu-24.04 + rust: nightly + - os: macos-14 + rust: stable + - os: macos-14 + rust: nightly + - os: macos-latest # macOS 15 + rust: stable + - os: windows-latest + rust: stable-x86_64-msvc + - os: windows-latest + rust: stable-i686-msvc + - os: windows-latest + rust: stable-x86_64-gnu + - os: windows-latest + rust: nightly-x86_64-msvc + - os: windows-latest + rust: nightly-i686-msvc + - os: windows-latest + rust: nightly-x86_64-gnu + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust (rustup) + run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} + shell: bash + - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV + shell: bash + + # full fidelity of backtraces on 32-bit msvc requires frame pointers, so + # enable that for our tests + - name: Force frame pointers + run: echo RUSTFLAGS="-Cforce-frame-pointers $RUSTFLAGS" >> $GITHUB_ENV + shell: bash + if: contains(matrix.rust, 'i686') + + # Starting with Ubuntu 22.04 libc6-dbg is needed. + - name: Install libc debug info + run: sudo apt-get install -y libc6-dbg + shell: bash + if: contains(matrix.os, 'ubuntu-24.04') + + - name: Enable collapse_debuginfo based on version + run: echo RUSTFLAGS="--cfg dbginfo=\"collapsible\" $RUSTFLAGS" >> $GITHUB_ENV + shell: bash + if: contains(matrix.rust, 'nightly') || contains(matrix.rust, 'beta') + + - run: cargo build + - run: cargo test + - run: cargo test --features "serialize-serde" + - run: cargo test --features "cpp_demangle" + - run: cargo test --no-default-features + - run: cargo test --no-default-features --features "std" + - run: cargo test --manifest-path crates/cpp_smoke_test/Cargo.toml + # This test is specifically about packed debuginfo with `*.dSYM` files + - run: cargo test --manifest-path crates/macos_frames_test/Cargo.toml + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: packed + CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: packed + - run: cargo test --manifest-path crates/without_debuginfo/Cargo.toml + - if: matrix.os != 'macos-latest' + run: cargo test --manifest-path crates/line-tables-only/Cargo.toml + # FIXME: This currently fails on macOS 15. + - if: matrix.os == 'macos-latest' + run: '! cargo test --manifest-path crates/line-tables-only/Cargo.toml' + + # Test debuginfo compression still works + - run: cargo test + if: contains(matrix.os, 'ubuntu') + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zlib" + - run: cargo test --features "ruzstd" + if: contains(matrix.os, 'ubuntu-24.04') || + (contains(matrix.os, 'ubuntu') && contains(matrix.rust, 'nightly')) + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zstd" + + # Test that, on macOS, packed/unpacked debuginfo both work + - run: cargo clean && cargo test + # Test that, on macOS, packed/unpacked debuginfo both work + if: contains(matrix.os, 'macos') + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: unpacked + CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: unpacked + - run: cargo clean && cargo test + if: contains(matrix.os, 'macos') + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: packed + CARGO_PROFILE_TEST_SPLIT_DEBUGINFO: packed + # Test that, on macOS, binaries with no UUID work + - run: cargo clean && cargo test + if: contains(matrix.os, 'macos') + env: + RUSTFLAGS: "-C link-arg=-Wl,-no_uuid" + + # Test that, on Linux, packed/unpacked debuginfo both work + - run: cargo clean && cargo test + if: matrix.rust == 'nightly' + env: + RUSTFLAGS: "-C split-debuginfo=unpacked -Zunstable-options" + - run: cargo clean && cargo test + if: matrix.rust == 'nightly' + env: + RUSTFLAGS: "-C split-debuginfo=packed -Zunstable-options" + + # Test that separate debug info works + - run: ./ci/debuglink-docker.sh + if: contains(matrix.os, 'ubuntu') + + # Test that backtraces are still symbolicated if we don't embed an absolute + # path to the PDB file in the binary. + # Add -Cforce-frame-pointers for stability. The test otherwise fails + # non-deterministically on i686-pc-windows-msvc because the stack cannot be + # unwound reliably. This failure is not related to the feature being tested. + - run: cargo clean && cargo test + if: contains(matrix.rust, 'msvc') + name: "Test that backtraces are symbolicated without absolute PDB path" + env: + RUSTFLAGS: "-Clink-arg=/PDBALTPATH:%_PDB% -Cforce-frame-pointers" + + # Test that including as a submodule will still work, both with and without + # the `backtrace` feature enabled. + # Building as if part of std requires nightly features to be available + - run: cargo build --manifest-path crates/as-if-std/Cargo.toml + if: matrix.rust == 'nightly' + - run: cargo build --manifest-path crates/as-if-std/Cargo.toml --no-default-features + if: matrix.rust == 'nightly' + + windows_arm64: + name: Windows AArch64 + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable + shell: bash + - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV + shell: bash + - run: rustup target add aarch64-pc-windows-msvc + - run: cargo test --no-run --target aarch64-pc-windows-msvc + + ios: + name: iOS + runs-on: macos-latest + strategy: + matrix: + include: + - target: aarch64-apple-ios + - target: x86_64-apple-ios + - target: aarch64-apple-ios-macabi + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - run: rustup target add ${{ matrix.target }} + - name: Run tests + run: cargo test ${{ contains(matrix.target, 'macabi') && '' || '--no-run' }} --target ${{ matrix.target }} + env: + RUSTFLAGS: -Dwarnings + + docker: + name: Docker + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + target: + - aarch64-unknown-linux-gnu + - arm-unknown-linux-gnueabihf + - armv7-unknown-linux-gnueabihf + - i586-unknown-linux-gnu + - i686-unknown-linux-gnu + - powerpc64-unknown-linux-gnu + - s390x-unknown-linux-gnu + - x86_64-pc-windows-gnu + - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - arm-linux-androideabi + - armv7-linux-androideabi + - aarch64-linux-android + - i686-linux-android + - x86_64-linux-android + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable + - run: rustup target add ${{ matrix.target }} + - run: cargo generate-lockfile + - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV + shell: bash + - run: ./ci/run-docker.sh ${{ matrix.target }} + + rustfmt: + name: Rustfmt + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update stable --no-self-update && rustup default stable && rustup component add rustfmt + - run: cargo fmt --all -- --check + + build: + name: Build Targets + runs-on: ubuntu-24.04 + strategy: + matrix: + target: + - wasm32-unknown-unknown + - wasm32-wasip1 + - x86_64-unknown-fuchsia + - x86_64-fortanix-unknown-sgx + - x86_64-unknown-illumos + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: rustup target add ${{ matrix.target }} + - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV + shell: bash + - run: cargo build --target ${{ matrix.target }} + - run: cargo build --manifest-path crates/as-if-std/Cargo.toml --target ${{ matrix.target }} + + msrv: + name: MSRV + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + - os: windows-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Rust + run: rustup update 1.82.0 --no-self-update && rustup default 1.82.0 + - run: cargo build + + miri: + name: Miri + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install Miri + run: | + rustup toolchain install nightly --component miri + rustup override set nightly + cargo miri setup + - run: MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test diff --git a/anneal/v2/vendor/backtrace/.github/workflows/publish.yml b/anneal/v2/vendor/backtrace/.github/workflows/publish.yml new file mode 100644 index 0000000000..9d74db39ed --- /dev/null +++ b/anneal/v2/vendor/backtrace/.github/workflows/publish.yml @@ -0,0 +1,52 @@ +name: Release-plz + +permissions: + pull-requests: write + contents: write + +on: + push: { branches: [master] } + +jobs: + # Release unpublished packages. + release-plz-release: + name: Release-plz release + runs-on: ubuntu-24.04 + if: ${{ github.repository_owner == 'rust-lang' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Rust toolchain + run: rustup update stable --no-self-update && rustup default stable + - name: Run release-plz + uses: release-plz/action@v0.5 + with: + command: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + # Create a PR with the new versions and changelog, preparing the next release. + release-plz-pr: + name: Release-plz PR + runs-on: ubuntu-24.04 + if: ${{ github.repository_owner == 'rust-lang' }} + concurrency: + group: release-plz-${{ github.ref }} + cancel-in-progress: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Rust toolchain + run: rustup update stable --no-self-update && rustup default stable + - name: Run release-plz + uses: release-plz/action@v0.5 + with: + command: release-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/anneal/v2/vendor/backtrace/CHANGELOG.md b/anneal/v2/vendor/backtrace/CHANGELOG.md new file mode 100644 index 0000000000..9a2cc4f3de --- /dev/null +++ b/anneal/v2/vendor/backtrace/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +Notable changes to this project should be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +The backtrace crate attempts to adhere to the modified [Cargo interpretation of SemVer](https://doc.rust-lang.org/cargo/reference/resolver.html#semver-compatibility). +As a unique component of `std` it may make exceptional changes in order to support `std`. + +## [Unreleased] + +## [0.3.76](https://github.com/rust-lang/backtrace-rs/compare/backtrace-v0.3.75...backtrace-v0.3.76) - 2025-09-26 + +### Behavior +- Fix inverted polarity of "full printing" logic in rust-lang/backtrace-rs#726: + Previously we used to do the opposite of what you would expect. + +### Platform Support + +- Windows: Removed hypothetical soundness risk from padding bytes in rust-lang/backtrace-rs#737 +- Fuchsia: Added appropriate alignment checks during `Elf_Nhdr` parsing in rust-lang/backtrace-rs#725 +- Cygwin: Added support in rust-lang/backtrace-rs#704 +- Windows (32-bit Arm): Restore support in rust-lang/backtrace-rs#685 +- NuttX (32-bit Arm): Use builtin `_Unwind_GetIP` in rust-lang/backtrace-rs#692 +- RTEMS: Enable libunwind in rust-lang/backtrace-rs#682 + +### Dependencies + +- Update cpp_demangle to 0.5 in rust-lang/backtrace-rs#732 +- Update memchr to 2.7.6 in rust-lang/backtrace-rs#734 +- Switch from windows-targets to windows-link in rust-lang/backtrace-rs#727 +- Update ruzstd to 0.8.1 in rust-lang/backtrace-rs#718 +- Update object to 0.37 in rust-lang/backtrace-rs#718 +- Update addr2line to 0.25 in rust-lang/backtrace-rs#718 diff --git a/anneal/v2/vendor/backtrace/Cargo.lock b/anneal/v2/vendor/backtrace/Cargo.lock new file mode 100644 index 0000000000..9f9086a3b1 --- /dev/null +++ b/anneal/v2/vendor/backtrace/Cargo.lock @@ -0,0 +1,169 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9acbfca36652500c911ddb767ed433e3ed99b032b5d935be73c6923662db1d43" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "backtrace" +version = "0.3.76" +dependencies = [ + "addr2line", + "cfg-if", + "cpp_demangle", + "libc", + "libloading", + "miniz_oxide", + "object", + "rustc-demangle", + "ruzstd", + "serde", + "windows-link", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpp_demangle" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcc405d55da54ad965aff198909afdcc8aeefc8ac6ba26d6abd19aa8aeacb2a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "gimli" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "object" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +dependencies = [ + "memchr", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "ruzstd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" diff --git a/anneal/v2/vendor/backtrace/Cargo.toml b/anneal/v2/vendor/backtrace/Cargo.toml new file mode 100644 index 0000000000..466be34c46 --- /dev/null +++ b/anneal/v2/vendor/backtrace/Cargo.toml @@ -0,0 +1,157 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.82.0" +name = "backtrace" +version = "0.3.76" +authors = ["The Rust Project Developers"] +build = false +exclude = ["/ci/"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +A library to acquire a stack trace (backtrace) at runtime in a Rust program. +""" +homepage = "https://github.com/rust-lang/backtrace-rs" +documentation = "https://docs.rs/backtrace" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/backtrace-rs" + +[features] +coresymbolication = [] +dbghelp = [] +default = ["std"] +dl_iterate_phdr = [] +dladdr = [] +kernel32 = [] +libunwind = [] +ruzstd = ["dep:ruzstd"] +serialize-serde = ["serde"] +std = [] +unix-backtrace = [] + +[lib] +name = "backtrace" +path = "src/lib.rs" + +[[example]] +name = "backtrace" +path = "examples/backtrace.rs" +required-features = ["std"] + +[[example]] +name = "raw" +path = "examples/raw.rs" +required-features = ["std"] + +[[test]] +name = "accuracy" +path = "tests/accuracy/main.rs" +required-features = ["std"] +edition = "2021" + +[[test]] +name = "concurrent-panics" +path = "tests/concurrent-panics.rs" +harness = false +required-features = ["std"] + +[[test]] +name = "current-exe-mismatch" +path = "tests/current-exe-mismatch.rs" +harness = false +required-features = ["std"] + +[[test]] +name = "long_fn_name" +path = "tests/long_fn_name.rs" +required-features = ["std"] + +[[test]] +name = "sgx-image-base" +path = "tests/sgx-image-base.rs" + +[[test]] +name = "skip_inner_frames" +path = "tests/skip_inner_frames.rs" +required-features = ["std"] + +[[test]] +name = "smoke" +path = "tests/smoke.rs" +required-features = ["std"] +edition = "2021" + +[[bench]] +name = "benchmarks" +path = "benches/benchmarks.rs" + +[dependencies.cfg-if] +version = "1.0" + +[dependencies.cpp_demangle] +version = "0.5.0" +features = ["alloc"] +optional = true +default-features = false + +[dependencies.rustc-demangle] +version = "0.1.24" + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[dev-dependencies.libloading] +version = "0.8" + +[target.'cfg(any(windows, target_os = "cygwin"))'.dependencies.windows-link] +version = "0.2" + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.addr2line] +version = "0.25.0" +default-features = false + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.libc] +version = "0.2.156" +default-features = false + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.miniz_oxide] +version = "0.8" +default-features = false + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.object] +version = "0.37.0" +features = [ + "read_core", + "elf", + "macho", + "pe", + "xcoff", + "unaligned", + "archive", +] +default-features = false + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.ruzstd] +version = "0.8.1" +optional = true +default-features = false + +[lints.rust] +unexpected_cfgs = "allow" diff --git a/anneal/v2/vendor/backtrace/Cargo.toml.orig b/anneal/v2/vendor/backtrace/Cargo.toml.orig new file mode 100644 index 0000000000..78f5276eab --- /dev/null +++ b/anneal/v2/vendor/backtrace/Cargo.toml.orig @@ -0,0 +1,121 @@ +[package] +name = "backtrace" +version = "0.3.76" +authors = ["The Rust Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-lang/backtrace-rs" +homepage = "https://github.com/rust-lang/backtrace-rs" +documentation = "https://docs.rs/backtrace" +description = """ +A library to acquire a stack trace (backtrace) at runtime in a Rust program. +""" +autoexamples = true +autotests = true +edition = "2021" +exclude = ["/ci/"] +rust-version = "1.82.0" + +[workspace] +members = ['crates/cpp_smoke_test', 'crates/as-if-std'] +exclude = [ + 'crates/without_debuginfo', + 'crates/macos_frames_test', + 'crates/line-tables-only', + 'crates/debuglink', +] + +[dependencies] +cfg-if = "1.0" +rustc-demangle = "0.1.24" + +# Optionally enable the ability to serialize a `Backtrace`, controlled through +# the `serialize-serde` feature below. +serde = { version = "1.0", optional = true, features = ['derive'] } + +# Optionally demangle C++ frames' symbols in backtraces. +cpp_demangle = { default-features = false, version = "0.5.0", optional = true, features = [ + "alloc", +] } + +[target.'cfg(any(windows, target_os = "cygwin"))'.dependencies] +windows-link = "0.2" + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] +miniz_oxide = { version = "0.8", default-features = false } +ruzstd = { version = "0.8.1", default-features = false, optional = true } +addr2line = { version = "0.25.0", default-features = false } +libc = { version = "0.2.156", default-features = false } + +[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.object] +version = "0.37.0" +default-features = false +features = ['read_core', 'elf', 'macho', 'pe', 'xcoff', 'unaligned', 'archive'] + +[dev-dependencies] +dylib-dep = { path = "crates/dylib-dep" } +libloading = "0.8" + +[features] +# By default libstd support is enabled. +default = ["std"] + +# Include std support. This enables types like `Backtrace`. +std = [] + +serialize-serde = ["serde"] + +ruzstd = ["dep:ruzstd"] + +#======================================= +# Deprecated/internal features +# +# Only here for backwards compatibility purposes or for internal testing +# purposes. New code should use none of these features. +coresymbolication = [] +dbghelp = [] +dl_iterate_phdr = [] +dladdr = [] +kernel32 = [] +libunwind = [] +unix-backtrace = [] + +[[example]] +name = "backtrace" +required-features = ["std"] + +[[example]] +name = "raw" +required-features = ["std"] + +[[test]] +name = "skip_inner_frames" +required-features = ["std"] + +[[test]] +name = "long_fn_name" +required-features = ["std"] + +[[test]] +name = "smoke" +required-features = ["std"] +edition = '2021' + +[[test]] +name = "accuracy" +required-features = ["std"] +edition = '2021' + +[[test]] +name = "concurrent-panics" +required-features = ["std"] +harness = false + +[[test]] +name = "current-exe-mismatch" +required-features = ["std"] +harness = false + +[lints.rust] +# This crate uses them pervasively +unexpected_cfgs = "allow" diff --git a/anneal/v2/vendor/backtrace/LICENSE-APACHE b/anneal/v2/vendor/backtrace/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/backtrace/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/backtrace/LICENSE-MIT b/anneal/v2/vendor/backtrace/LICENSE-MIT new file mode 100644 index 0000000000..39e0ed6602 --- /dev/null +++ b/anneal/v2/vendor/backtrace/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/backtrace/README.md b/anneal/v2/vendor/backtrace/README.md new file mode 100644 index 0000000000..cebbad6d90 --- /dev/null +++ b/anneal/v2/vendor/backtrace/README.md @@ -0,0 +1,85 @@ +# backtrace-rs + +[Documentation](https://docs.rs/backtrace) + +A library for acquiring backtraces at runtime for Rust. This library aims to +enhance the support of the standard library by providing a programmatic +interface to work with, but it also supports simply easily printing the current +backtrace like libstd's panics. + +## Install + +```toml +[dependencies] +backtrace = "0.3" +``` + +## Usage + +To simply capture a backtrace and defer dealing with it until a later time, +you can use the top-level `Backtrace` type. + +```rust +use backtrace::Backtrace; + +fn main() { + let bt = Backtrace::new(); + + // do_some_work(); + + println!("{bt:?}"); +} +``` + +If, however, you'd like more raw access to the actual tracing functionality, you +can use the `trace` and `resolve` functions directly. + +```rust +fn main() { + backtrace::trace(|frame| { + let ip = frame.ip(); + let symbol_address = frame.symbol_address(); + + // Resolve this instruction pointer to a symbol name + backtrace::resolve_frame(frame, |symbol| { + if let Some(name) = symbol.name() { + // ... + } + if let Some(filename) = symbol.filename() { + // ... + } + }); + + true // keep going to the next frame + }); +} +``` + +# Supported Rust Versions + +The `backtrace` crate is a core component of the standard library, and must +at times keep up with the evolution of various platforms in order to serve +the standard library's needs. This often means using recent libraries +that provide unwinding and symbolication for various platforms. +Thus `backtrace` is likely to use recent Rust features or depend on a library +which itself uses them. Its minimum supported Rust version, by policy, is +within a few versions of current stable, approximately "stable - 2". + +This policy takes precedence over versions written anywhere else in this repo. + +# License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + https://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in backtrace-rs by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/backtrace/benches/benchmarks.rs b/anneal/v2/vendor/backtrace/benches/benchmarks.rs new file mode 100644 index 0000000000..e14e733b8d --- /dev/null +++ b/anneal/v2/vendor/backtrace/benches/benchmarks.rs @@ -0,0 +1,92 @@ +#![feature(test)] + +extern crate test; + +#[cfg(feature = "std")] +use backtrace::Backtrace; + +#[bench] +#[cfg(feature = "std")] +fn trace(b: &mut test::Bencher) { + #[inline(never)] + fn the_function() { + backtrace::trace(|frame| { + let ip = frame.ip(); + test::black_box(ip); + true + }); + } + b.iter(the_function); +} + +#[bench] +#[cfg(feature = "std")] +fn trace_and_resolve_callback(b: &mut test::Bencher) { + #[inline(never)] + fn the_function() { + backtrace::trace(|frame| { + backtrace::resolve(frame.ip(), |symbol| { + let addr = symbol.addr(); + test::black_box(addr); + }); + true + }); + } + b.iter(the_function); +} + +#[bench] +#[cfg(feature = "std")] +fn trace_and_resolve_separate(b: &mut test::Bencher) { + #[inline(never)] + fn the_function(frames: &mut Vec<*mut std::ffi::c_void>) { + backtrace::trace(|frame| { + frames.push(frame.ip()); + true + }); + frames.iter().for_each(|frame_ip| { + backtrace::resolve(*frame_ip, |symbol| { + test::black_box(symbol); + }); + }); + } + let mut frames = Vec::with_capacity(1024); + b.iter(|| { + the_function(&mut frames); + frames.clear(); + }); +} + +#[bench] +#[cfg(feature = "std")] +fn new_unresolved(b: &mut test::Bencher) { + #[inline(never)] + fn the_function() { + let bt = Backtrace::new_unresolved(); + test::black_box(bt); + } + b.iter(the_function); +} + +#[bench] +#[cfg(feature = "std")] +fn new(b: &mut test::Bencher) { + #[inline(never)] + fn the_function() { + let bt = Backtrace::new(); + test::black_box(bt); + } + b.iter(the_function); +} + +#[bench] +#[cfg(feature = "std")] +fn new_unresolved_and_resolve_separate(b: &mut test::Bencher) { + #[inline(never)] + fn the_function() { + let mut bt = Backtrace::new_unresolved(); + bt.resolve(); + test::black_box(bt); + } + b.iter(the_function); +} diff --git a/anneal/v2/vendor/backtrace/bindings.txt b/anneal/v2/vendor/backtrace/bindings.txt new file mode 100644 index 0000000000..166224b99f --- /dev/null +++ b/anneal/v2/vendor/backtrace/bindings.txt @@ -0,0 +1,63 @@ +--out src/windows_sys.rs +--config sys flatten +--filter +Windows.Win32.Foundation.CloseHandle +Windows.Win32.Foundation.FALSE +Windows.Win32.Foundation.HINSTANCE +Windows.Win32.Foundation.INVALID_HANDLE_VALUE +Windows.Win32.Foundation.TRUE +Windows.Win32.Globalization.CP_UTF8 +Windows.Win32.Globalization.lstrlenW +Windows.Win32.Globalization.WideCharToMultiByte +Windows.Win32.System.Diagnostics.Debug.AddrModeFlat +Windows.Win32.System.Diagnostics.Debug.CONTEXT +Windows.Win32.System.Diagnostics.Debug.EnumerateLoadedModulesW64 +Windows.Win32.System.Diagnostics.Debug.IMAGEHLP_LINEW64 +Windows.Win32.System.Diagnostics.Debug.MAX_SYM_NAME +Windows.Win32.System.Diagnostics.Debug.PENUMLOADED_MODULES_CALLBACKW64 +Windows.Win32.System.Diagnostics.Debug.PFUNCTION_TABLE_ACCESS_ROUTINE64 +Windows.Win32.System.Diagnostics.Debug.PGET_MODULE_BASE_ROUTINE64 +Windows.Win32.System.Diagnostics.Debug.PREAD_PROCESS_MEMORY_ROUTINE64 +Windows.Win32.System.Diagnostics.Debug.PTRANSLATE_ADDRESS_ROUTINE64 +Windows.Win32.System.Diagnostics.Debug.RtlCaptureContext +Windows.Win32.System.Diagnostics.Debug.RtlLookupFunctionEntry +Windows.Win32.System.Diagnostics.Debug.RtlVirtualUnwind +Windows.Win32.System.Diagnostics.Debug.STACKFRAME64 +Windows.Win32.System.Diagnostics.Debug.STACKFRAME_EX +Windows.Win32.System.Diagnostics.Debug.StackWalk64 +Windows.Win32.System.Diagnostics.Debug.StackWalkEx +Windows.Win32.System.Diagnostics.Debug.SymAddrIncludeInlineTrace +Windows.Win32.System.Diagnostics.Debug.SYMBOL_INFOW +Windows.Win32.System.Diagnostics.Debug.SymFromAddrW +Windows.Win32.System.Diagnostics.Debug.SymFromInlineContextW +Windows.Win32.System.Diagnostics.Debug.SymFunctionTableAccess64 +Windows.Win32.System.Diagnostics.Debug.SymGetLineFromAddrW64 +Windows.Win32.System.Diagnostics.Debug.SymGetLineFromInlineContextW +Windows.Win32.System.Diagnostics.Debug.SymGetModuleBase64 +Windows.Win32.System.Diagnostics.Debug.SymGetOptions +Windows.Win32.System.Diagnostics.Debug.SymGetSearchPathW +Windows.Win32.System.Diagnostics.Debug.SymInitializeW +Windows.Win32.System.Diagnostics.Debug.SYMOPT_DEFERRED_LOADS +Windows.Win32.System.Diagnostics.Debug.SymQueryInlineTrace +Windows.Win32.System.Diagnostics.Debug.SymSetOptions +Windows.Win32.System.Diagnostics.Debug.SymSetSearchPathW +Windows.Win32.System.Diagnostics.ToolHelp.CreateToolhelp32Snapshot +Windows.Win32.System.Diagnostics.ToolHelp.Module32FirstW +Windows.Win32.System.Diagnostics.ToolHelp.Module32NextW +Windows.Win32.System.Diagnostics.ToolHelp.MODULEENTRY32W +Windows.Win32.System.Diagnostics.ToolHelp.TH32CS_SNAPMODULE +Windows.Win32.System.LibraryLoader.GetProcAddress +Windows.Win32.System.LibraryLoader.LoadLibraryA +Windows.Win32.System.Memory.CreateFileMappingA +Windows.Win32.System.Memory.FILE_MAP_READ +Windows.Win32.System.Memory.MapViewOfFile +Windows.Win32.System.Memory.PAGE_READONLY +Windows.Win32.System.Memory.UnmapViewOfFile +Windows.Win32.System.SystemInformation.IMAGE_FILE_MACHINE_I386 +Windows.Win32.System.Threading.CreateMutexA +Windows.Win32.System.Threading.GetCurrentProcess +Windows.Win32.System.Threading.GetCurrentProcessId +Windows.Win32.System.Threading.GetCurrentThread +Windows.Win32.System.Threading.INFINITE +Windows.Win32.System.Threading.ReleaseMutex +Windows.Win32.System.Threading.WaitForSingleObjectEx \ No newline at end of file diff --git a/anneal/v2/vendor/backtrace/examples/backtrace.rs b/anneal/v2/vendor/backtrace/examples/backtrace.rs new file mode 100644 index 0000000000..7ff6cd39eb --- /dev/null +++ b/anneal/v2/vendor/backtrace/examples/backtrace.rs @@ -0,0 +1,5 @@ +use backtrace::Backtrace; + +fn main() { + println!("{:?}", Backtrace::new()); +} diff --git a/anneal/v2/vendor/backtrace/examples/raw.rs b/anneal/v2/vendor/backtrace/examples/raw.rs new file mode 100644 index 0000000000..95e17dbd5e --- /dev/null +++ b/anneal/v2/vendor/backtrace/examples/raw.rs @@ -0,0 +1,52 @@ +fn main() { + foo(); +} + +fn foo() { + bar() +} +fn bar() { + baz() +} +fn baz() { + print() +} + +#[cfg(target_pointer_width = "32")] +const HEX_WIDTH: usize = 10; +#[cfg(target_pointer_width = "64")] +const HEX_WIDTH: usize = 20; + +fn print() { + let mut cnt = 0; + backtrace::trace(|frame| { + let ip = frame.ip(); + print!("frame #{:<2} - {:#02$x}", cnt, ip as usize, HEX_WIDTH); + cnt += 1; + + let mut resolved = false; + backtrace::resolve(frame.ip(), |symbol| { + if !resolved { + resolved = true; + } else { + print!("{}", vec![" "; 7 + 2 + 3 + HEX_WIDTH].join("")); + } + + if let Some(name) = symbol.name() { + print!(" - {name}"); + } else { + print!(" - "); + } + if let Some(file) = symbol.filename() { + if let Some(l) = symbol.lineno() { + print!("\n{:13}{:4$}@ {}:{}", "", "", file.display(), l, HEX_WIDTH); + } + } + println!(""); + }); + if !resolved { + println!(" - "); + } + true // keep going + }); +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/libunwind.rs b/anneal/v2/vendor/backtrace/src/backtrace/libunwind.rs new file mode 100644 index 0000000000..0564f2ead3 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/libunwind.rs @@ -0,0 +1,301 @@ +//! Backtrace support using libunwind/gcc_s/etc APIs. +//! +//! This module contains the ability to unwind the stack using libunwind-style +//! APIs. Note that there's a whole bunch of implementations of the +//! libunwind-like API, and this is just trying to be compatible with most of +//! them all at once instead of being picky. +//! +//! The libunwind API is powered by `_Unwind_Backtrace` and is in practice very +//! reliable at generating a backtrace. It's not entirely clear how it does it +//! (frame pointers? eh_frame info? both?) but it seems to work! +//! +//! Most of the complexity of this module is handling the various platform +//! differences across libunwind implementations. Otherwise this is a pretty +//! straightforward Rust binding to the libunwind APIs. +//! +//! This is the default unwinding API for all non-Windows platforms currently. + +use core::ffi::c_void; +use core::ptr::addr_of_mut; + +pub enum Frame { + Raw(*mut uw::_Unwind_Context), + Cloned { + ip: *mut c_void, + sp: *mut c_void, + symbol_address: *mut c_void, + }, +} + +// With a raw libunwind pointer it should only ever be access in a readonly +// threadsafe fashion, so it's `Sync`. When sending to other threads via `Clone` +// we always switch to a version which doesn't retain interior pointers, so we +// should be `Send` as well. +unsafe impl Send for Frame {} +unsafe impl Sync for Frame {} + +impl Frame { + pub fn ip(&self) -> *mut c_void { + let ctx = match *self { + Frame::Raw(ctx) => ctx, + Frame::Cloned { ip, .. } => return ip, + }; + #[allow(unused_mut)] + let mut ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void }; + + // To reduce TCB size in SGX enclaves, we do not want to implement + // symbol resolution functionality. Rather, we can print the offset of + // the address here, which could be later mapped to correct function. + #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] + { + let image_base = super::sgx_image_base::get_image_base(); + ip = usize::wrapping_sub(ip as usize, image_base as _) as _; + } + ip + } + + pub fn sp(&self) -> *mut c_void { + match *self { + Frame::Raw(ctx) => unsafe { uw::get_sp(ctx) as *mut c_void }, + Frame::Cloned { sp, .. } => sp, + } + } + + pub fn symbol_address(&self) -> *mut c_void { + if let Frame::Cloned { symbol_address, .. } = *self { + return symbol_address; + } + + // The macOS linker emits a "compact" unwind table that only includes an + // entry for a function if that function either has an LSDA or its + // encoding differs from that of the previous entry. Consequently, on + // macOS, `_Unwind_FindEnclosingFunction` is unreliable (it can return a + // pointer to some totally unrelated function). Instead, we just always + // return the ip. + // + // https://github.com/rust-lang/rust/issues/74771#issuecomment-664056788 + // + // Note the `skip_inner_frames.rs` test is skipped on macOS due to this + // clause, and if this is fixed that test in theory can be run on macOS! + if cfg!(target_vendor = "apple") { + self.ip() + } else { + unsafe { uw::_Unwind_FindEnclosingFunction(self.ip()) } + } + } + + pub fn module_base_address(&self) -> Option<*mut c_void> { + None + } +} + +impl Clone for Frame { + fn clone(&self) -> Frame { + Frame::Cloned { + ip: self.ip(), + sp: self.sp(), + symbol_address: self.symbol_address(), + } + } +} + +struct Bomb { + enabled: bool, +} + +impl Drop for Bomb { + fn drop(&mut self) { + if self.enabled { + panic!("cannot panic during the backtrace function"); + } + } +} + +#[inline(always)] +pub unsafe fn trace(mut cb: &mut dyn FnMut(&super::Frame) -> bool) { + unsafe { + uw::_Unwind_Backtrace(trace_fn, addr_of_mut!(cb).cast()); + } + + extern "C" fn trace_fn( + ctx: *mut uw::_Unwind_Context, + arg: *mut c_void, + ) -> uw::_Unwind_Reason_Code { + let cb = unsafe { &mut *arg.cast::<&mut dyn FnMut(&super::Frame) -> bool>() }; + let cx = super::Frame { + inner: Frame::Raw(ctx), + }; + + let mut bomb = Bomb { enabled: true }; + let keep_going = cb(&cx); + bomb.enabled = false; + + if keep_going { + uw::_URC_NO_REASON + } else { + uw::_URC_FAILURE + } + } +} + +/// Unwind library interface used for backtraces +/// +/// Note that dead code is allowed as here are just bindings +/// iOS doesn't use all of them it but adding more +/// platform-specific configs pollutes the code too much +#[allow(non_camel_case_types)] +#[allow(non_snake_case)] +#[allow(dead_code)] +mod uw { + pub use self::_Unwind_Reason_Code::*; + + use core::ffi::c_void; + + #[repr(C)] + pub enum _Unwind_Reason_Code { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9, // used only by ARM EABI + } + + pub enum _Unwind_Context {} + + pub type _Unwind_Trace_Fn = + extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code; + + unsafe extern "C" { + pub fn _Unwind_Backtrace( + trace: _Unwind_Trace_Fn, + trace_argument: *mut c_void, + ) -> _Unwind_Reason_Code; + } + + cfg_if::cfg_if! { + // available since GCC 4.2.0, should be fine for our purpose + if #[cfg(all( + not(all(target_os = "android", target_arch = "arm")), + not(all(target_os = "freebsd", target_arch = "arm")), + not(all(target_os = "linux", target_arch = "arm")), + not(all(target_os = "horizon", target_arch = "arm")), + not(all(target_os = "rtems", target_arch = "arm")), + not(all(target_os = "vita", target_arch = "arm")), + not(all(target_os = "nuttx", target_arch = "arm")), + ))] { + unsafe extern "C" { + pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t; + pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void; + + #[cfg(not(all(target_os = "linux", target_arch = "s390x")))] + // This function is a misnomer: rather than getting this frame's + // Canonical Frame Address (aka the caller frame's SP) it + // returns this frame's SP. + // + // https://github.com/libunwind/libunwind/blob/d32956507cf29d9b1a98a8bce53c78623908f4fe/src/unwind/GetCFA.c#L28-L35 + #[link_name = "_Unwind_GetCFA"] + pub fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t; + + } + + // s390x uses a biased CFA value, therefore we need to use + // _Unwind_GetGR to get the stack pointer register (%r15) + // instead of relying on _Unwind_GetCFA. + #[cfg(all(target_os = "linux", target_arch = "s390x"))] + pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + unsafe extern "C" { + pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, index: libc::c_int) -> libc::uintptr_t; + } + unsafe { _Unwind_GetGR(ctx, 15) } + } + } else { + use core::ptr::addr_of_mut; + + // On android and arm, the function `_Unwind_GetIP` and a bunch of + // others are macros, so we define functions containing the + // expansion of the macros. + // + // TODO: link to the header file that defines these macros, if you + // can find it. (I, fitzgen, cannot find the header file that some + // of these macro expansions were originally borrowed from.) + #[repr(C)] + enum _Unwind_VRS_Result { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2, + } + #[repr(C)] + enum _Unwind_VRS_RegClass { + _UVRSC_CORE = 0, + _UVRSC_VFP = 1, + _UVRSC_FPA = 2, + _UVRSC_WMMXD = 3, + _UVRSC_WMMXC = 4, + } + #[repr(C)] + enum _Unwind_VRS_DataRepresentation { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5, + } + + type _Unwind_Word = libc::c_uint; + unsafe extern "C" { + fn _Unwind_VRS_Get( + ctx: *mut _Unwind_Context, + klass: _Unwind_VRS_RegClass, + word: _Unwind_Word, + repr: _Unwind_VRS_DataRepresentation, + data: *mut c_void, + ) -> _Unwind_VRS_Result; + } + + pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + let mut val: _Unwind_Word = 0; + let ptr = addr_of_mut!(val); + unsafe { + let _ = _Unwind_VRS_Get( + ctx, + _Unwind_VRS_RegClass::_UVRSC_CORE, + 15, + _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, + ptr.cast::(), + ); + } + (val & !1) as libc::uintptr_t + } + + // R13 is the stack pointer on arm. + const SP: _Unwind_Word = 13; + + pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t { + let mut val: _Unwind_Word = 0; + let ptr = addr_of_mut!(val); + unsafe { + let _ = _Unwind_VRS_Get( + ctx, + _Unwind_VRS_RegClass::_UVRSC_CORE, + SP, + _Unwind_VRS_DataRepresentation::_UVRSD_UINT32, + ptr.cast::(), + ); + } + val as libc::uintptr_t + } + + // This function also doesn't exist on Android or ARM/Linux, so make it + // a no-op. + pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void { + pc + } + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/miri.rs b/anneal/v2/vendor/backtrace/src/backtrace/miri.rs new file mode 100644 index 0000000000..2c36be4241 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/miri.rs @@ -0,0 +1,119 @@ +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::ffi::c_void; + +unsafe extern "Rust" { + fn miri_backtrace_size(flags: u64) -> usize; + fn miri_get_backtrace(flags: u64, buf: *mut *mut ()); + fn miri_resolve_frame(ptr: *mut (), flags: u64) -> MiriFrame; + fn miri_resolve_frame_names(ptr: *mut (), flags: u64, name_buf: *mut u8, filename_buf: *mut u8); +} + +#[repr(C)] +pub struct MiriFrame { + pub name_len: usize, + pub filename_len: usize, + pub lineno: u32, + pub colno: u32, + pub fn_ptr: *mut c_void, +} + +#[derive(Clone, Debug)] +pub struct FullMiriFrame { + pub name: Box<[u8]>, + pub filename: Box<[u8]>, + pub lineno: u32, + pub colno: u32, + pub fn_ptr: *mut c_void, +} + +#[derive(Debug, Clone)] +pub struct Frame { + pub addr: *mut c_void, + pub inner: FullMiriFrame, +} + +// SAFETY: Miri guarantees that the returned pointer +// can be used from any thread. +unsafe impl Send for Frame {} +unsafe impl Sync for Frame {} + +impl Frame { + pub fn ip(&self) -> *mut c_void { + self.addr + } + + pub fn sp(&self) -> *mut c_void { + core::ptr::null_mut() + } + + pub fn symbol_address(&self) -> *mut c_void { + self.inner.fn_ptr + } + + pub fn module_base_address(&self) -> Option<*mut c_void> { + None + } +} + +// SAFETY: This function is safe to call. It is only marked as `unsafe` to +// avoid having to allow `unused_unsafe` since other implementations are +// unsafe. +pub unsafe fn trace bool>(cb: F) { + // SAFETY: Miri guarantees that the backtrace API functions + // can be called from any thread. + unsafe { trace_unsynchronized(cb) }; +} + +pub fn resolve_addr(ptr: *mut c_void) -> Frame { + // SAFETY: Miri will stop execution with an error if this pointer + // is invalid. + let frame = unsafe { miri_resolve_frame(ptr.cast::<()>(), 1) }; + + let mut name = Vec::with_capacity(frame.name_len); + let mut filename = Vec::with_capacity(frame.filename_len); + + // SAFETY: name and filename have been allocated with the amount + // of memory miri has asked for, and miri guarantees it will initialize it + unsafe { + miri_resolve_frame_names( + ptr.cast::<()>(), + 0, + name.as_mut_ptr(), + filename.as_mut_ptr(), + ); + + name.set_len(frame.name_len); + filename.set_len(frame.filename_len); + } + + Frame { + addr: ptr, + inner: FullMiriFrame { + name: name.into(), + filename: filename.into(), + lineno: frame.lineno, + colno: frame.colno, + fn_ptr: frame.fn_ptr, + }, + } +} + +unsafe fn trace_unsynchronized bool>(mut cb: F) { + let len = unsafe { miri_backtrace_size(0) }; + + let mut frames = Vec::with_capacity(len); + + unsafe { + miri_get_backtrace(1, frames.as_mut_ptr()); + + frames.set_len(len); + } + + for ptr in frames.iter() { + let frame = resolve_addr((*ptr).cast::()); + if !cb(&super::Frame { inner: frame }) { + return; + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/mod.rs b/anneal/v2/vendor/backtrace/src/backtrace/mod.rs new file mode 100644 index 0000000000..2a36214bd7 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/mod.rs @@ -0,0 +1,206 @@ +use core::ffi::c_void; +use core::fmt; + +/// Inspects the current call-stack, passing all active frames into the closure +/// provided to calculate a stack trace. +/// +/// This function is the workhorse of this library in calculating the stack +/// traces for a program. The given closure `cb` is yielded instances of a +/// `Frame` which represent information about that call frame on the stack. The +/// closure is yielded frames in a top-down fashion (most recently called +/// functions first). +/// +/// The closure's return value is an indication of whether the backtrace should +/// continue. A return value of `false` will terminate the backtrace and return +/// immediately. +/// +/// Once a `Frame` is acquired you will likely want to call `backtrace::resolve` +/// to convert the `ip` (instruction pointer) or symbol address to a `Symbol` +/// through which the name and/or filename/line number can be learned. +/// +/// Note that this is a relatively low-level function and if you'd like to, for +/// example, capture a backtrace to be inspected later, then the `Backtrace` +/// type may be more appropriate. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +/// +/// # Panics +/// +/// This function strives to never panic, but if the `cb` provided panics then +/// some platforms will force a double panic to abort the process. Some +/// platforms use a C library which internally uses callbacks which cannot be +/// unwound through, so panicking from `cb` may trigger a process abort. +/// +/// # Example +/// +/// ``` +/// extern crate backtrace; +/// +/// fn main() { +/// backtrace::trace(|frame| { +/// // ... +/// +/// true // continue the backtrace +/// }); +/// } +/// ``` +#[cfg(feature = "std")] +pub fn trace bool>(cb: F) { + let _guard = crate::lock::lock(); + unsafe { trace_unsynchronized(cb) } +} + +/// Same as `trace`, only unsafe as it's unsynchronized. +/// +/// This function does not have synchronization guarantees but is available +/// when the `std` feature of this crate isn't compiled in. See the `trace` +/// function for more documentation and examples. +/// +/// # Panics +/// +/// See information on `trace` for caveats on `cb` panicking. +pub unsafe fn trace_unsynchronized bool>(mut cb: F) { + unsafe { trace_imp(&mut cb) } +} + +/// A trait representing one frame of a backtrace, yielded to the `trace` +/// function of this crate. +/// +/// The tracing function's closure will be yielded frames, and the frame is +/// virtually dispatched as the underlying implementation is not always known +/// until runtime. +#[derive(Clone)] +pub struct Frame { + pub(crate) inner: FrameImp, +} + +impl Frame { + /// Returns the current instruction pointer of this frame. + /// + /// This is normally the next instruction to execute in the frame, but not + /// all implementations list this with 100% accuracy (but it's generally + /// pretty close). + /// + /// It is recommended to pass this value to `backtrace::resolve` to turn it + /// into a symbol name. + pub fn ip(&self) -> *mut c_void { + self.inner.ip() + } + + /// Returns the current stack pointer of this frame. + /// + /// In the case that a backend cannot recover the stack pointer for this + /// frame, a null pointer is returned. + pub fn sp(&self) -> *mut c_void { + self.inner.sp() + } + + /// Returns the starting symbol address of the frame of this function. + /// + /// This will attempt to rewind the instruction pointer returned by `ip` to + /// the start of the function, returning that value. In some cases, however, + /// backends will just return `ip` from this function. + /// + /// The returned value can sometimes be used if `backtrace::resolve` failed + /// on the `ip` given above. + pub fn symbol_address(&self) -> *mut c_void { + self.inner.symbol_address() + } + + /// Returns the base address of the module to which the frame belongs. + pub fn module_base_address(&self) -> Option<*mut c_void> { + self.inner.module_base_address() + } +} + +impl fmt::Debug for Frame { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Frame") + .field("ip", &self.ip()) + .field("symbol_address", &self.symbol_address()) + .finish() + } +} + +#[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] +mod sgx_image_base { + + #[cfg(not(feature = "std"))] + pub(crate) mod imp { + use core::ffi::c_void; + use core::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + + static IMAGE_BASE: AtomicUsize = AtomicUsize::new(0); + + /// Set the image base address. This is only available for Fortanix SGX + /// target when the `std` feature is not enabled. This can be used in the + /// standard library to set the correct base address. + #[doc(hidden)] + pub fn set_image_base(base_addr: *mut c_void) { + IMAGE_BASE.store(base_addr as _, SeqCst); + } + + pub(crate) fn get_image_base() -> *mut c_void { + IMAGE_BASE.load(SeqCst) as _ + } + } + + #[cfg(feature = "std")] + mod imp { + use core::ffi::c_void; + + pub(crate) fn get_image_base() -> *mut c_void { + std::os::fortanix_sgx::mem::image_base() as _ + } + } + + pub(crate) use imp::get_image_base; +} + +#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))] +pub use sgx_image_base::imp::set_image_base; + +cfg_if::cfg_if! { + // This needs to come first, to ensure that + // Miri takes priority over the host platform + if #[cfg(miri)] { + pub(crate) mod miri; + use self::miri::trace as trace_imp; + pub(crate) use self::miri::Frame as FrameImp; + } else if #[cfg( + any( + all( + unix, + not(target_os = "emscripten"), + not(all(target_os = "ios", target_arch = "arm")), + ), + all( + target_env = "sgx", + target_vendor = "fortanix", + ), + ) + )] { + mod libunwind; + use self::libunwind::trace as trace_imp; + pub(crate) use self::libunwind::Frame as FrameImp; + } else if #[cfg(all(windows, not(target_vendor = "uwp")))] { + cfg_if::cfg_if! { + if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec"))] { + mod win64; + use self::win64::trace as trace_imp; + pub(crate) use self::win64::Frame as FrameImp; + } else if #[cfg(any(target_arch = "x86", target_arch = "arm"))] { + mod win32; + use self::win32::trace as trace_imp; + pub(crate) use self::win32::Frame as FrameImp; + } + } + } else { + mod noop; + use self::noop::trace as trace_imp; + pub(crate) use self::noop::Frame as FrameImp; + } +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/noop.rs b/anneal/v2/vendor/backtrace/src/backtrace/noop.rs new file mode 100644 index 0000000000..98dbcfadb6 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/noop.rs @@ -0,0 +1,32 @@ +//! Empty implementation of unwinding used when no other implementation is +//! appropriate. + +use core::ffi::c_void; +use core::ptr::null_mut; + +// SAFETY: This function is safe to call. It is only marked as `unsafe` to +// avoid having to allow `unused_unsafe` since other implementations are +// unsafe. +#[inline(always)] +pub unsafe fn trace(_cb: &mut dyn FnMut(&super::Frame) -> bool) {} + +#[derive(Clone)] +pub struct Frame; + +impl Frame { + pub fn ip(&self) -> *mut c_void { + null_mut() + } + + pub fn sp(&self) -> *mut c_void { + null_mut() + } + + pub fn symbol_address(&self) -> *mut c_void { + null_mut() + } + + pub fn module_base_address(&self) -> Option<*mut c_void> { + None + } +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/win32.rs b/anneal/v2/vendor/backtrace/src/backtrace/win32.rs new file mode 100644 index 0000000000..9c459306a8 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/win32.rs @@ -0,0 +1,214 @@ +//! Backtrace strategy for Windows platforms. +//! +//! This module contains the ability to generate a backtrace on Windows using one +//! of two possible methods. The `StackWalkEx` function is primarily used if +//! possible, but not all systems have that. Failing that the `StackWalk64` +//! function is used instead. Note that `StackWalkEx` is favored because it +//! handles debuginfo internally and returns inline frame information. +//! +//! Note that all dbghelp support is loaded dynamically, see `src/dbghelp.rs` +//! for more information about that. + +use super::super::{dbghelp, windows_sys::*}; +use core::ffi::c_void; +use core::mem; + +#[derive(Clone, Copy)] +pub enum StackFrame { + New(STACKFRAME_EX), + Old(STACKFRAME64), +} + +#[derive(Clone, Copy)] +pub struct Frame { + pub(crate) stack_frame: StackFrame, + base_address: *mut c_void, +} + +// we're just sending around raw pointers and reading them, never interpreting +// them so this should be safe to both send and share across threads. +unsafe impl Send for Frame {} +unsafe impl Sync for Frame {} + +impl Frame { + pub fn ip(&self) -> *mut c_void { + self.addr_pc().Offset as *mut _ + } + + pub fn sp(&self) -> *mut c_void { + self.addr_stack().Offset as *mut _ + } + + pub fn symbol_address(&self) -> *mut c_void { + self.ip() + } + + pub fn module_base_address(&self) -> Option<*mut c_void> { + Some(self.base_address) + } + + #[cfg(not(target_env = "gnu"))] + pub fn inline_context(&self) -> Option { + match self.stack_frame { + StackFrame::New(ref new) => Some(new.InlineFrameContext), + StackFrame::Old(_) => None, + } + } + + fn addr_pc(&self) -> &ADDRESS64 { + match self.stack_frame { + StackFrame::New(ref new) => &new.AddrPC, + StackFrame::Old(ref old) => &old.AddrPC, + } + } + + fn addr_pc_mut(&mut self) -> &mut ADDRESS64 { + match self.stack_frame { + StackFrame::New(ref mut new) => &mut new.AddrPC, + StackFrame::Old(ref mut old) => &mut old.AddrPC, + } + } + + fn addr_frame_mut(&mut self) -> &mut ADDRESS64 { + match self.stack_frame { + StackFrame::New(ref mut new) => &mut new.AddrFrame, + StackFrame::Old(ref mut old) => &mut old.AddrFrame, + } + } + + fn addr_stack(&self) -> &ADDRESS64 { + match self.stack_frame { + StackFrame::New(ref new) => &new.AddrStack, + StackFrame::Old(ref old) => &old.AddrStack, + } + } + + fn addr_stack_mut(&mut self) -> &mut ADDRESS64 { + match self.stack_frame { + StackFrame::New(ref mut new) => &mut new.AddrStack, + StackFrame::Old(ref mut old) => &mut old.AddrStack, + } + } +} + +#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in windows metadata right now +struct MyContext(CONTEXT); + +#[inline(always)] +pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { + // Allocate necessary structures for doing the stack walk + let process = GetCurrentProcess(); + let thread = GetCurrentThread(); + + let mut context = mem::zeroed::(); + RtlCaptureContext(&mut context.0); + + // Ensure this process's symbols are initialized + let dbghelp = match dbghelp::init() { + Ok(dbghelp) => dbghelp, + Err(()) => return, // oh well... + }; + + let function_table_access = dbghelp.SymFunctionTableAccess64(); + let get_module_base = dbghelp.SymGetModuleBase64(); + + let process_handle = GetCurrentProcess(); + + // Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64` + // since it's in theory supported on more systems. + match (*dbghelp.dbghelp()).StackWalkEx() { + #[allow(non_snake_case)] + Some(StackWalkEx) => { + let mut inner: STACKFRAME_EX = mem::zeroed(); + inner.StackFrameSize = mem::size_of::() as u32; + let mut frame = super::Frame { + inner: Frame { + stack_frame: StackFrame::New(inner), + base_address: 0 as _, + }, + }; + let image = init_frame(&mut frame.inner, &context.0); + let frame_ptr = match &mut frame.inner.stack_frame { + StackFrame::New(ptr) => ptr as *mut STACKFRAME_EX, + _ => unreachable!(), + }; + + while StackWalkEx( + image as u32, + process, + thread, + frame_ptr, + &mut context.0 as *mut CONTEXT as *mut _, + None, + Some(function_table_access), + Some(get_module_base), + None, + 0, + ) == TRUE + { + frame.inner.base_address = get_module_base(process_handle, frame.ip() as _) as _; + + if !cb(&frame) { + break; + } + } + } + None => { + let mut frame = super::Frame { + inner: Frame { + stack_frame: StackFrame::Old(mem::zeroed()), + base_address: 0 as _, + }, + }; + let image = init_frame(&mut frame.inner, &context.0); + let frame_ptr = match &mut frame.inner.stack_frame { + StackFrame::Old(ptr) => ptr as *mut STACKFRAME64, + _ => unreachable!(), + }; + + while dbghelp.StackWalk64()( + image as u32, + process, + thread, + frame_ptr, + &mut context.0 as *mut CONTEXT as *mut _, + None, + Some(function_table_access), + Some(get_module_base), + None, + ) == TRUE + { + frame.inner.base_address = get_module_base(process_handle, frame.ip() as _) as _; + + if !cb(&frame) { + break; + } + } + } + } +} + +#[cfg(target_arch = "x86")] +fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> u16 { + frame.addr_pc_mut().Offset = ctx.Eip as u64; + frame.addr_pc_mut().Mode = AddrModeFlat; + frame.addr_stack_mut().Offset = ctx.Esp as u64; + frame.addr_stack_mut().Mode = AddrModeFlat; + frame.addr_frame_mut().Offset = ctx.Ebp as u64; + frame.addr_frame_mut().Mode = AddrModeFlat; + + IMAGE_FILE_MACHINE_I386 +} + +#[cfg(target_arch = "arm")] +fn init_frame(frame: &mut Frame, ctx: &CONTEXT) -> u16 { + frame.addr_pc_mut().Offset = ctx.Pc as u64; + frame.addr_pc_mut().Mode = AddrModeFlat; + frame.addr_stack_mut().Offset = ctx.Sp as u64; + frame.addr_stack_mut().Mode = AddrModeFlat; + unsafe { + frame.addr_frame_mut().Offset = ctx.R11 as u64; + } + frame.addr_frame_mut().Mode = AddrModeFlat; + IMAGE_FILE_MACHINE_ARMNT +} diff --git a/anneal/v2/vendor/backtrace/src/backtrace/win64.rs b/anneal/v2/vendor/backtrace/src/backtrace/win64.rs new file mode 100644 index 0000000000..81f635851b --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/backtrace/win64.rs @@ -0,0 +1,151 @@ +//! Backtrace strategy for Windows `x86_64` and `aarch64` platforms. +//! +//! This module contains the ability to capture a backtrace on Windows using +//! `RtlVirtualUnwind` to walk the stack one frame at a time. This function is much faster than using +//! `dbghelp!StackWalk*` because it does not load debug info to report inlined frames. +//! We still report inlined frames during symbolization by consulting the appropriate +//! `dbghelp` functions. + +use super::super::windows_sys::*; +use core::ffi::c_void; + +#[derive(Clone, Copy)] +pub struct Frame { + base_address: *mut c_void, + ip: *mut c_void, + sp: *mut c_void, + #[cfg(not(target_env = "gnu"))] + inline_context: Option, +} + +// we're just sending around raw pointers and reading them, never interpreting +// them so this should be safe to both send and share across threads. +unsafe impl Send for Frame {} +unsafe impl Sync for Frame {} + +impl Frame { + pub fn ip(&self) -> *mut c_void { + self.ip + } + + pub fn sp(&self) -> *mut c_void { + self.sp + } + + pub fn symbol_address(&self) -> *mut c_void { + self.ip + } + + pub fn module_base_address(&self) -> Option<*mut c_void> { + Some(self.base_address) + } + + #[cfg(not(target_env = "gnu"))] + pub fn inline_context(&self) -> Option { + self.inline_context + } +} + +#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in windows metadata right now +struct MyContext(CONTEXT); + +#[cfg(any(target_arch = "x86_64", target_arch = "arm64ec"))] +impl MyContext { + #[inline(always)] + fn ip(&self) -> u64 { + self.0.Rip + } + + #[inline(always)] + fn sp(&self) -> u64 { + self.0.Rsp + } +} + +#[cfg(target_arch = "aarch64")] +impl MyContext { + #[inline(always)] + fn ip(&self) -> usize { + self.0.Pc as usize + } + + #[inline(always)] + fn sp(&self) -> usize { + self.0.Sp as usize + } +} + +#[inline(always)] +pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { + use core::ptr; + + // Capture the initial context to start walking from. + // FIXME: shouldn't this have a Default impl? + let mut context = unsafe { core::mem::zeroed::() }; + unsafe { RtlCaptureContext(&mut context.0) }; + + loop { + let ip = context.ip(); + + // The base address of the module containing the function will be stored here + // when RtlLookupFunctionEntry returns successfully. + let mut base = 0; + // We use the `RtlLookupFunctionEntry` function in kernel32 which allows + // us to backtrace through JIT frames. + // Note that `RtlLookupFunctionEntry` only works for in-process backtraces, + // but that's all we support anyway, so it all lines up well. + let fn_entry = unsafe { RtlLookupFunctionEntry(ip, &mut base, ptr::null_mut()) }; + if fn_entry.is_null() { + // No function entry could be found - this may indicate a corrupt + // stack or that a binary was unloaded (amongst other issues). Stop + // walking and don't call the callback as we can't be confident in + // this frame or the rest of the stack. + break; + } + + let frame = super::Frame { + inner: Frame { + base_address: base as *mut c_void, + ip: ip as *mut c_void, + sp: context.sp() as *mut c_void, + #[cfg(not(target_env = "gnu"))] + inline_context: None, + }, + }; + + // We've loaded all the info about the current frame, so now call the + // callback. + if !cb(&frame) { + // Callback told us to stop, so we're done. + break; + } + + // Unwind to the next frame. + let previous_ip = ip; + let previous_sp = context.sp(); + let mut handler_data = 0usize; + let mut establisher_frame = 0; + unsafe { + RtlVirtualUnwind( + 0, + base, + ip, + fn_entry, + &mut context.0, + ptr::addr_of_mut!(handler_data).cast::<*mut c_void>(), + &mut establisher_frame, + ptr::null_mut(), + ); + } + + // RtlVirtualUnwind indicates the end of the stack in two different ways: + // * On x64, it sets the instruction pointer to 0. + // * On ARM64, it leaves the context unchanged (easiest way to check is + // to see if the instruction and stack pointers are the same). + // If we detect either of these, then unwinding is completed. + let ip = context.ip(); + if ip == 0 || (ip == previous_ip && context.sp() == previous_sp) { + break; + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/capture.rs b/anneal/v2/vendor/backtrace/src/capture.rs new file mode 100644 index 0000000000..e7de8792b1 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/capture.rs @@ -0,0 +1,621 @@ +#![allow(clippy::from_over_into)] + +#[cfg(feature = "serde")] +use crate::resolve; +use crate::PrintFmt; +use crate::{resolve_frame, trace, BacktraceFmt, Symbol, SymbolName}; +use core::ffi::c_void; +use std::fmt; +use std::path::{Path, PathBuf}; +use std::prelude::v1::*; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// Representation of an owned and self-contained backtrace. +/// +/// This structure can be used to capture a backtrace at various points in a +/// program and later used to inspect what the backtrace was at that time. +/// +/// `Backtrace` supports pretty-printing of backtraces through its `Debug` +/// implementation. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +#[derive(Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +pub struct Backtrace { + // Frames here are listed from top-to-bottom of the stack + frames: Box<[BacktraceFrame]>, +} + +#[derive(Clone, Copy)] +struct TracePtr(*mut c_void); +/// SAFETY: These pointers are always valid within a process and are not used for mutation. +unsafe impl Send for TracePtr {} +/// SAFETY: These pointers are always valid within a process and are not used for mutation. +unsafe impl Sync for TracePtr {} + +impl TracePtr { + fn into_void(self) -> *mut c_void { + self.0 + } + #[cfg(feature = "serde")] + fn from_addr(addr: usize) -> Self { + TracePtr(addr as *mut c_void) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for TracePtr { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct PrimitiveVisitor; + + impl<'de> serde::de::Visitor<'de> for PrimitiveVisitor { + type Value = TracePtr; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("usize") + } + + #[inline] + fn visit_u8(self, v: u8) -> Result + where + E: serde::de::Error, + { + Ok(TracePtr(v as usize as *mut c_void)) + } + + #[inline] + fn visit_u16(self, v: u16) -> Result + where + E: serde::de::Error, + { + Ok(TracePtr(v as usize as *mut c_void)) + } + + #[inline] + fn visit_u32(self, v: u32) -> Result + where + E: serde::de::Error, + { + if usize::BITS >= 32 { + Ok(TracePtr(v as usize as *mut c_void)) + } else { + Err(E::invalid_type( + serde::de::Unexpected::Unsigned(v as _), + &self, + )) + } + } + + #[inline] + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + if usize::BITS >= 64 { + Ok(TracePtr(v as usize as *mut c_void)) + } else { + Err(E::invalid_type( + serde::de::Unexpected::Unsigned(v as _), + &self, + )) + } + } + } + + deserializer.deserialize_u64(PrimitiveVisitor) + } +} + +#[cfg(feature = "serde")] +impl Serialize for TracePtr { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + serializer.serialize_u64(self.0 as usize as u64) + } +} + +fn _assert_send_sync() { + fn _assert() {} + _assert::(); +} + +/// Captured version of a frame in a backtrace. +/// +/// This type is returned as a list from `Backtrace::frames` and represents one +/// stack frame in a captured backtrace. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +#[derive(Clone)] +pub struct BacktraceFrame { + frame: Frame, + symbols: Option>, +} + +#[derive(Clone)] +enum Frame { + Raw(crate::Frame), + #[cfg(feature = "serde")] + Deserialized { + ip: TracePtr, + symbol_address: TracePtr, + module_base_address: Option, + }, +} + +impl Frame { + fn ip(&self) -> *mut c_void { + match *self { + Frame::Raw(ref f) => f.ip(), + #[cfg(feature = "serde")] + Frame::Deserialized { ip, .. } => ip.into_void(), + } + } + + fn symbol_address(&self) -> *mut c_void { + match *self { + Frame::Raw(ref f) => f.symbol_address(), + #[cfg(feature = "serde")] + Frame::Deserialized { symbol_address, .. } => symbol_address.into_void(), + } + } + + fn module_base_address(&self) -> Option<*mut c_void> { + match *self { + Frame::Raw(ref f) => f.module_base_address(), + #[cfg(feature = "serde")] + Frame::Deserialized { + module_base_address, + .. + } => module_base_address.map(|addr| addr.into_void()), + } + } + + /// Resolve all addresses in the frame to their symbolic names. + fn resolve_symbols(&self) -> Box<[BacktraceSymbol]> { + let mut symbols = Vec::new(); + let sym = |symbol: &Symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().into()), + addr: symbol.addr().map(TracePtr), + filename: symbol.filename().map(|m| m.to_owned()), + lineno: symbol.lineno(), + colno: symbol.colno(), + }); + }; + match *self { + Frame::Raw(ref f) => resolve_frame(f, sym), + #[cfg(feature = "serde")] + Frame::Deserialized { ip, .. } => { + resolve(ip.into_void(), sym); + } + } + symbols.into_boxed_slice() + } +} + +/// Captured version of a symbol in a backtrace. +/// +/// This type is returned as a list from `BacktraceFrame::symbols` and +/// represents the metadata for a symbol in a backtrace. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +#[derive(Clone)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +pub struct BacktraceSymbol { + name: Option>, + addr: Option, + filename: Option, + lineno: Option, + colno: Option, +} + +impl Backtrace { + /// Captures a backtrace at the callsite of this function, returning an + /// owned representation. + /// + /// This function is useful for representing a backtrace as an object in + /// Rust. This returned value can be sent across threads and printed + /// elsewhere, and the purpose of this value is to be entirely self + /// contained. + /// + /// Note that on some platforms acquiring a full backtrace and resolving it + /// can be extremely expensive. If the cost is too much for your application + /// it's recommended to instead use `Backtrace::new_unresolved()` which + /// avoids the symbol resolution step (which typically takes the longest) + /// and allows deferring that to a later date. + /// + /// # Examples + /// + /// ``` + /// use backtrace::Backtrace; + /// + /// let current_backtrace = Backtrace::new(); + /// ``` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[inline(never)] // want to make sure there's a frame here to remove + pub fn new() -> Backtrace { + let mut bt = Self::create(Self::new as usize); + bt.resolve(); + bt + } + + /// Similar to `new` except that this does not resolve any symbols, this + /// simply captures the backtrace as a list of addresses. + /// + /// At a later time the `resolve` function can be called to resolve this + /// backtrace's symbols into readable names. This function exists because + /// the resolution process can sometimes take a significant amount of time + /// whereas any one backtrace may only be rarely printed. + /// + /// # Examples + /// + /// ``` + /// use backtrace::Backtrace; + /// + /// let mut current_backtrace = Backtrace::new_unresolved(); + /// println!("{current_backtrace:?}"); // no symbol names + /// current_backtrace.resolve(); + /// println!("{current_backtrace:?}"); // symbol names now present + /// ``` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[inline(never)] // want to make sure there's a frame here to remove + pub fn new_unresolved() -> Backtrace { + Self::create(Self::new_unresolved as usize) + } + + fn create(ip: usize) -> Backtrace { + let mut frames = Vec::new(); + trace(|frame| { + frames.push(BacktraceFrame { + frame: Frame::Raw(frame.clone()), + symbols: None, + }); + + // clear inner frames, and start with call site. + if frame.symbol_address() as usize == ip { + frames.clear(); + } + + true + }); + frames.shrink_to_fit(); + + Backtrace { + frames: frames.into_boxed_slice(), + } + } + + /// Returns the frames from when this backtrace was captured. + /// + /// The first entry of this slice is likely the function `Backtrace::new`, + /// and the last frame is likely something about how this thread or the main + /// function started. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn frames(&self) -> &[BacktraceFrame] { + self.frames.as_ref() + } + + /// If this backtrace was created from `new_unresolved` then this function + /// will resolve all addresses in the backtrace to their symbolic names. + /// + /// If this backtrace has been previously resolved or was created through + /// `new`, this function does nothing. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn resolve(&mut self) { + self.frames.iter_mut().for_each(BacktraceFrame::resolve); + } +} + +impl From> for Backtrace { + fn from(frames: Vec) -> Self { + Backtrace { + frames: frames.into_boxed_slice(), + } + } +} + +impl From for BacktraceFrame { + fn from(frame: crate::Frame) -> Self { + BacktraceFrame { + frame: Frame::Raw(frame), + symbols: None, + } + } +} + +// we don't want to implement `impl From for Vec` on purpose, +// because "... additional directions for Vec can weaken type inference ..." +// more information on https://github.com/rust-lang/backtrace-rs/pull/526 +impl Into> for Backtrace { + fn into(self) -> Vec { + self.frames.into_vec() + } +} + +impl BacktraceFrame { + /// Same as `Frame::ip` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn ip(&self) -> *mut c_void { + self.frame.ip() + } + + /// Same as `Frame::symbol_address` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn symbol_address(&self) -> *mut c_void { + self.frame.symbol_address() + } + + /// Same as `Frame::module_base_address` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn module_base_address(&self) -> Option<*mut c_void> { + self.frame.module_base_address() + } + + /// Returns the list of symbols that this frame corresponds to. + /// + /// Normally there is only one symbol per frame, but sometimes if a number + /// of functions are inlined into one frame then multiple symbols will be + /// returned. The first symbol listed is the "innermost function", whereas + /// the last symbol is the outermost (last caller). + /// + /// Note that if this frame came from an unresolved backtrace then this will + /// return an empty list. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn symbols(&self) -> &[BacktraceSymbol] { + self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[]) + } + + /// Resolve all addresses in this frame to their symbolic names. + /// + /// If this frame has been previously resolved, this function does nothing. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn resolve(&mut self) { + if self.symbols.is_none() { + self.symbols = Some(self.frame.resolve_symbols()); + } + } +} + +impl BacktraceSymbol { + /// Same as `Symbol::name` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn name(&self) -> Option> { + self.name.as_ref().map(|s| SymbolName::new(s)) + } + + /// Same as `Symbol::addr` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn addr(&self) -> Option<*mut c_void> { + self.addr.map(|s| s.into_void()) + } + + /// Same as `Symbol::filename` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn filename(&self) -> Option<&Path> { + self.filename.as_deref() + } + + /// Same as `Symbol::lineno` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn lineno(&self) -> Option { + self.lineno + } + + /// Same as `Symbol::colno` + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn colno(&self) -> Option { + self.colno + } +} + +impl fmt::Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let style = if fmt.alternate() { + PrintFmt::Full + } else { + PrintFmt::Short + }; + + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = std::env::current_dir(); + let mut print_path = + move |fmt: &mut fmt::Formatter<'_>, path: crate::BytesOrWideString<'_>| { + let path = path.into_path_buf(); + if style != PrintFmt::Full { + if let Ok(cwd) = &cwd { + if let Ok(suffix) = path.strip_prefix(cwd) { + return fmt::Display::fmt(&suffix.display(), fmt); + } + } + } + fmt::Display::fmt(&path.display(), fmt) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in &self.frames { + f.frame().backtrace_frame(frame)?; + } + f.finish()?; + Ok(()) + } +} + +impl Default for Backtrace { + fn default() -> Backtrace { + Backtrace::new() + } +} + +impl fmt::Debug for BacktraceFrame { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("BacktraceFrame") + .field("ip", &self.ip()) + .field("symbol_address", &self.symbol_address()) + .finish() + } +} + +impl fmt::Debug for BacktraceSymbol { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("BacktraceSymbol") + .field("name", &self.name()) + .field("addr", &self.addr()) + .field("filename", &self.filename()) + .field("lineno", &self.lineno()) + .field("colno", &self.colno()) + .finish() + } +} + +#[cfg(feature = "serde")] +mod serde_impls { + use super::*; + use serde::de::Deserializer; + use serde::ser::Serializer; + use serde::{Deserialize, Serialize}; + + #[derive(Serialize, Deserialize)] + struct SerializedFrame { + ip: usize, + symbol_address: usize, + module_base_address: Option, + symbols: Option>, + } + + impl Serialize for BacktraceFrame { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + let BacktraceFrame { frame, symbols } = self; + SerializedFrame { + ip: frame.ip() as usize, + symbol_address: frame.symbol_address() as usize, + module_base_address: frame.module_base_address().map(|sym_a| sym_a as usize), + symbols: symbols.clone(), + } + .serialize(s) + } + } + + impl<'a> Deserialize<'a> for BacktraceFrame { + fn deserialize(d: D) -> Result + where + D: Deserializer<'a>, + { + let frame: SerializedFrame = SerializedFrame::deserialize(d)?; + Ok(BacktraceFrame { + frame: Frame::Deserialized { + ip: TracePtr::from_addr(frame.ip), + symbol_address: TracePtr::from_addr(frame.symbol_address), + module_base_address: frame.module_base_address.map(TracePtr::from_addr), + }, + symbols: frame.symbols, + }) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_frame_conversion() { + let mut frames = vec![]; + crate::trace(|frame| { + let converted = BacktraceFrame::from(frame.clone()); + frames.push(converted); + true + }); + + let mut manual = Backtrace::from(frames); + manual.resolve(); + let frames = manual.frames(); + + for frame in frames { + println!("{:?}", frame.ip()); + println!("{:?}", frame.symbol_address()); + println!("{:?}", frame.module_base_address()); + println!("{:?}", frame.symbols()); + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/dbghelp.rs b/anneal/v2/vendor/backtrace/src/dbghelp.rs new file mode 100644 index 0000000000..df31fefbb9 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/dbghelp.rs @@ -0,0 +1,487 @@ +//! A module to assist in managing dbghelp bindings on Windows +//! +//! Backtraces on Windows (at least for MSVC) are largely powered through +//! `dbghelp.dll` and the various functions that it contains. These functions +//! are currently loaded *dynamically* rather than linking to `dbghelp.dll` +//! statically. This is currently done by the standard library (and is in theory +//! required there), but is an effort to help reduce the static dll dependencies +//! of a library since backtraces are typically pretty optional. That being +//! said, `dbghelp.dll` almost always successfully loads on Windows. +//! +//! Note though that since we're loading all this support dynamically we can't +//! actually use the raw definitions in `windows_sys`, but rather we need to define +//! the function pointer types ourselves and use that. We don't really want to +//! be in the business of duplicating auto-generated bindings, so we assert that all bindings match +//! those in `windows_sys.rs`. +//! +//! Finally, you'll note here that the dll for `dbghelp.dll` is never unloaded, +//! and that's currently intentional. The thinking is that we can globally cache +//! it and use it between calls to the API, avoiding expensive loads/unloads. If +//! this is a problem for leak detectors or something like that we can cross the +//! bridge when we get there. + +#![allow(non_snake_case)] + +use alloc::vec::Vec; + +use super::windows_sys::*; +use core::ffi::c_void; +use core::mem; +use core::ptr; +use core::slice; + +// This macro is used to define a `Dbghelp` structure which internally contains +// all the function pointers that we might load. +macro_rules! dbghelp { + (extern "system" { + $(fn $name:ident($($arg:ident: $argty:ty),*) -> $ret: ty;)* + }) => ( + pub struct Dbghelp { + /// The loaded DLL for `dbghelp.dll` + dll: HINSTANCE, + + // Each function pointer for each function we might use + $($name: usize,)* + } + + static mut DBGHELP: Dbghelp = Dbghelp { + // Initially we haven't loaded the DLL + dll: ptr::null_mut(), + // Initially all functions are set to zero to say they need to be + // dynamically loaded. + $($name: 0,)* + }; + + // Convenience typedef for each function type. + $(pub type $name = unsafe extern "system" fn($($argty),*) -> $ret;)* + + impl Dbghelp { + /// Attempts to open `dbghelp.dll`. Returns success if it works or + /// error if `LoadLibraryW` fails. + fn ensure_open(&mut self) -> Result<(), ()> { + if !self.dll.is_null() { + return Ok(()) + } + let lib = b"dbghelp.dll\0"; + unsafe { + self.dll = LoadLibraryA(lib.as_ptr()); + if self.dll.is_null() { + Err(()) + } else { + Ok(()) + } + } + } + + // Function for each method we'd like to use. When called it will + // either read the cached function pointer or load it and return the + // loaded value. Loads are asserted to succeed. + $(pub fn $name(&mut self) -> Option<$name> { + // Assert that windows_sys::$name is declared to have the same + // argument types and return type as our declaration, although + // it might be either extern "C" or extern "system". + cfg_if::cfg_if! { + if #[cfg(any(target_arch = "x86", not(windows_raw_dylib)))] { + let _: unsafe extern "system" fn($($argty),*) -> $ret = super::windows_sys::$name; + } else { + let _: unsafe extern "C" fn($($argty),*) -> $ret = super::windows_sys::$name; + } + } + + unsafe { + if self.$name == 0 { + let name = concat!(stringify!($name), "\0"); + self.$name = self.symbol(name.as_bytes())?; + } + Some(mem::transmute::(self.$name)) + } + })* + + fn symbol(&self, symbol: &[u8]) -> Option { + unsafe { + GetProcAddress(self.dll, symbol.as_ptr()).map(|address|address as usize) + } + } + } + + // Convenience proxy to use the cleanup locks to reference dbghelp + // functions. + #[allow(dead_code)] + impl Init { + $(pub fn $name(&self) -> $name { + // FIXME: https://github.com/rust-lang/backtrace-rs/issues/678 + #[allow(static_mut_refs)] + unsafe { + DBGHELP.$name().unwrap() + } + })* + + pub fn dbghelp(&self) -> *mut Dbghelp { + #[allow(unused_unsafe)] + unsafe { ptr::addr_of_mut!(DBGHELP) } + } + } + ) + +} + +dbghelp! { + extern "system" { + fn SymGetOptions() -> u32; + fn SymSetOptions(options: u32) -> u32; + fn SymInitializeW( + handle: HANDLE, + path: PCWSTR, + invade: BOOL + ) -> BOOL; + fn SymGetSearchPathW( + hprocess: HANDLE, + searchpatha: PWSTR, + searchpathlength: u32 + ) -> BOOL; + fn SymSetSearchPathW( + hprocess: HANDLE, + searchpatha: PCWSTR + ) -> BOOL; + fn EnumerateLoadedModulesW64( + hprocess: HANDLE, + enumloadedmodulescallback: PENUMLOADED_MODULES_CALLBACKW64, + usercontext: *const c_void + ) -> BOOL; + fn StackWalk64( + MachineType: u32, + hProcess: HANDLE, + hThread: HANDLE, + StackFrame: *mut STACKFRAME64, + ContextRecord: *mut c_void, + ReadMemoryRoutine: PREAD_PROCESS_MEMORY_ROUTINE64, + FunctionTableAccessRoutine: PFUNCTION_TABLE_ACCESS_ROUTINE64, + GetModuleBaseRoutine: PGET_MODULE_BASE_ROUTINE64, + TranslateAddress: PTRANSLATE_ADDRESS_ROUTINE64 + ) -> BOOL; + fn SymFunctionTableAccess64( + hProcess: HANDLE, + AddrBase: u64 + ) -> *mut c_void; + fn SymGetModuleBase64( + hProcess: HANDLE, + AddrBase: u64 + ) -> u64; + fn SymFromAddrW( + hProcess: HANDLE, + Address: u64, + Displacement: *mut u64, + Symbol: *mut SYMBOL_INFOW + ) -> BOOL; + fn SymGetLineFromAddrW64( + hProcess: HANDLE, + dwAddr: u64, + pdwDisplacement: *mut u32, + Line: *mut IMAGEHLP_LINEW64 + ) -> BOOL; + fn StackWalkEx( + MachineType: u32, + hProcess: HANDLE, + hThread: HANDLE, + StackFrame: *mut STACKFRAME_EX, + ContextRecord: *mut c_void, + ReadMemoryRoutine: PREAD_PROCESS_MEMORY_ROUTINE64, + FunctionTableAccessRoutine: PFUNCTION_TABLE_ACCESS_ROUTINE64, + GetModuleBaseRoutine: PGET_MODULE_BASE_ROUTINE64, + TranslateAddress: PTRANSLATE_ADDRESS_ROUTINE64, + Flags: u32 + ) -> BOOL; + fn SymFromInlineContextW( + hProcess: HANDLE, + Address: u64, + InlineContext: u32, + Displacement: *mut u64, + Symbol: *mut SYMBOL_INFOW + ) -> BOOL; + fn SymGetLineFromInlineContextW( + hProcess: HANDLE, + dwAddr: u64, + InlineContext: u32, + qwModuleBaseAddress: u64, + pdwDisplacement: *mut u32, + Line: *mut IMAGEHLP_LINEW64 + ) -> BOOL; + fn SymAddrIncludeInlineTrace( + hProcess: HANDLE, + Address: u64 + ) -> u32; + fn SymQueryInlineTrace( + hProcess: HANDLE, + StartAddress: u64, + StartContext: u32, + StartRetAddress: u64, + CurAddress: u64, + CurContext: *mut u32, + CurFrameIndex: *mut u32 + ) -> BOOL; + } +} + +pub struct Init { + lock: HANDLE, +} + +/// Initialize all support necessary to access `dbghelp` API functions from this +/// crate. +/// +/// Note that this function is **safe**, it internally has its own +/// synchronization. Also note that it is safe to call this function multiple +/// times recursively. +pub fn init() -> Result { + use core::sync::atomic::{AtomicPtr, Ordering::SeqCst}; + + // Helper function for generating a name that's unique to the process. + fn mutex_name() -> [u8; 33] { + let mut name: [u8; 33] = *b"Local\\RustBacktraceMutex00000000\0"; + let mut id = unsafe { GetCurrentProcessId() }; + // Quick and dirty no alloc u32 to hex. + let mut index = name.len() - 1; + while id > 0 { + name[index - 1] = match (id & 0xF) as u8 { + h @ 0..=9 => b'0' + h, + h => b'A' + (h - 10), + }; + id >>= 4; + index -= 1; + } + name + } + + unsafe { + // First thing we need to do is to synchronize this function. This can + // be called concurrently from other threads or recursively within one + // thread. Note that it's trickier than that though because what we're + // using here, `dbghelp`, *also* needs to be synchronized with all other + // callers to `dbghelp` in this process. + // + // Typically there aren't really that many calls to `dbghelp` within the + // same process and we can probably safely assume that we're the only + // ones accessing it. There is, however, one primary other user we have + // to worry about which is ironically ourselves, but in the standard + // library. The Rust standard library depends on this crate for + // backtrace support, and this crate also exists on crates.io. This + // means that if the standard library is printing a panic backtrace it + // may race with this crate coming from crates.io, causing segfaults. + // + // To help solve this synchronization problem we employ a + // Windows-specific trick here (it is, after all, a Windows-specific + // restriction about synchronization). We create a *session-local* named + // mutex to protect this call. The intention here is that the standard + // library and this crate don't have to share Rust-level APIs to + // synchronize here but can instead work behind the scenes to make sure + // they're synchronizing with one another. That way when this function + // is called through the standard library or through crates.io we can be + // sure that the same mutex is being acquired. + // + // So all of that is to say that the first thing we do here is we + // atomically create a `HANDLE` which is a named mutex on Windows. We + // synchronize a bit with other threads sharing this function + // specifically and ensure that only one handle is created per instance + // of this function. Note that the handle is never closed once it's + // stored in the global. + // + // After we've actually go the lock we simply acquire it, and our `Init` + // handle we hand out will be responsible for dropping it eventually. + static LOCK: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + let mut lock = LOCK.load(SeqCst); + if lock.is_null() { + let name = mutex_name(); + lock = CreateMutexA(ptr::null_mut(), FALSE, name.as_ptr()); + if lock.is_null() { + return Err(()); + } + if let Err(other) = LOCK.compare_exchange(ptr::null_mut(), lock, SeqCst, SeqCst) { + debug_assert!(!other.is_null()); + CloseHandle(lock); + lock = other; + } + } + debug_assert!(!lock.is_null()); + let r = WaitForSingleObjectEx(lock, INFINITE, FALSE); + debug_assert_eq!(r, 0); + let ret = Init { lock }; + + // Ok, phew! Now that we're all safely synchronized, let's actually + // start processing everything. First up we need to ensure that + // `dbghelp.dll` is actually loaded in this process. We do this + // dynamically to avoid a static dependency. This has historically been + // done to work around weird linking issues and is intended at making + // binaries a bit more portable since this is largely just a debugging + // utility. + // + // Once we've opened `dbghelp.dll` we need to call some initialization + // functions in it, and that's detailed more below. We only do this + // once, though, so we've got a global boolean indicating whether we're + // done yet or not. + // FIXME: https://github.com/rust-lang/backtrace-rs/issues/678 + #[allow(static_mut_refs)] + DBGHELP.ensure_open()?; + + static mut INITIALIZED: bool = false; + if !INITIALIZED { + set_optional_options(ret.dbghelp()); + INITIALIZED = true; + } + Ok(ret) + } +} +unsafe fn set_optional_options(dbghelp: *mut Dbghelp) -> Option<()> { + unsafe { + let orig = (*dbghelp).SymGetOptions()?(); + + // Ensure that the `SYMOPT_DEFERRED_LOADS` flag is set, because + // according to MSVC's own docs about this: "This is the fastest, most + // efficient way to use the symbol handler.", so let's do that! + (*dbghelp).SymSetOptions()?(orig | SYMOPT_DEFERRED_LOADS); + + // Actually initialize symbols with MSVC. Note that this can fail, but we + // ignore it. There's not a ton of prior art for this per se, but LLVM + // internally seems to ignore the return value here and one of the + // sanitizer libraries in LLVM prints a scary warning if this fails but + // basically ignores it in the long run. + // + // One case this comes up a lot for Rust is that the standard library and + // this crate on crates.io both want to compete for `SymInitializeW`. The + // standard library historically wanted to initialize then cleanup most of + // the time, but now that it's using this crate it means that someone will + // get to initialization first and the other will pick up that + // initialization. + (*dbghelp).SymInitializeW()?(GetCurrentProcess(), ptr::null_mut(), TRUE); + + // The default search path for dbghelp will only look in the current working + // directory and (possibly) `_NT_SYMBOL_PATH` and `_NT_ALT_SYMBOL_PATH`. + // However, we also want to look in the directory of the executable + // and each DLL that is loaded. To do this, we need to update the search path + // to include these directories. + // + // See https://learn.microsoft.com/cpp/build/reference/pdbpath for an + // example of where symbols are usually searched for. + let mut search_path_buf = Vec::new(); + search_path_buf.resize(1024, 0); + + // Prefill the buffer with the current search path. + if (*dbghelp).SymGetSearchPathW()?( + GetCurrentProcess(), + search_path_buf.as_mut_ptr(), + search_path_buf.len() as _, + ) == TRUE + { + // Trim the buffer to the actual length of the string. + let len = lstrlenW(search_path_buf.as_mut_ptr()); + assert!(len >= 0); + search_path_buf.truncate(len as usize); + } else { + // If getting the search path fails, at least include the current directory. + search_path_buf.clear(); + search_path_buf.push(utf16_char('.')); + search_path_buf.push(utf16_char(';')); + } + + let mut search_path = SearchPath::new(search_path_buf); + + // Update the search path to include the directory of the executable and each DLL. + (*dbghelp).EnumerateLoadedModulesW64()?( + GetCurrentProcess(), + Some(enum_loaded_modules_callback), + ((&mut search_path) as *mut SearchPath) as *mut c_void, + ); + + let new_search_path = search_path.finalize(); + + // Set the new search path. + (*dbghelp).SymSetSearchPathW()?(GetCurrentProcess(), new_search_path.as_ptr()); + } + Some(()) +} + +struct SearchPath { + search_path_utf16: Vec, +} + +fn utf16_char(c: char) -> u16 { + let buf = &mut [0u16; 2]; + let buf = c.encode_utf16(buf); + assert!(buf.len() == 1); + buf[0] +} + +impl SearchPath { + fn new(initial_search_path: Vec) -> Self { + Self { + search_path_utf16: initial_search_path, + } + } + + /// Add a path to the search path if it is not already present. + fn add(&mut self, path: &[u16]) { + let sep = utf16_char(';'); + + // We could deduplicate in a case-insensitive way, but case-sensitivity + // can be configured by directory on Windows, so let's not do that. + // https://learn.microsoft.com/windows/wsl/case-sensitivity + if !self + .search_path_utf16 + .split(|&c| c == sep) + .any(|p| p == path) + { + if self.search_path_utf16.last() != Some(&sep) { + self.search_path_utf16.push(sep); + } + self.search_path_utf16.extend_from_slice(path); + } + } + + fn finalize(mut self) -> Vec { + // Add a null terminator. + self.search_path_utf16.push(0); + self.search_path_utf16 + } +} + +extern "system" fn enum_loaded_modules_callback( + module_name: PCWSTR, + _: u64, + _: u32, + user_context: *const c_void, +) -> BOOL { + // `module_name` is an absolute path like `C:\path\to\module.dll` + // or `C:\path\to\module.exe` + let len: usize = unsafe { lstrlenW(module_name).try_into().unwrap() }; + + if len == 0 { + // This should not happen, but if it does, we can just ignore it. + return TRUE; + } + + let module_name = unsafe { slice::from_raw_parts(module_name, len) }; + let path_sep = utf16_char('\\'); + let alt_path_sep = utf16_char('/'); + + let Some(end_of_directory) = module_name + .iter() + .rposition(|&c| c == path_sep || c == alt_path_sep) + else { + // `module_name` being an absolute path, it should always contain at least one + // path separator. If not, there is nothing we can do. + return TRUE; + }; + + let search_path = unsafe { &mut *(user_context as *mut SearchPath) }; + search_path.add(&module_name[..end_of_directory]); + + TRUE +} + +impl Drop for Init { + fn drop(&mut self) { + unsafe { + let r = ReleaseMutex(self.lock); + debug_assert!(r != 0); + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/lib.rs b/anneal/v2/vendor/backtrace/src/lib.rs new file mode 100644 index 0000000000..8e18835132 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/lib.rs @@ -0,0 +1,242 @@ +//! A library for acquiring a backtrace at runtime +//! +//! This library is meant to supplement the `RUST_BACKTRACE=1` support of the +//! standard library by allowing an acquisition of a backtrace at runtime +//! programmatically. The backtraces generated by this library do not need to be +//! parsed, for example, and expose the functionality of multiple backend +//! implementations. +//! +//! # Usage +//! +//! First, add this to your Cargo.toml +//! +//! ```toml +//! [dependencies] +//! backtrace = "0.3" +//! ``` +//! +//! Next: +//! +//! ``` +//! # // Unsafe here so test passes on no_std. +//! # #[cfg(feature = "std")] { +//! backtrace::trace(|frame| { +//! let ip = frame.ip(); +//! let symbol_address = frame.symbol_address(); +//! +//! // Resolve this instruction pointer to a symbol name +//! backtrace::resolve_frame(frame, |symbol| { +//! if let Some(name) = symbol.name() { +//! // ... +//! } +//! if let Some(filename) = symbol.filename() { +//! // ... +//! } +//! }); +//! +//! true // keep going to the next frame +//! }); +//! # } +//! ``` +//! +//! # Backtrace accuracy +//! +//! This crate implements best-effort attempts to get the native backtrace. This +//! is not always guaranteed to work, and some platforms don't return any +//! backtrace at all. If your application requires accurate backtraces then it's +//! recommended to closely evaluate this crate to see whether it's suitable +//! for your use case on your target platforms. +//! +//! Even on supported platforms, there's a number of reasons that backtraces may +//! be less-than-accurate, including but not limited to: +//! +//! * Unwind information may not be available. This crate primarily implements +//! backtraces by unwinding the stack, but not all functions may have +//! unwinding information (e.g. DWARF unwinding information). +//! +//! * Rust code may be compiled without unwinding information for some +//! functions. This can also happen for Rust code compiled with +//! `-Cpanic=abort`. You can remedy this, however, with +//! `-Cforce-unwind-tables` as a compiler option. +//! +//! * Unwind information may be inaccurate or corrupt. In the worst case +//! inaccurate unwind information can lead this library to segfault. In the +//! best case inaccurate information will result in a truncated stack trace. +//! +//! * Backtraces may not report filenames/line numbers correctly due to missing +//! or corrupt debug information. This won't lead to segfaults unlike corrupt +//! unwinding information, but missing or malformed debug information will +//! mean that filenames and line numbers will not be available. This may be +//! because debug information wasn't generated by the compiler, or it's just +//! missing on the filesystem. +//! +//! * Not all platforms are supported. For example there's no way to get a +//! backtrace on WebAssembly at the moment. +//! +//! * Crate features may be disabled. Currently this crate supports using Gimli +//! libbacktrace on non-Windows platforms for reading debuginfo for +//! backtraces. If both crate features are disabled, however, then these +//! platforms will generate a backtrace but be unable to generate symbols for +//! it. +//! +//! In most standard workflows for most standard platforms you generally don't +//! need to worry about these caveats. We'll try to fix ones where we can over +//! time, but otherwise it's important to be aware of the limitations of +//! unwinding-based backtraces! + +#![deny(missing_docs)] +#![no_std] +#![cfg_attr( + all(feature = "std", target_env = "sgx", target_vendor = "fortanix"), + feature(sgx_platform) +)] +#![warn(rust_2018_idioms)] +// When we're building as part of libstd, silence all warnings since they're +// irrelevant as this crate is developed out-of-tree. +#![cfg_attr(backtrace_in_libstd, allow(warnings))] +#![cfg_attr(not(feature = "std"), allow(dead_code))] + +#[cfg(feature = "std")] +#[macro_use] +extern crate std; + +// This is only used for gimli right now, which is only used on some platforms, and miri +// so don't worry if it's unused in other configurations. +#[allow(unused_extern_crates)] +extern crate alloc; + +pub use self::backtrace::{trace_unsynchronized, Frame}; +mod backtrace; + +pub use self::symbolize::resolve_frame_unsynchronized; +pub use self::symbolize::{resolve_unsynchronized, Symbol, SymbolName}; +mod symbolize; + +pub use self::types::BytesOrWideString; +mod types; + +#[cfg(feature = "std")] +pub use self::symbolize::clear_symbol_cache; + +mod print; +pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; + +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + pub use self::backtrace::trace; + pub use self::symbolize::{resolve, resolve_frame}; + pub use self::capture::{Backtrace, BacktraceFrame, BacktraceSymbol}; + mod capture; + } +} + +cfg_if::cfg_if! { + if #[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))] { + pub use self::backtrace::set_image_base; + } +} + +#[cfg(feature = "std")] +mod lock { + use std::cell::Cell; + use std::sync::{Mutex, MutexGuard}; + + /// A "Maybe" LockGuard + pub struct LockGuard(Option>); + + /// The global lock + static LOCK: Mutex<()> = Mutex::new(()); + // Whether this thread is the one that holds the lock + thread_local!(static LOCK_HELD: Cell = const { Cell::new(false) }); + + impl Drop for LockGuard { + fn drop(&mut self) { + // Don't do anything if we're a LockGuard(None) + if self.0.is_some() { + LOCK_HELD.with(|slot| { + // Immediately crash if we somehow aren't the thread holding this lock + assert!(slot.get()); + // We are no longer the thread holding this lock + slot.set(false); + }); + } + // lock implicitly released here, if we're a LockGuard(Some(..)) + } + } + + /// Acquire a partially unsound(!!!) global re-entrant lock over + /// backtrace's internals. + /// + /// That is, this lock can be acquired as many times as you want + /// on a single thread without deadlocking, allowing one thread + /// to acquire exclusive access to the ability to make backtraces. + /// Calls to this locking function are freely sprinkled in every place + /// where that needs to be enforced. + /// + /// + /// # Why + /// + /// This was first introduced to guard uses of Windows' dbghelp API, + /// which isn't threadsafe. It's unclear if other things now rely on + /// this locking. + /// + /// + /// # How + /// + /// The basic idea is to have a single global mutex, and a thread_local + /// boolean saying "yep this is the thread that acquired the mutex". + /// + /// The first time a thread acquires the lock, it is handed a + /// `LockGuard(Some(..))` that will actually release the lock on Drop. + /// All subsequence attempts to lock on the same thread will see + /// that their thread acquired the lock, and get `LockGuard(None)` + /// which will do nothing when dropped. + /// + /// + /// # Safety + /// + /// As long as you only ever assign the returned LockGuard to a freshly + /// declared local variable, it will do its job correctly, as the "first" + /// LockGuard will strictly outlive all subsequent LockGuards and + /// properly release the lock when the thread is done with backtracing. + /// + /// However if you ever attempt to store a LockGuard beyond the scope + /// it was acquired in, it might actually be a `LockGuard(None)` that + /// doesn't actually hold the lock! In this case another thread might + /// acquire the lock and you'll get races this system was intended to + /// avoid! + /// + /// This is why this is "partially unsound". As a public API this would + /// be unacceptable, but this is crate-private, and if you use this in + /// the most obvious and simplistic way it Just Works™. + /// + /// Note however that std specifically bypasses this lock, and uses + /// the `*_unsynchronized` backtrace APIs. This is "fine" because + /// it wraps its own calls to backtrace in a non-reentrant Mutex + /// that prevents two backtraces from getting interleaved during printing. + pub fn lock() -> LockGuard { + // If we're the thread holding this lock, pretend to acquire the lock + // again by returning a LockGuard(None) + if LOCK_HELD.with(|l| l.get()) { + return LockGuard(None); + } + // Insist that we totally are the thread holding the lock + // (our thread will block until we are) + LOCK_HELD.with(|s| s.set(true)); + // ok *actually* try to acquire the lock, blocking as necessary + LockGuard(Some(LOCK.lock().unwrap())) + } +} + +#[cfg(all( + windows, + any( + target_env = "msvc", + all(target_env = "gnu", any(target_arch = "x86", target_arch = "arm")) + ), + not(target_vendor = "uwp") +))] +mod dbghelp; +// Auto-generated by windows-bindgen/riddle +#[cfg(any(windows, target_os = "cygwin"))] +mod windows_sys; diff --git a/anneal/v2/vendor/backtrace/src/print.rs b/anneal/v2/vendor/backtrace/src/print.rs new file mode 100644 index 0000000000..888840eee4 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/print.rs @@ -0,0 +1,310 @@ +#[cfg(feature = "std")] +use super::{BacktraceFrame, BacktraceSymbol}; +use super::{BytesOrWideString, Frame, SymbolName}; +use core::ffi::c_void; +use core::fmt; + +const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); + +#[cfg(target_os = "fuchsia")] +mod fuchsia; + +/// A formatter for backtraces. +/// +/// This type can be used to print a backtrace regardless of where the backtrace +/// itself comes from. If you have a `Backtrace` type then its `Debug` +/// implementation already uses this printing format. +pub struct BacktraceFmt<'a, 'b> { + fmt: &'a mut fmt::Formatter<'b>, + frame_index: usize, + format: PrintFmt, + print_path: + &'a mut (dyn FnMut(&mut fmt::Formatter<'_>, BytesOrWideString<'_>) -> fmt::Result + 'b), +} + +/// The styles of printing that we can print +#[derive(Copy, Clone, Eq, PartialEq)] +#[non_exhaustive] +pub enum PrintFmt { + /// Prints a terser backtrace which ideally only contains relevant information + Short, + /// Prints a backtrace that contains all possible information + Full, +} + +impl<'a, 'b> BacktraceFmt<'a, 'b> { + /// Create a new `BacktraceFmt` which will write output to the provided + /// `fmt`. + /// + /// The `format` argument will control the style in which the backtrace is + /// printed, and the `print_path` argument will be used to print the + /// `BytesOrWideString` instances of filenames. This type itself doesn't do + /// any printing of filenames, but this callback is required to do so. + pub fn new( + fmt: &'a mut fmt::Formatter<'b>, + format: PrintFmt, + print_path: &'a mut (dyn FnMut(&mut fmt::Formatter<'_>, BytesOrWideString<'_>) -> fmt::Result + + 'b), + ) -> Self { + BacktraceFmt { + fmt, + frame_index: 0, + format, + print_path, + } + } + + /// Prints a preamble for the backtrace about to be printed. + /// + /// This is required on some platforms for backtraces to be fully + /// symbolicated later, and otherwise this should just be the first method + /// you call after creating a `BacktraceFmt`. + pub fn add_context(&mut self) -> fmt::Result { + #[cfg(target_os = "fuchsia")] + fuchsia::print_dso_context(self.fmt)?; + Ok(()) + } + + /// Adds a frame to the backtrace output. + /// + /// This commit returns an RAII instance of a `BacktraceFrameFmt` which can be used + /// to actually print a frame, and on destruction it will increment the + /// frame counter. + pub fn frame(&mut self) -> BacktraceFrameFmt<'_, 'a, 'b> { + BacktraceFrameFmt { + fmt: self, + symbol_index: 0, + } + } + + /// Completes the backtrace output. + /// + /// This is currently a no-op but is added for future compatibility with + /// backtrace formats. + pub fn finish(&mut self) -> fmt::Result { + #[cfg(target_os = "fuchsia")] + fuchsia::finish_context(self.fmt)?; + Ok(()) + } + + /// Inserts a message in the backtrace output. + /// + /// This allows information to be inserted between frames, + /// and won't increment the `frame_index` unlike the `frame` + /// method. + pub fn message(&mut self, msg: &str) -> fmt::Result { + self.fmt.write_str(msg) + } + + /// Return the inner formatter. + /// + /// This is used for writing custom information between frames with `write!` and `writeln!`, + /// and won't increment the `frame_index` unlike the `frame` method. + pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> { + self.fmt + } +} + +/// A formatter for just one frame of a backtrace. +/// +/// This type is created by the `BacktraceFmt::frame` function. +pub struct BacktraceFrameFmt<'fmt, 'a, 'b> { + fmt: &'fmt mut BacktraceFmt<'a, 'b>, + symbol_index: usize, +} + +impl BacktraceFrameFmt<'_, '_, '_> { + /// Prints a `BacktraceFrame` with this frame formatter. + /// + /// This will recursively print all `BacktraceSymbol` instances within the + /// `BacktraceFrame`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[cfg(feature = "std")] + pub fn backtrace_frame(&mut self, frame: &BacktraceFrame) -> fmt::Result { + let symbols = frame.symbols(); + for symbol in symbols { + self.backtrace_symbol(frame, symbol)?; + } + if symbols.is_empty() { + self.print_raw(frame.ip(), None, None, None)?; + } + Ok(()) + } + + /// Prints a `BacktraceSymbol` within a `BacktraceFrame`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[cfg(feature = "std")] + pub fn backtrace_symbol( + &mut self, + frame: &BacktraceFrame, + symbol: &BacktraceSymbol, + ) -> fmt::Result { + self.print_raw_with_column( + frame.ip(), + symbol.name(), + // TODO: this isn't great that we don't end up printing anything + // with non-utf8 filenames. Thankfully almost everything is utf8 so + // this shouldn't be too bad. + symbol + .filename() + .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))), + symbol.lineno(), + symbol.colno(), + )?; + Ok(()) + } + + /// Prints a raw traced `Frame` and `Symbol`, typically from within the raw + /// callbacks of this crate. + pub fn symbol(&mut self, frame: &Frame, symbol: &super::Symbol) -> fmt::Result { + self.print_raw_with_column( + frame.ip(), + symbol.name(), + symbol.filename_raw(), + symbol.lineno(), + symbol.colno(), + )?; + Ok(()) + } + + /// Adds a raw frame to the backtrace output. + /// + /// This method, unlike the previous, takes the raw arguments in case + /// they're being source from different locations. Note that this may be + /// called multiple times for one frame. + pub fn print_raw( + &mut self, + frame_ip: *mut c_void, + symbol_name: Option>, + filename: Option>, + lineno: Option, + ) -> fmt::Result { + self.print_raw_with_column(frame_ip, symbol_name, filename, lineno, None) + } + + /// Adds a raw frame to the backtrace output, including column information. + /// + /// This method, like the previous, takes the raw arguments in case + /// they're being source from different locations. Note that this may be + /// called multiple times for one frame. + pub fn print_raw_with_column( + &mut self, + frame_ip: *mut c_void, + symbol_name: Option>, + filename: Option>, + lineno: Option, + colno: Option, + ) -> fmt::Result { + // Fuchsia is unable to symbolize within a process so it has a special + // format which can be used to symbolize later. Print that instead of + // printing addresses in our own format here. + if cfg!(target_os = "fuchsia") { + self.print_raw_fuchsia(frame_ip)?; + } else { + self.print_raw_generic(frame_ip, symbol_name, filename, lineno, colno)?; + } + self.symbol_index += 1; + Ok(()) + } + + #[allow(unused_mut)] + fn print_raw_generic( + &mut self, + frame_ip: *mut c_void, + symbol_name: Option>, + filename: Option>, + lineno: Option, + colno: Option, + ) -> fmt::Result { + // No need to print "null" frames, it basically just means that the + // system backtrace was a bit eager to trace back super far. + if let PrintFmt::Short = self.fmt.format { + if frame_ip.is_null() { + return Ok(()); + } + } + + // Print the index of the frame as well as the optional instruction + // pointer of the frame. If we're beyond the first symbol of this frame + // though we just print appropriate whitespace. + if self.symbol_index == 0 { + write!(self.fmt.fmt, "{:4}: ", self.fmt.frame_index)?; + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{frame_ip:HEX_WIDTH$?} - ")?; + } + } else { + write!(self.fmt.fmt, " ")?; + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH + 3)?; + } + } + + // Next up write out the symbol name, using the alternate formatting for + // more information if we're a full backtrace. Here we also handle + // symbols which don't have a name, + match (symbol_name, &self.fmt.format) { + (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "{name:#}")?, + (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "{name}")?, + (None, _) => write!(self.fmt.fmt, "")?, + } + self.fmt.fmt.write_str("\n")?; + + // And last up, print out the filename/line number if they're available. + if let (Some(file), Some(line)) = (filename, lineno) { + self.print_fileline(file, line, colno)?; + } + + Ok(()) + } + + fn print_fileline( + &mut self, + file: BytesOrWideString<'_>, + line: u32, + colno: Option, + ) -> fmt::Result { + // Filename/line are printed on lines under the symbol name, so print + // some appropriate whitespace to sort of right-align ourselves. + if let PrintFmt::Full = self.fmt.format { + write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH)?; + } + write!(self.fmt.fmt, " at ")?; + + // Delegate to our internal callback to print the filename and then + // print out the line number. + (self.fmt.print_path)(self.fmt.fmt, file)?; + write!(self.fmt.fmt, ":{line}")?; + + // Add column number, if available. + if let Some(colno) = colno { + write!(self.fmt.fmt, ":{colno}")?; + } + + writeln!(self.fmt.fmt)?; + Ok(()) + } + + fn print_raw_fuchsia(&mut self, frame_ip: *mut c_void) -> fmt::Result { + // We only care about the first symbol of a frame + if self.symbol_index == 0 { + self.fmt.fmt.write_str("{{{bt:")?; + write!(self.fmt.fmt, "{}:{:?}", self.fmt.frame_index, frame_ip)?; + self.fmt.fmt.write_str("}}}\n")?; + } + Ok(()) + } +} + +impl Drop for BacktraceFrameFmt<'_, '_, '_> { + fn drop(&mut self) { + self.fmt.frame_index += 1; + } +} diff --git a/anneal/v2/vendor/backtrace/src/print/fuchsia.rs b/anneal/v2/vendor/backtrace/src/print/fuchsia.rs new file mode 100644 index 0000000000..15e3626d89 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/print/fuchsia.rs @@ -0,0 +1,432 @@ +use core::fmt::{self, Write}; +use core::slice::from_raw_parts; +use libc::c_char; +use object::NativeEndian as NE; + +unsafe extern "C" { + // dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer + // for every DSO that has been linked into the process. dl_iterate_phdr also + // ensures that the dynamic linker is locked from start to finish of the + // iteration. If the callback returns a non-zero value the iteration is + // terminated early. 'data' will be passed as the third argument to the + // callback on each call. 'size' gives the size of the dl_phdr_info. + #[allow(improper_ctypes)] + fn dl_iterate_phdr( + f: extern "C" fn(info: &dl_phdr_info, size: usize, data: &mut DsoPrinter<'_, '_>) -> i32, + data: &mut DsoPrinter<'_, '_>, + ) -> i32; +} + +// We need to parse out the build ID and some basic program header data +// which means that we need a bit of stuff from the ELF spec as well. + +const PT_LOAD: u32 = 1; +const PT_NOTE: u32 = 4; + +// Now we have to replicate, bit for bit, the structure of the dl_phdr_info +// type used by fuchsia's current dynamic linker. Chromium also has this ABI +// boundary as well as crashpad. Eventually we'd like to move these cases to +// use elf-search but we'd need to provide that in the SDK and that has not +// yet been done. Thus we (and they) are stuck having to use this method +// which incurs a tight coupling with the fuchsia libc. + +#[allow(non_camel_case_types)] +#[repr(C)] +struct dl_phdr_info { + addr: *const u8, + name: *const c_char, + phdr: *const Elf_Phdr, + phnum: u16, + adds: u64, + subs: u64, + tls_modid: usize, + tls_data: *const u8, +} + +impl dl_phdr_info { + fn program_headers(&self) -> PhdrIter<'_> { + PhdrIter { + phdrs: self.phdr_slice(), + base: self.addr, + } + } + // We have no way of knowing of checking if e_phoff and e_phnum are valid. + // libc should ensure this for us however so it's safe to form a slice here. + fn phdr_slice(&self) -> &[Elf_Phdr] { + unsafe { from_raw_parts(self.phdr, self.phnum as usize) } + } +} + +struct PhdrIter<'a> { + phdrs: &'a [Elf_Phdr], + base: *const u8, +} + +impl<'a> Iterator for PhdrIter<'a> { + type Item = Phdr<'a>; + fn next(&mut self) -> Option { + self.phdrs.split_first().map(|(phdr, new_phdrs)| { + self.phdrs = new_phdrs; + Phdr { + phdr, + base: self.base, + } + }) + } +} + +// Elf_Phdr represents a 64-bit ELF program header in the endianness of the target +// architecture. +#[allow(non_camel_case_types)] +#[derive(Clone, Debug)] +#[repr(C)] +struct Elf_Phdr { + p_type: u32, + p_flags: u32, + p_offset: u64, + p_vaddr: u64, + p_paddr: u64, + p_filesz: u64, + p_memsz: u64, + p_align: u64, +} + +// Phdr represents a valid ELF program header and its contents. +struct Phdr<'a> { + phdr: &'a Elf_Phdr, + base: *const u8, +} + +impl<'a> Phdr<'a> { + // We have no way of checking if p_addr or p_memsz are valid. Fuchsia's libc + // parses the notes first however so by virtue of being here these headers + // must be valid. NoteIter does not require the underlying data to be valid + // but it does require the bounds to be valid. We trust that libc has ensured + // that this is the case for us here. + fn notes(&self) -> NoteIter<'a> { + unsafe { + NoteIter::new( + self.base.add(self.phdr.p_offset as usize), + self.phdr.p_memsz as usize, + ) + } + } +} + +// The note type for build IDs. +const NT_GNU_BUILD_ID: u32 = 3; + +// Elf_Nhdr represents an ELF note header in the endianness of the target. +#[allow(non_camel_case_types)] +type Elf_Nhdr = object::elf::NoteHeader32; + +// Note represents an ELF note (header + contents). The name is left as a u8 +// slice because it is not always null terminated and rust makes it easy enough +// to check that the bytes match eitherway. +struct Note<'a> { + name: &'a [u8], + desc: &'a [u8], + tipe: u32, +} + +// NoteIter lets you safely iterate over a note segment. It terminates as soon +// as an error occurs or there are no more notes. If you iterate over invalid +// data it will function as though no notes were found. +struct NoteIter<'a> { + base: &'a [u8], + error: bool, +} + +impl<'a> NoteIter<'a> { + // It is an invariant of function that the pointer and size given denote a + // valid range of bytes that can all be read. The contents of these bytes + // can be anything but the range must be valid for this to be safe. + unsafe fn new(base: *const u8, size: usize) -> Self { + NoteIter { + base: unsafe { from_raw_parts(base, size) }, + error: false, + } + } +} + +// align_to aligns 'x' to 'to'-byte alignment assuming 'to' is a power of 2. +// This follows a standard pattern in C/C++ ELF parsing code where +// (x + to - 1) & -to is used. Rust does not let you negate usize so I use +// 2's-complement conversion to recreate that. +fn align_to(x: usize, to: usize) -> usize { + (x + to - 1) & (!to + 1) +} + +// take_bytes_align4 consumes num bytes from the slice (if present) and +// additionally ensures that the final slice is properlly aligned. If an +// either the number of bytes requested is too large or the slice can't be +// realigned afterwards due to not enough remaining bytes existing, None is +// returned and the slice is not modified. +fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> { + if bytes.len() < align_to(num, 4) { + return None; + } + let (out, bytes_new) = bytes.split_at(num); + *bytes = &bytes_new[align_to(num, 4) - num..]; + Some(out) +} + +/// This function has no invariants the caller must uphold, but +/// it will return `None`, without mutating, if `bytes` has insufficient size or alignment. +/// If this returns `Some(nhdr)`, then `bytes` was and remains 4-byte-aligned. +/// The values in the Elf_Nhdr fields might be nonsense. +fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> { + let (out, rest) = object::pod::from_bytes::(bytes).ok()?; + // Note that size_of::() is always a multiple of 4-bytes, so the + // 4-byte alignment is maintained. + *bytes = rest; + Some(out) +} + +impl<'a> Iterator for NoteIter<'a> { + type Item = Note<'a>; + fn next(&mut self) -> Option { + // Check if we've reached the end. + if self.base.is_empty() || self.error { + return None; + } + // We transmute out an nhdr but we carefully consider the resulting + // struct. We don't trust the namesz or descsz and we make no unsafe + // decisions based on the type. So even if we get out complete garbage + // we should still be safe. + let nhdr = take_nhdr(&mut self.base)?; + let name = take_bytes_align4(nhdr.n_namesz.get(NE) as usize, &mut self.base)?; + let desc = take_bytes_align4(nhdr.n_descsz.get(NE) as usize, &mut self.base)?; + Some(Note { + name: name, + desc: desc, + tipe: nhdr.n_type.get(NE), + }) + } +} + +struct Perm(u32); + +/// Indicates that a segment is executable. +const PERM_X: u32 = 0b00000001; +/// Indicates that a segment is writable. +const PERM_W: u32 = 0b00000010; +/// Indicates that a segment is readable. +const PERM_R: u32 = 0b00000100; + +impl core::fmt::Display for Perm { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let v = self.0; + if v & PERM_R != 0 { + f.write_char('r')? + } + if v & PERM_W != 0 { + f.write_char('w')? + } + if v & PERM_X != 0 { + f.write_char('x')? + } + Ok(()) + } +} + +/// Represents an ELF segment at runtime. +struct Segment { + /// Gives the runtime virtual address of this segment's contents. + addr: usize, + /// Gives the memory size of this segment's contents. + size: usize, + /// Gives the module virtual address of this segment with the ELF file. + mod_rel_addr: usize, + /// Gives the permissions found in the ELF file. These permissions are not + /// necessarily the permissions present at runtime however. + flags: Perm, +} + +/// Lets one iterate over Segments from a DSO. +struct SegmentIter<'a> { + phdrs: &'a [Elf_Phdr], + base: usize, +} + +impl Iterator for SegmentIter<'_> { + type Item = Segment; + + fn next(&mut self) -> Option { + self.phdrs.split_first().and_then(|(phdr, new_phdrs)| { + self.phdrs = new_phdrs; + if phdr.p_type != PT_LOAD { + self.next() + } else { + Some(Segment { + addr: phdr.p_vaddr as usize + self.base, + size: phdr.p_memsz as usize, + mod_rel_addr: phdr.p_vaddr as usize, + flags: Perm(phdr.p_flags), + }) + } + }) + } +} + +/// Represents an ELF DSO (Dynamic Shared Object). This type references +/// the data stored in the actual DSO rather than making its own copy. +struct Dso<'a> { + /// The dynamic linker always gives us a name, even if the name is empty. + /// In the case of the main executable this name will be empty. In the case + /// of a shared object it will be the soname (see DT_SONAME). + name: &'a str, + /// On Fuchsia virtually all binaries have build IDs but this is not a strict + /// requirement. There's no way to match up DSO information with a real ELF + /// file afterwards if there is no build_id so we require that every DSO + /// have one here. DSO's without a build_id are ignored. + build_id: &'a [u8], + + base: usize, + phdrs: &'a [Elf_Phdr], +} + +impl Dso<'_> { + /// Returns an iterator over Segments in this DSO. + fn segments(&self) -> SegmentIter<'_> { + SegmentIter { + phdrs: self.phdrs.as_ref(), + base: self.base, + } + } +} + +struct HexSlice<'a> { + bytes: &'a [u8], +} + +impl fmt::Display for HexSlice<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for byte in self.bytes { + write!(f, "{byte:02x}")?; + } + Ok(()) + } +} + +fn get_build_id<'a>(info: &'a dl_phdr_info) -> Option<&'a [u8]> { + for phdr in info.program_headers() { + if phdr.phdr.p_type == PT_NOTE { + for note in phdr.notes() { + if note.tipe == NT_GNU_BUILD_ID && (note.name == b"GNU\0" || note.name == b"GNU") { + return Some(note.desc); + } + } + } + } + None +} + +/// These errors encode issues that arise while parsing information about +/// each DSO. +enum Error { + /// NameError means that an error occurred while converting a C style string + /// into a rust string. + NameError, + /// BuildIDError means that we didn't find a build ID. This could either be + /// because the DSO had no build ID or because the segment containing the + /// build ID was malformed. + BuildIDError, +} + +/// Calls either 'dso' or 'error' for each DSO linked into the process by the +/// dynamic linker. +/// +/// # Arguments +/// +/// * `visitor` - A DsoPrinter that will have one of eats methods called foreach DSO. +fn for_each_dso(mut visitor: &mut DsoPrinter<'_, '_>) { + extern "C" fn callback( + info: &dl_phdr_info, + _size: usize, + visitor: &mut DsoPrinter<'_, '_>, + ) -> i32 { + // dl_iterate_phdr ensures that info.name will point to a valid + // location. + let name_len = unsafe { libc::strlen(info.name) }; + let name_slice: &[u8] = + unsafe { core::slice::from_raw_parts(info.name.cast::(), name_len) }; + let name = match core::str::from_utf8(name_slice) { + Ok(name) => name, + Err(_) => { + return visitor.error(Error::NameError) as i32; + } + }; + let build_id = match get_build_id(info) { + Some(build_id) => build_id, + None => { + return visitor.error(Error::BuildIDError) as i32; + } + }; + visitor.dso(Dso { + name: name, + build_id: build_id, + phdrs: info.phdr_slice(), + base: info.addr as usize, + }) as i32 + } + unsafe { dl_iterate_phdr(callback, &mut visitor) }; +} + +struct DsoPrinter<'a, 'b> { + writer: &'a mut core::fmt::Formatter<'b>, + module_count: usize, + error: core::fmt::Result, +} + +impl DsoPrinter<'_, '_> { + fn dso(&mut self, dso: Dso<'_>) -> bool { + let mut write = || { + write!( + self.writer, + "{{{{{{module:{:#x}:{}:elf:{}}}}}}}\n", + self.module_count, + dso.name, + HexSlice { + bytes: dso.build_id.as_ref() + } + )?; + for seg in dso.segments() { + write!( + self.writer, + "{{{{{{mmap:{:#x}:{:#x}:load:{:#x}:{}:{:#x}}}}}}}\n", + seg.addr, seg.size, self.module_count, seg.flags, seg.mod_rel_addr + )?; + } + self.module_count += 1; + Ok(()) + }; + match write() { + Ok(()) => false, + Err(err) => { + self.error = Err(err); + true + } + } + } + fn error(&mut self, _error: Error) -> bool { + false + } +} + +/// This function prints the Fuchsia symbolizer markup for all information contained in a DSO. +pub fn print_dso_context(out: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + out.write_str("{{{reset:begin}}}\n")?; + let mut visitor = DsoPrinter { + writer: out, + module_count: 0, + error: Ok(()), + }; + for_each_dso(&mut visitor); + visitor.error +} + +/// This function prints the Fuchsia symbolizer markup to end the backtrace. +pub fn finish_context(out: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + out.write_str("{{{reset:end}}}\n") +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/dbghelp.rs b/anneal/v2/vendor/backtrace/src/symbolize/dbghelp.rs new file mode 100644 index 0000000000..243eb2777d --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/dbghelp.rs @@ -0,0 +1,325 @@ +//! Symbolication strategy using `dbghelp.dll` on Windows, only used for MSVC +//! +//! This symbolication strategy, like with backtraces, uses dynamically loaded +//! information from `dbghelp.dll`. (see `src/dbghelp.rs` for info about why +//! it's dynamically loaded). +//! +//! This API selects its resolution strategy based on the frame provided or the +//! information we have at hand. If a frame from `StackWalkEx` is given to us +//! then we use similar APIs to generate correct information about inlined +//! functions. Otherwise if all we have is an address or an older stack frame +//! from `StackWalk64` we use the older APIs for symbolication. +//! +//! There's a good deal of support in this module, but a good chunk of it is +//! converting back and forth between Windows types and Rust types. For example +//! symbols come to us as wide strings which we then convert to utf-8 strings if +//! we can. + +#![allow(bad_style)] + +use super::super::{dbghelp, windows_sys::*}; +use super::{BytesOrWideString, ResolveWhat, SymbolName}; +use core::cmp; +use core::ffi::c_void; +use core::marker; +use core::mem::{self, MaybeUninit}; +use core::ptr; +use core::slice; + +// FIXME: replace with ptr::from_ref once MSRV is high enough +#[inline(always)] +#[must_use] +const fn ptr_from_ref(r: &T) -> *const T { + r +} + +// Store an OsString on std so we can provide the symbol name and filename. +pub struct Symbol<'a> { + name: *const [u8], + addr: *mut c_void, + line: Option, + filename: Option<*const [u16]>, + #[cfg(feature = "std")] + _filename_cache: Option<::std::ffi::OsString>, + #[cfg(not(feature = "std"))] + _filename_cache: (), + _marker: marker::PhantomData<&'a i32>, +} + +impl Symbol<'_> { + pub fn name(&self) -> Option> { + Some(SymbolName::new(unsafe { &*self.name })) + } + + pub fn addr(&self) -> Option<*mut c_void> { + Some(self.addr) + } + + pub fn filename_raw(&self) -> Option> { + self.filename + .map(|slice| unsafe { BytesOrWideString::Wide(&*slice) }) + } + + pub fn colno(&self) -> Option { + None + } + + pub fn lineno(&self) -> Option { + self.line + } + + #[cfg(feature = "std")] + pub fn filename(&self) -> Option<&::std::path::Path> { + use std::path::Path; + + self._filename_cache.as_ref().map(Path::new) + } +} + +#[repr(C, align(8))] +struct Aligned8(T); + +#[cfg(not(target_vendor = "win7"))] +pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) { + // Ensure this process's symbols are initialized + let dbghelp = match dbghelp::init() { + Ok(dbghelp) => dbghelp, + Err(()) => return, // oh well... + }; + unsafe { + match what { + ResolveWhat::Address(_) => { + resolve_with_inline(&dbghelp, what.address_or_ip(), None, cb) + } + ResolveWhat::Frame(frame) => { + resolve_with_inline(&dbghelp, frame.ip(), frame.inner.inline_context(), cb) + } + }; + } +} + +#[cfg(target_vendor = "win7")] +pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) { + // Ensure this process's symbols are initialized + let dbghelp = match dbghelp::init() { + Ok(dbghelp) => dbghelp, + Err(()) => return, // oh well... + }; + + unsafe { + let resolve_inner = if (*dbghelp.dbghelp()).SymAddrIncludeInlineTrace().is_some() { + // We are on a version of dbghelp 6.2+, which contains the more modern + // Inline APIs. + resolve_with_inline + } else { + // We are on an older version of dbghelp which doesn't contain the Inline + // APIs. + resolve_legacy + }; + match what { + ResolveWhat::Address(_) => resolve_inner(&dbghelp, what.address_or_ip(), None, cb), + ResolveWhat::Frame(frame) => { + resolve_inner(&dbghelp, frame.ip(), frame.inner.inline_context(), cb) + } + }; + } +} + +/// Resolve the address using the legacy dbghelp API. +/// +/// This should work all the way down to Windows XP. The inline context is +/// ignored, since this concept was only introduced in dbghelp 6.2+. +#[cfg(target_vendor = "win7")] +unsafe fn resolve_legacy( + dbghelp: &dbghelp::Init, + addr: *mut c_void, + _inline_context: Option, + cb: &mut dyn FnMut(&super::Symbol), +) -> Option<()> { + let addr = super::adjust_ip(addr) as u64; + unsafe { + do_resolve( + |info| dbghelp.SymFromAddrW()(GetCurrentProcess(), addr, &mut 0, info), + |line| dbghelp.SymGetLineFromAddrW64()(GetCurrentProcess(), addr, &mut 0, line), + cb, + ); + } + Some(()) +} + +/// Resolve the address using the modern dbghelp APIs. +/// +/// Note that calling this function requires having dbghelp 6.2+ loaded - and +/// will panic otherwise. +unsafe fn resolve_with_inline( + dbghelp: &dbghelp::Init, + addr: *mut c_void, + inline_context: Option, + cb: &mut dyn FnMut(&super::Symbol), +) -> Option<()> { + unsafe { + let current_process = GetCurrentProcess(); + // Ensure we have the functions we need. Return if any aren't found. + let SymFromInlineContextW = (*dbghelp.dbghelp()).SymFromInlineContextW()?; + let SymGetLineFromInlineContextW = (*dbghelp.dbghelp()).SymGetLineFromInlineContextW()?; + + let addr = super::adjust_ip(addr) as u64; + + let (inlined_frame_count, inline_context) = if let Some(ic) = inline_context { + (0, ic) + } else { + let SymAddrIncludeInlineTrace = (*dbghelp.dbghelp()).SymAddrIncludeInlineTrace()?; + let SymQueryInlineTrace = (*dbghelp.dbghelp()).SymQueryInlineTrace()?; + + let mut inlined_frame_count = SymAddrIncludeInlineTrace(current_process, addr); + + let mut inline_context = 0; + + // If there is are inlined frames but we can't load them for some reason OR if there are no + // inlined frames, then we disregard inlined_frame_count and inline_context. + if (inlined_frame_count > 0 + && SymQueryInlineTrace( + current_process, + addr, + 0, + addr, + addr, + &mut inline_context, + &mut 0, + ) != TRUE) + || inlined_frame_count == 0 + { + inlined_frame_count = 0; + inline_context = 0; + } + + (inlined_frame_count, inline_context) + }; + + let last_inline_context = inline_context + 1 + inlined_frame_count; + + for inline_context in inline_context..last_inline_context { + do_resolve( + |info| SymFromInlineContextW(current_process, addr, inline_context, &mut 0, info), + |line| { + SymGetLineFromInlineContextW( + current_process, + addr, + inline_context, + 0, + &mut 0, + line, + ) + }, + cb, + ); + } + } + Some(()) +} + +/// This function is only meant to be called with certain Windows API functions as its arguments, +/// using closures to simplify away here-unspecified arguments: +/// - `sym_from_addr`: either `SymFromAddrW` or `SymFromInlineContextW` +/// - `get_line_from_addr`: `SymGetLineFromAddrW64` or `SymGetLineFromInlineContextW` +unsafe fn do_resolve( + sym_from_addr: impl FnOnce(*mut SYMBOL_INFOW) -> BOOL, + get_line_from_addr: impl FnOnce(&mut IMAGEHLP_LINEW64) -> BOOL, + cb: &mut dyn FnMut(&super::Symbol), +) { + const SIZE: usize = 2 * MAX_SYM_NAME as usize + mem::size_of::(); + let mut data = MaybeUninit::>::zeroed(); + let info = data.as_mut_ptr().cast::(); + unsafe { (*info).MaxNameLen = MAX_SYM_NAME as u32 }; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + unsafe { (*info).SizeOfStruct = 88 }; + + if sym_from_addr(info) != TRUE { + return; + } + + // If the symbol name is greater than MaxNameLen, SymFromAddrW will + // give a buffer of (MaxNameLen - 1) characters and set NameLen to + // the real value. + // SAFETY: We assume NameLen has been initialized by SymFromAddrW, and we initialized MaxNameLen + let name_len = unsafe { cmp::min((*info).NameLen as usize, (*info).MaxNameLen as usize - 1) }; + // Name must be initialized by SymFromAddrW, but we only interact with it as a pointer anyways. + let name_ptr = (&raw const (*info).Name).cast::(); + + // Reencode the utf-16 symbol to utf-8 so we can use `SymbolName::new` like + // all other platforms + let mut name_buffer = [0_u8; 256]; + let mut name_len = unsafe { + WideCharToMultiByte( + CP_UTF8, + 0, + name_ptr, + name_len as i32, + name_buffer.as_mut_ptr(), + name_buffer.len() as i32, + core::ptr::null_mut(), + core::ptr::null_mut(), + ) as usize + }; + if name_len == 0 { + // If the returned length is zero that means the buffer wasn't big enough. + // However, the buffer will be filled with as much as will fit. + name_len = name_buffer.len(); + } else if name_len > name_buffer.len() { + // This can't happen. + return; + } + let name = ptr::addr_of!(name_buffer[..name_len]); + + let mut line = IMAGEHLP_LINEW64 { + SizeOfStruct: 0, + Key: core::ptr::null_mut(), + LineNumber: 0, + FileName: core::ptr::null_mut(), + Address: 0, + }; + line.SizeOfStruct = mem::size_of::() as u32; + + let mut filename = None; + let mut lineno = None; + if get_line_from_addr(&mut line) == TRUE { + lineno = Some(line.LineNumber); + + let base = line.FileName; + let mut len = 0; + while unsafe { *base.offset(len) != 0 } { + len += 1; + } + + let len = len as usize; + + unsafe { + filename = Some(ptr_from_ref(slice::from_raw_parts(base, len))); + } + } + + cb(&super::Symbol { + inner: Symbol { + name, + // SAFETY: we assume Address has been initialized by SymFromAddrW + addr: unsafe { (*info).Address } as *mut _, + line: lineno, + filename, + _filename_cache: unsafe { cache(filename) }, + _marker: marker::PhantomData, + }, + }) +} + +#[cfg(feature = "std")] +unsafe fn cache(filename: Option<*const [u16]>) -> Option<::std::ffi::OsString> { + use std::os::windows::ffi::OsStringExt; + unsafe { filename.map(|f| ::std::ffi::OsString::from_wide(&*f)) } +} + +#[cfg(not(feature = "std"))] +unsafe fn cache(_filename: Option<*const [u16]>) {} + +pub unsafe fn clear_symbol_cache() {} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli.rs new file mode 100644 index 0000000000..d7ff410ce4 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli.rs @@ -0,0 +1,567 @@ +//! Support for symbolication using the `gimli` crate on crates.io +//! +//! This is the default symbolication implementation for Rust. + +use self::gimli::read::EndianSlice; +use self::gimli::NativeEndian as Endian; +use self::mmap::Mmap; +use self::stash::Stash; +use super::BytesOrWideString; +use super::ResolveWhat; +use super::SymbolName; +use addr2line::gimli; +use core::convert::TryInto; +use core::mem; +use libc::c_void; +use mystd::ffi::OsString; +use mystd::fs::File; +use mystd::path::Path; +use mystd::prelude::v1::*; + +#[cfg(backtrace_in_libstd)] +mod mystd { + pub use crate::*; +} +#[cfg(not(backtrace_in_libstd))] +extern crate std as mystd; + +cfg_if::cfg_if! { + if #[cfg(windows)] { + #[path = "gimli/mmap_windows.rs"] + mod mmap; + } else if #[cfg(target_vendor = "apple")] { + #[path = "gimli/mmap_unix.rs"] + mod mmap; + } else if #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "haiku", + target_os = "hurd", + target_os = "linux", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + target_os = "aix", + target_os = "cygwin", + ))] { + #[path = "gimli/mmap_unix.rs"] + mod mmap; + } else { + #[path = "gimli/mmap_fake.rs"] + mod mmap; + } +} + +mod lru; +mod stash; + +use lru::Lru; + +const MAPPINGS_CACHE_SIZE: usize = 4; + +struct Mapping { + // 'static lifetime is a lie to hack around lack of support for self-referential structs. + cx: Context<'static>, + _map: Mmap, + stash: Stash, +} + +enum Either { + #[allow(dead_code)] + A(A), + B(B), +} + +impl Mapping { + /// Creates a `Mapping` by ensuring that the `data` specified is used to + /// create a `Context` and it can only borrow from that or the `Stash` of + /// decompressed sections or auxiliary data. + fn mk(data: Mmap, mk: F) -> Option + where + F: for<'a> FnOnce(&'a [u8], &'a Stash) -> Option>, + { + Mapping::mk_or_other(data, move |data, stash| { + let cx = mk(data, stash)?; + Some(Either::B(cx)) + }) + } + + /// Creates a `Mapping` from `data`, or if the closure decides to, returns a + /// different mapping. + fn mk_or_other(data: Mmap, mk: F) -> Option + where + F: for<'a> FnOnce(&'a [u8], &'a Stash) -> Option>>, + { + let stash = Stash::new(); + let cx = match mk(&data, &stash)? { + Either::A(mapping) => return Some(mapping), + Either::B(cx) => cx, + }; + Some(Mapping { + // Convert to 'static lifetimes since the symbols should + // only borrow `map` and `stash` and we're preserving them below. + cx: unsafe { core::mem::transmute::, Context<'static>>(cx) }, + _map: data, + stash, + }) + } +} + +struct Context<'a> { + dwarf: addr2line::Context>, + object: Object<'a>, + package: Option>>, +} + +impl<'data> Context<'data> { + // #[feature(optimize_attr)] is enabled when we're built inside libstd + #[cfg_attr(backtrace_in_libstd, optimize(size))] + fn new( + stash: &'data Stash, + object: Object<'data>, + sup: Option>, + dwp: Option>, + ) -> Option> { + let mut sections = gimli::Dwarf::load(|id| -> Result<_, ()> { + if cfg!(not(target_os = "aix")) { + let data = object.section(stash, id.name()).unwrap_or(&[]); + Ok(EndianSlice::new(data, Endian)) + } else if let Some(name) = id.xcoff_name() { + let data = object.section(stash, name).unwrap_or(&[]); + Ok(EndianSlice::new(data, Endian)) + } else { + Ok(EndianSlice::new(&[], Endian)) + } + }) + .ok()?; + + if let Some(sup) = sup { + sections + .load_sup(|id| -> Result<_, ()> { + let data = sup.section(stash, id.name()).unwrap_or(&[]); + Ok(EndianSlice::new(data, Endian)) + }) + .ok()?; + } + let dwarf = addr2line::Context::from_dwarf(sections).ok()?; + + let mut package = None; + if let Some(dwp) = dwp { + package = Some( + gimli::DwarfPackage::load( + |id| -> Result<_, gimli::Error> { + let data = id + .dwo_name() + .and_then(|name| dwp.section(stash, name)) + .unwrap_or(&[]); + Ok(EndianSlice::new(data, Endian)) + }, + EndianSlice::new(&[], Endian), + ) + .ok()?, + ); + } + + Some(Context { + dwarf, + object, + package, + }) + } + + fn find_frames( + &'_ self, + stash: &'data Stash, + probe: u64, + ) -> gimli::Result>> { + use addr2line::{LookupContinuation, LookupResult}; + + let mut l = self.dwarf.find_frames(probe); + loop { + let (load, continuation) = match l { + LookupResult::Output(output) => break output, + LookupResult::Load { load, continuation } => (load, continuation), + }; + + l = continuation.resume(handle_split_dwarf(self.package.as_ref(), stash, load)); + } + } +} + +fn mmap(path: &Path) -> Option { + let file = File::open(path).ok()?; + let len = file.metadata().ok()?.len().try_into().ok()?; + unsafe { Mmap::map(&file, len, 0) } +} + +cfg_if::cfg_if! { + if #[cfg(any(windows, target_os = "cygwin"))] { + mod coff; + use self::coff::{handle_split_dwarf, Object}; + } else if #[cfg(any(target_vendor = "apple"))] { + mod macho; + use self::macho::{handle_split_dwarf, Object}; + } else if #[cfg(target_os = "aix")] { + mod xcoff; + use self::xcoff::{handle_split_dwarf, Object}; + } else { + mod elf; + use self::elf::{handle_split_dwarf, Object}; + } +} + +cfg_if::cfg_if! { + if #[cfg(any(windows, target_os = "cygwin"))] { + mod libs_windows; + use libs_windows::native_libraries; + } else if #[cfg(target_vendor = "apple")] { + mod libs_macos; + use libs_macos::native_libraries; + } else if #[cfg(target_os = "illumos")] { + mod libs_illumos; + use libs_illumos::native_libraries; + } else if #[cfg(all( + any( + target_os = "linux", + target_os = "fuchsia", + target_os = "freebsd", + target_os = "hurd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "nto", + target_os = "android", + ), + not(target_env = "uclibc"), + ))] { + mod libs_dl_iterate_phdr; + use libs_dl_iterate_phdr::native_libraries; + #[path = "gimli/parse_running_mmaps_unix.rs"] + mod parse_running_mmaps; + } else if #[cfg(target_env = "libnx")] { + mod libs_libnx; + use libs_libnx::native_libraries; + } else if #[cfg(target_os = "haiku")] { + mod libs_haiku; + use libs_haiku::native_libraries; + } else if #[cfg(target_os = "aix")] { + mod libs_aix; + use libs_aix::native_libraries; + } else { + // Everything else should doesn't know how to load native libraries. + fn native_libraries() -> Vec { + Vec::new() + } + } +} + +#[derive(Default)] +struct Cache { + /// All known shared libraries that have been loaded. + libraries: Vec, + + /// Mappings cache where we retain parsed dwarf information. + /// + /// This list has a fixed capacity for its entire lifetime which never + /// increases. The `usize` element of each pair is an index into `libraries` + /// above where `usize::max_value()` represents the current executable. The + /// `Mapping` is corresponding parsed dwarf information. + /// + /// Note that this is basically an LRU cache and we'll be shifting things + /// around in here as we symbolize addresses. + mappings: Lru<(usize, Mapping), MAPPINGS_CACHE_SIZE>, +} + +struct Library { + name: OsString, + #[cfg(target_os = "android")] + /// On Android, the dynamic linker [can map libraries directly from a + /// ZIP archive][ndk-linker-changes] (typically an `.apk`). + /// + /// The linker requires that these libraries are stored uncompressed + /// and page-aligned. + /// + /// These "embedded" libraries have filepaths of the form + /// `/path/to/my.apk!/lib/mylib.so` (where `/path/to/my.apk` is the archive + /// and `lib/mylib.so` is the name of the library within the archive). + /// + /// This mechanism is present on Android since API level 23. + /// + /// [ndk-linker-changes]: https://android.googlesource.com/platform/bionic/+/main/android-changes-for-ndk-developers.md#opening-shared-libraries-directly-from-an-apk + zip_offset: Option, + #[cfg(target_os = "aix")] + /// On AIX, the library mmapped can be a member of a big-archive file. + /// For example, with a big-archive named libfoo.a containing libbar.so, + /// one can use `dlopen("libfoo.a(libbar.so)", RTLD_MEMBER | RTLD_LAZY)` + /// to use the `libbar.so` library. In this case, only `libbar.so` is + /// mmapped, not the whole `libfoo.a`. + member_name: OsString, + /// Segments of this library loaded into memory, and where they're loaded. + segments: Vec, + /// The "bias" of this library, typically where it's loaded into memory. + /// This value is added to each segment's stated address to get the actual + /// virtual memory address that the segment is loaded into. Additionally + /// this bias is subtracted from real virtual memory addresses to index into + /// debuginfo and the symbol table. + bias: usize, +} + +struct LibrarySegment { + /// The stated address of this segment in the object file. This is not + /// actually where the segment is loaded, but rather this address plus the + /// containing library's `bias` is where to find it. + stated_virtual_memory_address: usize, + /// The size of this segment in memory. + len: usize, +} + +fn create_mapping(lib: &Library) -> Option { + cfg_if::cfg_if! { + if #[cfg(target_os = "aix")] { + Mapping::new(lib.name.as_ref(), &lib.member_name) + } else if #[cfg(target_os = "android")] { + Mapping::new_android(lib.name.as_ref(), lib.zip_offset) + } else { + Mapping::new(lib.name.as_ref()) + } + } +} + +/// Try to extract the archive path from an "embedded" library path +/// (e.g. `/path/to/my.apk` from `/path/to/my.apk!/mylib.so`). +/// +/// Returns `None` if the path does not contain a `!/` separator. +#[cfg(target_os = "android")] +fn extract_zip_path_android(path: &mystd::ffi::OsStr) -> Option<&mystd::ffi::OsStr> { + use mystd::os::unix::ffi::OsStrExt; + + path.as_bytes() + .windows(2) + .enumerate() + .find(|(_, chunk)| chunk == b"!/") + .map(|(index, _)| mystd::ffi::OsStr::from_bytes(path.as_bytes().split_at(index).0)) +} + +// unsafe because this is required to be externally synchronized +pub unsafe fn clear_symbol_cache() { + unsafe { + Cache::with_global(|cache| cache.mappings.clear()); + } +} + +impl Cache { + fn new() -> Cache { + Cache { + mappings: Lru::default(), + libraries: native_libraries(), + } + } + + // unsafe because this is required to be externally synchronized + // #[feature(optimize_attr)] is enabled when we're built inside libstd + #[cfg_attr(backtrace_in_libstd, optimize(size))] + unsafe fn with_global(f: impl FnOnce(&mut Self)) { + // A very small, very simple LRU cache for debug info mappings. + // + // The hit rate should be very high, since the typical stack doesn't cross + // between many shared libraries. + // + // The `addr2line::Context` structures are pretty expensive to create. Its + // cost is expected to be amortized by subsequent `locate` queries, which + // leverage the structures built when constructing `addr2line::Context`s to + // get nice speedups. If we didn't have this cache, that amortization would + // never happen, and symbolicating backtraces would be ssssllllooooowwww. + static mut MAPPINGS_CACHE: Option = None; + + unsafe { + // FIXME: https://github.com/rust-lang/backtrace-rs/issues/678 + #[allow(static_mut_refs)] + f(MAPPINGS_CACHE.get_or_insert_with(Cache::new)) + } + } + + fn avma_to_svma(&self, addr: *const u8) -> Option<(usize, *const u8)> { + self.libraries + .iter() + .enumerate() + .filter_map(|(i, lib)| { + // First up, test if this `lib` has any segment containing the + // `addr` (handling relocation). If this check passes then we + // can continue below and actually translate the address. + // + // Note that we're using `wrapping_add` here to avoid overflow + // checks. It's been seen in the wild that the SVMA + bias + // computation overflows. It seems a bit odd that would happen + // but there's not a huge amount we can do about it other than + // probably just ignore those segments since they're likely + // pointing off into space. This originally came up in + // rust-lang/backtrace-rs#329. + if !lib.segments.iter().any(|s| { + let svma = s.stated_virtual_memory_address; + let start = svma.wrapping_add(lib.bias); + let end = start.wrapping_add(s.len); + let address = addr as usize; + start <= address && address < end + }) { + return None; + } + + // Now that we know `lib` contains `addr`, we can offset with + // the bias to find the stated virtual memory address. + let svma = (addr as usize).wrapping_sub(lib.bias); + Some((i, svma as *const u8)) + }) + .next() + } + + fn mapping_for_lib<'a>(&'a mut self, lib: usize) -> Option<(&'a mut Context<'a>, &'a Stash)> { + let cache_idx = self.mappings.iter().position(|(lib_id, _)| *lib_id == lib); + + let cache_entry = if let Some(idx) = cache_idx { + self.mappings.move_to_front(idx) + } else { + // When the mapping is not in the cache, create a new mapping and insert it, + // which will also evict the oldest entry. + create_mapping(&self.libraries[lib]) + .and_then(|mapping| self.mappings.push_front((lib, mapping))) + }; + + let (_, mapping) = cache_entry?; + let cx: &'a mut Context<'static> = &mut mapping.cx; + let stash: &'a Stash = &mapping.stash; + // don't leak the `'static` lifetime, make sure it's scoped to just + // ourselves + Some(( + unsafe { mem::transmute::<&'a mut Context<'static>, &'a mut Context<'a>>(cx) }, + stash, + )) + } +} + +pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) { + let addr = what.address_or_ip(); + let mut call = |sym: Symbol<'_>| { + // Extend the lifetime of `sym` to `'static` since we are unfortunately + // required to here, but it's only ever going out as a reference so no + // reference to it should be persisted beyond this frame anyway. + // SAFETY: praying the above is correct + let sym = unsafe { mem::transmute::, Symbol<'static>>(sym) }; + (cb)(&super::Symbol { inner: sym }); + }; + + unsafe { + Cache::with_global(|cache| { + let (lib, addr) = match cache.avma_to_svma(addr.cast_const().cast::()) { + Some(pair) => pair, + None => return, + }; + + // Finally, get a cached mapping or create a new mapping for this file, and + // evaluate the DWARF info to find the file/line/name for this address. + let (cx, stash) = match cache.mapping_for_lib(lib) { + Some((cx, stash)) => (cx, stash), + None => return, + }; + let mut any_frames = false; + if let Ok(mut frames) = cx.find_frames(stash, addr as u64) { + while let Ok(Some(frame)) = frames.next() { + any_frames = true; + let name = match frame.function { + Some(f) => Some(f.name.slice()), + None => cx.object.search_symtab(addr as u64), + }; + call(Symbol::Frame { + addr: addr as *mut c_void, + location: frame.location, + name, + }); + } + } + if !any_frames { + if let Some((object_cx, object_addr)) = cx.object.search_object_map(addr as u64) { + if let Ok(mut frames) = object_cx.find_frames(stash, object_addr) { + while let Ok(Some(frame)) = frames.next() { + any_frames = true; + call(Symbol::Frame { + addr: addr as *mut c_void, + location: frame.location, + name: frame.function.map(|f| f.name.slice()), + }); + } + } + } + } + if !any_frames { + if let Some(name) = cx.object.search_symtab(addr as u64) { + call(Symbol::Symtab { name }); + } + } + }); + } +} + +pub enum Symbol<'a> { + /// We were able to locate frame information for this symbol, and + /// `addr2line`'s frame internally has all the nitty gritty details. + Frame { + addr: *mut c_void, + location: Option>, + name: Option<&'a [u8]>, + }, + /// Couldn't find debug information, but we found it in the symbol table of + /// the elf executable. + Symtab { name: &'a [u8] }, +} + +impl Symbol<'_> { + pub fn name(&self) -> Option> { + match self { + Symbol::Frame { name, .. } => { + let name = name.as_ref()?; + Some(SymbolName::new(name)) + } + Symbol::Symtab { name, .. } => Some(SymbolName::new(name)), + } + } + + pub fn addr(&self) -> Option<*mut c_void> { + match self { + Symbol::Frame { addr, .. } => Some(*addr), + Symbol::Symtab { .. } => None, + } + } + + pub fn filename_raw(&self) -> Option> { + match self { + Symbol::Frame { location, .. } => { + let file = location.as_ref()?.file?; + Some(BytesOrWideString::Bytes(file.as_bytes())) + } + Symbol::Symtab { .. } => None, + } + } + + pub fn filename(&self) -> Option<&Path> { + match self { + Symbol::Frame { location, .. } => { + let file = location.as_ref()?.file?; + Some(Path::new(file)) + } + Symbol::Symtab { .. } => None, + } + } + + pub fn lineno(&self) -> Option { + match self { + Symbol::Frame { location, .. } => location.as_ref()?.line, + Symbol::Symtab { .. } => None, + } + } + + pub fn colno(&self) -> Option { + match self { + Symbol::Frame { location, .. } => location.as_ref()?.column, + Symbol::Symtab { .. } => None, + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/coff.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/coff.rs new file mode 100644 index 0000000000..031afea0a8 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/coff.rs @@ -0,0 +1,116 @@ +use super::mystd::path::Path; +use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::TryFrom; +use object::pe::{ImageDosHeader, ImageSymbol}; +use object::read::coff::ImageSymbol as _; +use object::read::pe::{ImageNtHeaders, ImageOptionalHeader, SectionTable}; +use object::read::StringTable; +use object::LittleEndian as LE; + +#[cfg(target_pointer_width = "32")] +type Pe = object::pe::ImageNtHeaders32; +#[cfg(target_pointer_width = "64")] +type Pe = object::pe::ImageNtHeaders64; + +impl Mapping { + pub fn new(path: &Path) -> Option { + let map = super::mmap(path)?; + Mapping::mk(map, |data, stash| { + Context::new(stash, Object::parse(data)?, None, None) + }) + } +} + +pub struct Object<'a> { + data: &'a [u8], + sections: SectionTable<'a>, + symbols: Vec<(usize, &'a ImageSymbol)>, + strings: StringTable<'a>, +} + +pub fn get_image_base(data: &[u8]) -> Option { + let dos_header = ImageDosHeader::parse(data).ok()?; + let mut offset = dos_header.nt_headers_offset().into(); + let (nt_headers, _) = Pe::parse(data, &mut offset).ok()?; + usize::try_from(nt_headers.optional_header().image_base()).ok() +} + +impl<'a> Object<'a> { + fn parse(data: &'a [u8]) -> Option> { + let dos_header = ImageDosHeader::parse(data).ok()?; + let mut offset = dos_header.nt_headers_offset().into(); + let (nt_headers, _) = Pe::parse(data, &mut offset).ok()?; + let sections = nt_headers.sections(data, offset).ok()?; + let symtab = nt_headers.symbols(data).ok()?; + let strings = symtab.strings(); + let image_base = usize::try_from(nt_headers.optional_header().image_base()).ok()?; + + // Collect all the symbols into a local vector which is sorted + // by address and contains enough data to learn about the symbol + // name. Note that we only look at function symbols and also + // note that the sections are 1-indexed because the zero section + // is special (apparently). + let mut symbols = Vec::new(); + for (_, sym) in symtab.iter() { + if sym.derived_type() != object::pe::IMAGE_SYM_DTYPE_FUNCTION { + continue; + } + let Some(section_index) = sym.section() else { + continue; + }; + let addr = usize::try_from(sym.value.get(LE)).ok()?; + let section = sections.section(section_index).ok()?; + let va = usize::try_from(section.virtual_address.get(LE)).ok()?; + symbols.push((addr + va + image_base, sym)); + } + symbols.sort_unstable_by_key(|x| x.0); + Some(Object { + data, + sections, + strings, + symbols, + }) + } + + pub fn section(&self, _: &Stash, name: &str) -> Option<&'a [u8]> { + Some( + self.sections + .section_by_name(self.strings, name.as_bytes())? + .1 + .pe_data(self.data) + .ok()?, + ) + } + + pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> { + // Note that unlike other formats COFF doesn't embed the size of + // each symbol. As a last ditch effort search for the *closest* + // symbol to a particular address and return that one. This gets + // really wonky once symbols start getting removed because the + // symbols returned here can be totally incorrect, but we have + // no idea of knowing how to detect that. + let addr = usize::try_from(addr).ok()?; + let i = match self.symbols.binary_search_by_key(&addr, |p| p.0) { + Ok(i) => i, + // typically `addr` isn't in the array, but `i` is where + // we'd insert it, so the previous position must be the + // greatest less than `addr` + Err(i) => i.checked_sub(1)?, + }; + self.symbols[i].1.name(self.strings).ok() + } + + pub(super) fn search_object_map(&self, _addr: u64) -> Option<(&Context<'_>, u64)> { + None + } +} + +pub(super) fn handle_split_dwarf<'data>( + _package: Option<&gimli::DwarfPackage>>, + _stash: &'data Stash, + _load: addr2line::SplitDwarfLoad>, +) -> Option>>> { + None +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/elf.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/elf.rs new file mode 100644 index 0000000000..e32fbad457 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/elf.rs @@ -0,0 +1,567 @@ +#![allow(clippy::useless_conversion)] + +use super::mystd::ffi::OsStr; +use super::mystd::fs; +use super::mystd::os::unix::ffi::OsStrExt; +use super::mystd::path::{Path, PathBuf}; +use super::Either; +use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash}; +use alloc::string::String; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; +use core::str; +#[cfg(feature = "ruzstd")] +use object::elf::ELFCOMPRESS_ZSTD; +use object::elf::{ELFCOMPRESS_ZLIB, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED}; +use object::read::elf::{CompressionHeader, FileHeader, SectionHeader, SectionTable, Sym}; +use object::read::StringTable; +use object::{BigEndian, Bytes, NativeEndian}; + +#[cfg(target_pointer_width = "32")] +type Elf = object::elf::FileHeader32; +#[cfg(target_pointer_width = "64")] +type Elf = object::elf::FileHeader64; + +impl Mapping { + pub fn new(path: &Path) -> Option { + let map = super::mmap(path)?; + Mapping::mk_or_other(map, |map, stash| { + let object = Object::parse(map)?; + + // Try to locate an external debug file using the build ID. + if let Some(path_debug) = object.build_id().and_then(locate_build_id) { + if let Some(mapping) = Mapping::new_debug(path, path_debug, None) { + return Some(Either::A(mapping)); + } + } + + // Try to locate an external debug file using the GNU debug link section. + if let Some((path_debug, crc)) = object.gnu_debuglink_path(path) { + if let Some(mapping) = Mapping::new_debug(path, path_debug, Some(crc)) { + return Some(Either::A(mapping)); + } + } + + let dwp = Mapping::load_dwarf_package(path, stash); + + Context::new(stash, object, None, dwp).map(Either::B) + }) + } + + /// On Android, shared objects can be loaded directly from a ZIP archive + /// (see: [`super::Library::zip_offset`]). + /// + /// If `zip_offset` is not None, we interpret the `path` as an + /// "embedded" library path, and the value of `zip_offset` tells us where + /// in the ZIP archive the library data starts. + /// + /// We expect `zip_offset` to be page-aligned because the dynamic linker + /// requires this. Otherwise, loading the embedded library will fail. + /// + /// If we fail to load an embedded library for any reason, we fallback to + /// interpreting the path as a literal file on disk (same as calling [`Self::new`]). + #[cfg(target_os = "android")] + pub fn new_android(path: &Path, zip_offset: Option) -> Option { + fn map_embedded_library(path: &Path, zip_offset: u64) -> Option { + // get path of ZIP archive (delimited by `!/`) + let zip_path = Path::new(super::extract_zip_path_android(path.as_os_str())?); + + let file = fs::File::open(zip_path).ok()?; + let len = file.metadata().ok()?.len(); + + // NOTE: we map the remainder of the entire archive instead of just the library so we don't have to determine its length + // NOTE: mmap will fail if `zip_offset` is not page-aligned + let map = unsafe { + super::mmap::Mmap::map(&file, usize::try_from(len - zip_offset).ok()?, zip_offset) + }?; + + Mapping::mk(map, |map, stash| { + Context::new(stash, Object::parse(&map)?, None, None) + }) + } + + // if ZIP offset is given, try mapping as a ZIP-embedded library + // otherwise, fallback to mapping as a literal filepath + if let Some(zip_offset) = zip_offset { + map_embedded_library(path, zip_offset).or_else(|| Self::new(path)) + } else { + Self::new(path) + } + } + + /// Load debuginfo from an external debug file. + fn new_debug(original_path: &Path, path: PathBuf, crc: Option) -> Option { + let map = super::mmap(&path)?; + Mapping::mk(map, |map, stash| { + let object = Object::parse(map)?; + + if let Some(_crc) = crc { + // TODO: check crc + } + + // Try to locate a supplementary object file. + let mut sup = None; + if let Some((path_sup, build_id_sup)) = object.gnu_debugaltlink_path(&path) { + if let Some(map_sup) = super::mmap(&path_sup) { + let map_sup = stash.cache_mmap(map_sup); + if let Some(sup_) = Object::parse(map_sup) { + if sup_.build_id() == Some(build_id_sup) { + sup = Some(sup_); + } + } + } + } + + let dwp = Mapping::load_dwarf_package(original_path, stash); + + Context::new(stash, object, sup, dwp) + }) + } + + /// Try to locate a DWARF package file. + fn load_dwarf_package<'data>(path: &Path, stash: &'data Stash) -> Option> { + let mut path_dwp = path.to_path_buf(); + let dwp_extension = path + .extension() + .map(|previous_extension| { + let mut previous_extension = previous_extension.to_os_string(); + previous_extension.push(".dwp"); + previous_extension + }) + .unwrap_or_else(|| "dwp".into()); + path_dwp.set_extension(dwp_extension); + if let Some(map_dwp) = super::mmap(&path_dwp) { + let map_dwp = stash.cache_mmap(map_dwp); + if let Some(dwp_) = Object::parse(map_dwp) { + return Some(dwp_); + } + } + + None + } +} + +struct ParsedSym { + address: u64, + size: u64, + name: u32, +} + +pub struct Object<'a> { + /// Zero-sized type representing the native endianness. + /// + /// We could use a literal instead, but this helps ensure correctness. + endian: NativeEndian, + /// The entire file data. + data: &'a [u8], + sections: SectionTable<'a, Elf>, + strings: StringTable<'a>, + /// List of pre-parsed and sorted symbols by base address. + syms: Vec, +} + +impl<'a> Object<'a> { + fn parse(data: &'a [u8]) -> Option> { + let elf = Elf::parse(data).ok()?; + let endian = elf.endian().ok()?; + let sections = elf.sections(endian, data).ok()?; + let mut syms = sections + .symbols(endian, data, object::elf::SHT_SYMTAB) + .ok()?; + if syms.is_empty() { + syms = sections + .symbols(endian, data, object::elf::SHT_DYNSYM) + .ok()?; + } + let strings = syms.strings(); + + let mut syms = syms + .iter() + // Only look at function/object symbols. This mirrors what + // libbacktrace does and in general we're only symbolicating + // function addresses in theory. Object symbols correspond + // to data, and maybe someone's crazy enough to have a + // function go into static data? + .filter(|sym| { + let st_type = sym.st_type(); + st_type == object::elf::STT_FUNC || st_type == object::elf::STT_OBJECT + }) + // skip anything that's in an undefined section header, + // since it means it's an imported function and we're only + // symbolicating with locally defined functions. + .filter(|sym| sym.st_shndx(endian) != object::elf::SHN_UNDEF) + .map(|sym| { + let address = sym.st_value(endian).into(); + let size = sym.st_size(endian).into(); + let name = sym.st_name(endian); + ParsedSym { + address, + size, + name, + } + }) + .collect::>(); + syms.sort_unstable_by_key(|s| s.address); + Some(Object { + endian, + data, + sections, + strings, + syms, + }) + } + + pub fn section(&self, stash: &'a Stash, name: &str) -> Option<&'a [u8]> { + if let Some(section) = self.section_header(name) { + let mut data = Bytes(section.data(self.endian, self.data).ok()?); + + // Check for DWARF-standard (gABI) compression, i.e., as generated + // by ld's `--compress-debug-sections=zlib-gabi` and + // `--compress-debug-sections=zstd` flags. + let flags: u64 = section.sh_flags(self.endian).into(); + if (flags & u64::from(SHF_COMPRESSED)) == 0 { + // Not compressed. + return Some(data.0); + } + + let header = data.read::<::CompressionHeader>().ok()?; + match header.ch_type(self.endian) { + ELFCOMPRESS_ZLIB => { + let size = usize::try_from(header.ch_size(self.endian)).ok()?; + let buf = stash.allocate(size); + decompress_zlib(data.0, buf)?; + return Some(buf); + } + #[cfg(feature = "ruzstd")] + ELFCOMPRESS_ZSTD => { + let size = usize::try_from(header.ch_size(self.endian)).ok()?; + let buf = stash.allocate(size); + decompress_zstd(data.0, buf)?; + return Some(buf); + } + _ => return None, // Unknown compression type. + } + } + + // Check for the nonstandard GNU compression format, i.e., as generated + // by ld's `--compress-debug-sections=zlib-gnu` flag. This means that if + // we're actually asking for `.debug_info` then we need to look up a + // section named `.zdebug_info`. + if !name.starts_with(".debug_") { + return None; + } + let debug_name = name[7..].as_bytes(); + let compressed_section = self + .sections + .iter() + .filter_map(|header| { + let name = self.sections.section_name(self.endian, header).ok()?; + if name.starts_with(b".zdebug_") && &name[8..] == debug_name { + Some(header) + } else { + None + } + }) + .next()?; + let mut data = Bytes(compressed_section.data(self.endian, self.data).ok()?); + if data.read_bytes(8).ok()?.0 != b"ZLIB\0\0\0\0" { + return None; + } + let size = usize::try_from(data.read::>().ok()?.get(BigEndian)).ok()?; + let buf = stash.allocate(size); + decompress_zlib(data.0, buf)?; + Some(buf) + } + + fn section_header(&self, name: &str) -> Option<&::SectionHeader> { + self.sections + .section_by_name(self.endian, name.as_bytes()) + .map(|(_index, section)| section) + } + + pub fn search_symtab(&self, addr: u64) -> Option<&[u8]> { + // Same sort of binary search as Windows above + let i = match self.syms.binary_search_by_key(&addr, |sym| sym.address) { + Ok(i) => i, + Err(i) => i.checked_sub(1)?, + }; + let sym = self.syms.get(i)?; + if sym.address <= addr && addr <= sym.address + sym.size { + self.strings.get(sym.name).ok() + } else { + None + } + } + + pub(super) fn search_object_map(&self, _addr: u64) -> Option<(&Context<'_>, u64)> { + None + } + + fn build_id(&self) -> Option<&'a [u8]> { + for section in self.sections.iter() { + if let Ok(Some(mut notes)) = section.notes(self.endian, self.data) { + while let Ok(Some(note)) = notes.next() { + if note.name() == ELF_NOTE_GNU && note.n_type(self.endian) == NT_GNU_BUILD_ID { + return Some(note.desc()); + } + } + } + } + None + } + + // The contents of the ".gnu_debuglink" section is documented at: + // https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html + fn gnu_debuglink_path(&self, path: &Path) -> Option<(PathBuf, u32)> { + let section = self.section_header(".gnu_debuglink")?; + let data = section.data(self.endian, self.data).ok()?; + let len = data.iter().position(|x| *x == 0)?; + let filename = OsStr::from_bytes(&data[..len]); + let offset = (len + 1 + 3) & !3; + let crc_bytes = data + .get(offset..offset + 4) + .and_then(|bytes| bytes.try_into().ok())?; + let crc = u32::from_ne_bytes(crc_bytes); + let path_debug = locate_debuglink(path, filename)?; + Some((path_debug, crc)) + } + + // The format of the ".gnu_debugaltlink" section is based on gdb. + fn gnu_debugaltlink_path(&self, path: &Path) -> Option<(PathBuf, &'a [u8])> { + let section = self.section_header(".gnu_debugaltlink")?; + let data = section.data(self.endian, self.data).ok()?; + let len = data.iter().position(|x| *x == 0)?; + let filename = OsStr::from_bytes(&data[..len]); + let build_id = &data[len + 1..]; + let path_sup = locate_debugaltlink(path, filename, build_id)?; + Some((path_sup, build_id)) + } +} + +fn decompress_zlib(input: &[u8], output: &mut [u8]) -> Option<()> { + use miniz_oxide::inflate::core::inflate_flags::{ + TINFL_FLAG_PARSE_ZLIB_HEADER, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF, + }; + use miniz_oxide::inflate::core::{decompress, DecompressorOxide}; + use miniz_oxide::inflate::TINFLStatus; + + let (status, in_read, out_read) = decompress( + &mut DecompressorOxide::new(), + input, + output, + 0, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | TINFL_FLAG_PARSE_ZLIB_HEADER, + ); + if status == TINFLStatus::Done && in_read == input.len() && out_read == output.len() { + Some(()) + } else { + None + } +} + +#[cfg(feature = "ruzstd")] +fn decompress_zstd(mut input: &[u8], mut output: &mut [u8]) -> Option<()> { + use ruzstd::decoding::errors::{FrameDecoderError, ReadFrameHeaderError}; + use ruzstd::io::Read; + + while !input.is_empty() { + let mut decoder = match ruzstd::decoding::StreamingDecoder::new(&mut input) { + Ok(decoder) => decoder, + Err(FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame { + length, + .. + })) => { + input = &input.get(length as usize..)?; + continue; + } + Err(_) => return None, + }; + loop { + let bytes_written = decoder.read(output).ok()?; + if bytes_written == 0 { + break; + } + output = &mut output[bytes_written..]; + } + } + + if !output.is_empty() { + // Lengths didn't match, something is wrong. + return None; + } + + Some(()) +} + +const DEBUG_PATH: &str = "/usr/lib/debug"; + +fn debug_path_exists() -> bool { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "freebsd", target_os = "hurd", target_os = "linux"))] { + use core::sync::atomic::{AtomicU8, Ordering}; + static DEBUG_PATH_EXISTS: AtomicU8 = AtomicU8::new(0); + + let mut exists = DEBUG_PATH_EXISTS.load(Ordering::Relaxed); + if exists == 0 { + exists = if Path::new(DEBUG_PATH).is_dir() { + 1 + } else { + 2 + }; + DEBUG_PATH_EXISTS.store(exists, Ordering::Relaxed); + } + exists == 1 + } else { + false + } + } +} + +/// Locate a debug file based on its build ID. +/// +/// The format of build id paths is documented at: +/// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html +fn locate_build_id(build_id: &[u8]) -> Option { + const BUILD_ID_PATH: &str = "/usr/lib/debug/.build-id/"; + const BUILD_ID_SUFFIX: &str = ".debug"; + + if build_id.len() < 2 { + return None; + } + + if !debug_path_exists() { + return None; + } + + let mut path = + String::with_capacity(BUILD_ID_PATH.len() + BUILD_ID_SUFFIX.len() + build_id.len() * 2 + 1); + path.push_str(BUILD_ID_PATH); + path.push(char::from_digit((build_id[0] >> 4) as u32, 16)?); + path.push(char::from_digit((build_id[0] & 0xf) as u32, 16)?); + path.push('/'); + for byte in &build_id[1..] { + path.push(char::from_digit((byte >> 4) as u32, 16)?); + path.push(char::from_digit((byte & 0xf) as u32, 16)?); + } + path.push_str(BUILD_ID_SUFFIX); + Some(PathBuf::from(path)) +} + +/// Locate a file specified in a `.gnu_debuglink` section. +/// +/// `path` is the file containing the section. +/// `filename` is from the contents of the section. +/// +/// Search order is based on gdb, documented at: +/// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html +/// +/// gdb also allows the user to customize the debug search path, but we don't. +/// +/// gdb also supports debuginfod, but we don't yet. +fn locate_debuglink(path: &Path, filename: &OsStr) -> Option { + let path = fs::canonicalize(path).ok()?; + let parent = path.parent()?; + let mut f = + PathBuf::with_capacity(DEBUG_PATH.len() + parent.as_os_str().len() + filename.len() + 2); + let filename = Path::new(filename); + + // Try "/parent/filename" if it differs from "path" + f.push(parent); + f.push(filename); + if f != path && f.is_file() { + return Some(f); + } + + // Try "/parent/.debug/filename" + f.clear(); + f.push(parent); + f.push(".debug"); + f.push(filename); + if f.is_file() { + return Some(f); + } + + if debug_path_exists() { + // Try "/usr/lib/debug/parent/filename" + f.clear(); + f.push(DEBUG_PATH); + f.push(parent.strip_prefix("/").unwrap()); + f.push(filename); + if f.is_file() { + return Some(f); + } + } + + None +} + +/// Locate a file specified in a `.gnu_debugaltlink` section. +/// +/// `path` is the file containing the section. +/// `filename` and `build_id` are the contents of the section. +/// +/// Search order is based on gdb: +/// - filename, which is either absolute or relative to `path` +/// - the build ID path under `BUILD_ID_PATH` +/// +/// gdb also allows the user to customize the debug search path, but we don't. +/// +/// gdb also supports debuginfod, but we don't yet. +fn locate_debugaltlink(path: &Path, filename: &OsStr, build_id: &[u8]) -> Option { + let filename = Path::new(filename); + if filename.is_absolute() { + if filename.is_file() { + return Some(filename.into()); + } + } else { + let path = fs::canonicalize(path).ok()?; + let parent = path.parent()?; + let mut f = PathBuf::from(parent); + f.push(filename); + if f.is_file() { + return Some(f); + } + } + + locate_build_id(build_id) +} + +pub(super) fn handle_split_dwarf<'data>( + package: Option<&gimli::DwarfPackage>>, + stash: &'data Stash, + load: addr2line::SplitDwarfLoad>, +) -> Option>>> { + if let Some(dwp) = package.as_ref() { + if let Ok(Some(cu)) = dwp.find_cu(load.dwo_id, &load.parent) { + return Some(Arc::new(cu)); + } + } + + let mut path = PathBuf::new(); + if let Some(p) = load.comp_dir.as_ref() { + path.push(OsStr::from_bytes(&p)); + } + + path.push(OsStr::from_bytes(&load.path.as_ref()?)); + + if let Some(map_dwo) = super::mmap(&path) { + let map_dwo = stash.cache_mmap(map_dwo); + if let Some(dwo) = Object::parse(map_dwo) { + return gimli::Dwarf::load(|id| -> Result<_, ()> { + let data = id + .dwo_name() + .and_then(|name| dwo.section(stash, name)) + .unwrap_or(&[]); + Ok(EndianSlice::new(data, Endian)) + }) + .ok() + .map(|mut dwo_dwarf| { + dwo_dwarf.make_dwo(&load.parent); + Arc::new(dwo_dwarf) + }); + } + } + + None +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_aix.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_aix.rs new file mode 100644 index 0000000000..01270a71c9 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_aix.rs @@ -0,0 +1,85 @@ +use super::mystd::env; +use super::mystd::ffi::OsStr; +use super::mystd::os::unix::prelude::*; +use super::xcoff; +use super::{Library, LibrarySegment}; +use alloc::borrow::ToOwned; +use alloc::vec; +use alloc::vec::Vec; +use core::ffi::{c_int, CStr}; +use core::mem; + +const EXE_IMAGE_BASE: u64 = 0x100000000; + +unsafe extern "C" { + #[link_name = "_Errno"] + fn errno_location() -> *mut c_int; +} + +fn errno() -> i32 { + unsafe { (*errno_location()) as i32 } +} + +/// On AIX, we use `loadquery` with `L_GETINFO` flag to query libraries mmapped. +/// See https://www.ibm.com/docs/en/aix/7.2?topic=l-loadquery-subroutine for +/// detailed information of `loadquery`. +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + unsafe { + let mut buffer = vec![mem::zeroed::(); 64]; + loop { + if libc::loadquery( + libc::L_GETINFO, + buffer.as_mut_ptr().cast::(), + (mem::size_of::() * buffer.len()) as u32, + ) != -1 + { + break; + } else { + match errno() { + libc::ENOMEM => { + buffer.resize(buffer.len() * 2, mem::zeroed::()); + } + _ => { + // If other error occurs, return empty libraries. + return Vec::new(); + } + } + } + } + let mut current = buffer.as_mut_ptr(); + loop { + let text_base = (*current).ldinfo_textorg as usize; + let filename_ptr: *const libc::c_char = &(*current).ldinfo_filename[0]; + let bytes = CStr::from_ptr(filename_ptr).to_bytes(); + let member_name_ptr = filename_ptr.offset((bytes.len() + 1) as isize); + let mut filename = OsStr::from_bytes(bytes).to_owned(); + if text_base == EXE_IMAGE_BASE as usize { + if let Ok(exe) = env::current_exe() { + filename = exe.into_os_string(); + } + } + let bytes = CStr::from_ptr(member_name_ptr).to_bytes(); + let member_name = OsStr::from_bytes(bytes).to_owned(); + if let Some(image) = xcoff::parse_image(filename.as_ref(), &member_name) { + ret.push(Library { + name: filename, + member_name, + segments: vec![LibrarySegment { + stated_virtual_memory_address: image.base as usize, + len: image.size, + }], + bias: (text_base + image.offset).wrapping_sub(image.base as usize), + }); + } + if (*current).ldinfo_next == 0 { + break; + } + current = current + .cast::() + .offset((*current).ldinfo_next as isize) + .cast::(); + } + } + return ret; +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs new file mode 100644 index 0000000000..d52819f656 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs @@ -0,0 +1,122 @@ +// Other Unix (e.g. Linux) platforms use ELF as an object file format +// and typically implement an API called `dl_iterate_phdr` to load +// native libraries. + +use super::mystd::env; +use super::mystd::ffi::{OsStr, OsString}; +use super::mystd::os::unix::prelude::*; +use super::{parse_running_mmaps, Library, LibrarySegment}; +use alloc::borrow::ToOwned; +use alloc::vec::Vec; +use core::ffi::CStr; +use core::slice; + +struct CallbackData { + libs: Vec, + maps: Option>, +} +pub(super) fn native_libraries() -> Vec { + let mut cb_data = CallbackData { + libs: Vec::new(), + #[cfg(not(target_os = "hurd"))] + maps: parse_running_mmaps::parse_maps().ok(), + #[cfg(target_os = "hurd")] + maps: None, + }; + unsafe { + libc::dl_iterate_phdr(Some(callback), core::ptr::addr_of_mut!(cb_data).cast()); + } + cb_data.libs +} + +fn infer_current_exe( + maps: &Option>, + base_addr: usize, +) -> OsString { + #[cfg(not(target_os = "hurd"))] + if let Some(entries) = maps { + let opt_path = entries + .iter() + .find(|e| e.ip_matches(base_addr) && e.pathname().len() > 0) + .map(|e| e.pathname()) + .cloned(); + if let Some(path) = opt_path { + return path; + } + } + + env::current_exe().map(|e| e.into()).unwrap_or_default() +} + +/// # Safety +/// `info` must be a valid pointer. +/// `data` must be a valid pointer to `CallbackData`. +#[forbid(unsafe_op_in_unsafe_fn)] +unsafe extern "C" fn callback( + info: *mut libc::dl_phdr_info, + _size: libc::size_t, + data: *mut libc::c_void, +) -> libc::c_int { + // SAFETY: We are guaranteed these fields: + let dlpi_addr = unsafe { (*info).dlpi_addr }; + let dlpi_name = unsafe { (*info).dlpi_name }; + let dlpi_phdr = unsafe { (*info).dlpi_phdr }; + let dlpi_phnum = unsafe { (*info).dlpi_phnum }; + // SAFETY: We assured this. + let CallbackData { libs, maps } = unsafe { &mut *data.cast::() }; + // most implementations give us the main program first + let is_main = libs.is_empty(); + // we may be statically linked, which means we are main and mostly one big blob of code + let is_static = dlpi_addr == 0; + // sometimes we get a null or 0-len CStr, based on libc's whims, but these mean the same thing + let no_given_name = dlpi_name.is_null() + // SAFETY: we just checked for null + || unsafe { *dlpi_name == 0 }; + let name = if is_static { + // don't try to look up our name from /proc/self/maps, it'll get silly + env::current_exe().unwrap_or_default().into_os_string() + } else if is_main && no_given_name { + infer_current_exe(&maps, dlpi_addr as usize) + } else { + // this fallback works even if we are main, because some platforms give the name anyways + if dlpi_name.is_null() { + OsString::new() + } else { + // SAFETY: we just checked for nullness + OsStr::from_bytes(unsafe { CStr::from_ptr(dlpi_name) }.to_bytes()).to_owned() + } + }; + #[cfg(target_os = "android")] + let zip_offset: Option = { + // only check for ZIP-embedded file if we have data from /proc/self/maps + maps.as_ref().and_then(|maps| { + // check if file is embedded within a ZIP archive by searching for `!/` + super::extract_zip_path_android(&name).and_then(|_| { + // find MapsEntry matching library's base address and get its file offset + maps.iter() + .find(|m| m.ip_matches(dlpi_addr as usize)) + .map(|m| m.offset()) + }) + }) + }; + let headers = if dlpi_phdr.is_null() || dlpi_phnum == 0 { + &[] + } else { + // SAFETY: We just checked for nullness or 0-len slices + unsafe { slice::from_raw_parts(dlpi_phdr, dlpi_phnum as usize) } + }; + libs.push(Library { + name, + #[cfg(target_os = "android")] + zip_offset, + segments: headers + .iter() + .map(|header| LibrarySegment { + len: header.p_memsz as usize, + stated_virtual_memory_address: header.p_vaddr as usize, + }) + .collect(), + bias: dlpi_addr as usize, + }); + 0 +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs new file mode 100644 index 0000000000..ddfd6b4753 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs @@ -0,0 +1,50 @@ +// Haiku implements the image_info struct and the get_next_image_info() +// functions to iterate through the loaded executable images. The +// image_info struct contains a pointer to the start of the .text +// section within the virtual address space, as well as the size of +// that section. All the read-only segments of the ELF-binary are in +// that part of the address space. + +use super::mystd::ffi::OsStr; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment}; +use alloc::borrow::ToOwned; +use alloc::vec::Vec; +use core::ffi::CStr; +use core::mem::MaybeUninit; + +pub(super) fn native_libraries() -> Vec { + let mut libraries: Vec = Vec::new(); + + unsafe { + let mut info = MaybeUninit::::zeroed(); + let mut cookie: i32 = 0; + // Load the first image to get a valid info struct + let mut status = + libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, info.as_mut_ptr()); + if status != libc::B_OK { + return libraries; + } + let mut info = info.assume_init(); + + while status == libc::B_OK { + let mut segments = Vec::new(); + segments.push(LibrarySegment { + stated_virtual_memory_address: 0, + len: info.text_size as usize, + }); + + let bytes = CStr::from_ptr(info.name.as_ptr()).to_bytes(); + let name = OsStr::from_bytes(bytes).to_owned(); + libraries.push(Library { + name: name, + segments: segments, + bias: info.text as usize, + }); + + status = libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, &mut info); + } + } + + libraries +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs new file mode 100644 index 0000000000..025eb250fd --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs @@ -0,0 +1,101 @@ +use super::mystd::ffi::OsStr; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment}; +use alloc::borrow::ToOwned; +use alloc::vec::Vec; +use core::ffi::CStr; +use core::mem; +use object::NativeEndian; + +#[cfg(target_pointer_width = "64")] +use object::elf::{FileHeader64 as FileHeader, ProgramHeader64 as ProgramHeader}; + +type EHdr = FileHeader; +type PHdr = ProgramHeader; + +#[repr(C)] +struct LinkMap { + l_addr: libc::c_ulong, + l_name: *const libc::c_char, + l_ld: *const libc::c_void, + l_next: *const LinkMap, + l_prev: *const LinkMap, + l_refname: *const libc::c_char, +} + +const RTLD_SELF: *const libc::c_void = -3isize as *const libc::c_void; +const RTLD_DI_LINKMAP: libc::c_int = 2; + +unsafe extern "C" { + fn dlinfo( + handle: *const libc::c_void, + request: libc::c_int, + p: *mut libc::c_void, + ) -> libc::c_int; +} + +pub(super) fn native_libraries() -> Vec { + let mut libs = Vec::new(); + + // Request the current link map from the runtime linker: + let map = unsafe { + let mut map: *const LinkMap = mem::zeroed(); + if dlinfo( + RTLD_SELF, + RTLD_DI_LINKMAP, + core::ptr::addr_of_mut!(map).cast::(), + ) != 0 + { + return libs; + } + map + }; + + // Each entry in the link map represents a loaded object: + let mut l = map; + while !l.is_null() { + // Fetch the fully qualified path of the loaded object: + let bytes = unsafe { CStr::from_ptr((*l).l_name) }.to_bytes(); + let name = OsStr::from_bytes(bytes).to_owned(); + + // The base address of the object loaded into memory: + let addr = unsafe { (*l).l_addr }; + + // Use the ELF header for this object to locate the program + // header: + let e: *const EHdr = unsafe { (*l).l_addr as *const EHdr }; + let phoff = unsafe { (*e).e_phoff }.get(NativeEndian); + let phnum = unsafe { (*e).e_phnum }.get(NativeEndian); + let etype = unsafe { (*e).e_type }.get(NativeEndian); + + let phdr: *const PHdr = (addr + phoff) as *const PHdr; + let phdr = unsafe { core::slice::from_raw_parts(phdr, phnum as usize) }; + + libs.push(Library { + name, + segments: phdr + .iter() + .map(|p| { + let memsz = p.p_memsz.get(NativeEndian); + let vaddr = p.p_vaddr.get(NativeEndian); + LibrarySegment { + len: memsz as usize, + stated_virtual_memory_address: vaddr as usize, + } + }) + .collect(), + bias: if etype == object::elf::ET_EXEC { + // Program header addresses for the base executable are + // already absolute. + 0 + } else { + // Other addresses are relative to the object base. + addr as usize + }, + }); + + l = unsafe { (*l).l_next }; + } + + libs +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs new file mode 100644 index 0000000000..7f2807804e --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs @@ -0,0 +1,28 @@ +use super::{Library, LibrarySegment}; +use alloc::vec::Vec; + +// DevkitA64 doesn't natively support debug info, but the build system will +// place debug info at the path `romfs:/debug_info.elf`. +pub(super) fn native_libraries() -> Vec { + unsafe extern "C" { + static __start__: u8; + } + + let bias = core::ptr::addr_of!(__start__) as usize; + + let mut ret = Vec::new(); + let mut segments = Vec::new(); + segments.push(LibrarySegment { + stated_virtual_memory_address: 0, + len: usize::max_value() - bias, + }); + + let path = "romfs:/debug_info.elf"; + ret.push(Library { + name: path.into(), + segments, + bias, + }); + + ret +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_macos.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_macos.rs new file mode 100644 index 0000000000..f65811b2b8 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_macos.rs @@ -0,0 +1,154 @@ +#![allow(deprecated)] + +use super::mystd::ffi::OsStr; +use super::mystd::os::unix::prelude::*; +use super::mystd::prelude::v1::*; +use super::{Library, LibrarySegment}; +use core::convert::TryInto; +use core::ffi::CStr; +use core::mem; + +// FIXME: replace with ptr::from_ref once MSRV is high enough +#[inline(always)] +#[must_use] +const fn ptr_from_ref(r: &T) -> *const T { + r +} + +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + let images = unsafe { libc::_dyld_image_count() }; + for i in 0..images { + ret.extend(native_library(i)); + } + return ret; +} + +fn native_library(i: u32) -> Option { + use object::macho; + use object::read::macho::{MachHeader, Segment}; + use object::NativeEndian; + + // Fetch the name of this library which corresponds to the path of + // where to load it as well. + let name = unsafe { + let name = libc::_dyld_get_image_name(i); + if name.is_null() { + return None; + } + CStr::from_ptr(name) + }; + + // Load the image header of this library and delegate to `object` to + // parse all the load commands so we can figure out all the segments + // involved here. + let (mut load_commands, endian) = unsafe { + let header = libc::_dyld_get_image_header(i); + if header.is_null() { + return None; + } + match (*header).magic { + macho::MH_MAGIC => { + let endian = NativeEndian; + let header = &*header.cast::>(); + let data = core::slice::from_raw_parts( + ptr_from_ref(header).cast::(), + mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, + ); + (header.load_commands(endian, data, 0).ok()?, endian) + } + macho::MH_MAGIC_64 => { + let endian = NativeEndian; + let header = &*header.cast::>(); + let data = core::slice::from_raw_parts( + ptr_from_ref(header).cast::(), + mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, + ); + (header.load_commands(endian, data, 0).ok()?, endian) + } + _ => return None, + } + }; + + // Iterate over the segments and register known regions for segments + // that we find. Additionally record information bout text segments + // for processing later, see comments below. + let mut segments = Vec::new(); + let mut first_text = 0; + let mut text_fileoff_zero = false; + while let Some(cmd) = load_commands.next().ok()? { + if let Some((seg, _)) = cmd.segment_32().ok()? { + if seg.name() == b"__TEXT" { + first_text = segments.len(); + if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { + text_fileoff_zero = true; + } + } + segments.push(LibrarySegment { + len: seg.vmsize(endian).try_into().ok()?, + stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, + }); + } + if let Some((seg, _)) = cmd.segment_64().ok()? { + if seg.name() == b"__TEXT" { + first_text = segments.len(); + if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { + text_fileoff_zero = true; + } + } + segments.push(LibrarySegment { + len: seg.vmsize(endian).try_into().ok()?, + stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, + }); + } + } + + // Determine the "slide" for this library which ends up being the + // bias we use to figure out where in memory objects are loaded. + // This is a bit of a weird computation though and is the result of + // trying a few things in the wild and seeing what sticks. + // + // The general idea is that the `bias` plus a segment's + // `stated_virtual_memory_address` is going to be where in the + // actual address space the segment resides. The other thing we rely + // on though is that a real address minus the `bias` is the index to + // look up in the symbol table and debuginfo. + // + // It turns out, though, that for system loaded libraries these + // calculations are incorrect. For native executables, however, it + // appears correct. Lifting some logic from LLDB's source it has + // some special-casing for the first `__TEXT` section loaded from + // file offset 0 with a nonzero size. For whatever reason when this + // is present it appears to mean that the symbol table is relative + // to just the vmaddr slide for the library. If it's *not* present + // then the symbol table is relative to the vmaddr slide plus the + // segment's stated address. + // + // To handle this situation if we *don't* find a text section at + // file offset zero then we increase the bias by the first text + // sections's stated address and decrease all stated addresses by + // that amount as well. That way the symbol table is always appears + // relative to the library's bias amount. This appears to have the + // right results for symbolizing via the symbol table. + // + // Honestly I'm not entirely sure whether this is right or if + // there's something else that should indicate how to do this. For + // now though this seems to work well enough (?) and we should + // always be able to tweak this over time if necessary. + // + // For some more information see #318 + let mut slide = unsafe { libc::_dyld_get_image_vmaddr_slide(i) as usize }; + if !text_fileoff_zero { + let adjust = segments[first_text].stated_virtual_memory_address; + for segment in segments.iter_mut() { + segment.stated_virtual_memory_address -= adjust; + } + slide += adjust; + } + + Some(Library { + name: OsStr::from_bytes(name.to_bytes()).to_owned(), + segments, + bias: slide, + }) +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_windows.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_windows.rs new file mode 100644 index 0000000000..1d9a74ccd2 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/libs_windows.rs @@ -0,0 +1,158 @@ +use super::super::super::windows_sys::*; +use super::mystd::ffi::OsString; +use super::{coff, mmap, Library, LibrarySegment}; +use alloc::vec; +use alloc::vec::Vec; +use core::mem; +use core::mem::MaybeUninit; + +// For loading native libraries on Windows, see some discussion on +// rust-lang/rust#71060 for the various strategies here. +pub(super) fn native_libraries() -> Vec { + let mut ret = Vec::new(); + unsafe { + add_loaded_images(&mut ret); + } + return ret; +} + +unsafe fn add_loaded_images(ret: &mut Vec) { + unsafe { + let snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); + if snap == INVALID_HANDLE_VALUE { + return; + } + + // huge struct, probably should avoid manually initializing it even if we can + let mut me = MaybeUninit::::zeroed().assume_init(); + me.dwSize = mem::size_of_val(&me) as u32; + if Module32FirstW(snap, &mut me) == TRUE { + loop { + if let Some(lib) = load_library(&me) { + ret.push(lib); + } + + if Module32NextW(snap, &mut me) != TRUE { + break; + } + } + } + + CloseHandle(snap); + } +} + +// Safety: long_path should be null-terminated +#[cfg(target_os = "cygwin")] +unsafe fn get_posix_path(long_path: &[u16]) -> Option { + use super::mystd::os::unix::ffi::OsStringExt; + + unsafe extern "C" { + // Doc: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html + // Src: https://github.com/cygwin/cygwin/blob/718a15ba50e0d01c79800bd658c2477f9a603540/winsup/cygwin/path.cc#L3902 + // Safety: + // * `what` should be `CCP_WIN_W_TO_POSIX` here + // * `from` is null-terminated UTF-16 path + // * `to` is buffer, the buffer size is `size`. + fn cygwin_conv_path( + what: libc::c_uint, + from: *const u16, + to: *mut u8, + size: libc::size_t, + ) -> libc::ssize_t; + } + const CCP_WIN_W_TO_POSIX: libc::c_uint = 3; + + // If `size` is 0, returns needed buffer size, including null terminator; + // or -1 if error. + // Safety: if `size` is 0, `to` is not used. + let name_len = unsafe { + cygwin_conv_path( + CCP_WIN_W_TO_POSIX, + long_path.as_ptr(), + core::ptr::null_mut(), + 0, + ) + }; + // Expect at least 1 for null terminator. + // It's not likely to return error here. + if name_len < 1 { + return None; + } + let name_len = name_len as usize; + let mut name_buffer = Vec::with_capacity(name_len); + // Safety: `name_buffer` is large enough. + let res = unsafe { + cygwin_conv_path( + CCP_WIN_W_TO_POSIX, + long_path.as_ptr(), + name_buffer.as_mut_ptr(), + name_len, + ) + }; + // It's not likely to return error here. + if res != 0 { + return None; + } + // Remove the null terminator. + unsafe { name_buffer.set_len(name_len - 1) }; + let name = OsString::from_vec(name_buffer); + Some(name) +} + +unsafe fn load_library(me: &MODULEENTRY32W) -> Option { + #[cfg(windows)] + let name = { + use super::mystd::os::windows::prelude::*; + let pos = me + .szExePath + .iter() + .position(|i| *i == 0) + .unwrap_or(me.szExePath.len()); + OsString::from_wide(&me.szExePath[..pos]) + }; + #[cfg(target_os = "cygwin")] + // Safety: the path with max length MAX_PATH always contains a null + // terminator. Don't slice it. + let name = unsafe { get_posix_path(&me.szExePath[..])? }; + + // MinGW libraries currently don't support ASLR + // (rust-lang/rust#16514), but DLLs can still be relocated around in + // the address space. It appears that addresses in debug info are + // all as-if this library was loaded at its "image base", which is a + // field in its COFF file headers. Since this is what debuginfo + // seems to list we parse the symbol table and store addresses as if + // the library was loaded at "image base" as well. + // + // The library may not be loaded at "image base", however. + // (presumably something else may be loaded there?) This is where + // the `bias` field comes into play, and we need to figure out the + // value of `bias` here. Unfortunately though it's not clear how to + // acquire this from a loaded module. What we do have, however, is + // the actual load address (`modBaseAddr`). + // + // As a bit of a cop-out for now we mmap the file, read the file + // header information, then drop the mmap. This is wasteful because + // we'll probably reopen the mmap later, but this should work well + // enough for now. + // + // Once we have the `image_base` (desired load location) and the + // `base_addr` (actual load location) we can fill in the `bias` + // (difference between the actual and desired) and then the stated + // address of each segment is the `image_base` since that's what the + // file says. + // + // For now it appears that unlike ELF/MachO we can make do with one + // segment per library, using `modBaseSize` as the whole size. + let mmap = mmap(name.as_ref())?; + let image_base = coff::get_image_base(&mmap)?; + let base_addr = me.modBaseAddr as usize; + Some(Library { + name, + bias: base_addr.wrapping_sub(image_base), + segments: vec![LibrarySegment { + stated_virtual_memory_address: image_base, + len: me.modBaseSize as usize, + }], + }) +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/lru.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/lru.rs new file mode 100644 index 0000000000..b7cf5a5b5a --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/lru.rs @@ -0,0 +1,75 @@ +use core::mem::{self, MaybeUninit}; +use core::ptr; + +/// least-recently-used cache with static size +pub(crate) struct Lru { + // SAFETY: len <= initialized values + len: usize, + arr: [MaybeUninit; N], +} + +impl Default for Lru { + fn default() -> Self { + Lru { + len: 0, + arr: [const { MaybeUninit::uninit() }; N], + } + } +} + +impl Lru { + #[inline] + pub fn clear(&mut self) { + let len = self.len; + self.len = 0; + // SAFETY: we can't touch these values again due to setting self.len = 0 + unsafe { ptr::drop_in_place(ptr::addr_of_mut!(self.arr[0..len]) as *mut [T]) } + } + + #[inline] + pub fn iter(&self) -> impl Iterator { + self.arr[0..self.len] + .iter() + // SAFETY: we only iterate initialized values due to our len invariant + .map(|init| unsafe { init.assume_init_ref() }) + } + + #[inline] + pub fn push_front(&mut self, value: T) -> Option<&mut T> { + if N == 0 { + return None; + } else if self.len == N { + self.len = N - 1; + // SAFETY: we maintain len invariant and bail on N == 0 + unsafe { ptr::drop_in_place(self.arr.as_mut_ptr().cast::().add(N - 1)) }; + }; + let len_to_init = self.len + 1; + let mut last = MaybeUninit::new(value); + for elem in self.arr[0..len_to_init].iter_mut() { + // OPT(size): using `mem::swap` allows surprising size regressions + last = mem::replace(elem, last); + } + self.len = len_to_init; + + self.arr + .first_mut() + // SAFETY: we just pushed it + .map(|elem| unsafe { elem.assume_init_mut() }) + } + + #[inline] + pub fn move_to_front(&mut self, idx: usize) -> Option<&mut T> { + let elem = self.arr[0..self.len].get_mut(idx)?; + // SAFETY: we already bailed if the index is bad, so our slicing will be infallible, + // so it is permissible to allow the len invariant to decay, as we always restore it + let mut last = mem::replace(elem, MaybeUninit::uninit()); + for elem in self.arr[0..=idx].iter_mut() { + // OPT(size): using `mem::swap` allows surprising size regressions + last = mem::replace(elem, last); + } + self.arr + .first_mut() + // SAFETY: we have restored the len invariant + .map(|elem| unsafe { elem.assume_init_mut() }) + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/macho.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/macho.rs new file mode 100644 index 0000000000..fcbe609866 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/macho.rs @@ -0,0 +1,318 @@ +use super::mystd::path::Path; +use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash}; +use alloc::boxed::Box; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::TryInto; +use object::macho; +use object::read::macho::{MachHeader, Nlist, Section, Segment as _}; +use object::{Bytes, NativeEndian}; + +#[cfg(target_pointer_width = "32")] +type Mach = object::macho::MachHeader32; +#[cfg(target_pointer_width = "64")] +type Mach = object::macho::MachHeader64; +type MachSegment = ::Segment; +type MachSection = ::Section; +type MachNlist = ::Nlist; + +impl Mapping { + // The loading path for macOS is so different we just have a completely + // different implementation of the function here. On macOS we need to go + // probing the filesystem for a bunch of files. + pub fn new(path: &Path) -> Option { + // First up we need to load the unique UUID which is stored in the macho + // header of the file we're reading, specified at `path`. + let map = super::mmap(path)?; + let (macho, data) = find_header(&map)?; + let endian = macho.endian().ok()?; + let uuid = macho.uuid(endian, data, 0).ok()?; + + // Next we need to look for a `*.dSYM` file. For now we just probe the + // containing directory and look around for something that matches + // `*.dSYM`. Once it's found we root through the dwarf resources that it + // contains and try to find a macho file which has a matching UUID as + // the one of our own file. If we find a match that's the dwarf file we + // want to return. + if let Some(uuid) = uuid { + if let Some(parent) = path.parent() { + if let Some(mapping) = Mapping::load_dsym(parent, uuid) { + return Some(mapping); + } + } + } + + // Looks like nothing matched our UUID, so let's at least return our own + // file. This should have the symbol table for at least some + // symbolication purposes. + Mapping::mk(map, |data, stash| { + let (macho, data) = find_header(data)?; + let endian = macho.endian().ok()?; + let obj = Object::parse(macho, endian, data)?; + Context::new(stash, obj, None, None) + }) + } + + fn load_dsym(dir: &Path, uuid: [u8; 16]) -> Option { + for entry in dir.read_dir().ok()? { + let entry = entry.ok()?; + let filename = match entry.file_name().into_string() { + Ok(name) => name, + Err(_) => continue, + }; + if !filename.ends_with(".dSYM") { + continue; + } + let candidates = entry.path().join("Contents/Resources/DWARF"); + if let Some(mapping) = Mapping::try_dsym_candidate(&candidates, uuid) { + return Some(mapping); + } + } + None + } + + fn try_dsym_candidate(dir: &Path, uuid: [u8; 16]) -> Option { + // Look for files in the `DWARF` directory which have a matching uuid to + // the original object file. If we find one then we found the debug + // information. + for entry in dir.read_dir().ok()? { + let entry = entry.ok()?; + let map = super::mmap(&entry.path())?; + let candidate = Mapping::mk(map, |data, stash| { + let (macho, data) = find_header(data)?; + let endian = macho.endian().ok()?; + let entry_uuid = macho.uuid(endian, data, 0).ok()??; + if entry_uuid != uuid { + return None; + } + let obj = Object::parse(macho, endian, data)?; + Context::new(stash, obj, None, None) + }); + if let Some(candidate) = candidate { + return Some(candidate); + } + } + + None + } +} + +fn find_header(data: &'_ [u8]) -> Option<(&'_ Mach, &'_ [u8])> { + use object::endian::BigEndian; + + let desired_cpu = || { + if cfg!(target_arch = "x86") { + Some(macho::CPU_TYPE_X86) + } else if cfg!(target_arch = "x86_64") { + Some(macho::CPU_TYPE_X86_64) + } else if cfg!(target_arch = "arm") { + Some(macho::CPU_TYPE_ARM) + } else if cfg!(target_arch = "aarch64") { + Some(macho::CPU_TYPE_ARM64) + } else { + None + } + }; + + let mut data = Bytes(data); + match data + .clone() + .read::>() + .ok()? + .get(NativeEndian) + { + macho::MH_MAGIC_64 | macho::MH_CIGAM_64 | macho::MH_MAGIC | macho::MH_CIGAM => {} + + macho::FAT_MAGIC | macho::FAT_CIGAM => { + let mut header_data = data; + let endian = BigEndian; + let header = header_data.read::().ok()?; + let nfat = header.nfat_arch.get(endian); + let arch = (0..nfat) + .filter_map(|_| header_data.read::().ok()) + .find(|arch| desired_cpu() == Some(arch.cputype.get(endian)))?; + let offset = arch.offset.get(endian); + let size = arch.size.get(endian); + data = data + .read_bytes_at(offset.try_into().ok()?, size.try_into().ok()?) + .ok()?; + } + + macho::FAT_MAGIC_64 | macho::FAT_CIGAM_64 => { + let mut header_data = data; + let endian = BigEndian; + let header = header_data.read::().ok()?; + let nfat = header.nfat_arch.get(endian); + let arch = (0..nfat) + .filter_map(|_| header_data.read::().ok()) + .find(|arch| desired_cpu() == Some(arch.cputype.get(endian)))?; + let offset = arch.offset.get(endian); + let size = arch.size.get(endian); + data = data + .read_bytes_at(offset.try_into().ok()?, size.try_into().ok()?) + .ok()?; + } + + _ => return None, + } + + Mach::parse(data.0, 0).ok().map(|h| (h, data.0)) +} + +// This is used both for executables/libraries and source object files. +pub struct Object<'a> { + endian: NativeEndian, + data: &'a [u8], + dwarf: Option<&'a [MachSection]>, + syms: Vec<(&'a [u8], u64)>, + syms_sort_by_name: bool, + // Only set for executables/libraries, and not the source object files. + object_map: Option>, + // The outer Option is for lazy loading, and the inner Option allows load errors to be cached. + object_mappings: Box<[Option>]>, +} + +impl<'a> Object<'a> { + fn parse(mach: &'a Mach, endian: NativeEndian, data: &'a [u8]) -> Option> { + let is_object = mach.filetype(endian) == object::macho::MH_OBJECT; + let mut dwarf = None; + let mut syms = Vec::new(); + let mut syms_sort_by_name = false; + let mut commands = mach.load_commands(endian, data, 0).ok()?; + let mut object_map = None; + let mut object_mappings = Vec::new(); + while let Ok(Some(command)) = commands.next() { + if let Some((segment, section_data)) = MachSegment::from_command(command).ok()? { + // Object files should have all sections in a single unnamed segment load command. + if segment.name() == b"__DWARF" || (is_object && segment.name() == b"") { + dwarf = segment.sections(endian, section_data).ok(); + } + } else if let Some(symtab) = command.symtab().ok()? { + let symbols = symtab.symbols::(endian, data).ok()?; + syms = symbols + .iter() + .filter_map(|nlist: &MachNlist| { + let name = nlist.name(endian, symbols.strings()).ok()?; + if name.len() > 0 && nlist.is_definition() { + Some((name, u64::from(nlist.n_value(endian)))) + } else { + None + } + }) + .collect(); + if is_object { + // We never search object file symbols by address. + // Instead, we already know the symbol name from the executable, and we + // need to search by name to find the matching symbol in the object file. + syms.sort_unstable_by_key(|(name, _)| *name); + syms_sort_by_name = true; + } else { + syms.sort_unstable_by_key(|(_, addr)| *addr); + let map = symbols.object_map(endian); + object_mappings.resize_with(map.objects().len(), || None); + object_map = Some(map); + } + } + } + + Some(Object { + endian, + data, + dwarf, + syms, + syms_sort_by_name, + object_map, + object_mappings: object_mappings.into_boxed_slice(), + }) + } + + pub fn section(&self, _: &Stash, name: &str) -> Option<&'a [u8]> { + let name = name.as_bytes(); + let dwarf = self.dwarf?; + let section = dwarf.into_iter().find(|section| { + let section_name = section.name(); + section_name == name || { + section_name.starts_with(b"__") + && name.starts_with(b".") + && §ion_name[2..] == &name[1..] + } + })?; + Some(section.data(self.endian, self.data).ok()?) + } + + pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> { + debug_assert!(!self.syms_sort_by_name); + let i = match self.syms.binary_search_by_key(&addr, |(_, addr)| *addr) { + Ok(i) => i, + Err(i) => i.checked_sub(1)?, + }; + let (sym, _addr) = self.syms.get(i)?; + Some(sym) + } + + /// Try to load a context for an object file. + /// + /// If dsymutil was not run, then the DWARF may be found in the source object files. + pub(super) fn search_object_map<'b>(&'b mut self, addr: u64) -> Option<(&'b Context<'b>, u64)> { + // `object_map` contains a map from addresses to symbols and object paths. + // Look up the address and get a mapping for the object. + let object_map = self.object_map.as_ref()?; + let symbol = object_map.get(addr)?; + let object_index = symbol.object_index(); + let mapping = self.object_mappings.get_mut(object_index)?; + if mapping.is_none() { + // No cached mapping, so create it. + *mapping = Some(object_mapping(object_map.objects().get(object_index)?)); + } + let cx: &'b Context<'static> = &mapping.as_ref()?.as_ref()?.cx; + // Don't leak the `'static` lifetime, make sure it's scoped to just ourselves. + let cx = unsafe { core::mem::transmute::<&'b Context<'static>, &'b Context<'b>>(cx) }; + + // We must translate the address in order to be able to look it up + // in the DWARF in the object file. + debug_assert!(cx.object.syms.is_empty() || cx.object.syms_sort_by_name); + let i = cx + .object + .syms + .binary_search_by_key(&symbol.name(), |(name, _)| *name) + .ok()?; + let object_symbol = cx.object.syms.get(i)?; + let object_addr = addr + .wrapping_sub(symbol.address()) + .wrapping_add(object_symbol.1); + Some((cx, object_addr)) + } +} + +fn object_mapping(file: &object::read::ObjectMapFile<'_>) -> Option { + use super::mystd::ffi::OsStr; + use super::mystd::os::unix::prelude::*; + + let map = super::mmap(Path::new(OsStr::from_bytes(file.path())))?; + let member_name = file.member(); + Mapping::mk(map, |data, stash| { + let data = match member_name { + Some(member_name) => { + let archive = object::read::archive::ArchiveFile::parse(data).ok()?; + let member = archive + .members() + .filter_map(Result::ok) + .find(|m| m.name() == member_name)?; + member.data(data).ok()? + } + None => data, + }; + let (macho, data) = find_header(data)?; + let endian = macho.endian().ok()?; + let obj = Object::parse(macho, endian, data)?; + Context::new(stash, obj, None, None) + }) +} + +pub(super) fn handle_split_dwarf<'data>( + _package: Option<&gimli::DwarfPackage>>, + _stash: &'data Stash, + _load: addr2line::SplitDwarfLoad>, +) -> Option>>> { + None +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs new file mode 100644 index 0000000000..71697fc30c --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs @@ -0,0 +1,27 @@ +use super::mystd::io::{Read, Seek, SeekFrom}; +use super::File; +use alloc::vec::Vec; +use core::ops::Deref; + +pub struct Mmap { + vec: Vec, +} + +impl Mmap { + pub unsafe fn map(mut file: &File, len: usize, offset: u64) -> Option { + let mut mmap = Mmap { + vec: Vec::with_capacity(len), + }; + file.seek(SeekFrom::Start(offset)); + file.read_to_end(&mut mmap.vec).ok()?; + Some(mmap) + } +} + +impl Deref for Mmap { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.vec[..] + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs new file mode 100644 index 0000000000..24ebeb3c79 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs @@ -0,0 +1,51 @@ +use super::mystd::fs::File; +use super::mystd::os::unix::prelude::*; +use core::ops::Deref; +use core::ptr; +use core::slice; + +#[cfg(not(all(target_os = "linux", target_env = "gnu")))] +use libc::mmap as mmap64; +#[cfg(all(target_os = "linux", target_env = "gnu"))] +use libc::mmap64; + +pub struct Mmap { + ptr: *mut libc::c_void, + len: usize, +} + +impl Mmap { + pub unsafe fn map(file: &File, len: usize, offset: u64) -> Option { + let ptr = unsafe { + mmap64( + ptr::null_mut(), + len, + libc::PROT_READ, + libc::MAP_PRIVATE, + file.as_raw_fd(), + offset.try_into().ok()?, + ) + }; + if ptr == libc::MAP_FAILED { + return None; + } + Some(Mmap { ptr, len }) + } +} + +impl Deref for Mmap { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) } + } +} + +impl Drop for Mmap { + fn drop(&mut self) { + unsafe { + let r = libc::munmap(self.ptr, self.len); + debug_assert_eq!(r, 0); + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs new file mode 100644 index 0000000000..d3c02723e1 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs @@ -0,0 +1,67 @@ +use super::super::super::windows_sys::*; + +use super::mystd::fs::File; +use super::mystd::os::windows::prelude::*; +use core::ffi::c_void; +use core::ops::Deref; +use core::ptr; +use core::slice; + +pub struct Mmap { + // keep the file alive to prevent it from being deleted which would cause + // us to read bad data. + _file: File, + ptr: *mut c_void, + len: usize, +} + +impl Mmap { + pub unsafe fn map(file: &File, len: usize, offset: u64) -> Option { + unsafe { + let file = file.try_clone().ok()?; + let mapping = CreateFileMappingA( + file.as_raw_handle(), + ptr::null_mut(), + PAGE_READONLY, + 0, + 0, + ptr::null(), + ); + if mapping.is_null() { + return None; + } + let ptr = MapViewOfFile( + mapping, + FILE_MAP_READ, + (offset >> 32) as u32, + offset as u32, + len, + ); + CloseHandle(mapping); + if ptr.Value.is_null() { + return None; + } + Some(Mmap { + _file: file, + ptr: ptr.Value, + len, + }) + } + } +} +impl Deref for Mmap { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.ptr.cast_const().cast::(), self.len) } + } +} + +impl Drop for Mmap { + fn drop(&mut self) { + unsafe { + let r = UnmapViewOfFile(MEMORY_MAPPED_VIEW_ADDRESS { Value: self.ptr }); + debug_assert!(r != 0); + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs new file mode 100644 index 0000000000..5803d5dcab --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs @@ -0,0 +1,304 @@ +// Note: This file is only currently used on targets that call out to the code +// in `mod libs_dl_iterate_phdr` (e.g. linux, freebsd, ...); it may be more +// general purpose, but it hasn't been tested elsewhere. + +use super::mystd::ffi::OsString; +use super::mystd::fs::File; +use super::mystd::io::Read; +use alloc::string::String; +use alloc::vec::Vec; +use core::str::FromStr; + +#[derive(PartialEq, Eq, Debug)] +pub(super) struct MapsEntry { + /// start (inclusive) and limit (exclusive) of address range. + address: (usize, usize), + /// The perms field are the permissions for the entry + /// + /// r = read + /// w = write + /// x = execute + /// s = shared + /// p = private (copy on write) + perms: [char; 4], + /// Offset into the file (or "whatever"). + offset: u64, + /// device (major, minor) + dev: (usize, usize), + /// inode on the device. 0 indicates that no inode is associated with the memory region (e.g. uninitalized data aka BSS). + inode: usize, + /// Usually the file backing the mapping. + /// + /// Note: The man page for proc includes a note about "coordination" by + /// using readelf to see the Offset field in ELF program headers. pnkfelix + /// is not yet sure if that is intended to be a comment on pathname, or what + /// form/purpose such coordination is meant to have. + /// + /// There are also some pseudo-paths: + /// "[stack]": The initial process's (aka main thread's) stack. + /// "[stack:]": a specific thread's stack. (This was only present for a limited range of Linux verisons; it was determined to be too expensive to provide.) + /// "[vdso]": Virtual dynamically linked shared object + /// "[heap]": The process's heap + /// + /// The pathname can be blank, which means it is an anonymous mapping + /// obtained via mmap. + /// + /// Newlines in pathname are replaced with an octal escape sequence. + /// + /// The pathname may have "(deleted)" appended onto it if the file-backed + /// path has been deleted. + /// + /// Note that modifications like the latter two indicated above imply that + /// in general the pathname may be ambiguous. (I.e. you cannot tell if the + /// denoted filename actually ended with the text "(deleted)", or if that + /// was added by the maps rendering. + pathname: OsString, +} + +pub(super) fn parse_maps() -> Result, &'static str> { + let mut v = Vec::new(); + let mut proc_self_maps = + File::open("/proc/self/maps").map_err(|_| "Couldn't open /proc/self/maps")?; + let mut buf = String::new(); + let _bytes_read = proc_self_maps + .read_to_string(&mut buf) + .map_err(|_| "Couldn't read /proc/self/maps")?; + for line in buf.lines() { + v.push(line.parse()?); + } + + Ok(v) +} + +impl MapsEntry { + pub(super) fn pathname(&self) -> &OsString { + &self.pathname + } + + pub(super) fn ip_matches(&self, ip: usize) -> bool { + self.address.0 <= ip && ip < self.address.1 + } + + #[cfg(target_os = "android")] + pub(super) fn offset(&self) -> u64 { + self.offset + } +} + +impl FromStr for MapsEntry { + type Err = &'static str; + + // Format: address perms offset dev inode pathname + // e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]" + // e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" + // e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0" + // + // Note that paths may contain spaces, so we can't use `str::split` for parsing (until + // Split::remainder is stabilized #77998). + fn from_str(s: &str) -> Result { + let (range_str, s) = s.trim_start().split_once(' ').unwrap_or((s, "")); + if range_str.is_empty() { + return Err("Couldn't find address"); + } + + let (perms_str, s) = s.trim_start().split_once(' ').unwrap_or((s, "")); + if perms_str.is_empty() { + return Err("Couldn't find permissions"); + } + + let (offset_str, s) = s.trim_start().split_once(' ').unwrap_or((s, "")); + if offset_str.is_empty() { + return Err("Couldn't find offset"); + } + + let (dev_str, s) = s.trim_start().split_once(' ').unwrap_or((s, "")); + if dev_str.is_empty() { + return Err("Couldn't find dev"); + } + + let (inode_str, s) = s.trim_start().split_once(' ').unwrap_or((s, "")); + if inode_str.is_empty() { + return Err("Couldn't find inode"); + } + + // Pathname may be omitted in which case it will be empty + let pathname_str = s.trim_start(); + + let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number"); + let hex64 = |s| u64::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number"); + + let address = if let Some((start, limit)) = range_str.split_once('-') { + (hex(start)?, hex(limit)?) + } else { + return Err("Couldn't parse address range"); + }; + let perms: [char; 4] = { + let mut chars = perms_str.chars(); + let mut c = || chars.next().ok_or("insufficient perms"); + let perms = [c()?, c()?, c()?, c()?]; + if chars.next().is_some() { + return Err("too many perms"); + } + perms + }; + let offset = hex64(offset_str)?; + let dev = if let Some((major, minor)) = dev_str.split_once(':') { + (hex(major)?, hex(minor)?) + } else { + return Err("Couldn't parse dev"); + }; + let inode = hex(inode_str)?; + let pathname = pathname_str.into(); + + Ok(MapsEntry { + address, + perms, + offset, + dev, + inode, + pathname, + }) + } +} + +// Make sure we can parse 64-bit sample output if we're on a 64-bit target. +#[cfg(target_pointer_width = "64")] +#[test] +fn check_maps_entry_parsing_64bit() { + assert_eq!( + "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \ + [vsyscall]" + .parse::() + .unwrap(), + MapsEntry { + address: (0xffffffffff600000, 0xffffffffff601000), + perms: ['-', '-', 'x', 'p'], + offset: 0x00000000, + dev: (0x00, 0x00), + inode: 0x0, + pathname: "[vsyscall]".into(), + } + ); + + assert_eq!( + "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \ + /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2" + .parse::() + .unwrap(), + MapsEntry { + address: (0x7f5985f46000, 0x7f5985f48000), + perms: ['r', 'w', '-', 'p'], + offset: 0x00039000, + dev: (0x103, 0x06), + inode: 0x76021795, + pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2".into(), + } + ); + assert_eq!( + "35b1a21000-35b1a22000 rw-p 00000000 00:00 0" + .parse::() + .unwrap(), + MapsEntry { + address: (0x35b1a21000, 0x35b1a22000), + perms: ['r', 'w', '-', 'p'], + offset: 0x00000000, + dev: (0x00, 0x00), + inode: 0x0, + pathname: Default::default(), + } + ); +} + +// (This output was taken from a 32-bit machine, but will work on any target) +#[test] +fn check_maps_entry_parsing_32bit() { + /* Example snippet of output: + 08056000-08077000 rw-p 00000000 00:00 0 [heap] + b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive + b7e02000-b7e03000 rw-p 00000000 00:00 0 + */ + assert_eq!( + "08056000-08077000 rw-p 00000000 00:00 0 \ + [heap]" + .parse::() + .unwrap(), + MapsEntry { + address: (0x08056000, 0x08077000), + perms: ['r', 'w', '-', 'p'], + offset: 0x00000000, + dev: (0x00, 0x00), + inode: 0x0, + pathname: "[heap]".into(), + } + ); + + assert_eq!( + "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \ + /usr/lib/locale/locale-archive" + .parse::() + .unwrap(), + MapsEntry { + address: (0xb7c79000, 0xb7e02000), + perms: ['r', '-', '-', 'p'], + offset: 0x00000000, + dev: (0x08, 0x01), + inode: 0x60662705, + pathname: "/usr/lib/locale/locale-archive".into(), + } + ); + assert_eq!( + "b7e02000-b7e03000 rw-p 00000000 00:00 0" + .parse::() + .unwrap(), + MapsEntry { + address: (0xb7e02000, 0xb7e03000), + perms: ['r', 'w', '-', 'p'], + offset: 0x00000000, + dev: (0x00, 0x00), + inode: 0x0, + pathname: Default::default(), + } + ); + assert_eq!( + "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \ + /executable/path/with some spaces" + .parse::() + .unwrap(), + MapsEntry { + address: (0xb7c79000, 0xb7e02000), + perms: ['r', '-', '-', 'p'], + offset: 0x00000000, + dev: (0x08, 0x01), + inode: 0x60662705, + pathname: "/executable/path/with some spaces".into(), + } + ); + assert_eq!( + "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \ + /executable/path/with multiple-continuous spaces " + .parse::() + .unwrap(), + MapsEntry { + address: (0xb7c79000, 0xb7e02000), + perms: ['r', '-', '-', 'p'], + offset: 0x00000000, + dev: (0x08, 0x01), + inode: 0x60662705, + pathname: "/executable/path/with multiple-continuous spaces ".into(), + } + ); + assert_eq!( + " b7c79000-b7e02000 r--p 00000000 08:01 60662705 \ + /executable/path/starts-with-spaces" + .parse::() + .unwrap(), + MapsEntry { + address: (0xb7c79000, 0xb7e02000), + perms: ['r', '-', '-', 'p'], + offset: 0x00000000, + dev: (0x08, 0x01), + inode: 0x60662705, + pathname: "/executable/path/starts-with-spaces".into(), + } + ); +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/stash.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/stash.rs new file mode 100644 index 0000000000..5ec06e2403 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/stash.rs @@ -0,0 +1,51 @@ +#![allow(clippy::all)] +// only used on Linux right now, so allow dead code elsewhere +#![cfg_attr(not(target_os = "linux"), allow(dead_code))] + +use super::Mmap; +use alloc::vec; +use alloc::vec::Vec; +use core::cell::UnsafeCell; + +/// A simple arena allocator for byte buffers. +pub struct Stash { + buffers: UnsafeCell>>, + mmaps: UnsafeCell>, +} + +impl Stash { + pub fn new() -> Stash { + Stash { + buffers: UnsafeCell::new(Vec::new()), + mmaps: UnsafeCell::new(Vec::new()), + } + } + + /// Allocates a buffer of the specified size and returns a mutable reference + /// to it. + pub fn allocate(&self, size: usize) -> &mut [u8] { + // SAFETY: this is the only function that ever constructs a mutable + // reference to `self.buffers`. + let buffers = unsafe { &mut *self.buffers.get() }; + let i = buffers.len(); + buffers.push(vec![0; size]); + // SAFETY: we never remove elements from `self.buffers`, so a reference + // to the data inside any buffer will live as long as `self` does. + &mut buffers[i] + } + + /// Stores a `Mmap` for the lifetime of this `Stash`, returning a pointer + /// which is scoped to just this lifetime. + pub fn cache_mmap(&self, map: Mmap) -> &[u8] { + // SAFETY: this is the only location for a mutable pointer to + // `mmaps`, and this structure isn't threadsafe to shared across + // threads either. We also never remove elements from `self.mmaps`, + // so a reference to the data inside the map will live as long as + // `self` does. + unsafe { + let mmaps = &mut *self.mmaps.get(); + mmaps.push(map); + mmaps.last().unwrap() + } + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/gimli/xcoff.rs b/anneal/v2/vendor/backtrace/src/symbolize/gimli/xcoff.rs new file mode 100644 index 0000000000..18c61cbd51 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/gimli/xcoff.rs @@ -0,0 +1,188 @@ +use super::mystd::ffi::OsStr; +use super::mystd::os::unix::ffi::OsStrExt; +use super::mystd::path::Path; +use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash}; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::ops::Deref; +use core::str; +use object::read::archive::ArchiveFile; +use object::read::xcoff::{FileHeader, SectionHeader, XcoffFile, XcoffSymbol}; +use object::Object as _; +use object::ObjectSection as _; +use object::ObjectSymbol as _; +use object::SymbolFlags; + +#[cfg(target_pointer_width = "32")] +type Xcoff = object::xcoff::FileHeader32; +#[cfg(target_pointer_width = "64")] +type Xcoff = object::xcoff::FileHeader64; + +impl Mapping { + pub fn new(path: &Path, member_name: &OsStr) -> Option { + let map = super::mmap(path)?; + Mapping::mk(map, |data, stash| { + if member_name.is_empty() { + Context::new(stash, Object::parse(data)?, None, None) + } else { + let archive = ArchiveFile::parse(data).ok()?; + for member in archive + .members() + .filter_map(|m| m.ok()) + .filter(|m| OsStr::from_bytes(m.name()) == member_name) + { + let member_data = member.data(data).ok()?; + if let Some(obj) = Object::parse(member_data) { + return Context::new(stash, obj, None, None); + } + } + None + } + }) + } +} + +struct ParsedSym<'a> { + address: u64, + size: u64, + name: &'a str, +} + +pub struct Object<'a> { + syms: Vec>, + file: XcoffFile<'a, Xcoff>, +} + +pub struct Image { + pub offset: usize, + pub base: u64, + pub size: usize, +} + +pub fn parse_xcoff(data: &[u8]) -> Option { + let mut offset = 0; + let header = Xcoff::parse(data, &mut offset).ok()?; + let _ = header.aux_header(data, &mut offset).ok()?; + let sections = header.sections(data, &mut offset).ok()?; + if let Some(section) = sections.iter().find(|s| { + if let Ok(name) = str::from_utf8(&s.s_name()[0..5]) { + name == ".text" + } else { + false + } + }) { + Some(Image { + offset: section.s_scnptr() as usize, + base: section.s_paddr() as u64, + size: section.s_size() as usize, + }) + } else { + None + } +} + +pub fn parse_image(path: &Path, member_name: &OsStr) -> Option { + let map = super::mmap(path)?; + let data = map.deref(); + if member_name.is_empty() { + return parse_xcoff(data); + } else { + let archive = ArchiveFile::parse(data).ok()?; + for member in archive + .members() + .filter_map(|m| m.ok()) + .filter(|m| OsStr::from_bytes(m.name()) == member_name) + { + let member_data = member.data(data).ok()?; + if let Some(image) = parse_xcoff(member_data) { + return Some(image); + } + } + None + } +} + +impl<'a> Object<'a> { + fn get_concrete_size(file: &XcoffFile<'a, Xcoff>, sym: &XcoffSymbol<'a, '_, Xcoff>) -> u64 { + match sym.flags() { + SymbolFlags::Xcoff { + n_sclass: _, + x_smtyp: _, + x_smclas: _, + containing_csect: Some(index), + } => { + if let Ok(tgt_sym) = file.symbol_by_index(index) { + Self::get_concrete_size(file, &tgt_sym) + } else { + 0 + } + } + _ => sym.size(), + } + } + + fn parse(data: &'a [u8]) -> Option> { + let file = XcoffFile::parse(data).ok()?; + let mut syms = file + .symbols() + .filter_map(|sym| { + let name = sym.name().map_or("", |v| v); + let address = sym.address(); + let size = Self::get_concrete_size(&file, &sym); + if name == ".text" || name == ".data" { + // We don't want to include ".text" and ".data" symbols. + // If they are included, since their ranges cover other + // symbols, when searching a symbol for a given address, + // ".text" or ".data" is returned. That's not what we expect. + None + } else { + Some(ParsedSym { + address, + size, + name, + }) + } + }) + .collect::>(); + syms.sort_by_key(|s| s.address); + Some(Object { syms, file }) + } + + pub fn section(&self, _: &Stash, name: &str) -> Option<&'a [u8]> { + Some(self.file.section_by_name(name)?.data().ok()?) + } + + pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> { + // Symbols, except ".text" and ".data", are sorted and are not overlapped each other, + // so we can just perform a binary search here. + let i = match self.syms.binary_search_by_key(&addr, |sym| sym.address) { + Ok(i) => i, + Err(i) => i.checked_sub(1)?, + }; + let sym = self.syms.get(i)?; + if (sym.address..sym.address + sym.size).contains(&addr) { + // On AIX, for a function call, for example, `foo()`, we have + // two symbols `foo` and `.foo`. `foo` references the function + // descriptor and `.foo` references the function entry. + // See https://www.ibm.com/docs/en/xl-fortran-aix/16.1.0?topic=calls-linkage-convention-function + // for more information. + // We trim the prefix `.` here, so that the rust demangler can work + // properly. + Some(sym.name.trim_start_matches(".").as_bytes()) + } else { + None + } + } + + pub(super) fn search_object_map(&self, _addr: u64) -> Option<(&Context<'_>, u64)> { + None + } +} + +pub(super) fn handle_split_dwarf<'data>( + _package: Option<&gimli::DwarfPackage>>, + _stash: &'data Stash, + _load: addr2line::SplitDwarfLoad>, +) -> Option>>> { + None +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/miri.rs b/anneal/v2/vendor/backtrace/src/symbolize/miri.rs new file mode 100644 index 0000000000..5b0dc3084b --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/miri.rs @@ -0,0 +1,56 @@ +use core::ffi::c_void; +use core::marker::PhantomData; + +use super::super::backtrace::miri::{resolve_addr, Frame}; +use super::BytesOrWideString; +use super::{ResolveWhat, SymbolName}; + +pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) { + let sym = match what { + ResolveWhat::Address(addr) => Symbol { + inner: resolve_addr(addr), + _unused: PhantomData, + }, + ResolveWhat::Frame(frame) => Symbol { + inner: frame.inner.clone(), + _unused: PhantomData, + }, + }; + cb(&super::Symbol { inner: sym }) +} + +pub struct Symbol<'a> { + inner: Frame, + _unused: PhantomData<&'a ()>, +} + +impl<'a> Symbol<'a> { + pub fn name(&self) -> Option> { + Some(SymbolName::new(&self.inner.inner.name)) + } + + pub fn addr(&self) -> Option<*mut c_void> { + Some(self.inner.addr) + } + + pub fn filename_raw(&self) -> Option> { + Some(BytesOrWideString::Bytes(&self.inner.inner.filename)) + } + + pub fn lineno(&self) -> Option { + Some(self.inner.inner.lineno) + } + + pub fn colno(&self) -> Option { + Some(self.inner.inner.colno) + } + + #[cfg(feature = "std")] + pub fn filename(&self) -> Option<&std::path::Path> { + Some(std::path::Path::new( + core::str::from_utf8(&self.inner.inner.filename).unwrap(), + )) + } +} + +pub unsafe fn clear_symbol_cache() {} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/mod.rs b/anneal/v2/vendor/backtrace/src/symbolize/mod.rs new file mode 100644 index 0000000000..62714f04dc --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/mod.rs @@ -0,0 +1,452 @@ +use core::{fmt, str}; + +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + use std::path::Path; + use std::prelude::v1::*; + } +} + +use super::backtrace::Frame; +use super::types::BytesOrWideString; +use core::ffi::c_void; +use rustc_demangle::{try_demangle, Demangle}; + +/// Resolve an address to a symbol, passing the symbol to the specified +/// closure. +/// +/// This function will look up the given address in areas such as the local +/// symbol table, dynamic symbol table, or DWARF debug info (depending on the +/// activated implementation) to find symbols to yield. +/// +/// The closure may not be called if resolution could not be performed, and it +/// also may be called more than once in the case of inlined functions. +/// +/// Symbols yielded represent the execution at the specified `addr`, returning +/// file/line pairs for that address (if available). +/// +/// Note that if you have a `Frame` then it's recommended to use the +/// `resolve_frame` function instead of this one. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +/// +/// # Panics +/// +/// This function strives to never panic, but if the `cb` provided panics then +/// some platforms will force a double panic to abort the process. Some +/// platforms use a C library which internally uses callbacks which cannot be +/// unwound through, so panicking from `cb` may trigger a process abort. +/// +/// # Example +/// +/// ``` +/// extern crate backtrace; +/// +/// fn main() { +/// backtrace::trace(|frame| { +/// let ip = frame.ip(); +/// +/// backtrace::resolve(ip, |symbol| { +/// // ... +/// }); +/// +/// false // only look at the top frame +/// }); +/// } +/// ``` +#[cfg(feature = "std")] +pub fn resolve(addr: *mut c_void, cb: F) { + let _guard = crate::lock::lock(); + unsafe { resolve_unsynchronized(addr, cb) } +} + +/// Resolve a previously captured frame to a symbol, passing the symbol to the +/// specified closure. +/// +/// This function performs the same function as `resolve` except that it takes a +/// `Frame` as an argument instead of an address. This can allow some platform +/// implementations of backtracing to provide more accurate symbol information +/// or information about inline frames for example. It's recommended to use this +/// if you can. +/// +/// # Required features +/// +/// This function requires the `std` feature of the `backtrace` crate to be +/// enabled, and the `std` feature is enabled by default. +/// +/// # Panics +/// +/// This function strives to never panic, but if the `cb` provided panics then +/// some platforms will force a double panic to abort the process. Some +/// platforms use a C library which internally uses callbacks which cannot be +/// unwound through, so panicking from `cb` may trigger a process abort. +/// +/// # Example +/// +/// ``` +/// extern crate backtrace; +/// +/// fn main() { +/// backtrace::trace(|frame| { +/// backtrace::resolve_frame(frame, |symbol| { +/// // ... +/// }); +/// +/// false // only look at the top frame +/// }); +/// } +/// ``` +#[cfg(feature = "std")] +pub fn resolve_frame(frame: &Frame, cb: F) { + let _guard = crate::lock::lock(); + unsafe { resolve_frame_unsynchronized(frame, cb) } +} + +pub enum ResolveWhat<'a> { + Address(*mut c_void), + Frame(&'a Frame), +} + +impl<'a> ResolveWhat<'a> { + #[allow(dead_code)] + fn address_or_ip(&self) -> *mut c_void { + match self { + ResolveWhat::Address(a) => adjust_ip(*a), + ResolveWhat::Frame(f) => adjust_ip(f.ip()), + } + } +} + +// IP values from stack frames are typically (always?) the instruction +// *after* the call that's the actual stack trace. Symbolizing this on +// causes the filename/line number to be one ahead and perhaps into +// the void if it's near the end of the function. +// +// This appears to basically always be the case on all platforms, so we always +// subtract one from a resolved ip to resolve it to the previous call +// instruction instead of the instruction being returned to. +// +// Ideally we would not do this. Ideally we would require callers of the +// `resolve` APIs here to manually do the -1 and account that they want location +// information for the *previous* instruction, not the current. Ideally we'd +// also expose on `Frame` if we are indeed the address of the next instruction +// or the current. +// +// For now though this is a pretty niche concern so we just internally always +// subtract one. Consumers should keep working and getting pretty good results, +// so we should be good enough. +fn adjust_ip(a: *mut c_void) -> *mut c_void { + if a.is_null() { + a + } else { + (a as usize - 1) as *mut c_void + } +} + +/// Same as `resolve`, only unsafe as it's unsynchronized. +/// +/// This function does not have synchronization guarantees but is available when +/// the `std` feature of this crate isn't compiled in. See the `resolve` +/// function for more documentation and examples. +/// +/// # Panics +/// +/// See information on `resolve` for caveats on `cb` panicking. +pub unsafe fn resolve_unsynchronized(addr: *mut c_void, mut cb: F) +where + F: FnMut(&Symbol), +{ + unsafe { imp::resolve(ResolveWhat::Address(addr), &mut cb) } +} + +/// Same as `resolve_frame`, only unsafe as it's unsynchronized. +/// +/// This function does not have synchronization guarantees but is available +/// when the `std` feature of this crate isn't compiled in. See the +/// `resolve_frame` function for more documentation and examples. +/// +/// # Panics +/// +/// See information on `resolve_frame` for caveats on `cb` panicking. +pub unsafe fn resolve_frame_unsynchronized(frame: &Frame, mut cb: F) +where + F: FnMut(&Symbol), +{ + unsafe { imp::resolve(ResolveWhat::Frame(frame), &mut cb) } +} + +/// A trait representing the resolution of a symbol in a file. +/// +/// This trait is yielded as a trait object to the closure given to the +/// `backtrace::resolve` function, and it is virtually dispatched as it's +/// unknown which implementation is behind it. +/// +/// A symbol can give contextual information about a function, for example the +/// name, filename, line number, precise address, etc. Not all information is +/// always available in a symbol, however, so all methods return an `Option`. +pub struct Symbol { + // TODO: this lifetime bound needs to be persisted eventually to `Symbol`, + // but that's currently a breaking change. For now this is safe since + // `Symbol` is only ever handed out by reference and can't be cloned. + inner: imp::Symbol<'static>, +} + +impl Symbol { + /// Returns the name of this function. + /// + /// The returned structure can be used to query various properties about the + /// symbol name: + /// + /// * The `Display` implementation will print out the demangled symbol. + /// * The raw `str` value of the symbol can be accessed (if it's valid + /// utf-8). + /// * The raw bytes for the symbol name can be accessed. + pub fn name(&self) -> Option> { + self.inner.name() + } + + /// Returns the starting address of this function. + pub fn addr(&self) -> Option<*mut c_void> { + self.inner.addr() + } + + /// Returns the raw filename as a slice. This is mainly useful for `no_std` + /// environments. + pub fn filename_raw(&self) -> Option> { + self.inner.filename_raw() + } + + /// Returns the column number for where this symbol is currently executing. + /// + /// Only gimli currently provides a value here and even then only if `filename` + /// returns `Some`, and so it is then consequently subject to similar caveats. + pub fn colno(&self) -> Option { + self.inner.colno() + } + + /// Returns the line number for where this symbol is currently executing. + /// + /// This return value is typically `Some` if `filename` returns `Some`, and + /// is consequently subject to similar caveats. + pub fn lineno(&self) -> Option { + self.inner.lineno() + } + + /// Returns the file name where this function was defined. + /// + /// This is currently only available when libbacktrace or gimli is being + /// used (e.g. unix platforms other) and when a binary is compiled with + /// debuginfo. If neither of these conditions is met then this will likely + /// return `None`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + #[cfg(feature = "std")] + #[allow(unreachable_code)] + pub fn filename(&self) -> Option<&Path> { + self.inner.filename() + } +} + +impl fmt::Debug for Symbol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_struct("Symbol"); + if let Some(name) = self.name() { + d.field("name", &name); + } + if let Some(addr) = self.addr() { + d.field("addr", &addr); + } + + #[cfg(feature = "std")] + { + if let Some(filename) = self.filename() { + d.field("filename", &filename); + } + } + + if let Some(lineno) = self.lineno() { + d.field("lineno", &lineno); + } + d.finish() + } +} + +cfg_if::cfg_if! { + if #[cfg(feature = "cpp_demangle")] { + // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust + // failed. + struct OptionCppSymbol<'a>(Option<::cpp_demangle::BorrowedSymbol<'a>>); + + impl<'a> OptionCppSymbol<'a> { + fn parse(input: &'a [u8]) -> OptionCppSymbol<'a> { + OptionCppSymbol(::cpp_demangle::BorrowedSymbol::new(input).ok()) + } + + fn none() -> OptionCppSymbol<'a> { + OptionCppSymbol(None) + } + } + } +} + +/// A wrapper around a symbol name to provide ergonomic accessors to the +/// demangled name, the raw bytes, the raw string, etc. +pub struct SymbolName<'a> { + bytes: &'a [u8], + demangled: Option>, + #[cfg(feature = "cpp_demangle")] + cpp_demangled: OptionCppSymbol<'a>, +} + +impl<'a> SymbolName<'a> { + /// Creates a new symbol name from the raw underlying bytes. + pub fn new(bytes: &'a [u8]) -> SymbolName<'a> { + let str_bytes = str::from_utf8(bytes).ok(); + let demangled = str_bytes.and_then(|s| try_demangle(s).ok()); + + #[cfg(feature = "cpp_demangle")] + let cpp = if demangled.is_none() { + OptionCppSymbol::parse(bytes) + } else { + OptionCppSymbol::none() + }; + + SymbolName { + bytes, + demangled, + #[cfg(feature = "cpp_demangle")] + cpp_demangled: cpp, + } + } + + /// Returns the raw (mangled) symbol name as a `str` if the symbol is valid utf-8. + /// + /// Use the `Display` implementation if you want the demangled version. + pub fn as_str(&self) -> Option<&'a str> { + self.demangled + .as_ref() + .map(|s| s.as_str()) + .or_else(|| str::from_utf8(self.bytes).ok()) + } + + /// Returns the raw symbol name as a list of bytes + pub fn as_bytes(&self) -> &'a [u8] { + self.bytes + } +} + +fn format_symbol_name( + fmt: fn(&str, &mut fmt::Formatter<'_>) -> fmt::Result, + mut bytes: &[u8], + f: &mut fmt::Formatter<'_>, +) -> fmt::Result { + while bytes.len() > 0 { + match str::from_utf8(bytes) { + Ok(name) => { + fmt(name, f)?; + break; + } + Err(err) => { + fmt("\u{FFFD}", f)?; + + match err.error_len() { + Some(len) => bytes = &bytes[err.valid_up_to() + len..], + None => break, + } + } + } + } + Ok(()) +} + +impl<'a> fmt::Display for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(ref s) = self.demangled { + return s.fmt(f); + } + + #[cfg(feature = "cpp_demangle")] + { + // This may fail to print if the demangled symbol isn't actually + // valid, so handle the error here gracefully by not propagating + // it outwards. + if let Some(ref cpp) = self.cpp_demangled.0 { + if let Ok(s) = cpp.demangle() { + return s.fmt(f); + } + } + } + + format_symbol_name(fmt::Display::fmt, self.bytes, f) + } +} + +impl<'a> fmt::Debug for SymbolName<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(ref s) = self.demangled { + return s.fmt(f); + } + + #[cfg(all(feature = "std", feature = "cpp_demangle"))] + { + // This may fail to print if the demangled symbol isn't actually + // valid, so handle the error here gracefully by not propagating + // it outwards. + if let Some(ref cpp) = self.cpp_demangled.0 { + if let Ok(s) = cpp.demangle() { + return s.fmt(f); + } + } + } + + format_symbol_name(fmt::Debug::fmt, self.bytes, f) + } +} + +/// Attempt to reclaim that cached memory used to symbolicate addresses. +/// +/// This method will attempt to release any global data structures that have +/// otherwise been cached globally or in the thread which typically represent +/// parsed DWARF information or similar. +/// +/// # Caveats +/// +/// While this function is always available it doesn't actually do anything on +/// most implementations. Libraries like dbghelp or libbacktrace do not provide +/// facilities to deallocate state and manage the allocated memory. For now the +/// `std` feature of this crate is the only feature where this +/// function has any effect. +#[cfg(feature = "std")] +pub fn clear_symbol_cache() { + let _guard = crate::lock::lock(); + unsafe { + imp::clear_symbol_cache(); + } +} + +cfg_if::cfg_if! { + if #[cfg(miri)] { + mod miri; + use miri as imp; + } else if #[cfg(all(windows, target_env = "msvc", not(target_vendor = "uwp")))] { + mod dbghelp; + use dbghelp as imp; + } else if #[cfg(all( + any(unix, all(windows, target_env = "gnu")), + not(target_vendor = "uwp"), + not(target_os = "emscripten"), + any(not(backtrace_in_libstd), feature = "backtrace"), + ))] { + mod gimli; + use gimli as imp; + } else { + mod noop; + use noop as imp; + } +} diff --git a/anneal/v2/vendor/backtrace/src/symbolize/noop.rs b/anneal/v2/vendor/backtrace/src/symbolize/noop.rs new file mode 100644 index 0000000000..c53336531b --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/symbolize/noop.rs @@ -0,0 +1,41 @@ +//! Empty symbolication strategy used to compile for platforms that have no +//! support. + +use super::{BytesOrWideString, ResolveWhat, SymbolName}; +use core::ffi::c_void; +use core::marker; + +pub unsafe fn resolve(_addr: ResolveWhat<'_>, _cb: &mut dyn FnMut(&super::Symbol)) {} + +pub struct Symbol<'a> { + _marker: marker::PhantomData<&'a i32>, +} + +impl Symbol<'_> { + pub fn name(&self) -> Option> { + None + } + + pub fn addr(&self) -> Option<*mut c_void> { + None + } + + pub fn filename_raw(&self) -> Option> { + None + } + + #[cfg(feature = "std")] + pub fn filename(&self) -> Option<&::std::path::Path> { + None + } + + pub fn lineno(&self) -> Option { + None + } + + pub fn colno(&self) -> Option { + None + } +} + +pub unsafe fn clear_symbol_cache() {} diff --git a/anneal/v2/vendor/backtrace/src/types.rs b/anneal/v2/vendor/backtrace/src/types.rs new file mode 100644 index 0000000000..c419247a6d --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/types.rs @@ -0,0 +1,83 @@ +//! Platform dependent types. + +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + use std::borrow::Cow; + use std::fmt; + use std::path::PathBuf; + use std::prelude::v1::*; + use std::str; + } +} + +/// A platform independent representation of a string. When working with `std` +/// enabled it is recommended to the convenience methods for providing +/// conversions to `std` types. +#[derive(Debug)] +pub enum BytesOrWideString<'a> { + /// A slice, typically provided on Unix platforms. + Bytes(&'a [u8]), + /// Wide strings typically from Windows. + Wide(&'a [u16]), +} + +#[cfg(feature = "std")] +impl<'a> BytesOrWideString<'a> { + /// Lossy converts to a `Cow`, will allocate if `Bytes` is not valid + /// UTF-8 or if `BytesOrWideString` is `Wide`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn to_str_lossy(&self) -> Cow<'a, str> { + use self::BytesOrWideString::*; + + match *self { + Bytes(slice) => String::from_utf8_lossy(slice), + Wide(wide) => Cow::Owned(String::from_utf16_lossy(wide)), + } + } + + /// Provides a `Path` representation of `BytesOrWideString`. + /// + /// # Required features + /// + /// This function requires the `std` feature of the `backtrace` crate to be + /// enabled, and the `std` feature is enabled by default. + pub fn into_path_buf(self) -> PathBuf { + #[cfg(unix)] + { + use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; + + if let BytesOrWideString::Bytes(slice) = self { + return PathBuf::from(OsStr::from_bytes(slice)); + } + } + + #[cfg(windows)] + { + use std::ffi::OsString; + use std::os::windows::ffi::OsStringExt; + + if let BytesOrWideString::Wide(slice) = self { + return PathBuf::from(OsString::from_wide(slice)); + } + } + + if let BytesOrWideString::Bytes(b) = self { + if let Ok(s) = str::from_utf8(b) { + return PathBuf::from(s); + } + } + unreachable!() + } +} + +#[cfg(feature = "std")] +impl<'a> fmt::Display for BytesOrWideString<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_str_lossy().fmt(f) + } +} diff --git a/anneal/v2/vendor/backtrace/src/windows_sys.rs b/anneal/v2/vendor/backtrace/src/windows_sys.rs new file mode 100644 index 0000000000..ddd5393c25 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/windows_sys.rs @@ -0,0 +1,668 @@ +// Bindings generated by `windows-bindgen` 0.58.0 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +windows_link::link!("dbghelp.dll" "system" fn EnumerateLoadedModulesW64(hprocess : HANDLE, enumloadedmodulescallback : PENUMLOADED_MODULES_CALLBACKW64, usercontext : *const core::ffi::c_void) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn StackWalk64(machinetype : u32, hprocess : HANDLE, hthread : HANDLE, stackframe : *mut STACKFRAME64, contextrecord : *mut core::ffi::c_void, readmemoryroutine : PREAD_PROCESS_MEMORY_ROUTINE64, functiontableaccessroutine : PFUNCTION_TABLE_ACCESS_ROUTINE64, getmodulebaseroutine : PGET_MODULE_BASE_ROUTINE64, translateaddress : PTRANSLATE_ADDRESS_ROUTINE64) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn StackWalkEx(machinetype : u32, hprocess : HANDLE, hthread : HANDLE, stackframe : *mut STACKFRAME_EX, contextrecord : *mut core::ffi::c_void, readmemoryroutine : PREAD_PROCESS_MEMORY_ROUTINE64, functiontableaccessroutine : PFUNCTION_TABLE_ACCESS_ROUTINE64, getmodulebaseroutine : PGET_MODULE_BASE_ROUTINE64, translateaddress : PTRANSLATE_ADDRESS_ROUTINE64, flags : u32) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymAddrIncludeInlineTrace(hprocess : HANDLE, address : u64) -> u32); +windows_link::link!("dbghelp.dll" "system" fn SymFromAddrW(hprocess : HANDLE, address : u64, displacement : *mut u64, symbol : *mut SYMBOL_INFOW) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymFromInlineContextW(hprocess : HANDLE, address : u64, inlinecontext : u32, displacement : *mut u64, symbol : *mut SYMBOL_INFOW) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymFunctionTableAccess64(hprocess : HANDLE, addrbase : u64) -> *mut core::ffi::c_void); +windows_link::link!("dbghelp.dll" "system" fn SymGetLineFromAddrW64(hprocess : HANDLE, dwaddr : u64, pdwdisplacement : *mut u32, line : *mut IMAGEHLP_LINEW64) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymGetLineFromInlineContextW(hprocess : HANDLE, dwaddr : u64, inlinecontext : u32, qwmodulebaseaddress : u64, pdwdisplacement : *mut u32, line : *mut IMAGEHLP_LINEW64) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymGetModuleBase64(hprocess : HANDLE, qwaddr : u64) -> u64); +windows_link::link!("dbghelp.dll" "system" fn SymGetOptions() -> u32); +windows_link::link!("dbghelp.dll" "system" fn SymGetSearchPathW(hprocess : HANDLE, searchpatha : PWSTR, searchpathlength : u32) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymInitializeW(hprocess : HANDLE, usersearchpath : PCWSTR, finvadeprocess : BOOL) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymQueryInlineTrace(hprocess : HANDLE, startaddress : u64, startcontext : u32, startretaddress : u64, curaddress : u64, curcontext : *mut u32, curframeindex : *mut u32) -> BOOL); +windows_link::link!("dbghelp.dll" "system" fn SymSetOptions(symoptions : u32) -> u32); +windows_link::link!("dbghelp.dll" "system" fn SymSetSearchPathW(hprocess : HANDLE, searchpatha : PCWSTR) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn CloseHandle(hobject : HANDLE) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn CreateFileMappingA(hfile : HANDLE, lpfilemappingattributes : *const SECURITY_ATTRIBUTES, flprotect : PAGE_PROTECTION_FLAGS, dwmaximumsizehigh : u32, dwmaximumsizelow : u32, lpname : PCSTR) -> HANDLE); +windows_link::link!("kernel32.dll" "system" fn CreateMutexA(lpmutexattributes : *const SECURITY_ATTRIBUTES, binitialowner : BOOL, lpname : PCSTR) -> HANDLE); +windows_link::link!("kernel32.dll" "system" fn CreateToolhelp32Snapshot(dwflags : CREATE_TOOLHELP_SNAPSHOT_FLAGS, th32processid : u32) -> HANDLE); +windows_link::link!("kernel32.dll" "system" fn GetCurrentProcess() -> HANDLE); +windows_link::link!("kernel32.dll" "system" fn GetCurrentProcessId() -> u32); +windows_link::link!("kernel32.dll" "system" fn GetCurrentThread() -> HANDLE); +windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC); +windows_link::link!("kernel32.dll" "system" fn LoadLibraryA(lplibfilename : PCSTR) -> HMODULE); +windows_link::link!("kernel32.dll" "system" fn MapViewOfFile(hfilemappingobject : HANDLE, dwdesiredaccess : FILE_MAP, dwfileoffsethigh : u32, dwfileoffsetlow : u32, dwnumberofbytestomap : usize) -> MEMORY_MAPPED_VIEW_ADDRESS); +windows_link::link!("kernel32.dll" "system" fn Module32FirstW(hsnapshot : HANDLE, lpme : *mut MODULEENTRY32W) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn Module32NextW(hsnapshot : HANDLE, lpme : *mut MODULEENTRY32W) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn ReleaseMutex(hmutex : HANDLE) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn RtlCaptureContext(contextrecord : *mut CONTEXT)); +#[cfg(target_arch = "aarch64")] +windows_link::link!("kernel32.dll" "system" fn RtlLookupFunctionEntry(controlpc : usize, imagebase : *mut usize, historytable : *mut UNWIND_HISTORY_TABLE) -> *mut IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY); +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +windows_link::link!("kernel32.dll" "system" fn RtlLookupFunctionEntry(controlpc : u64, imagebase : *mut u64, historytable : *mut UNWIND_HISTORY_TABLE) -> *mut IMAGE_RUNTIME_FUNCTION_ENTRY); +#[cfg(target_arch = "aarch64")] +windows_link::link!("kernel32.dll" "system" fn RtlVirtualUnwind(handlertype : RTL_VIRTUAL_UNWIND_HANDLER_TYPE, imagebase : usize, controlpc : usize, functionentry : *const IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY, contextrecord : *mut CONTEXT, handlerdata : *mut *mut core::ffi::c_void, establisherframe : *mut usize, contextpointers : *mut KNONVOLATILE_CONTEXT_POINTERS) -> EXCEPTION_ROUTINE); +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +windows_link::link!("kernel32.dll" "system" fn RtlVirtualUnwind(handlertype : RTL_VIRTUAL_UNWIND_HANDLER_TYPE, imagebase : u64, controlpc : u64, functionentry : *const IMAGE_RUNTIME_FUNCTION_ENTRY, contextrecord : *mut CONTEXT, handlerdata : *mut *mut core::ffi::c_void, establisherframe : *mut u64, contextpointers : *mut KNONVOLATILE_CONTEXT_POINTERS) -> EXCEPTION_ROUTINE); +windows_link::link!("kernel32.dll" "system" fn UnmapViewOfFile(lpbaseaddress : MEMORY_MAPPED_VIEW_ADDRESS) -> BOOL); +windows_link::link!("kernel32.dll" "system" fn WaitForSingleObjectEx(hhandle : HANDLE, dwmilliseconds : u32, balertable : BOOL) -> WAIT_EVENT); +windows_link::link!("kernel32.dll" "system" fn WideCharToMultiByte(codepage : u32, dwflags : u32, lpwidecharstr : PCWSTR, cchwidechar : i32, lpmultibytestr : PSTR, cbmultibyte : i32, lpdefaultchar : PCSTR, lpuseddefaultchar : *mut BOOL) -> i32); +windows_link::link!("kernel32.dll" "system" fn lstrlenW(lpstring : PCWSTR) -> i32); +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ADDRESS64 { + pub Offset: u64, + pub Segment: u16, + pub Mode: ADDRESS_MODE, +} +pub type ADDRESS_MODE = i32; +#[repr(C)] +#[derive(Clone, Copy)] +pub union ARM64_NT_NEON128 { + pub Anonymous: ARM64_NT_NEON128_0, + pub D: [f64; 2], + pub S: [f32; 4], + pub H: [u16; 8], + pub B: [u8; 16], +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ARM64_NT_NEON128_0 { + pub Low: u64, + pub High: i64, +} +pub const AddrModeFlat: ADDRESS_MODE = 3i32; +pub type BOOL = i32; +#[repr(C)] +#[cfg(target_arch = "aarch64")] +#[derive(Clone, Copy)] +pub struct CONTEXT { + pub ContextFlags: CONTEXT_FLAGS, + pub Cpsr: u32, + pub Anonymous: CONTEXT_0, + pub Sp: u64, + pub Pc: u64, + pub V: [ARM64_NT_NEON128; 32], + pub Fpcr: u32, + pub Fpsr: u32, + pub Bcr: [u32; 8], + pub Bvr: [u64; 8], + pub Wcr: [u32; 2], + pub Wvr: [u64; 2], +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +#[derive(Clone, Copy)] +pub union CONTEXT_0 { + pub Anonymous: CONTEXT_0_0, + pub X: [u64; 31], +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +#[derive(Clone, Copy)] +pub struct CONTEXT_0_0 { + pub X0: u64, + pub X1: u64, + pub X2: u64, + pub X3: u64, + pub X4: u64, + pub X5: u64, + pub X6: u64, + pub X7: u64, + pub X8: u64, + pub X9: u64, + pub X10: u64, + pub X11: u64, + pub X12: u64, + pub X13: u64, + pub X14: u64, + pub X15: u64, + pub X16: u64, + pub X17: u64, + pub X18: u64, + pub X19: u64, + pub X20: u64, + pub X21: u64, + pub X22: u64, + pub X23: u64, + pub X24: u64, + pub X25: u64, + pub X26: u64, + pub X27: u64, + pub X28: u64, + pub Fp: u64, + pub Lr: u64, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct CONTEXT { + pub P1Home: u64, + pub P2Home: u64, + pub P3Home: u64, + pub P4Home: u64, + pub P5Home: u64, + pub P6Home: u64, + pub ContextFlags: CONTEXT_FLAGS, + pub MxCsr: u32, + pub SegCs: u16, + pub SegDs: u16, + pub SegEs: u16, + pub SegFs: u16, + pub SegGs: u16, + pub SegSs: u16, + pub EFlags: u32, + pub Dr0: u64, + pub Dr1: u64, + pub Dr2: u64, + pub Dr3: u64, + pub Dr6: u64, + pub Dr7: u64, + pub Rax: u64, + pub Rcx: u64, + pub Rdx: u64, + pub Rbx: u64, + pub Rsp: u64, + pub Rbp: u64, + pub Rsi: u64, + pub Rdi: u64, + pub R8: u64, + pub R9: u64, + pub R10: u64, + pub R11: u64, + pub R12: u64, + pub R13: u64, + pub R14: u64, + pub R15: u64, + pub Rip: u64, + pub Anonymous: CONTEXT_0, + pub VectorRegister: [M128A; 26], + pub VectorControl: u64, + pub DebugControl: u64, + pub LastBranchToRip: u64, + pub LastBranchFromRip: u64, + pub LastExceptionToRip: u64, + pub LastExceptionFromRip: u64, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub union CONTEXT_0 { + pub FltSave: XSAVE_FORMAT, + pub Anonymous: CONTEXT_0_0, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct CONTEXT_0_0 { + pub Header: [M128A; 2], + pub Legacy: [M128A; 8], + pub Xmm0: M128A, + pub Xmm1: M128A, + pub Xmm2: M128A, + pub Xmm3: M128A, + pub Xmm4: M128A, + pub Xmm5: M128A, + pub Xmm6: M128A, + pub Xmm7: M128A, + pub Xmm8: M128A, + pub Xmm9: M128A, + pub Xmm10: M128A, + pub Xmm11: M128A, + pub Xmm12: M128A, + pub Xmm13: M128A, + pub Xmm14: M128A, + pub Xmm15: M128A, +} +#[repr(C)] +#[cfg(target_arch = "x86")] +#[derive(Clone, Copy)] +pub struct CONTEXT { + pub ContextFlags: CONTEXT_FLAGS, + pub Dr0: u32, + pub Dr1: u32, + pub Dr2: u32, + pub Dr3: u32, + pub Dr6: u32, + pub Dr7: u32, + pub FloatSave: FLOATING_SAVE_AREA, + pub SegGs: u32, + pub SegFs: u32, + pub SegEs: u32, + pub SegDs: u32, + pub Edi: u32, + pub Esi: u32, + pub Ebx: u32, + pub Edx: u32, + pub Ecx: u32, + pub Eax: u32, + pub Ebp: u32, + pub Eip: u32, + pub SegCs: u32, + pub EFlags: u32, + pub Esp: u32, + pub SegSs: u32, + pub ExtendedRegisters: [u8; 512], +} + +pub type CONTEXT_FLAGS = u32; +pub const CP_UTF8: u32 = 65001u32; +pub type CREATE_TOOLHELP_SNAPSHOT_FLAGS = u32; +pub type EXCEPTION_DISPOSITION = i32; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], +} +pub type EXCEPTION_ROUTINE = Option< + unsafe extern "system" fn( + exceptionrecord: *mut EXCEPTION_RECORD, + establisherframe: *const core::ffi::c_void, + contextrecord: *mut CONTEXT, + dispatchercontext: *const core::ffi::c_void, + ) -> EXCEPTION_DISPOSITION, +>; +pub const FALSE: BOOL = 0i32; +pub type FARPROC = Option isize>; +pub type FILE_MAP = u32; +pub const FILE_MAP_READ: FILE_MAP = 4u32; +#[repr(C)] +#[cfg(any( + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "x86_64" +))] +#[derive(Clone, Copy)] +pub struct FLOATING_SAVE_AREA { + pub ControlWord: u32, + pub StatusWord: u32, + pub TagWord: u32, + pub ErrorOffset: u32, + pub ErrorSelector: u32, + pub DataOffset: u32, + pub DataSelector: u32, + pub RegisterArea: [u8; 80], + pub Cr0NpxState: u32, +} +#[repr(C)] +#[cfg(target_arch = "x86")] +#[derive(Clone, Copy)] +pub struct FLOATING_SAVE_AREA { + pub ControlWord: u32, + pub StatusWord: u32, + pub TagWord: u32, + pub ErrorOffset: u32, + pub ErrorSelector: u32, + pub DataOffset: u32, + pub DataSelector: u32, + pub RegisterArea: [u8; 80], + pub Spare0: u32, +} +pub type HANDLE = *mut core::ffi::c_void; +pub type HINSTANCE = *mut core::ffi::c_void; +pub type HMODULE = *mut core::ffi::c_void; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IMAGEHLP_LINEW64 { + pub SizeOfStruct: u32, + pub Key: *mut core::ffi::c_void, + pub LineNumber: u32, + pub FileName: PWSTR, + pub Address: u64, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY { + pub BeginAddress: u32, + pub Anonymous: IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_0, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub union IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_0 { + pub UnwindData: u32, + pub Anonymous: IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_0_0, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_0_0 { + pub _bitfield: u32, +} +pub type IMAGE_FILE_MACHINE = u16; +pub const IMAGE_FILE_MACHINE_I386: IMAGE_FILE_MACHINE = 332u16; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IMAGE_RUNTIME_FUNCTION_ENTRY { + pub BeginAddress: u32, + pub EndAddress: u32, + pub Anonymous: IMAGE_RUNTIME_FUNCTION_ENTRY_0, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub union IMAGE_RUNTIME_FUNCTION_ENTRY_0 { + pub UnwindInfoAddress: u32, + pub UnwindData: u32, +} +pub const INFINITE: u32 = 4294967295u32; +pub const INVALID_HANDLE_VALUE: HANDLE = -1i32 as _; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct KDHELP64 { + pub Thread: u64, + pub ThCallbackStack: u32, + pub ThCallbackBStore: u32, + pub NextCallback: u32, + pub FramePointer: u32, + pub KiCallUserMode: u64, + pub KeUserCallbackDispatcher: u64, + pub SystemRangeStart: u64, + pub KiUserExceptionDispatcher: u64, + pub StackBase: u64, + pub StackLimit: u64, + pub BuildVersion: u32, + pub RetpolineStubFunctionTableSize: u32, + pub RetpolineStubFunctionTable: u64, + pub RetpolineStubOffset: u32, + pub RetpolineStubSize: u32, + pub Reserved0: [u64; 2], +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +#[derive(Clone, Copy)] +pub struct KNONVOLATILE_CONTEXT_POINTERS { + pub X19: *mut u64, + pub X20: *mut u64, + pub X21: *mut u64, + pub X22: *mut u64, + pub X23: *mut u64, + pub X24: *mut u64, + pub X25: *mut u64, + pub X26: *mut u64, + pub X27: *mut u64, + pub X28: *mut u64, + pub Fp: *mut u64, + pub Lr: *mut u64, + pub D8: *mut u64, + pub D9: *mut u64, + pub D10: *mut u64, + pub D11: *mut u64, + pub D12: *mut u64, + pub D13: *mut u64, + pub D14: *mut u64, + pub D15: *mut u64, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct KNONVOLATILE_CONTEXT_POINTERS { + pub Anonymous1: KNONVOLATILE_CONTEXT_POINTERS_0, + pub Anonymous2: KNONVOLATILE_CONTEXT_POINTERS_1, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub union KNONVOLATILE_CONTEXT_POINTERS_0 { + pub FloatingContext: [*mut M128A; 16], + pub Anonymous: KNONVOLATILE_CONTEXT_POINTERS_0_0, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct KNONVOLATILE_CONTEXT_POINTERS_0_0 { + pub Xmm0: *mut M128A, + pub Xmm1: *mut M128A, + pub Xmm2: *mut M128A, + pub Xmm3: *mut M128A, + pub Xmm4: *mut M128A, + pub Xmm5: *mut M128A, + pub Xmm6: *mut M128A, + pub Xmm7: *mut M128A, + pub Xmm8: *mut M128A, + pub Xmm9: *mut M128A, + pub Xmm10: *mut M128A, + pub Xmm11: *mut M128A, + pub Xmm12: *mut M128A, + pub Xmm13: *mut M128A, + pub Xmm14: *mut M128A, + pub Xmm15: *mut M128A, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub union KNONVOLATILE_CONTEXT_POINTERS_1 { + pub IntegerContext: [*mut u64; 16], + pub Anonymous: KNONVOLATILE_CONTEXT_POINTERS_1_0, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct KNONVOLATILE_CONTEXT_POINTERS_1_0 { + pub Rax: *mut u64, + pub Rcx: *mut u64, + pub Rdx: *mut u64, + pub Rbx: *mut u64, + pub Rsp: *mut u64, + pub Rbp: *mut u64, + pub Rsi: *mut u64, + pub Rdi: *mut u64, + pub R8: *mut u64, + pub R9: *mut u64, + pub R10: *mut u64, + pub R11: *mut u64, + pub R12: *mut u64, + pub R13: *mut u64, + pub R14: *mut u64, + pub R15: *mut u64, +} +#[repr(C)] +#[cfg(target_arch = "x86")] +#[derive(Clone, Copy)] +pub struct KNONVOLATILE_CONTEXT_POINTERS { + pub Dummy: u32, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct M128A { + pub Low: u64, + pub High: i64, +} +pub const MAX_SYM_NAME: u32 = 2000u32; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct MEMORY_MAPPED_VIEW_ADDRESS { + pub Value: *mut core::ffi::c_void, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct MODULEENTRY32W { + pub dwSize: u32, + pub th32ModuleID: u32, + pub th32ProcessID: u32, + pub GlblcntUsage: u32, + pub ProccntUsage: u32, + pub modBaseAddr: *mut u8, + pub modBaseSize: u32, + pub hModule: HMODULE, + pub szModule: [u16; 256], + pub szExePath: [u16; 260], +} +pub type NTSTATUS = i32; +pub type PAGE_PROTECTION_FLAGS = u32; +pub const PAGE_READONLY: PAGE_PROTECTION_FLAGS = 2u32; +pub type PCSTR = *const u8; +pub type PCWSTR = *const u16; +pub type PENUMLOADED_MODULES_CALLBACKW64 = Option< + unsafe extern "system" fn( + modulename: PCWSTR, + modulebase: u64, + modulesize: u32, + usercontext: *const core::ffi::c_void, + ) -> BOOL, +>; +pub type PFUNCTION_TABLE_ACCESS_ROUTINE64 = + Option *mut core::ffi::c_void>; +pub type PGET_MODULE_BASE_ROUTINE64 = + Option u64>; +pub type PREAD_PROCESS_MEMORY_ROUTINE64 = Option< + unsafe extern "system" fn( + hprocess: HANDLE, + qwbaseaddress: u64, + lpbuffer: *mut core::ffi::c_void, + nsize: u32, + lpnumberofbytesread: *mut u32, + ) -> BOOL, +>; +pub type PSTR = *mut u8; +pub type PTRANSLATE_ADDRESS_ROUTINE64 = Option< + unsafe extern "system" fn(hprocess: HANDLE, hthread: HANDLE, lpaddr: *const ADDRESS64) -> u64, +>; +pub type PWSTR = *mut u16; +pub type RTL_VIRTUAL_UNWIND_HANDLER_TYPE = u32; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct SECURITY_ATTRIBUTES { + pub nLength: u32, + pub lpSecurityDescriptor: *mut core::ffi::c_void, + pub bInheritHandle: BOOL, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct STACKFRAME64 { + pub AddrPC: ADDRESS64, + pub AddrReturn: ADDRESS64, + pub AddrFrame: ADDRESS64, + pub AddrStack: ADDRESS64, + pub AddrBStore: ADDRESS64, + pub FuncTableEntry: *mut core::ffi::c_void, + pub Params: [u64; 4], + pub Far: BOOL, + pub Virtual: BOOL, + pub Reserved: [u64; 3], + pub KdHelp: KDHELP64, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct STACKFRAME_EX { + pub AddrPC: ADDRESS64, + pub AddrReturn: ADDRESS64, + pub AddrFrame: ADDRESS64, + pub AddrStack: ADDRESS64, + pub AddrBStore: ADDRESS64, + pub FuncTableEntry: *mut core::ffi::c_void, + pub Params: [u64; 4], + pub Far: BOOL, + pub Virtual: BOOL, + pub Reserved: [u64; 3], + pub KdHelp: KDHELP64, + pub StackFrameSize: u32, + pub InlineFrameContext: u32, +} +#[repr(C)] +#[derive(Clone, Copy)] +pub struct SYMBOL_INFOW { + pub SizeOfStruct: u32, + pub TypeIndex: u32, + pub Reserved: [u64; 2], + pub Index: u32, + pub Size: u32, + pub ModBase: u64, + pub Flags: SYMBOL_INFO_FLAGS, + pub Value: u64, + pub Address: u64, + pub Register: u32, + pub Scope: u32, + pub Tag: u32, + pub NameLen: u32, + pub MaxNameLen: u32, + pub Name: [u16; 1], +} +pub type SYMBOL_INFO_FLAGS = u32; +pub const SYMOPT_DEFERRED_LOADS: u32 = 4u32; +pub const TH32CS_SNAPMODULE: CREATE_TOOLHELP_SNAPSHOT_FLAGS = 8u32; +pub const TRUE: BOOL = 1i32; +#[repr(C)] +#[cfg(any( + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "x86_64" +))] +#[derive(Clone, Copy)] +pub struct UNWIND_HISTORY_TABLE { + pub Count: u32, + pub LocalHint: u8, + pub GlobalHint: u8, + pub Search: u8, + pub Once: u8, + pub LowAddress: usize, + pub HighAddress: usize, + pub Entry: [UNWIND_HISTORY_TABLE_ENTRY; 12], +} +#[repr(C)] +#[cfg(target_arch = "aarch64")] +#[derive(Clone, Copy)] +pub struct UNWIND_HISTORY_TABLE_ENTRY { + pub ImageBase: usize, + pub FunctionEntry: *mut IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY, +} +#[repr(C)] +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +#[derive(Clone, Copy)] +pub struct UNWIND_HISTORY_TABLE_ENTRY { + pub ImageBase: usize, + pub FunctionEntry: *mut IMAGE_RUNTIME_FUNCTION_ENTRY, +} +pub type WAIT_EVENT = u32; +#[repr(C)] +#[cfg(any( + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "x86_64" +))] +#[derive(Clone, Copy)] +pub struct XSAVE_FORMAT { + pub ControlWord: u16, + pub StatusWord: u16, + pub TagWord: u8, + pub Reserved1: u8, + pub ErrorOpcode: u16, + pub ErrorOffset: u32, + pub ErrorSelector: u16, + pub Reserved2: u16, + pub DataOffset: u32, + pub DataSelector: u16, + pub Reserved3: u16, + pub MxCsr: u32, + pub MxCsr_Mask: u32, + pub FloatRegisters: [M128A; 8], + pub XmmRegisters: [M128A; 16], + pub Reserved4: [u8; 96], +} +#[repr(C)] +#[cfg(target_arch = "x86")] +#[derive(Clone, Copy)] +pub struct XSAVE_FORMAT { + pub ControlWord: u16, + pub StatusWord: u16, + pub TagWord: u8, + pub Reserved1: u8, + pub ErrorOpcode: u16, + pub ErrorOffset: u32, + pub ErrorSelector: u16, + pub Reserved2: u16, + pub DataOffset: u32, + pub DataSelector: u16, + pub Reserved3: u16, + pub MxCsr: u32, + pub MxCsr_Mask: u32, + pub FloatRegisters: [M128A; 8], + pub XmmRegisters: [M128A; 8], + pub Reserved4: [u8; 224], +} + +#[cfg(target_arch = "arm")] +include!("./windows_sys_arm32_shim.rs"); diff --git a/anneal/v2/vendor/backtrace/src/windows_sys_arm32_shim.rs b/anneal/v2/vendor/backtrace/src/windows_sys_arm32_shim.rs new file mode 100644 index 0000000000..4df9064c99 --- /dev/null +++ b/anneal/v2/vendor/backtrace/src/windows_sys_arm32_shim.rs @@ -0,0 +1,53 @@ +pub const ARM_MAX_BREAKPOINTS: usize = 8; +pub const ARM_MAX_WATCHPOINTS: usize = 1; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct NEON128 { + pub Low: u64, + pub High: i64, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub union CONTEXT_FloatRegs { + pub Q: [NEON128; 16], + pub D: [u64; 32], + pub S: [u32; 32], +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CONTEXT { + pub ContextFlags: u32, + pub R0: u32, + pub R1: u32, + pub R2: u32, + pub R3: u32, + pub R4: u32, + pub R5: u32, + pub R6: u32, + pub R7: u32, + pub R8: u32, + pub R9: u32, + pub R10: u32, + pub R11: u32, + pub R12: u32, + // Control registers + pub Sp: u32, + pub Lr: u32, + pub Pc: u32, + pub Cpsr: u32, + // Floating-point registers + pub Fpsrc: u32, + pub Padding: u32, + pub u: CONTEXT_FloatRegs, + // Debug registers + pub Bvr: [u32; ARM_MAX_BREAKPOINTS], + pub Bcr: [u32; ARM_MAX_BREAKPOINTS], + pub Wvr: [u32; ARM_MAX_WATCHPOINTS], + pub Wcr: [u32; ARM_MAX_WATCHPOINTS], + pub Padding2: [u32; 2], +} + +pub const IMAGE_FILE_MACHINE_ARMNT: IMAGE_FILE_MACHINE = 0x01c4; diff --git a/anneal/v2/vendor/backtrace/tests/accuracy/auxiliary.rs b/anneal/v2/vendor/backtrace/tests/accuracy/auxiliary.rs new file mode 100644 index 0000000000..9c8015d9ae --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/accuracy/auxiliary.rs @@ -0,0 +1,15 @@ +#[inline(never)] +pub fn callback(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} + +#[inline(always)] +pub fn callback_inlined(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} diff --git a/anneal/v2/vendor/backtrace/tests/accuracy/main.rs b/anneal/v2/vendor/backtrace/tests/accuracy/main.rs new file mode 100644 index 0000000000..b50e4451f0 --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/accuracy/main.rs @@ -0,0 +1,121 @@ +#![cfg(dbginfo = "collapsible")] +mod auxiliary; + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +#[collapse_debuginfo(yes)] +macro_rules! check { + ($($pos:expr),*) => ({ + verify(&[$($pos,)* pos!()]); + }) +} + +type Pos = (&'static str, u32); + +#[test] +fn doit() { + if + // Skip musl which is by default statically linked and doesn't support + // dynamic libraries. + !cfg!(target_env = "musl") + // Skip Miri, since it doesn't support dynamic libraries. + && !cfg!(miri) + { + // TODO(#238) this shouldn't have to happen first in this function, but + // currently it does. + let mut dir = std::env::current_exe().unwrap(); + dir.pop(); + if cfg!(windows) { + dir.push("dylib_dep.dll"); + } else if cfg!(target_vendor = "apple") { + dir.push("libdylib_dep.dylib"); + } else if cfg!(target_os = "aix") { + dir.push("libdylib_dep.a"); + } else { + dir.push("libdylib_dep.so"); + } + unsafe { + let lib = libloading::Library::new(&dir).unwrap(); + let api = lib.get::(b"foo").unwrap(); + api(pos!(), |a, b| { + check!(a, b); + }); + } + } + + outer(pos!()); +} + +#[inline(never)] +fn outer(main_pos: Pos) { + inner(main_pos, pos!()); + inner_inlined(main_pos, pos!()); +} + +#[inline(never)] +#[rustfmt::skip] +fn inner(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +#[inline(always)] +#[rustfmt::skip] +fn inner_inlined(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + + #[inline(always)] + fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(main_pos, outer_pos, inner_pos); + } + inner_further_inlined(main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(main_pos, outer_pos, pos!()); +} + +fn verify(filelines: &[Pos]) { + let trace = backtrace::Backtrace::new(); + println!("-----------------------------------"); + println!("looking for:"); + for (file, line) in filelines.iter().rev() { + println!("\t{file}:{line}"); + } + println!("found:\n{trace:?}"); + let mut symbols = trace.frames().iter().flat_map(|frame| frame.symbols()); + let mut iter = filelines.iter().rev(); + while let Some((file, line)) = iter.next() { + loop { + let sym = match symbols.next() { + Some(sym) => sym, + None => panic!("failed to find {file}:{line}"), + }; + if let Some(filename) = sym.filename() { + if let Some(lineno) = sym.lineno() { + if filename.ends_with(file) && lineno == *line { + break; + } + } + } + } + } +} diff --git a/anneal/v2/vendor/backtrace/tests/common/mod.rs b/anneal/v2/vendor/backtrace/tests/common/mod.rs new file mode 100644 index 0000000000..3c07934fd7 --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/common/mod.rs @@ -0,0 +1,14 @@ +/// Some tests only make sense in contexts where they can re-exec the test +/// itself. Not all contexts support this, so you can call this method to find +/// out which case you are in. +pub fn cannot_reexec_the_test() -> bool { + // These run in docker containers on CI where they can't re-exec the test, + // so just skip these for CI. No other reason this can't run on those + // platforms though. + // Miri does not have support for re-execing a file + cfg!(unix) + && (cfg!(target_arch = "arm") + || cfg!(target_arch = "aarch64") + || cfg!(target_arch = "s390x")) + || cfg!(miri) +} diff --git a/anneal/v2/vendor/backtrace/tests/concurrent-panics.rs b/anneal/v2/vendor/backtrace/tests/concurrent-panics.rs new file mode 100644 index 0000000000..350c247dbb --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/concurrent-panics.rs @@ -0,0 +1,72 @@ +use std::env; +use std::panic; +use std::process::Command; +use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; +use std::sync::Arc; +use std::thread; + +const PANICS: usize = 100; +const THREADS: usize = 8; +const VAR: &str = "__THE_TEST_YOU_ARE_LUKE"; + +mod common; + +fn main() { + // If we cannot re-exec this test, there's no point in trying to do it. + if common::cannot_reexec_the_test() { + println!("test result: ok"); + return; + } + + if env::var(VAR).is_err() { + parent(); + } else { + child(); + } +} + +fn parent() { + let me = env::current_exe().unwrap(); + let result = Command::new(&me) + .env("RUST_BACKTRACE", "1") + .env(VAR, "1") + .output() + .unwrap(); + if result.status.success() { + println!("test result: ok"); + return; + } + println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout)); + println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr)); + println!("code: {}", result.status); + panic!(); +} + +fn child() { + let done = Arc::new(AtomicBool::new(false)); + let done2 = done.clone(); + let a = thread::spawn(move || loop { + if done2.load(SeqCst) { + break format!("{:?}", backtrace::Backtrace::new()); + } + }); + + let threads = (0..THREADS) + .map(|_| { + thread::spawn(|| { + for _ in 0..PANICS { + assert!(panic::catch_unwind(|| { + panic!(); + }) + .is_err()); + } + }) + }) + .collect::>(); + for thread in threads { + thread.join().unwrap(); + } + + done.store(true, SeqCst); + a.join().unwrap(); +} diff --git a/anneal/v2/vendor/backtrace/tests/current-exe-mismatch.rs b/anneal/v2/vendor/backtrace/tests/current-exe-mismatch.rs new file mode 100644 index 0000000000..d99c574ac1 --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/current-exe-mismatch.rs @@ -0,0 +1,139 @@ +// rust-lang/rust#101913: when you run your program explicitly via `ld.so`, +// `std::env::current_exe` will return the path of *that* program, and not +// the Rust program itself. + +// This behavior is only known to be supported on Linux and FreeBSD, see +// https://mail-index.netbsd.org/tech-toolchain/2024/07/27/msg004469.html + +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +mod common; + +fn main() { + if cfg!(target_os = "netbsd") { + // NetBSD doesn't support this silliness, so because this is an fn main test, + // just pass it on there. If we used ui-test or something we'd use + //@ ignore-netbsd + return; + } + + if std::env::var(VAR).is_err() { + // the parent waits for the child; then we then handle either printing + // "test result: ok", "test result: ignored", or panicking. + match parent() { + Ok(()) => { + println!("test result: ok"); + } + Err(EarlyExit::IgnoreTest) => { + println!("test result: ignored"); + } + Err(EarlyExit::IoError(e)) => { + println!("{} parent encountered IoError: {:?}", file!(), e); + panic!(); + } + } + } else { + // println!("{} running child", file!()); + child().unwrap(); + } +} + +const VAR: &str = "__THE_TEST_YOU_ARE_LUKE"; + +#[derive(Debug)] +enum EarlyExit { + IgnoreTest, + IoError(std::io::Error), +} + +impl From for EarlyExit { + fn from(e: std::io::Error) -> Self { + EarlyExit::IoError(e) + } +} + +fn parent() -> Result<(), EarlyExit> { + // If we cannot re-exec this test, there's no point in trying to do it. + if common::cannot_reexec_the_test() { + return Err(EarlyExit::IgnoreTest); + } + + let me = std::env::current_exe().unwrap(); + let ld_so = find_interpreter(&me)?; + + // use interp to invoke current exe, yielding child test. + // + // (if you're curious what you might compare this against, you can try + // swapping in the below definition for `result`, which is the easy case of + // not using the ld.so interpreter directly that Rust handled fine even + // prior to resolution of rust-lang/rust#101913.) + // + // let result = Command::new(me).env(VAR, "1").output()?; + let result = Command::new(ld_so).env(VAR, "1").arg(&me).output().unwrap(); + + if result.status.success() { + return Ok(()); + } + println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout)); + println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr)); + println!("code: {}", result.status); + panic!(); +} + +fn child() -> Result<(), EarlyExit> { + let bt = backtrace::Backtrace::new(); + println!("{bt:?}"); + + let mut found_my_name = false; + + let my_filename = file!(); + 'frames: for frame in bt.frames() { + let symbols = frame.symbols(); + if symbols.is_empty() { + continue; + } + + for sym in symbols { + if let Some(filename) = sym.filename() { + if filename.ends_with(my_filename) { + // huzzah! + found_my_name = true; + break 'frames; + } + } + } + } + + assert!(found_my_name); + + Ok(()) +} + +// we use the `readelf` command to extract the path to the interpreter requested +// by our binary. +// +// if we cannot `readelf` for some reason, or if we fail to parse its output, +// then we will just give up on this test (and not treat it as a test failure). +fn find_interpreter(me: &Path) -> Result { + let result = Command::new("readelf") + .arg("-l") + .arg(me) + .output() + .map_err(|_| EarlyExit::IgnoreTest)?; + if result.status.success() { + let r = BufReader::new(&result.stdout[..]); + for line in r.lines() { + let line = line?; + let line = line.trim(); + let prefix = "[Requesting program interpreter: "; + if let Some((_, suffix)) = line.split_once(prefix) { + if let Some((found_path, _)) = suffix.rsplit_once("]") { + return Ok(found_path.into()); + } + } + } + } + Err(EarlyExit::IgnoreTest) +} diff --git a/anneal/v2/vendor/backtrace/tests/long_fn_name.rs b/anneal/v2/vendor/backtrace/tests/long_fn_name.rs new file mode 100644 index 0000000000..4a03825b6c --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/long_fn_name.rs @@ -0,0 +1,48 @@ +use backtrace::Backtrace; + +// 50-character module name +mod _234567890_234567890_234567890_234567890_234567890 { + // 50-character struct name + #[allow(non_camel_case_types)] + pub struct _234567890_234567890_234567890_234567890_234567890(T); + impl _234567890_234567890_234567890_234567890_234567890 { + #[allow(dead_code)] + pub fn new() -> crate::Backtrace { + crate::Backtrace::new() + } + } +} + +// Long function names must be truncated to (MAX_SYM_NAME - 1) characters. +// Only run this test for msvc, since gnu prints "" for all frames. +#[test] +#[cfg(all(windows, target_env = "msvc"))] +fn test_long_fn_name() { + use _234567890_234567890_234567890_234567890_234567890::_234567890_234567890_234567890_234567890_234567890 as S; + + // 10 repetitions of struct name, so fully qualified function name is + // atleast 10 * (50 + 50) * 2 = 2000 characters long. + // It's actually longer since it also includes `::`, `<>` and the + // name of the current module + let bt = S::>>>>>>>>>::new(); + println!("{bt:?}"); + + let mut found_long_name_frame = false; + + for frame in bt.frames() { + let symbols = frame.symbols(); + if symbols.is_empty() { + continue; + } + + if let Some(function_name) = symbols[0].name() { + let function_name = function_name.as_str().unwrap(); + if function_name.contains("::_234567890_234567890_234567890_234567890_234567890") { + found_long_name_frame = true; + assert!(function_name.len() > 200); + } + } + } + + assert!(found_long_name_frame); +} diff --git a/anneal/v2/vendor/backtrace/tests/sgx-image-base.rs b/anneal/v2/vendor/backtrace/tests/sgx-image-base.rs new file mode 100644 index 0000000000..c29a8b67a0 --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/sgx-image-base.rs @@ -0,0 +1,56 @@ +#![cfg(all(target_env = "sgx", target_vendor = "fortanix"))] +#![feature(sgx_platform)] + +#[cfg(feature = "std")] +#[test] +fn sgx_image_base_with_std() { + use backtrace::trace; + + let image_base = std::os::fortanix_sgx::mem::image_base(); + + let mut frame_ips = Vec::new(); + trace(|frame| { + frame_ips.push(frame.ip()); + true + }); + + assert!(frame_ips.len() > 0); + for ip in frame_ips { + let ip: u64 = ip as _; + assert!(ip < image_base); + } +} + +#[cfg(not(feature = "std"))] +#[test] +fn sgx_image_base_no_std() { + use backtrace::trace_unsynchronized; + + fn guess_image_base() -> u64 { + let mut top_frame_ip = None; + unsafe { + trace_unsynchronized(|frame| { + top_frame_ip = Some(frame.ip()); + false + }); + } + top_frame_ip.unwrap() as u64 & 0xFFFFFF000000 + } + + let image_base = guess_image_base(); + backtrace::set_image_base(image_base as _); + + let mut frame_ips = Vec::new(); + unsafe { + trace_unsynchronized(|frame| { + frame_ips.push(frame.ip()); + true + }); + } + + assert!(frame_ips.len() > 0); + for ip in frame_ips { + let ip: u64 = ip as _; + assert!(ip < image_base); + } +} diff --git a/anneal/v2/vendor/backtrace/tests/skip_inner_frames.rs b/anneal/v2/vendor/backtrace/tests/skip_inner_frames.rs new file mode 100644 index 0000000000..e62a1603ef --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/skip_inner_frames.rs @@ -0,0 +1,51 @@ +use backtrace::Backtrace; +use core::ffi::c_void; + +// This test only works on platforms which have a working `symbol_address` +// function for frames which reports the starting address of a symbol. As a +// result it's only enabled on a few platforms. +const ENABLED: bool = cfg!(all( + // Windows hasn't really been tested, and macOS doesn't support actually + // finding an enclosing frame, so disable this + target_os = "linux", + // On ARM finding the enclosing function is simply returning the ip itself. + not(target_arch = "arm"), +)); + +#[test] +#[inline(never)] +fn backtrace_new_unresolved_should_start_with_call_site_trace() { + if !ENABLED { + return; + } + let mut b = Backtrace::new_unresolved(); + b.resolve(); + println!("{b:?}"); + + assert!(!b.frames().is_empty()); + + let this_ip = backtrace_new_unresolved_should_start_with_call_site_trace as *mut c_void; + println!("this_ip: {:p}", this_ip); + let frame_ip = b.frames().first().unwrap().symbol_address(); + assert_eq!(this_ip, frame_ip); +} + +#[test] +#[inline(never)] +fn backtrace_new_should_start_with_call_site_trace() { + if !ENABLED { + return; + } + let b = Backtrace::new(); + println!("{b:?}"); + + assert!(!b.frames().is_empty()); + + let this_ip = backtrace_new_should_start_with_call_site_trace as *mut c_void; + let frame_ip = b.frames().first().unwrap().symbol_address(); + assert_eq!(this_ip, frame_ip); + + let trace = format!("{b:?}"); + // FIXME: need more stacktrace content tests + assert!(trace.ends_with("\n")); +} diff --git a/anneal/v2/vendor/backtrace/tests/smoke.rs b/anneal/v2/vendor/backtrace/tests/smoke.rs new file mode 100644 index 0000000000..fd5684f97c --- /dev/null +++ b/anneal/v2/vendor/backtrace/tests/smoke.rs @@ -0,0 +1,325 @@ +use backtrace::Frame; +use core::ffi::c_void; +use std::ptr; +use std::thread; + +fn get_actual_fn_pointer(fp: *mut c_void) -> *mut c_void { + // On AIX, the function name references a function descriptor. + // A function descriptor consists of (See https://reviews.llvm.org/D62532) + // * The address of the entry point of the function. + // * The TOC base address for the function. + // * The environment pointer. + // Deref `fp` directly so that we can get the address of `fp`'s + // entry point in text section. + // + // For TOC, one can find more information in + // https://www.ibm.com/docs/en/aix/7.2?topic=program-understanding-programming-toc + if cfg!(target_os = "aix") { + unsafe { + let actual_fn_entry = *(fp as *const *mut c_void); + actual_fn_entry + } + } else { + fp as *mut c_void + } +} + +#[test] +// FIXME: shouldn't ignore this test on i686-msvc, unsure why it's failing +#[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)] +#[inline(never)] +#[rustfmt::skip] // we care about line numbers here +fn smoke_test_frames() { + frame_1(line!()); + #[inline(never)] fn frame_1(start_line: u32) { frame_2(start_line) } + #[inline(never)] fn frame_2(start_line: u32) { frame_3(start_line) } + #[inline(never)] fn frame_3(start_line: u32) { frame_4(start_line) } + #[inline(never)] fn frame_4(start_line: u32) { + let mut v = Vec::new(); + backtrace::trace(|cx| { + v.push(cx.clone()); + true + }); + + // Various platforms have various bits of weirdness about their + // backtraces. To find a good starting spot let's search through the + // frames + let target = get_actual_fn_pointer(frame_4 as *mut c_void); + let offset = v + .iter() + .map(|frame| frame.symbol_address()) + .enumerate() + .filter_map(|(i, sym)| { + if sym >= target { + Some((sym, i)) + } else { + None + } + }) + .min() + .unwrap() + .1; + let mut frames = v[offset..].iter(); + + assert_frame( + frames.next().unwrap(), + get_actual_fn_pointer(frame_4 as *mut c_void) as usize, + "frame_4", + "tests/smoke.rs", + start_line + 6, + 9, + ); + assert_frame( + frames.next().unwrap(), + get_actual_fn_pointer(frame_3 as *mut c_void) as usize, + "frame_3", + "tests/smoke.rs", + start_line + 3, + 52, + ); + assert_frame( + frames.next().unwrap(), + get_actual_fn_pointer(frame_2 as *mut c_void) as usize, + "frame_2", + "tests/smoke.rs", + start_line + 2, + 52, + ); + assert_frame( + frames.next().unwrap(), + get_actual_fn_pointer(frame_1 as *mut c_void) as usize, + "frame_1", + "tests/smoke.rs", + start_line + 1, + 52, + ); + assert_frame( + frames.next().unwrap(), + get_actual_fn_pointer(smoke_test_frames as *mut c_void) as usize, + "smoke_test_frames", + "", + 0, + 0, + ); + } + + fn assert_frame( + frame: &Frame, + actual_fn_pointer: usize, + expected_name: &str, + expected_file: &str, + expected_line: u32, + expected_col: u32, + ) { + backtrace::resolve_frame(frame, |sym| { + print!("symbol ip:{:?} address:{:?} ", frame.ip(), frame.symbol_address()); + if let Some(name) = sym.name() { + print!("name:{name} "); + } + if let Some(file) = sym.filename() { + print!("file:{} ", file.display()); + } + if let Some(lineno) = sym.lineno() { + print!("lineno:{lineno} "); + } + if let Some(colno) = sym.colno() { + print!("colno:{colno} "); + } + println!(); + }); + + let ip = frame.ip() as usize; + let sym = frame.symbol_address() as usize; + assert!(ip >= sym); + assert!( + sym >= actual_fn_pointer, + "{:?} < {:?} ({} {}:{}:{})", + sym as *const usize, + actual_fn_pointer as *const usize, + expected_name, + expected_file, + expected_line, + expected_col, + ); + + // windows dbghelp is *quite* liberal (and wrong) in many of its reports + // right now... + // + // This assertion can also fail for release builds, so skip it there + if cfg!(debug_assertions) { + assert!(sym - actual_fn_pointer < 1024); + } + + let mut resolved = 0; + + let mut name = None; + let mut addr = None; + let mut col = None; + let mut line = None; + let mut file = None; + backtrace::resolve_frame(frame, |sym| { + resolved += 1; + name = sym.name().map(|v| v.to_string()); + addr = sym.addr(); + col = sym.colno(); + line = sym.lineno(); + file = sym.filename().map(|v| v.to_path_buf()); + }); + assert!(resolved > 0); + + let name = name.expect("didn't find a name"); + + // in release mode names get weird as functions can get merged + // together with `mergefunc`, so only assert this in debug mode + if cfg!(debug_assertions) { + assert!( + name.contains(expected_name), + "didn't find `{expected_name}` in `{name}`" + ); + } + + addr.expect("didn't find a symbol"); + + if cfg!(debug_assertions) { + let line = line.expect("didn't find a line number"); + let file = file.expect("didn't find a line number"); + if !expected_file.is_empty() { + assert!( + file.ends_with(expected_file), + "{file:?} didn't end with {expected_file:?}" + ); + } + if expected_line != 0 { + assert_eq!( + line, + expected_line, + "bad line number on frame for `{expected_name}`: {line} != {expected_line}"); + } + + // dbghelp on MSVC doesn't support column numbers + if !cfg!(target_env = "msvc") { + let col = col.expect("didn't find a column number"); + if expected_col != 0 { + assert_eq!( + col, + expected_col, + "bad column number on frame for `{expected_name}`: {col} != {expected_col}"); + } + } + } + } +} + +#[test] +fn many_threads() { + let threads = (0..16) + .map(|_| { + thread::spawn(|| { + for _ in 0..16 { + backtrace::trace(|frame| { + backtrace::resolve(frame.ip(), |symbol| { + let _s = symbol.name().map(|s| s.to_string()); + }); + true + }); + } + }) + }) + .collect::>(); + + for t in threads { + t.join().unwrap() + } +} + +#[test] +#[cfg(feature = "serde")] +fn is_serde() { + extern crate serde; + + fn is_serialize() {} + fn is_deserialize() {} + + is_serialize::(); + is_deserialize::(); +} + +#[test] +fn sp_smoke_test() { + let mut refs = vec![]; + recursive_stack_references(&mut refs); + return; + + #[inline(never)] + fn recursive_stack_references(refs: &mut Vec<*mut c_void>) { + assert!(refs.len() < 5); + + let mut x = refs.len(); + refs.push(ptr::addr_of_mut!(x).cast()); + + if refs.len() < 5 { + recursive_stack_references(refs); + eprintln!("exiting: {x}"); + return; + } + + backtrace::trace(make_trace_closure(refs)); + eprintln!("exiting: {x}"); + } + + // NB: the following `make_*` functions are pulled out of line, rather than + // defining their results as inline closures at their call sites, so that + // the resulting closures don't have "recursive_stack_references" in their + // mangled names. + + fn make_trace_closure<'a>( + refs: &'a mut Vec<*mut c_void>, + ) -> impl FnMut(&backtrace::Frame) -> bool + 'a { + let mut child_sp = None; + let mut child_ref = None; + move |frame| { + eprintln!("\n=== frame ==================================="); + + let mut is_recursive_stack_references = false; + backtrace::resolve(frame.ip(), |sym| { + is_recursive_stack_references |= + sym.name() + .and_then(|name| name.as_str()) + .map_or(false, |name| { + eprintln!("name = {name}"); + name.contains("recursive_stack_references") + }) + }); + + let sp = frame.sp(); + eprintln!("sp = {sp:p}"); + if sp as usize == 0 { + // If the SP is null, then we don't have an implementation for + // getting the SP on this target. Just keep walking the stack, + // but don't make our assertions about the on-stack pointers and + // SP values. + return true; + } + + // The stack grows down. + if let Some(child_sp) = child_sp { + assert!(child_sp <= sp); + } + + if is_recursive_stack_references { + let r = refs.pop().unwrap(); + eprintln!("ref = {:p}", r); + if sp as usize != 0 { + assert!(r > sp); + if let Some(child_ref) = child_ref { + assert!(sp >= child_ref); + } + } + child_ref = Some(r); + } + + child_sp = Some(sp); + true + } + } +} diff --git a/anneal/v2/vendor/block-buffer-0.10.4/.cargo-checksum.json b/anneal/v2/vendor/block-buffer-0.10.4/.cargo-checksum.json new file mode 100644 index 0000000000..97b339d374 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"83f3846b9d1b0a039b5ca05f910516a6b6f1039e04f5eaadf915456b1259ef71","CHANGELOG.md":"aa53da4c09163e6c269f9536ade5363ae62549295b4f4a85bdf923540f6442e1","Cargo.toml":"c76e4bd298cd6223882238449e31939d75613e82757ca87e249df843decf5f9a","Cargo.toml.orig":"fa80221c48c162058fb829ff845746f7db0ffbc274067b5850bc3d50a437495f","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"d5c22aa3118d240e877ad41c5d9fa232f9c77d757d4aac0c2f943afc0a95e0ef","README.md":"9bf3545872bdad2fb41557be5cefc21a48f0c7804f8124e24b67760429036472","src/lib.rs":"b437252d389042d894b1ef17859b043e827d2bd2a1bca4b5311c67dff565274d","src/sealed.rs":"9327ee3e567ae779b83c2b7f4f3ff56fcb2117163e023e7b0e37759e7e8d1f5c","tests/mod.rs":"a42403629557eea432a8797f2d81a4ab65de15ce9a2db933496c53f05669e1d7"},"package":"3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"} \ No newline at end of file diff --git a/anneal/v2/vendor/block-buffer-0.10.4/.cargo_vcs_info.json b/anneal/v2/vendor/block-buffer-0.10.4/.cargo_vcs_info.json new file mode 100644 index 0000000000..c42a69ad10 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6d35952d3d3b124bc1049ad6fb406b42b1ce4bfe" + }, + "path_in_vcs": "block-buffer" +} \ No newline at end of file diff --git a/anneal/v2/vendor/block-buffer-0.10.4/CHANGELOG.md b/anneal/v2/vendor/block-buffer-0.10.4/CHANGELOG.md new file mode 100644 index 0000000000..66bcf0a1a4 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.10.4 (2023-03-09) +### Fixed +- Unsoundness triggered by zero block size ([#844]) + +[#844]: https://github.com/RustCrypto/utils/pull/844 + +## 0.10.3 (2022-09-04) +### Added +- `try_new` method ([#799]) + +[#799]: https://github.com/RustCrypto/utils/pull/799 + +## 0.10.2 (2021-02-08) +### Fixed +- Eliminate unreachable panic in `LazyBuffer::digest_blocks` ([#731]) + +[#731]: https://github.com/RustCrypto/utils/pull/731 + +## 0.10.1 (2021-02-05) +### Fixed +- Use `as_mut_ptr` to get a pointer for mutation in the `set_data` method ([#728]) + +[#728]: https://github.com/RustCrypto/utils/pull/728 + +## 0.10.0 (2020-12-07) [YANKED] +### Changed +- Significant reduction of number of unreachable panics. ([#671]) +- Added buffer kind type parameter to `BlockBuffer`, respective marker types, and type aliases. ([#671]) +- Various `BlockBuffer` method changes. ([#671]) + +### Removed +- `pad_with` method and dependency on `block-padding`. ([#671]) + +[#671]: https://github.com/RustCrypto/utils/pull/671 + +## 0.10.0 (2020-12-08) +### Changed +- Rename `input_block(s)` methods to `digest_block(s)`. ([#113]) +- Upgrade the `block-padding` dependency to v0.3. ([#113]) + +### Added +- `par_xor_data`, `xor_data`, and `set_data` methods. ([#113]) + +### Removed +- The `input_lazy` method. ([#113]) + +[#113]: https://github.com/RustCrypto/utils/pull/113 diff --git a/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml b/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml new file mode 100644 index 0000000000..4e50744a93 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml @@ -0,0 +1,32 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "block-buffer" +version = "0.10.4" +authors = ["RustCrypto Developers"] +description = "Buffer type for block processing of data" +documentation = "https://docs.rs/block-buffer" +readme = "README.md" +keywords = [ + "block", + "buffer", +] +categories = [ + "cryptography", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RustCrypto/utils" + +[dependencies.generic-array] +version = "0.14" diff --git a/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml.orig b/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml.orig new file mode 100644 index 0000000000..e663069261 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/Cargo.toml.orig @@ -0,0 +1,15 @@ +[package] +name = "block-buffer" +version = "0.10.4" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +description = "Buffer type for block processing of data" +documentation = "https://docs.rs/block-buffer" +repository = "https://github.com/RustCrypto/utils" +keywords = ["block", "buffer"] +categories = ["cryptography", "no-std"] +edition = "2018" +readme = "README.md" + +[dependencies] +generic-array = "0.14" diff --git a/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-APACHE b/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-APACHE new file mode 100644 index 0000000000..78173fa2e7 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-MIT b/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-MIT new file mode 100644 index 0000000000..502cee6e85 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2018-2019 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/block-buffer-0.10.4/README.md b/anneal/v2/vendor/block-buffer-0.10.4/README.md new file mode 100644 index 0000000000..cb134cc91b --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/README.md @@ -0,0 +1,40 @@ +# [RustCrypto]: Block Buffer + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Buffer type for block processing of data with minimized amount of unreachable panics. + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/block-buffer.svg +[crate-link]: https://crates.io/crates/block-buffer +[docs-image]: https://docs.rs/block-buffer/badge.svg +[docs-link]: https://docs.rs/block-buffer/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils +[build-image]: https://github.com/RustCrypto/utils/workflows/block-buffer/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/block-buffer.yml + +[//]: # (general links) + +[RustCrypto]: https://github.com/rustcrypto diff --git a/anneal/v2/vendor/block-buffer-0.10.4/src/lib.rs b/anneal/v2/vendor/block-buffer-0.10.4/src/lib.rs new file mode 100644 index 0000000000..441621e93b --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/src/lib.rs @@ -0,0 +1,350 @@ +//! Fixed size buffer for block processing of data. +#![no_std] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![warn(missing_docs, rust_2018_idioms)] + +pub use generic_array; + +use core::{fmt, marker::PhantomData, slice}; +use generic_array::{ + typenum::{IsLess, Le, NonZero, U256}, + ArrayLength, GenericArray, +}; + +mod sealed; + +/// Block on which `BlockBuffer` operates. +pub type Block = GenericArray; + +/// Trait for buffer kinds. +pub trait BufferKind: sealed::Sealed {} + +/// Eager block buffer kind, which guarantees that buffer position +/// always lies in the range of `0..BlockSize`. +#[derive(Copy, Clone, Debug, Default)] +pub struct Eager {} + +/// Lazy block buffer kind, which guarantees that buffer position +/// always lies in the range of `0..=BlockSize`. +#[derive(Copy, Clone, Debug, Default)] +pub struct Lazy {} + +impl BufferKind for Eager {} +impl BufferKind for Lazy {} + +/// Eager block buffer. +pub type EagerBuffer = BlockBuffer; +/// Lazy block buffer. +pub type LazyBuffer = BlockBuffer; + +/// Block buffer error. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct Error; + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Block buffer error") + } +} + +/// Buffer for block processing of data. +#[derive(Debug)] +pub struct BlockBuffer +where + BlockSize: ArrayLength + IsLess, + Le: NonZero, + Kind: BufferKind, +{ + buffer: Block, + pos: u8, + _pd: PhantomData, +} + +impl Default for BlockBuffer +where + BlockSize: ArrayLength + IsLess, + Le: NonZero, + Kind: BufferKind, +{ + fn default() -> Self { + if BlockSize::USIZE == 0 { + panic!("Block size can not be equal to zero"); + } + Self { + buffer: Default::default(), + pos: 0, + _pd: PhantomData, + } + } +} + +impl Clone for BlockBuffer +where + BlockSize: ArrayLength + IsLess, + Le: NonZero, + Kind: BufferKind, +{ + fn clone(&self) -> Self { + Self { + buffer: self.buffer.clone(), + pos: self.pos, + _pd: PhantomData, + } + } +} + +impl BlockBuffer +where + BlockSize: ArrayLength + IsLess, + Le: NonZero, + Kind: BufferKind, +{ + /// Create new buffer from slice. + /// + /// # Panics + /// If slice length is not valid for used buffer kind. + #[inline(always)] + pub fn new(buf: &[u8]) -> Self { + Self::try_new(buf).unwrap() + } + + /// Create new buffer from slice. + /// + /// Returns an error if slice length is not valid for used buffer kind. + #[inline(always)] + pub fn try_new(buf: &[u8]) -> Result { + if BlockSize::USIZE == 0 { + panic!("Block size can not be equal to zero"); + } + let pos = buf.len(); + if !Kind::invariant(pos, BlockSize::USIZE) { + return Err(Error); + } + let mut buffer = Block::::default(); + buffer[..pos].copy_from_slice(buf); + Ok(Self { + buffer, + pos: pos as u8, + _pd: PhantomData, + }) + } + + /// Digest data in `input` in blocks of size `BlockSize` using + /// the `compress` function, which accepts slice of blocks. + #[inline] + pub fn digest_blocks( + &mut self, + mut input: &[u8], + mut compress: impl FnMut(&[Block]), + ) { + let pos = self.get_pos(); + // using `self.remaining()` for some reason + // prevents panic elimination + let rem = self.size() - pos; + let n = input.len(); + // Note that checking condition `pos + n < BlockSize` is + // equivalent to checking `n < rem`, where `rem` is equal + // to `BlockSize - pos`. Using the latter allows us to work + // around compiler accounting for possible overflow of + // `pos + n` which results in it inserting unreachable + // panic branches. Using `unreachable_unchecked` in `get_pos` + // we convince compiler that `BlockSize - pos` never underflows. + if Kind::invariant(n, rem) { + // double slicing allows to remove panic branches + self.buffer[pos..][..n].copy_from_slice(input); + self.set_pos_unchecked(pos + n); + return; + } + if pos != 0 { + let (left, right) = input.split_at(rem); + input = right; + self.buffer[pos..].copy_from_slice(left); + compress(slice::from_ref(&self.buffer)); + } + + let (blocks, leftover) = Kind::split_blocks(input); + if !blocks.is_empty() { + compress(blocks); + } + + let n = leftover.len(); + self.buffer[..n].copy_from_slice(leftover); + self.set_pos_unchecked(n); + } + + /// Reset buffer by setting cursor position to zero. + #[inline(always)] + pub fn reset(&mut self) { + self.set_pos_unchecked(0); + } + + /// Pad remaining data with zeros and return resulting block. + #[inline(always)] + pub fn pad_with_zeros(&mut self) -> &mut Block { + let pos = self.get_pos(); + self.buffer[pos..].iter_mut().for_each(|b| *b = 0); + self.set_pos_unchecked(0); + &mut self.buffer + } + + /// Return current cursor position. + #[inline(always)] + pub fn get_pos(&self) -> usize { + let pos = self.pos as usize; + if !Kind::invariant(pos, BlockSize::USIZE) { + debug_assert!(false); + // SAFETY: `pos` never breaks the invariant + unsafe { + core::hint::unreachable_unchecked(); + } + } + pos + } + + /// Return slice of data stored inside the buffer. + #[inline(always)] + pub fn get_data(&self) -> &[u8] { + &self.buffer[..self.get_pos()] + } + + /// Set buffer content and cursor position. + /// + /// # Panics + /// If `pos` is bigger or equal to block size. + #[inline] + pub fn set(&mut self, buf: Block, pos: usize) { + assert!(Kind::invariant(pos, BlockSize::USIZE)); + self.buffer = buf; + self.set_pos_unchecked(pos); + } + + /// Return size of the internal buffer in bytes. + #[inline(always)] + pub fn size(&self) -> usize { + BlockSize::USIZE + } + + /// Return number of remaining bytes in the internal buffer. + #[inline(always)] + pub fn remaining(&self) -> usize { + self.size() - self.get_pos() + } + + #[inline(always)] + fn set_pos_unchecked(&mut self, pos: usize) { + debug_assert!(Kind::invariant(pos, BlockSize::USIZE)); + self.pos = pos as u8; + } +} + +impl BlockBuffer +where + BlockSize: ArrayLength + IsLess, + Le: NonZero, +{ + /// Set `data` to generated blocks. + #[inline] + pub fn set_data( + &mut self, + mut data: &mut [u8], + mut process_blocks: impl FnMut(&mut [Block]), + ) { + let pos = self.get_pos(); + let r = self.remaining(); + let n = data.len(); + if pos != 0 { + if n < r { + // double slicing allows to remove panic branches + data.copy_from_slice(&self.buffer[pos..][..n]); + self.set_pos_unchecked(pos + n); + return; + } + let (left, right) = data.split_at_mut(r); + data = right; + left.copy_from_slice(&self.buffer[pos..]); + } + + let (blocks, leftover) = to_blocks_mut(data); + process_blocks(blocks); + + let n = leftover.len(); + if n != 0 { + let mut block = Default::default(); + process_blocks(slice::from_mut(&mut block)); + leftover.copy_from_slice(&block[..n]); + self.buffer = block; + } + self.set_pos_unchecked(n); + } + + /// Compress remaining data after padding it with `delim`, zeros and + /// the `suffix` bytes. If there is not enough unused space, `compress` + /// will be called twice. + /// + /// # Panics + /// If suffix length is bigger than block size. + #[inline(always)] + pub fn digest_pad( + &mut self, + delim: u8, + suffix: &[u8], + mut compress: impl FnMut(&Block), + ) { + if suffix.len() > BlockSize::USIZE { + panic!("suffix is too long"); + } + let pos = self.get_pos(); + self.buffer[pos] = delim; + for b in &mut self.buffer[pos + 1..] { + *b = 0; + } + + let n = self.size() - suffix.len(); + if self.size() - pos - 1 < suffix.len() { + compress(&self.buffer); + let mut block = Block::::default(); + block[n..].copy_from_slice(suffix); + compress(&block); + } else { + self.buffer[n..].copy_from_slice(suffix); + compress(&self.buffer); + } + self.set_pos_unchecked(0) + } + + /// Pad message with 0x80, zeros and 64-bit message length using + /// big-endian byte order. + #[inline] + pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + self.digest_pad(0x80, &data_len.to_be_bytes(), compress); + } + + /// Pad message with 0x80, zeros and 64-bit message length using + /// little-endian byte order. + #[inline] + pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + self.digest_pad(0x80, &data_len.to_le_bytes(), compress); + } + + /// Pad message with 0x80, zeros and 128-bit message length using + /// big-endian byte order. + #[inline] + pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { + self.digest_pad(0x80, &data_len.to_be_bytes(), compress); + } +} + +/// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. +#[inline(always)] +fn to_blocks_mut>(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { + let nb = data.len() / N::USIZE; + let (left, right) = data.split_at_mut(nb * N::USIZE); + let p = left.as_mut_ptr() as *mut Block; + // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for + // mutation + let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; + (blocks, right) +} diff --git a/anneal/v2/vendor/block-buffer-0.10.4/src/sealed.rs b/anneal/v2/vendor/block-buffer-0.10.4/src/sealed.rs new file mode 100644 index 0000000000..247dec2339 --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/src/sealed.rs @@ -0,0 +1,67 @@ +use super::{ArrayLength, Block}; +use core::slice; + +/// Sealed trait for buffer kinds. +pub trait Sealed { + /// Invariant guaranteed by a buffer kind, i.e. with correct + /// buffer code this function always returns true. + fn invariant(pos: usize, block_size: usize) -> bool; + + /// Split input data into slice of blocks and tail. + fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]); +} + +impl Sealed for super::Eager { + #[inline(always)] + fn invariant(pos: usize, block_size: usize) -> bool { + pos < block_size + } + + #[inline(always)] + fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + let nb = data.len() / N::USIZE; + let blocks_len = nb * N::USIZE; + let tail_len = data.len() - blocks_len; + // SAFETY: we guarantee that created slices do not point + // outside of `data` + unsafe { + let blocks_ptr = data.as_ptr() as *const Block; + let tail_ptr = data.as_ptr().add(blocks_len); + ( + slice::from_raw_parts(blocks_ptr, nb), + slice::from_raw_parts(tail_ptr, tail_len), + ) + } + } +} + +impl Sealed for super::Lazy { + #[inline(always)] + fn invariant(pos: usize, block_size: usize) -> bool { + pos <= block_size + } + + #[inline(always)] + fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + if data.is_empty() { + return (&[], &[]); + } + let (nb, tail_len) = if data.len() % N::USIZE == 0 { + (data.len() / N::USIZE - 1, N::USIZE) + } else { + let nb = data.len() / N::USIZE; + (nb, data.len() - nb * N::USIZE) + }; + let blocks_len = nb * N::USIZE; + // SAFETY: we guarantee that created slices do not point + // outside of `data` + unsafe { + let blocks_ptr = data.as_ptr() as *const Block; + let tail_ptr = data.as_ptr().add(blocks_len); + ( + slice::from_raw_parts(blocks_ptr, nb), + slice::from_raw_parts(tail_ptr, tail_len), + ) + } + } +} diff --git a/anneal/v2/vendor/block-buffer-0.10.4/tests/mod.rs b/anneal/v2/vendor/block-buffer-0.10.4/tests/mod.rs new file mode 100644 index 0000000000..ee08f979fa --- /dev/null +++ b/anneal/v2/vendor/block-buffer-0.10.4/tests/mod.rs @@ -0,0 +1,196 @@ +use block_buffer::{ + generic_array::typenum::{U10, U16, U24, U4, U8}, + Block, EagerBuffer, LazyBuffer, +}; + +#[test] +fn test_eager_digest_pad() { + let mut buf = EagerBuffer::::default(); + let inputs = [ + &b"01234567"[..], + &b"89"[..], + &b"abcdefghij"[..], + &b"klmnopqrs"[..], + &b"tuv"[..], + &b"wx"[..], + ]; + let exp_blocks = [ + (0, &[b"0123", b"4567"][..]), + (2, &[b"89ab"][..]), + (2, &[b"cdef", b"ghij"][..]), + (3, &[b"klmn", b"opqr"][..]), + (4, &[b"stuv"][..]), + ]; + let exp_poses = [0, 2, 0, 1, 0, 2]; + + let mut n = 0; + for (i, input) in inputs.iter().enumerate() { + buf.digest_blocks(input, |b| { + let (j, exp) = exp_blocks[n]; + n += 1; + assert_eq!(i, j); + assert_eq!(b.len(), exp.len()); + assert!(b.iter().zip(exp.iter()).all(|v| v.0[..] == v.1[..])); + }); + assert_eq!(exp_poses[i], buf.get_pos()); + } + assert_eq!(buf.pad_with_zeros()[..], b"wx\0\0"[..]); + assert_eq!(buf.get_pos(), 0); +} + +#[test] +fn test_lazy_digest_pad() { + let mut buf = LazyBuffer::::default(); + let inputs = [ + &b"01234567"[..], + &b"89"[..], + &b"abcdefghij"[..], + &b"klmnopqrs"[..], + ]; + let expected = [ + (0, &[b"0123"][..]), + (1, &[b"4567"][..]), + (2, &[b"89ab"][..]), + (2, &[b"cdef"][..]), + (3, &[b"ghij"][..]), + (3, &[b"klmn", b"opqr"][..]), + ]; + let exp_poses = [4, 2, 4, 1]; + + let mut n = 0; + for (i, input) in inputs.iter().enumerate() { + buf.digest_blocks(input, |b| { + let (j, exp) = expected[n]; + n += 1; + assert_eq!(i, j); + assert_eq!(b.len(), exp.len()); + assert!(b.iter().zip(exp.iter()).all(|v| v.0[..] == v.1[..])); + }); + assert_eq!(exp_poses[i], buf.get_pos()); + } + assert_eq!(buf.pad_with_zeros()[..], b"s\0\0\0"[..]); + assert_eq!(buf.get_pos(), 0); +} + +#[test] +fn test_eager_set_data() { + let mut buf = EagerBuffer::::default(); + + let mut n = 0u8; + let mut gen = |blocks: &mut [Block]| { + for block in blocks { + block.iter_mut().for_each(|b| *b = n); + n += 1; + } + }; + + let mut out = [0u8; 6]; + buf.set_data(&mut out, &mut gen); + assert_eq!(out, [0, 0, 0, 0, 1, 1]); + assert_eq!(buf.get_pos(), 2); + + let mut out = [0u8; 3]; + buf.set_data(&mut out, &mut gen); + assert_eq!(out, [1, 1, 2]); + assert_eq!(buf.get_pos(), 1); + + let mut out = [0u8; 3]; + buf.set_data(&mut out, &mut gen); + assert_eq!(out, [2, 2, 2]); + assert_eq!(n, 3); + assert_eq!(buf.get_pos(), 0); +} + +#[test] +#[rustfmt::skip] +fn test_eager_paddings() { + let mut buf_be = EagerBuffer::::new(&[0x42]); + let mut buf_le = buf_be.clone(); + let mut out_be = Vec::::new(); + let mut out_le = Vec::::new(); + let len = 0x0001_0203_0405_0607; + buf_be.len64_padding_be(len, |block| out_be.extend(block)); + buf_le.len64_padding_le(len, |block| out_le.extend(block)); + + assert_eq!( + out_be, + [ + 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + ], + ); + assert_eq!( + out_le, + [ + 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + ], + ); + + let mut buf_be = EagerBuffer::::new(&[0x42]); + let mut buf_le = buf_be.clone(); + let mut out_be = Vec::::new(); + let mut out_le = Vec::::new(); + buf_be.len64_padding_be(len, |block| out_be.extend(block)); + buf_le.len64_padding_le(len, |block| out_le.extend(block)); + + assert_eq!( + out_be, + [0x42, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + ); + assert_eq!( + out_le, + [0x42, 0x80, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00], + ); + + let mut buf = EagerBuffer::::new(&[0x42]); + let mut out = Vec::::new(); + let len = 0x0001_0203_0405_0607_0809_0a0b_0c0d_0e0f; + buf.len128_padding_be(len, |block| out.extend(block)); + assert_eq!( + out, + [ + 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + ], + ); + + let mut buf = EagerBuffer::::new(&[0x42]); + let mut out = Vec::::new(); + let len = 0x0001_0203_0405_0607_0809_0a0b_0c0d_0e0f; + buf.len128_padding_be(len, |block| out.extend(block)); + assert_eq!( + out, + [ + 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + ], + ); + + let mut buf = EagerBuffer::::new(&[0x42]); + let mut out = Vec::::new(); + buf.digest_pad(0xff, &[0x10, 0x11, 0x12], |block| out.extend(block)); + assert_eq!( + out, + [0x42, 0xff, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12], + ); + + let mut buf = EagerBuffer::::new(&[0x42]); + let mut out = Vec::::new(); + buf.digest_pad(0xff, &[0x10, 0x11], |block| out.extend(block)); + assert_eq!( + out, + [0x42, 0xff, 0x10, 0x11], + ); +} + +#[test] +fn test_try_new() { + assert!(EagerBuffer::::try_new(&[0; 3]).is_ok()); + assert!(EagerBuffer::::try_new(&[0; 4]).is_err()); + assert!(LazyBuffer::::try_new(&[0; 4]).is_ok()); + assert!(LazyBuffer::::try_new(&[0; 5]).is_err()); +} diff --git a/anneal/v2/vendor/bumpalo/.cargo-checksum.json b/anneal/v2/vendor/bumpalo/.cargo-checksum.json new file mode 100644 index 0000000000..d3a1d5670f --- /dev/null +++ b/anneal/v2/vendor/bumpalo/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"b1ed86135b2a0bf33517a9f38484fbb9409cf12f3c0667f8c3282cbd77b6aa72","CHANGELOG.md":"ea0358e7d2ca93b2a6f0a1cd192bb671a5bec93bf43c593df341f7dc213cbf06","Cargo.lock":"892e89a25464ab84e41aea30af956ae6b9370e618deda2f05bf880131e780537","Cargo.toml":"a6d2d81f09f1c739f738032bbcb5ecf4d3ce56d2f75e2e8bae9c753b09a6db4c","Cargo.toml.orig":"1102797ebfedc54126105c71195ec74e9643d709ec5f4b956f10fae225f83746","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"65f94e99ddaf4f5d1782a6dae23f35d4293a9a01444a13135a6887017d353cee","README.md":"050b1853333be74aa06088e47f5d53bc18840319d4dd256760d3d860e5e52879","rustfmt.toml":"a2538728f61824b4adab4a970c812fe7bba765b70ccc007303e9d894895f9ad8","src/alloc.rs":"3a9645d9e8db1f2a8549ee928cafa5263a828f25c88ce4d2b07996ecc14bfa81","src/boxed.rs":"ad0ead49343b0eb66464d8c7ec645e145d00558e6a2507d7d7a8c777fc9f5c68","src/collections/collect_in.rs":"0588a4ff3967a4323abb4218bbd615af4b123639ab4fae9130c6590c258b3d15","src/collections/mod.rs":"d58dc46eb4f9fcdde574f09bc5b8646f53e42d49c169561d98e0c23e5b36848a","src/collections/raw_vec.rs":"c045b13f3ac191f1c597f87a7385f59078a3d091f7888d8449d65b9e6f67e315","src/collections/str/lossy.rs":"c5d62b16e01071e2a574ae41ef6693ad12f1e6c786c5d38f7a13ebd6cb23c088","src/collections/str/mod.rs":"d82a8bd417fbf52a589d89a16ea2a0ac4f6ac920c3976ab1f5b6ac0c8493c4f2","src/collections/string.rs":"9cbca6a0c6ae8b9c961d7a140d5146ba4c1f2e7a317c33e2e693911f2848044d","src/collections/vec.rs":"ebb91c051e92c00c192c7b25eea9a5961ff9895a4fe195b29a2d71d0422b4a8c","src/lib.rs":"55dff8791dc6a799e8302439c0b89e532f83677422ebfd0f7a6cacb59aa63bbc"},"package":"72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"} \ No newline at end of file diff --git a/anneal/v2/vendor/bumpalo/.cargo_vcs_info.json b/anneal/v2/vendor/bumpalo/.cargo_vcs_info.json new file mode 100644 index 0000000000..51556aa675 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "84654ace6be4444da3ff102a0a0af3b38c4df4fb" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/bumpalo/CHANGELOG.md b/anneal/v2/vendor/bumpalo/CHANGELOG.md new file mode 100644 index 0000000000..86d43570b9 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/CHANGELOG.md @@ -0,0 +1,929 @@ +## Unreleased + +Released YYYY-MM-DD. + +### Added + +* TODO (or remove section if none) + +### Changed + +* TODO (or remove section if none) + +### Deprecated + +* TODO (or remove section if none) + +### Removed + +* TODO (or remove section if none) + +### Fixed + +* TODO (or remove section if none) + +### Security + +* TODO (or remove section if none) + +-------------------------------------------------------------------------------- + +## 3.20.3 + +Released 2026-05-22. + +### Fixed + +* Fixed the `try_alloc_slice_fill_with`, `alloc_slice_try_fill_with`, + `alloc_slice_fill_with` methods to properly rewind the bump pointer on + allocation, initialization, and panic failure and avoid wasting bump capacity. +* Fixed a drop bug in `bumpalo::collections::vec::DrainFilter` (used by `retain` + and `retain_mut`) when the predicate panics. + +-------------------------------------------------------------------------------- + +## 3.20.2 + +Released 2026-02-19. + +### Fixed + +* Restored `Send` and `Sync` implementations for `Box` for `T: ?Sized` types + as well. + +-------------------------------------------------------------------------------- + +## 3.20.1 + +Released 2026-02-18. + +### Fixed + +* Restored `Send` and `Sync` implementations for `Box` when `T: Send` and `T: + Sync` respectively. + +-------------------------------------------------------------------------------- + +## 3.20.0 + +Released 2026-02-18. + +### Added + +* Added the `bumpalo::collections::Vec::pop_if` method. + +### Fixed + +* Fixed a bug in the `bumpalo::collections::String::retain` method in the face + of panics. +* Made `bumpalo::collections::Box` covariant with `T` (just like + `std::boxed::Box`). + +-------------------------------------------------------------------------------- + +## 3.19.1 + +Released 2025-12-16. + +### Changed + +* Annotated `bumpalo::collections::String::from_str_in` as `#[inline]`. + +### Fixed + +* Fixed compilation failures with the latest nightly Rust when enabling the + unstable `allocator_api` feature. + +-------------------------------------------------------------------------------- + +## 3.19.0 + +Released 2025-06-24. + +### Added + +* Added `bumpalo::collections::Vec::retain_mut`, similar to + `std::vec::Vec::retain_mut`. + +-------------------------------------------------------------------------------- + +## 3.18.1 + +Released 2025-06-05. + +### Removed + +* Removed the `allocator-api2` version bump from 3.18.0, as it was not actually + semver compatible. + +-------------------------------------------------------------------------------- + +## 3.18.0 (yanked) + +Released 2025-06-05. + +### Added + +* Added support for enforcing a minimum alignment on all allocations inside a + `Bump` arena, which can provide speed ups when allocating objects whose + alignment is less than or equal to that minimum. +* Added `serde` serialization support for `bumpalo::collections::String`. +* Added some missing fallible slice allocation function variants. + +### Changed + +* Replaced `extend_from_slice` implementation with a formally-verified version + that is also faster and more-optimizable for LLVM. +* Updated `allocator-api2` support to version `0.3.*`. + +### Fixed + +* Fixed a bug where the `allocated_bytes` metrics helper was accidentally + including the size of `bumpalo`'s footer, rather than just reporting the + user-allocated bytes. + +-------------------------------------------------------------------------------- + +## 3.17.0 + +Released 2025-01-28. + +### Added + +* Added a bunch of `try_` allocation methods for slices and `str`: + * `try_alloc_slice_fill_default` + * `try_alloc_slice_fill_iter` + * `try_alloc_slice_fill_clone` + * `try_alloc_slice_fill_copy` + * `try_alloc_slice_fill_with` + * `try_alloc_str` + * `try_alloc_slice_clone` + * `try_alloc_slice_copy` + +### Changed + +* Minimum supported Rust version reduced to 1.71.1 + +### Fixed + +* Fixed a stacked-borrows MIRI bug in `dealloc` + +-------------------------------------------------------------------------------- + +## 3.16.0 + +Released 2024-04-08. + +### Added + +* Added an optional, off-by-default dependency on the `serde` crate. Enabling + this dependency allows you to serialize Bumpalo's collection and box + types. Deserialization is not implemented, due to constraints of the + deserialization trait. + +-------------------------------------------------------------------------------- + +## 3.15.4 + +Released 2024-03-07. + +### Added + +* Added the `bumpalo::collections::Vec::extend_from_slices_copy` method, which + is a faster way to extend a vec from multiple slices when the element is + `Copy` than calling `extend_from_slice_copy` N times. + +-------------------------------------------------------------------------------- + +## 3.15.3 + +Released 2024-02-22. + +### Added + +* Added additional performance improvements to `bumpalo::collections::Vec` + related to reserving capacity. + +-------------------------------------------------------------------------------- + +## 3.15.2 + +Released 2024-02-21. + +### Added + +* Add a `bumpalo::collections::Vec::extend_from_slice_copy` method. This doesn't + exist on the standard library's `Vec` but they have access to specialization, + so their regular `extend_from_slice` has a specialization for `Copy` + types. Using this new method for `Copy` types is a ~80x performance + improvement over the plain `extend_from_slice` method. + +-------------------------------------------------------------------------------- + +## 3.15.1 + +Released 2024-02-20. + +### Fixed + +* Fixed the MSRV listed in `Cargo.toml`, whose update was forgotten when the + MSRV bumped in release 3.15.0. + +-------------------------------------------------------------------------------- + +## 3.15.0 + +Released 2024-02-15. + +### Changed + +* The minimum supported Rust version (MSRV) is now 1.73.0. +* `bumpalo::collections::String::push_str` and + `bumpalo::collections::String::from_str_in` received significant performance + improvements. +* Allocator trait methods are now marked `#[inline]`, increasing performance for + some callers. + +### Fixed + +* Fixed an edge-case bug in the `Allocator::shrink` method. + +-------------------------------------------------------------------------------- + +## 3.14.0 + +Released 2023-09-14. + +### Added + +* Added the `std` cargo feature, which enables implementations of `std` traits + for various things. Right now that is just `std::io::Write` for + `bumpalo::collections::Vec`, but could be more in the future. + +-------------------------------------------------------------------------------- + +## 3.13.0 + +Released 2023-05-22. + +### Added + +* New `"allocator-api2"` feature enables the use of the allocator API on + stable. This feature uses a crate that mirrors the API of the unstable Rust + `allocator_api` feature. If the feature is enabled, references to `Bump` will + implement `allocator_api2::Allocator`. This allows `Bump` to be used as an + allocator for collection types from `allocator-api2` and any other crates that + support `allocator-api2`. + +### Changed + +* The minimum supported Rust version (MSRV) is now 1.63.0. + +-------------------------------------------------------------------------------- + +## 3.12.2 + +Released 2023-05-09. + +### Changed + +* Added `rust-version` metadata to `Cargo.toml` which helps `cargo` with version + resolution. + +-------------------------------------------------------------------------------- + +## 3.12.1 + +Released 2023-04-21. + +### Fixed + +* Fixed a bug where `Bump::try_with_capacity(n)` where `n > isize::MAX` could + lead to attempts to create invalid `Layout`s. + +-------------------------------------------------------------------------------- + +## 3.12.0 + +Released 2023-01-17. + +### Added + +* Added the `bumpalo::boxed::Box::bump` and `bumpalo::collections::String::bump` + getters to get the underlying `Bump` that a string or box was allocated into. + +### Changed + +* Some uses of `Box` that MIRI did not previously consider as UB are now + reported as UB, and `bumpalo`'s internals have been adjusted to avoid the new + UB. + +-------------------------------------------------------------------------------- + +## 3.11.1 + +Released 2022-10-18. + +### Security + +* Fixed a bug where when `std::vec::IntoIter` was ported to + `bumpalo::collections::vec::IntoIter`, it didn't get its underlying `Bump`'s + lifetime threaded through. This meant that `rustc` was not checking the + borrows for `bumpalo::collections::IntoIter` and this could result in + use-after-free bugs. + +-------------------------------------------------------------------------------- + +## 3.11.0 + +Released 2022-08-17. + +### Added + +* Added support for per-`Bump` allocation limits. These are enforced only in the + slow path when allocating new chunks in the `Bump`, not in the bump allocation + hot path, and therefore impose near zero overhead. +* Added the `bumpalo::boxed::Box::into_inner` method. + +### Changed + +* Updated to Rust 2021 edition. +* The minimum supported Rust version (MSRV) is now 1.56.0. + +-------------------------------------------------------------------------------- + +## 3.10.0 + +Released 2022-06-01. + +### Added + +* Implement `bumpalo::collections::FromIteratorIn` for `Option` and `Result`, + just like `core` does for `FromIterator`. +* Implement `bumpalo::collections::FromIteratorIn` for `bumpalo::boxed::Box<'a, + [T]>`. +* Added running tests under MIRI in CI for additional confidence in unsafe code. +* Publicly exposed `bumpalo::collections::Vec::drain_filter` since the + corresponding `std::vec::Vec` method has stabilized. + +### Changed + +* `Bump::new` will not allocate a backing chunk until the first allocation + inside the bump arena now. + +### Fixed + +* Properly account for alignment changes when growing or shrinking an existing + allocation. +* Removed all internal integer-to-pointer casts, to play better with UB checkers + like MIRI. + +-------------------------------------------------------------------------------- + +## 3.9.1 + +Released 2022-01-06. + +### Fixed + +* Fixed link to logo in docs and README.md + +-------------------------------------------------------------------------------- + +## 3.9.0 + +Released 2022-01-05. + +### Changed + +* The minimum supported Rust version (MSRV) has been raised to Rust 1.54.0. + +* `bumpalo::collections::Vec` implements relevant traits for all arrays of + any size `N` via const generics. Previously, it was just arrays up to length + 32. Similar for `bumpalo::boxed::Box<[T; N]>`. + +-------------------------------------------------------------------------------- + +## 3.8.0 + +Released 2021-10-19. + +### Added + +* Added the `CollectIn` and `FromIteratorIn` traits to make building a + collection from an iterator easier. These new traits live in the + `bumpalo::collections` module and are implemented by + `bumpalo::collections::{String,Vec}`. + +* Added the `Bump::iter_allocated_chunks_raw` method, which is an `unsafe`, raw + version of `Bump::iter_allocated_chunks`. The new method does not take an + exclusive borrow of the `Bump` and yields raw pointer-and-length pairs for + each chunk in the bump. It is the caller's responsibility to ensure that no + allocation happens in the `Bump` while iterating over chunks and that there + are no active borrows of allocated data if they want to turn any + pointer-and-length pairs into slices. + +-------------------------------------------------------------------------------- + +## 3.7.1 + +Released 2021-09-17. + +### Changed + +* The packaged crate uploaded to crates.io when `bumpalo` is published is now + smaller, thanks to excluding unnecessary files. + +-------------------------------------------------------------------------------- + +## 3.7.0 + +Released 2020-05-28. + +### Added + +* Added `Borrow` and `BorrowMut` trait implementations for + `bumpalo::collections::Vec` and + `bumpalo::collections::String`. [#108](https://github.com/fitzgen/bumpalo/pull/108) + +### Changed + +* When allocating a new chunk fails, don't immediately give up. Instead, try + allocating a chunk that is half that size, and if that fails, then try half of + *that* size, etc until either we successfully allocate a chunk or we fail to + allocate the minimum chunk size and then finally give + up. [#111](https://github.com/fitzgen/bumpalo/pull/111) + +-------------------------------------------------------------------------------- + +## 3.6.1 + +Released 2020-02-18. + +### Added + +* Improved performance of `Bump`'s `Allocator::grow_zeroed` trait method + implementation. [#99](https://github.com/fitzgen/bumpalo/pull/99) + +-------------------------------------------------------------------------------- + +## 3.6.0 + +Released 2020-01-29. + +### Added + +* Added a few new flavors of allocation: + + * `try_alloc` for fallible, by-value allocation + + * `try_alloc_with` for fallible allocation with an infallible initializer + function + + * `alloc_try_with` for infallible allocation with a fallible initializer + function + + * `try_alloc_try_with` method for fallible allocation with a fallible + initializer function + + We already have infallible, by-value allocation (`alloc`) and infallible + allocation with an infallible initializer (`alloc_with`). With these new + methods, we now have every combination covered. + + Thanks to [Tamme Schichler](https://github.com/Tamschi) for contributing these + methods! + +-------------------------------------------------------------------------------- + +## 3.5.0 + +Released 2020-01-22. + +### Added + +* Added experimental, unstable support for the unstable, nightly Rust + `allocator_api` feature. + + The `allocator_api` feature defines an `Allocator` trait and exposes custom + allocators for `std` types. Bumpalo has a matching `allocator_api` cargo + feature to enable implementing `Allocator` and using `Bump` with `std` + collections. + + First, enable the `allocator_api` feature in your `Cargo.toml`: + + ```toml + [dependencies] + bumpalo = { version = "3.5", features = ["allocator_api"] } + ``` + + Next, enable the `allocator_api` nightly Rust feature in your `src/lib.rs` or `src/main.rs`: + + ```rust + # #[cfg(feature = "allocator_api")] + # { + #![feature(allocator_api)] + # } + ``` + + Finally, use `std` collections with `Bump`, so that their internal heap + allocations are made within the given bump arena: + + ``` + # #![cfg_attr(feature = "allocator_api", feature(allocator_api))] + # #[cfg(feature = "allocator_api")] + # { + #![feature(allocator_api)] + use bumpalo::Bump; + + // Create a new bump arena. + let bump = Bump::new(); + + // Create a `Vec` whose elements are allocated within the bump arena. + let mut v = Vec::new_in(&bump); + v.push(0); + v.push(1); + v.push(2); + # } + ``` + + I'm very excited to see custom allocators in `std` coming along! Thanks to + Arthur Gautier for implementing support for the `allocator_api` feature for + Bumpalo. + +-------------------------------------------------------------------------------- + +## 3.4.0 + +Released 2020-06-01. + +### Added + +* Added the `bumpalo::boxed::Box` type. It is an owned pointer referencing a + bump-allocated value, and it runs `T`'s `Drop` implementation on the + referenced value when dropped. This type can be used by enabling the `"boxed"` + cargo feature flag. + +-------------------------------------------------------------------------------- + +## 3.3.0 + +Released 2020-05-13. + +### Added + +* Added fallible allocation methods to `Bump`: `try_new`, `try_with_capacity`, + and `try_alloc_layout`. + +* Added `Bump::chunk_capacity` + +* Added `bumpalo::collections::Vec::try_reserve[_exact]` + +-------------------------------------------------------------------------------- + +## 3.2.1 + +Released 2020-03-24. + +### Security + +* When `realloc`ing, if we allocate new space, we need to copy the old + allocation's bytes into the new space. There are `old_size` number of bytes in + the old allocation, but we were accidentally copying `new_size` number of + bytes, which could lead to copying bytes into the realloc'd space from past + the chunk that we're bump allocating out of, from unknown memory. + + If an attacker can cause `realloc`s, and can read the `realoc`ed data back, + this could allow them to read things from other regions of memory that they + shouldn't be able to. For example, if some crypto keys happened to live in + memory right after a chunk we were bump allocating out of, this could allow + the attacker to read the crypto keys. + + Beyond just fixing the bug and adding a regression test, I've also taken two + additional steps: + + 1. While we were already running the testsuite under `valgrind` in CI, because + `valgrind` exits with the same code that the program did, if there are + invalid reads/writes that happen not to trigger a segfault, the program can + still exit OK and we will be none the wiser. I've enabled the + `--error-exitcode=1` flag for `valgrind` in CI so that tests eagerly fail + in these scenarios. + + 2. I've written a quickcheck test to exercise `realloc`. Without the bug fix + in this patch, this quickcheck immediately triggers invalid reads when run + under `valgrind`. We didn't previously have quickchecks that exercised + `realloc` because `realloc` isn't publicly exposed directly, and instead + can only be indirectly called. This new quickcheck test exercises `realloc` + via `bumpalo::collections::Vec::resize` and + `bumpalo::collections::Vec::shrink_to_fit` calls. + + This bug was introduced in version 3.0.0. + + See [#69](https://github.com/fitzgen/bumpalo/issues/69) for details. + +-------------------------------------------------------------------------------- + +## 3.2.0 + +Released 2020-02-07. + +### Added + +* Added the `bumpalo::collections::Vec::into_bump_slice_mut` method to turn a + `bumpalo::collections::Vec<'bump, T>` into a `&'bump mut [T]`. + +-------------------------------------------------------------------------------- + +## 3.1.2 + +Released 2020-01-07. + +### Fixed + +* The `bumpalo::collections::format!` macro did not used to accept a trailing + comma like `format!(in bump; "{}", 1,)`, but it does now. + +-------------------------------------------------------------------------------- + +## 3.1.1 + +Released 2020-01-03. + +### Fixed + +* The `bumpalo::collections::vec!` macro did not used to accept a trailing + comma like `vec![in bump; 1, 2,]`, but it does now. + +-------------------------------------------------------------------------------- + +## 3.1.0 + +Released 2019-12-27. + +### Added + +* Added the `Bump::allocated_bytes` diagnostic method for counting the total + number of bytes a `Bump` has allocated. + +-------------------------------------------------------------------------------- + +# 3.0.0 + +Released 2019-12-20. + +## Added + +* Added `Bump::alloc_str` for copying string slices into a `Bump`. + +* Added `Bump::alloc_slice_copy` and `Bump::alloc_slice_clone` for copying or + cloning slices into a `Bump`. + +* Added `Bump::alloc_slice_fill_iter` for allocating a slice in the `Bump` from + an iterator. + +* Added `Bump::alloc_slice_fill_copy` and `Bump::alloc_slice_fill_clone` for + creating slices of length `n` that are filled with copies or clones of an + initial element. + +* Added `Bump::alloc_slice_fill_default` for creating slices of length `n` with + the element type's default instance. + +* Added `Bump::alloc_slice_fill_with` for creating slices of length `n` whose + elements are initialized with a function or closure. + +* Added `Bump::iter_allocated_chunks` as a replacement for the old + `Bump::each_allocated_chunk`. The `iter_allocated_chunks` version returns an + iterator, which is more idiomatic than its old, callback-taking counterpart. + Additionally, `iter_allocated_chunks` exposes the chunks as `MaybeUninit`s + instead of slices, which makes it usable in more situations without triggering + undefined behavior. See also the note about bump direction in the "changed" + section; if you're iterating chunks, you're likely affected by that change! + +* Added `Bump::with_capacity` so that you can pre-allocate a chunk with the + requested space. + +### Changed + +* **BREAKING:** The direction we allocate within a chunk has changed. It used to + be "upwards", from low addresses within a chunk towards high addresses. It is + now "downwards", from high addresses towards lower addresses. + + Additionally, the order in which we iterate over allocated chunks has changed! + We used to iterate over chunks from oldest chunk to youngest chunk, and now we + do the opposite: the youngest chunks are iterated over first, and the oldest + chunks are iterated over last. + + If you were using `Bump::each_allocated_chunk` to iterate over data that you + had previously allocated, and *you want to iterate in order of + oldest-to-youngest allocation*, you need to reverse the chunks iterator and + also reverse the order in which you loop through the data within a chunk! + + For example, if you had this code: + + ```rust + unsafe { + bump.each_allocated_chunk(|chunk| { + for byte in chunk { + // Touch each byte in oldest-to-youngest allocation order... + } + }); + } + ``` + + It should become this code: + + ```rust + let mut chunks: Vec<_> = bump.iter_allocated_chunks().collect(); + chunks.reverse(); + for chunk in chunks { + for byte in chunk.iter().rev() { + let byte = unsafe { byte.assume_init() }; + // Touch each byte in oldest-to-youngest allocation order... + } + } + ``` + + The good news is that this change yielded a *speed up in allocation throughput + of 3-19%!* + + See https://github.com/fitzgen/bumpalo/pull/37 and + https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html for details. + +* **BREAKING:** The `collections` cargo feature is no longer on by default. You + must explicitly turn it on if you intend to use the `bumpalo::collections` + module. + +* `Bump::reset` will now retain only the last allocated chunk (the biggest), + rather than only the first allocated chunk (the smallest). This should enable + `Bump` to better adapt to workload sizes and quickly reach a steady state + where new chunks are not requested from the global allocator. + +### Removed + +* The `Bump::each_allocated_chunk` method is removed in favor of + `Bump::iter_allocated_chunks`. Note that its safety requirements for reading + from the allocated chunks are slightly different from the old + `each_allocated_chunk`: only up to 16-byte alignment is supported now. If you + allocate anything with greater alignment than that into the bump arena, there + might be uninitialized padding inserted in the chunks, and therefore it is no + longer safe to read them via `MaybeUninit::assume_init`. See also the note + about bump direction in the "changed" section; if you're iterating chunks, + you're likely affected by that change! + +* The `std` cargo feature has been removed, since this crate is now always + no-std. + +## Fixed + +* Fixed a bug involving potential integer overflows with large requested + allocation sizes. + +-------------------------------------------------------------------------------- + +# 2.6.0 + +Released 2019-08-19. + +* Implement `Send` for `Bump`. + +-------------------------------------------------------------------------------- + +# 2.5.0 + +Released 2019-07-01. + +* Add `alloc_slice_copy` and `alloc_slice_clone` methods that allocate space for + slices and either copy (with bound `T: Copy`) or clone (with bound `T: Clone`) + the provided slice's data into the newly allocated space. + +-------------------------------------------------------------------------------- + +# 2.4.3 + +Released 2019-05-20. + +* Fixed a bug where chunks were always deallocated with the default chunk + layout, not the layout that the chunk was actually allocated with (i.e. if we + started growing larger chunks with larger layouts, we would deallocate those + chunks with an incorrect layout). + +-------------------------------------------------------------------------------- + +# 2.4.2 + +Released 2019-05-17. + +* Added an implementation `Default` for `Bump`. +* Made it so that if bump allocation within a chunk overflows, we still try to + allocate a new chunk to bump out of for the requested allocation. This can + avoid some OOMs in scenarios where the chunk we are currently allocating out + of is very near the high end of the address space, and there is still + available address space lower down for new chunks. + +-------------------------------------------------------------------------------- + +# 2.4.1 + +Released 2019-04-19. + +* Added readme metadata to Cargo.toml so it shows up on crates.io + +-------------------------------------------------------------------------------- + +# 2.4.0 + +Released 2019-04-19. + +* Added support for `realloc`ing in-place when the pointer being `realloc`ed is + the last allocation made from the bump arena. This should speed up various + `String`, `Vec`, and `format!` operations in many cases. + +-------------------------------------------------------------------------------- + +# 2.3.0 + +Released 2019-03-26. + +* Add the `alloc_with` method, that (usually) avoids stack-allocating the + allocated value and then moving it into the bump arena. This avoids potential + stack overflows in release mode when allocating very large objects, and also + some `memcpy` calls. This is similar to the `copyless` crate. Read [the + `alloc_with` doc comments][alloc-with-doc-comments] and [the original issue + proposing this API][issue-proposing-alloc-with] for more. + +[alloc-with-doc-comments]: https://github.com/fitzgen/bumpalo/blob/9f47aee8a6839ba65c073b9ad5372aacbbd02352/src/lib.rs#L436-L475 +[issue-proposing-alloc-with]: https://github.com/fitzgen/bumpalo/issues/10 + +-------------------------------------------------------------------------------- + +# 2.2.2 + +Released 2019-03-18. + +* Fix a regression from 2.2.1 where chunks were not always aligned to the chunk + footer's alignment. + +-------------------------------------------------------------------------------- + +# 2.2.1 + +Released 2019-03-18. + +* Fix a regression in 2.2.0 where newly allocated bump chunks could fail to have + capacity for a large requested bump allocation in some corner cases. + +-------------------------------------------------------------------------------- + +# 2.2.0 + +Released 2019-03-15. + +* Chunks in an arena now start out small, and double in size as more chunks are + requested. + +-------------------------------------------------------------------------------- + +# 2.1.0 + +Released 2019-02-12. + +* Added the `into_bump_slice` method on `bumpalo::collections::Vec`. + +-------------------------------------------------------------------------------- + +# 2.0.0 + +Released 2019-02-11. + +* Removed the `BumpAllocSafe` trait. +* Correctly detect overflows from large allocations and panic. + +-------------------------------------------------------------------------------- + +# 1.2.0 + +Released 2019-01-15. + +* Fixed an overly-aggressive `debug_assert!` that had false positives. +* Ported to Rust 2018 edition. + +-------------------------------------------------------------------------------- + +# 1.1.0 + +Released 2018-11-28. + +* Added the `collections` module, which contains ports of `std`'s collection + types that are compatible with backing their storage in `Bump` arenas. +* Lifted the limits on size and alignment of allocations. + +-------------------------------------------------------------------------------- + +# 1.0.2 + +-------------------------------------------------------------------------------- + +# 1.0.1 + +-------------------------------------------------------------------------------- + +# 1.0.0 diff --git a/anneal/v2/vendor/bumpalo/Cargo.lock b/anneal/v2/vendor/bumpalo/Cargo.lock new file mode 100644 index 0000000000..03f8b14c8c --- /dev/null +++ b/anneal/v2/vendor/bumpalo/Cargo.lock @@ -0,0 +1,697 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e" + +[[package]] +name = "allocator-api2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c880a97d28a3681c0267bd29cff89621202715b065127cd445fa0f0fe0aa2880" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blink-alloc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce4c15bad517bc0fb4a44523adf470e2c3eb3a365769327acdba849948ea3705" +dependencies = [ + "allocator-api2 0.4.0", +] + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "bumpalo" +version = "3.20.3" +dependencies = [ + "allocator-api2 0.2.14", + "blink-alloc", + "criterion", + "quickcheck", + "rand", + "rayon", + "rayon-core", + "serde", + "serde_json", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "once_cell", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "either" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "js-sys" +version = "0.3.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "plotters" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger", + "log", + "rand", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa 1.0.3", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +dependencies = [ + "bumpalo 3.11.0", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.99", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.99", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" + +[[package]] +name = "web-sys" +version = "0.3.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/anneal/v2/vendor/bumpalo/Cargo.toml b/anneal/v2/vendor/bumpalo/Cargo.toml new file mode 100644 index 0000000000..30fe787c61 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/Cargo.toml @@ -0,0 +1,99 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.71.1" +name = "bumpalo" +version = "3.20.3" +authors = ["Nick Fitzgerald "] +build = false +exclude = [ + "/.github/*", + "/benches", + "/tests", + "valgrind.supp", + "bumpalo.png", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A fast bump allocation arena for Rust." +documentation = "https://docs.rs/bumpalo" +readme = "README.md" +keywords = [ + "arena", + "bump", + "allocator", +] +categories = [ + "memory-management", + "rust-patterns", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/fitzgen/bumpalo" + +[package.metadata.docs.rs] +all-features = true + +[features] +allocator_api = [] +bench_allocator_api = [ + "allocator_api", + "blink-alloc/nightly", +] +boxed = [] +collections = [] +default = [] +serde = ["dep:serde"] +std = [] + +[lib] +name = "bumpalo" +path = "src/lib.rs" +bench = false + +[dependencies.allocator-api2] +version = "0.2.8" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0.171" +optional = true + +[dev-dependencies.blink-alloc] +version = "=0.4.0" + +[dev-dependencies.criterion] +version = "0.3.6" + +[dev-dependencies.quickcheck] +version = "=1.0.3" + +[dev-dependencies.rand] +version = "0.8.5" + +[dev-dependencies.rayon] +version = "=1.10.0" + +[dev-dependencies.rayon-core] +version = "=1.12.1" + +[dev-dependencies.serde] +version = "1.0.197" +features = ["derive"] + +[dev-dependencies.serde_json] +version = "1.0.115" diff --git a/anneal/v2/vendor/bumpalo/Cargo.toml.orig b/anneal/v2/vendor/bumpalo/Cargo.toml.orig new file mode 100644 index 0000000000..e6be0547ae --- /dev/null +++ b/anneal/v2/vendor/bumpalo/Cargo.toml.orig @@ -0,0 +1,73 @@ +[package] +authors = ["Nick Fitzgerald "] +categories = ["memory-management", "rust-patterns", "no-std"] +description = "A fast bump allocation arena for Rust." +documentation = "https://docs.rs/bumpalo" +keywords = ["arena", "bump", "allocator"] +edition = "2021" +exclude = ["/.github/*", "/benches", "/tests", "valgrind.supp", "bumpalo.png"] +license = "MIT OR Apache-2.0" +name = "bumpalo" +readme = "README.md" +repository = "https://github.com/fitzgen/bumpalo" +rust-version = "1.71.1" +version = "3.20.3" + +[package.metadata.docs.rs] +all-features = true + +[lib] +path = "src/lib.rs" +bench = false + +[[bench]] +name = "benches" +path = "benches/benches.rs" +harness = false +required-features = ["collections"] + +[[bench]] +name = "allocator_api" +path = "benches/allocator_api.rs" +harness = false +required-features = ["bench_allocator_api"] + +[[test]] +name = "try_alloc" +path = "tests/try_alloc.rs" +harness = false + +[dependencies] +# This dependency provides a version of the unstable nightly Rust `Allocator` +# trait on stable Rust. Enabling this feature means that `bumpalo` will +# implement its `Allocator` trait. +allocator-api2 = { version = "0.2.8", default-features = false, optional = true } + +# This dependency is here to allow integration with Serde, if the `serde` feature is enabled +serde = { version = "1.0.171", optional = true } + +[dev-dependencies] +quickcheck = "=1.0.3" +criterion = "0.3.6" +rand = "0.8.5" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" +blink-alloc = { version = "=0.4.0" } + +# Make sure that criterion pulls in a rayon that supports our MSRV. +rayon = { version = "=1.10.0" } +rayon-core = { version = "=1.12.1" } + +[features] +default = [] +collections = [] +boxed = [] +allocator_api = [] +std = [] +serde = ["dep:serde"] + +# Feature for bumpalo's internal development only. Do not use! +bench_allocator_api = ["allocator_api", "blink-alloc/nightly"] + +# [profile.bench] +# debug = true diff --git a/anneal/v2/vendor/bumpalo/LICENSE-APACHE b/anneal/v2/vendor/bumpalo/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/bumpalo/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/bumpalo/LICENSE-MIT b/anneal/v2/vendor/bumpalo/LICENSE-MIT new file mode 100644 index 0000000000..bac6fb98de --- /dev/null +++ b/anneal/v2/vendor/bumpalo/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2019 Nick Fitzgerald + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/bumpalo/README.md b/anneal/v2/vendor/bumpalo/README.md new file mode 100644 index 0000000000..9c80b3037e --- /dev/null +++ b/anneal/v2/vendor/bumpalo/README.md @@ -0,0 +1,261 @@ +# `bumpalo` + +**A fast bump allocation arena for Rust.** + +[![](https://docs.rs/bumpalo/badge.svg)](https://docs.rs/bumpalo/) +[![](https://img.shields.io/crates/v/bumpalo.svg)](https://crates.io/crates/bumpalo) +[![](https://img.shields.io/crates/d/bumpalo.svg)](https://crates.io/crates/bumpalo) +[![Build Status](https://github.com/fitzgen/bumpalo/workflows/Rust/badge.svg)](https://github.com/fitzgen/bumpalo/actions?query=workflow%3ARust) + +![](https://github.com/fitzgen/bumpalo/raw/main/bumpalo.png) + +### Bump Allocation + +Bump allocation is a fast, but limited approach to allocation. We have a chunk +of memory, and we maintain a pointer within that memory. Whenever we allocate an +object, we do a quick check that we have enough capacity left in our chunk to +allocate the object and then update the pointer by the object's size. *That's +it!* + +The disadvantage of bump allocation is that there is no general way to +deallocate individual objects or reclaim the memory region for a +no-longer-in-use object. + +These trade offs make bump allocation well-suited for *phase-oriented* +allocations. That is, a group of objects that will all be allocated during the +same program phase, used, and then can all be deallocated together as a group. + +### Deallocation en Masse, but no `Drop` + +To deallocate all the objects in the arena at once, we can simply reset the bump +pointer back to the start of the arena's memory chunk. This makes mass +deallocation *extremely* fast, but allocated objects' [`Drop`] implementations are +not invoked. + +> **However:** [`bumpalo::boxed::Box`][box] can be used to wrap +> `T` values allocated in the `Bump` arena, and calls `T`'s `Drop` +> implementation when the `Box` wrapper goes out of scope. This is similar to +> how [`std::boxed::Box`] works, except without deallocating its backing memory. + +[`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html +[box]: https://docs.rs/bumpalo/latest/bumpalo/boxed/struct.Box.html +[`std::boxed::Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html + +### What happens when the memory chunk is full? + +This implementation will allocate a new memory chunk from the global allocator +and then start bump allocating into this new memory chunk. + +### Example + +```rust +use bumpalo::Bump; + +struct Doggo { + cuteness: u64, + age: u8, + scritches_required: bool, +} + +// Create a new arena to bump allocate into. +let bump = Bump::new(); + +// Allocate values into the arena. +let scooter = bump.alloc(Doggo { + cuteness: u64::MAX, + age: 8, + scritches_required: true, +}); + +// Exclusive, mutable references to the just-allocated value are returned. +assert!(scooter.scritches_required); +scooter.age += 1; +``` + +### Collections + +When the `"collections"` cargo feature is enabled, a fork of some of the `std` +library's collections are available in the [`collections`] module. These +collection types are modified to allocate their space inside `bumpalo::Bump` +arenas. + +[`collections`]: https://docs.rs/bumpalo/latest/bumpalo/collections/index.html + +```rust +#[cfg(feature = "collections")] +{ + use bumpalo::{Bump, collections::Vec}; + + // Create a new bump arena. + let bump = Bump::new(); + + // Create a vector of integers whose storage is backed by the bump arena. The + // vector cannot outlive its backing arena, and this property is enforced with + // Rust's lifetime rules. + let mut v = Vec::new_in(&bump); + + // Push a bunch of integers onto `v`! + for i in 0..100 { + v.push(i); + } +} +``` + +Eventually [all `std` collection types will be parameterized by an +allocator](https://github.com/rust-lang/rust/issues/42774) and we can remove +this `collections` module and use the `std` versions. + +For unstable, nightly-only support for custom allocators in `std`, see the +`allocator_api` section below. + +### `bumpalo::boxed::Box` + +When the `"boxed"` cargo feature is enabled, a fork of `std::boxed::Box` +is available in the `boxed` module. This `Box` type is modified to allocate its +space inside `bumpalo::Bump` arenas. + +**A `Box` runs `T`'s drop implementation when the `Box` is dropped.** You +can use this to work around the fact that `Bump` does not drop values allocated +in its space itself. + +```rust +#[cfg(feature = "boxed")] +{ + use bumpalo::{Bump, boxed::Box}; + use std::sync::atomic::{AtomicUsize, Ordering}; + + static NUM_DROPPED: AtomicUsize = AtomicUsize::new(0); + + struct CountDrops; + + impl Drop for CountDrops { + fn drop(&mut self) { + NUM_DROPPED.fetch_add(1, Ordering::SeqCst); + } + } + + // Create a new bump arena. + let bump = Bump::new(); + + // Create a `CountDrops` inside the bump arena. + let mut c = Box::new_in(CountDrops, &bump); + + // No `CountDrops` have been dropped yet. + assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 0); + + // Drop our `Box`. + drop(c); + + // Its `Drop` implementation was run, and so `NUM_DROPS` has been + // incremented. + assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 1); +} +``` + +#### Serde + +Adding the `serde` feature flag will enable transparent serialization of `Vec`s, `String`s +and boxed values. + +```toml +[dependencies] +bumpalo = { version = "3.18", features = ["collections", "boxed", "serde"] } +``` + +```rust,ignore +use bumpalo::{Bump, boxed::Box, collections::Vec}; + +// Create a new bump arena. +let bump = Bump::new(); + +// Create a `Box` +let box = Box::new_in("hello", &bump); + +// Serialize with serde_json +assert_eq!(serde_json::to_string(&box).unwrap(), "\"hello\""); + +// Create a `Vec` +let vec = Vec::new_in( &bump); +vec.push(1); +vec.push(2); + +// Serialize with serde_json +assert_eq!(serde_json::to_string(&vec).unwrap(), "[1, 2]"); +``` + +### `#![no_std]` Support + +Bumpalo is a `no_std` crate by default. It depends only on the `alloc` and `core` crates. + +### `std` Support + +You can optionally decide to enable the `std` feature in order to enable some +std only trait implementations for some collections: + +* `std::io::Write` for `Vec<'bump, u8>` + +### Thread support + +The `Bump` is `!Sync`, which makes it hard to use in certain situations around +threads ‒ for example in `rayon`. + +The [`bumpalo-herd`](https://crates.io/crates/bumpalo-herd) crate provides a +pool of `Bump` allocators for use in such situations. + +### Nightly Rust `allocator_api` Support + +The unstable, nightly-only Rust `allocator_api` feature defines an [`Allocator`] +trait and exposes custom allocators for `std` types. Bumpalo has a matching +`allocator_api` cargo feature to enable implementing `Allocator` and using +`Bump` with `std` collections. Note that, as `feature(allocator_api)` is +unstable and only in nightly Rust, Bumpalo's matching `allocator_api` cargo +feature should be considered unstable, and will not follow the semver +conventions that the rest of the crate does. + +First, enable the `allocator_api` feature in your `Cargo.toml`: + +```toml +[dependencies] +bumpalo = { version = "3", features = ["allocator_api"] } +``` + +Next, enable the `allocator_api` nightly Rust feature in your `src/lib.rs` or +`src/main.rs`: + +```rust,ignore +#![feature(allocator_api)] +``` + +Finally, use `std` collections with `Bump`, so that their internal heap +allocations are made within the given bump arena: + +```rust,ignore +use bumpalo::Bump; + +// Create a new bump arena. +let bump = Bump::new(); + +// Create a `Vec` whose elements are allocated within the bump arena. +let mut v = Vec::new_in(&bump); +v.push(0); +v.push(1); +v.push(2); +``` + +[`Allocator`]: https://doc.rust-lang.org/std/alloc/trait.Allocator.html + +### Using the `Allocator` API on Stable Rust + +You can enable the `allocator-api2` Cargo feature and `bumpalo` will use [the +`allocator-api2` crate](https://crates.io/crates/allocator-api2) to implement +the unstable nightly`Allocator` API on stable Rust. This means that +`bumpalo::Bump` will be usable with any collection that is generic over +`allocator_api2::Allocator`. + +### Minimum Supported Rust Version (MSRV) + +This crate is guaranteed to compile on stable Rust **1.71.1** and up. It might +compile with older versions but that may change in any new patch release. + +We reserve the right to increment the MSRV on minor releases, however we will +strive to only do it deliberately and for good reasons. diff --git a/anneal/v2/vendor/bumpalo/rustfmt.toml b/anneal/v2/vendor/bumpalo/rustfmt.toml new file mode 100644 index 0000000000..70f60c642c --- /dev/null +++ b/anneal/v2/vendor/bumpalo/rustfmt.toml @@ -0,0 +1 @@ +edition = '2024' diff --git a/anneal/v2/vendor/bumpalo/src/alloc.rs b/anneal/v2/vendor/bumpalo/src/alloc.rs new file mode 100644 index 0000000000..6947e2a6cf --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/alloc.rs @@ -0,0 +1,794 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unstable_name_collisions)] +#![allow(dead_code)] +#![allow(deprecated)] + +//! Memory allocation APIs + +use core::cmp; +use core::fmt; +use core::mem; +use core::ptr::{self, NonNull}; +use core::usize; + +pub use core::alloc::{Layout, LayoutErr}; + +fn new_layout_err() -> LayoutErr { + Layout::from_size_align(1, 3).unwrap_err() +} + +pub fn handle_alloc_error(layout: Layout) -> ! { + panic!("encountered allocation error: {:?}", layout) +} + +pub trait UnstableLayoutMethods { + fn padding_needed_for(&self, align: usize) -> usize; + fn repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr>; + fn array(n: usize) -> Result; +} + +impl UnstableLayoutMethods for Layout { + fn padding_needed_for(&self, align: usize) -> usize { + let len = self.size(); + + // Rounded up value is: + // len_rounded_up = (len + align - 1) & !(align - 1); + // and then we return the padding difference: `len_rounded_up - len`. + // + // We use modular arithmetic throughout: + // + // 1. align is guaranteed to be > 0, so align - 1 is always + // valid. + // + // 2. `len + align - 1` can overflow by at most `align - 1`, + // so the &-mask with `!(align - 1)` will ensure that in the + // case of overflow, `len_rounded_up` will itself be 0. + // Thus the returned padding, when added to `len`, yields 0, + // which trivially satisfies the alignment `align`. + // + // (Of course, attempts to allocate blocks of memory whose + // size and padding overflow in the above manner should cause + // the allocator to yield an error anyway.) + + let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); + len_rounded_up.wrapping_sub(len) + } + + fn repeat(&self, n: usize) -> Result<(Layout, usize), LayoutErr> { + let padded_size = self + .size() + .checked_add(self.padding_needed_for(self.align())) + .ok_or_else(new_layout_err)?; + let alloc_size = padded_size.checked_mul(n).ok_or_else(new_layout_err)?; + + unsafe { + // self.align is already known to be valid and alloc_size has been + // padded already. + Ok(( + Layout::from_size_align_unchecked(alloc_size, self.align()), + padded_size, + )) + } + } + + fn array(n: usize) -> Result { + Layout::new::().repeat(n).map(|(k, offs)| { + debug_assert!(offs == mem::size_of::()); + k + }) + } +} + +/// Represents the combination of a starting address and +/// a total capacity of the returned block. +// #[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Debug)] +pub struct Excess(pub NonNull, pub usize); + +fn size_align() -> (usize, usize) { + (mem::size_of::(), mem::align_of::()) +} + +/// The `AllocErr` error indicates an allocation failure +/// that may be due to resource exhaustion or to +/// something wrong when combining the given input arguments with this +/// allocator. +// #[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AllocErr; + +// (we need this for downstream impl of trait Error) +// #[unstable(feature = "allocator_api", issue = "32838")] +impl fmt::Display for AllocErr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("memory allocation failed") + } +} + +/// The `CannotReallocInPlace` error is used when `grow_in_place` or +/// `shrink_in_place` were unable to reuse the given memory block for +/// a requested layout. +// #[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CannotReallocInPlace; + +// #[unstable(feature = "allocator_api", issue = "32838")] +impl CannotReallocInPlace { + pub fn description(&self) -> &str { + "cannot reallocate allocator's memory in place" + } +} + +// (we need this for downstream impl of trait Error) +// #[unstable(feature = "allocator_api", issue = "32838")] +impl fmt::Display for CannotReallocInPlace { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.description()) + } +} + +/// An implementation of `Alloc` can allocate, reallocate, and +/// deallocate arbitrary blocks of data described via `Layout`. +/// +/// Some of the methods require that a memory block be *currently +/// allocated* via an allocator. This means that: +/// +/// * the starting address for that memory block was previously +/// returned by a previous call to an allocation method (`alloc`, +/// `alloc_zeroed`, `alloc_excess`, `alloc_one`, `alloc_array`) or +/// reallocation method (`realloc`, `realloc_excess`, or +/// `realloc_array`), and +/// +/// * the memory block has not been subsequently deallocated, where +/// blocks are deallocated either by being passed to a deallocation +/// method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being +/// passed to a reallocation method (see above) that returns `Ok`. +/// +/// A note regarding zero-sized types and zero-sized layouts: many +/// methods in the `Alloc` trait state that allocation requests +/// must be non-zero size, or else undefined behavior can result. +/// +/// * However, some higher-level allocation methods (`alloc_one`, +/// `alloc_array`) are well-defined on zero-sized types and can +/// optionally support them: it is left up to the implementor +/// whether to return `Err`, or to return `Ok` with some pointer. +/// +/// * If an `Alloc` implementation chooses to return `Ok` in this +/// case (i.e. the pointer denotes a zero-sized inaccessible block) +/// then that returned pointer must be considered "currently +/// allocated". On such an allocator, *all* methods that take +/// currently-allocated pointers as inputs must accept these +/// zero-sized pointers, *without* causing undefined behavior. +/// +/// * In other words, if a zero-sized pointer can flow out of an +/// allocator, then that allocator must likewise accept that pointer +/// flowing back into its deallocation and reallocation methods. +/// +/// Some of the methods require that a layout *fit* a memory block. +/// What it means for a layout to "fit" a memory block means (or +/// equivalently, for a memory block to "fit" a layout) is that the +/// following two conditions must hold: +/// +/// 1. The block's starting address must be aligned to `layout.align()`. +/// +/// 2. The block's size must fall in the range `[use_min, use_max]`, where: +/// +/// * `use_min` is `self.usable_size(layout).0`, and +/// +/// * `use_max` is the capacity that was (or would have been) +/// returned when (if) the block was allocated via a call to +/// `alloc_excess` or `realloc_excess`. +/// +/// Note that: +/// +/// * the size of the layout most recently used to allocate the block +/// is guaranteed to be in the range `[use_min, use_max]`, and +/// +/// * a lower-bound on `use_max` can be safely approximated by a call to +/// `usable_size`. +/// +/// * if a layout `k` fits a memory block (denoted by `ptr`) +/// currently allocated via an allocator `a`, then it is legal to +/// use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`. +/// +/// # Unsafety +/// +/// The `Alloc` trait is an `unsafe` trait for a number of reasons, and +/// implementors must ensure that they adhere to these contracts: +/// +/// * Pointers returned from allocation functions must point to valid memory and +/// retain their validity until at least the instance of `Alloc` is dropped +/// itself. +/// +/// * `Layout` queries and calculations in general must be correct. Callers of +/// this trait are allowed to rely on the contracts defined on each method, +/// and implementors must ensure such contracts remain true. +/// +/// Note that this list may get tweaked over time as clarifications are made in +/// the future. +// #[unstable(feature = "allocator_api", issue = "32838")] +pub unsafe trait Alloc { + // (Note: some existing allocators have unspecified but well-defined + // behavior in response to a zero size allocation request ; + // e.g. in C, `malloc` of 0 will either return a null pointer or a + // unique pointer, but will not have arbitrary undefined + // behavior. + // However in jemalloc for example, + // `mallocx(0)` is documented as undefined behavior.) + + /// Returns a pointer meeting the size and alignment guarantees of + /// `layout`. + /// + /// If this method returns an `Ok(addr)`, then the `addr` returned + /// will be non-null address pointing to a block of storage + /// suitable for holding an instance of `layout`. + /// + /// The returned block of storage may or may not have its contents + /// initialized. (Extension subtraits might restrict this + /// behavior, e.g. to ensure initialization to particular sets of + /// bit patterns.) + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure that `layout` has non-zero size. + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints. + /// + /// Implementations are encouraged to return `Err` on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr>; + + /// Deallocate the memory referenced by `ptr`. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must denote a block of memory currently allocated via + /// this allocator, + /// + /// * `layout` must *fit* that block of memory, + /// + /// * In addition to fitting the block of memory `layout`, the + /// alignment of the `layout` must match the alignment used + /// to allocate that block of memory. + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); + + // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == + // usable_size + + /// Returns bounds on the guaranteed usable size of a successful + /// allocation created with the specified `layout`. + /// + /// In particular, if one has a memory block allocated via a given + /// allocator `a` and layout `k` where `a.usable_size(k)` returns + /// `(l, u)`, then one can pass that block to `a.dealloc()` with a + /// layout in the size range [l, u]. + /// + /// (All implementors of `usable_size` must ensure that + /// `l <= k.size() <= u`) + /// + /// Both the lower- and upper-bounds (`l` and `u` respectively) + /// are provided, because an allocator based on size classes could + /// misbehave if one attempts to deallocate a block without + /// providing a correct value for its size (i.e., one within the + /// range `[l, u]`). + /// + /// Clients who wish to make use of excess capacity are encouraged + /// to use the `alloc_excess` and `realloc_excess` instead, as + /// this method is constrained to report conservative values that + /// serve as valid bounds for *all possible* allocation method + /// calls. + /// + /// However, for clients that do not wish to track the capacity + /// returned by `alloc_excess` locally, this method is likely to + /// produce useful results. + #[inline] + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + (layout.size(), layout.size()) + } + + // == METHODS FOR MEMORY REUSE == + // realloc. alloc_excess, realloc_excess + + /// Returns a pointer suitable for holding data described by + /// a new layout with `layout`’s alignment and a size given + /// by `new_size`. To + /// accomplish this, this may extend or shrink the allocation + /// referenced by `ptr` to fit the new layout. + /// + /// If this returns `Ok`, then ownership of the memory block + /// referenced by `ptr` has been transferred to this + /// allocator. The memory may or may not have been freed, and + /// should be considered unusable (unless of course it was + /// transferred back to the caller again via the return value of + /// this method). + /// + /// If this method returns `Err`, then ownership of the memory + /// block has not been transferred to this allocator, and the + /// contents of the memory block are unaltered. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above). (The `new_size` + /// argument need not fit it.) + /// + /// * `new_size` must be greater than zero. + /// + /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, + /// must not overflow (i.e. the rounded value must be less than `usize::MAX`). + /// + /// (Extension subtraits might provide more specific bounds on + /// behavior, e.g. guarantee a sentinel address or a null pointer + /// in response to a zero-size allocation request.) + /// + /// # Errors + /// + /// Returns `Err` only if the new layout + /// does not meet the allocator's size + /// and alignment constraints of the allocator, or if reallocation + /// otherwise fails. + /// + /// Implementations are encouraged to return `Err` on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn realloc( + &mut self, + ptr: NonNull, + layout: Layout, + new_size: usize, + ) -> Result, AllocErr> { + let old_size = layout.size(); + + if new_size >= old_size { + if let Ok(()) = self.grow_in_place(ptr, layout, new_size) { + return Ok(ptr); + } + } else if new_size < old_size { + if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { + return Ok(ptr); + } + } + + // otherwise, fall back on alloc + copy + dealloc. + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let result = self.alloc(new_layout); + if let Ok(new_ptr) = result { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); + self.dealloc(ptr, layout); + } + result + } + + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { + let size = layout.size(); + let p = self.alloc(layout); + if let Ok(p) = p { + ptr::write_bytes(p.as_ptr(), 0, size); + } + p + } + + /// Behaves like `alloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { + let usable_size = self.usable_size(&layout); + self.alloc(layout).map(|p| Excess(p, usable_size.1)) + } + + /// Behaves like `realloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `realloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `realloc`. + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn realloc_excess( + &mut self, + ptr: NonNull, + layout: Layout, + new_size: usize, + ) -> Result { + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let usable_size = self.usable_size(&new_layout); + self.realloc(ptr, layout, new_size) + .map(|p| Excess(p, usable_size.1)) + } + + /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`. + /// + /// If this returns `Ok`, then the allocator has asserted that the + /// memory block referenced by `ptr` now fits `new_size`, and thus can + /// be used to carry data of a layout of that size and same alignment as + /// `layout`. (The allocator is allowed to + /// expend effort to accomplish this, such as extending the memory block to + /// include successor blocks, or virtual memory tricks.) + /// + /// Regardless of what this method returns, ownership of the + /// memory block referenced by `ptr` has not been transferred, and + /// the contents of the memory block are unaltered. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above); note the + /// `new_size` argument need not fit it, + /// + /// * `new_size` must not be less than `layout.size()`, + /// + /// # Errors + /// + /// Returns `Err(CannotReallocInPlace)` when the allocator is + /// unable to assert that the memory block referenced by `ptr` + /// could fit `layout`. + /// + /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error` + /// function; clients are expected either to be able to recover from + /// `grow_in_place` failures without aborting, or to fall back on + /// another reallocation method before resorting to an abort. + unsafe fn grow_in_place( + &mut self, + ptr: NonNull, + layout: Layout, + new_size: usize, + ) -> Result<(), CannotReallocInPlace> { + let _ = ptr; // this default implementation doesn't care about the actual address. + debug_assert!(new_size >= layout.size()); + let (_l, u) = self.usable_size(&layout); + // _l <= layout.size() [guaranteed by usable_size()] + // layout.size() <= new_layout.size() [required by this method] + if new_size <= u { + Ok(()) + } else { + Err(CannotReallocInPlace) + } + } + + /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`. + /// + /// If this returns `Ok`, then the allocator has asserted that the + /// memory block referenced by `ptr` now fits `new_size`, and + /// thus can only be used to carry data of that smaller + /// layout. (The allocator is allowed to take advantage of this, + /// carving off portions of the block for reuse elsewhere.) The + /// truncated contents of the block within the smaller layout are + /// unaltered, and ownership of block has not been transferred. + /// + /// If this returns `Err`, then the memory block is considered to + /// still represent the original (larger) `layout`. None of the + /// block has been carved off for reuse elsewhere, ownership of + /// the memory block has not been transferred, and the contents of + /// the memory block are unaltered. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * `layout` must *fit* the `ptr` (see above); note the + /// `new_size` argument need not fit it, + /// + /// * `new_size` must not be greater than `layout.size()` + /// (and must be greater than zero), + /// + /// # Errors + /// + /// Returns `Err(CannotReallocInPlace)` when the allocator is + /// unable to assert that the memory block referenced by `ptr` + /// could fit `layout`. + /// + /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error` + /// function; clients are expected either to be able to recover from + /// `shrink_in_place` failures without aborting, or to fall back + /// on another reallocation method before resorting to an abort. + unsafe fn shrink_in_place( + &mut self, + ptr: NonNull, + layout: Layout, + new_size: usize, + ) -> Result<(), CannotReallocInPlace> { + let _ = ptr; // this default implementation doesn't care about the actual address. + debug_assert!(new_size <= layout.size()); + let (l, _u) = self.usable_size(&layout); + // layout.size() <= _u [guaranteed by usable_size()] + // new_layout.size() <= layout.size() [required by this method] + if l <= new_size { + Ok(()) + } else { + Err(CannotReallocInPlace) + } + } + + // == COMMON USAGE PATTERNS == + // alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array + + /// Allocates a block suitable for holding an instance of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` + /// must be considered "currently allocated" and must be + /// acceptable input to methods such as `realloc` or `dealloc`, + /// *even if* `T` is a zero-sized type. In other words, if your + /// `Alloc` implementation overrides this method in a manner + /// that can return a zero-sized `ptr`, then all reallocation and + /// deallocation methods need to be similarly overridden to accept + /// such values as input. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `T` does not meet allocator's size or alignment constraints. + /// + /// For zero-sized `T`, may return either of `Ok` or `Err`, but + /// will *not* yield undefined behavior. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + fn alloc_one(&mut self) -> Result, AllocErr> + where + Self: Sized, + { + let k = Layout::new::(); + if k.size() > 0 { + unsafe { self.alloc(k).map(|p| p.cast()) } + } else { + Err(AllocErr) + } + } + + /// Deallocates a block suitable for holding an instance of `T`. + /// + /// The given block must have been produced by this allocator, + /// and must be suitable for storing a `T` (in terms of alignment + /// as well as minimum and maximum size); otherwise yields + /// undefined behavior. + /// + /// Captures a common usage pattern for allocators. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure both: + /// + /// * `ptr` must denote a block of memory currently allocated via this allocator + /// + /// * the layout of `T` must *fit* that block of memory. + unsafe fn dealloc_one(&mut self, ptr: NonNull) + where + Self: Sized, + { + let k = Layout::new::(); + if k.size() > 0 { + self.dealloc(ptr.cast(), k); + } + } + + /// Allocates a block suitable for holding `n` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` + /// must be considered "currently allocated" and must be + /// acceptable input to methods such as `realloc` or `dealloc`, + /// *even if* `T` is a zero-sized type. In other words, if your + /// `Alloc` implementation overrides this method in a manner + /// that can return a zero-sized `ptr`, then all reallocation and + /// deallocation methods need to be similarly overridden to accept + /// such values as input. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `[T; n]` does not meet allocator's size or alignment + /// constraints. + /// + /// For zero-sized `T` or `n == 0`, may return either of `Ok` or + /// `Err`, but will *not* yield undefined behavior. + /// + /// Always returns `Err` on arithmetic overflow. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + fn alloc_array(&mut self, n: usize) -> Result, AllocErr> + where + Self: Sized, + { + match Layout::array::(n) { + Ok(layout) if layout.size() > 0 => unsafe { self.alloc(layout).map(|p| p.cast()) }, + _ => Err(AllocErr), + } + } + + /// Reallocates a block previously suitable for holding `n_old` + /// instances of `T`, returning a block suitable for holding + /// `n_new` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// The returned block is suitable for passing to the + /// `alloc`/`realloc` methods of this allocator. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure all of the following: + /// + /// * `ptr` must be currently allocated via this allocator, + /// + /// * the layout of `[T; n_old]` must *fit* that block of memory. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `[T; n_new]` does not meet allocator's size or alignment + /// constraints. + /// + /// For zero-sized `T` or `n_new == 0`, may return either of `Ok` or + /// `Err`, but will *not* yield undefined behavior. + /// + /// Always returns `Err` on arithmetic overflow. + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn realloc_array( + &mut self, + ptr: NonNull, + n_old: usize, + n_new: usize, + ) -> Result, AllocErr> + where + Self: Sized, + { + match (Layout::array::(n_old), Layout::array::(n_new)) { + (Ok(ref k_old), Ok(ref k_new)) if k_old.size() > 0 && k_new.size() > 0 => { + debug_assert!(k_old.align() == k_new.align()); + self.realloc(ptr.cast(), *k_old, k_new.size()) + .map(NonNull::cast) + } + _ => Err(AllocErr), + } + } + + /// Deallocates a block suitable for holding `n` instances of `T`. + /// + /// Captures a common usage pattern for allocators. + /// + /// # Safety + /// + /// This function is unsafe because undefined behavior can result + /// if the caller does not ensure both: + /// + /// * `ptr` must denote a block of memory currently allocated via this allocator + /// + /// * the layout of `[T; n]` must *fit* that block of memory. + /// + /// # Errors + /// + /// Returning `Err` indicates that either `[T; n]` or the given + /// memory block does not meet allocator's size or alignment + /// constraints. + /// + /// Always returns `Err` on arithmetic overflow. + unsafe fn dealloc_array(&mut self, ptr: NonNull, n: usize) -> Result<(), AllocErr> + where + Self: Sized, + { + match Layout::array::(n) { + Ok(k) if k.size() > 0 => { + self.dealloc(ptr.cast(), k); + Ok(()) + } + _ => Err(AllocErr), + } + } +} diff --git a/anneal/v2/vendor/bumpalo/src/boxed.rs b/anneal/v2/vendor/bumpalo/src/boxed.rs new file mode 100644 index 0000000000..40f8108a77 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/boxed.rs @@ -0,0 +1,747 @@ +//! A pointer type for bump allocation. +//! +//! [`Box<'a, T>`] provides the simplest form of +//! bump allocation in `bumpalo`. Boxes provide ownership for this allocation, and +//! drop their contents when they go out of scope. +//! +//! # Examples +//! +//! Move a value from the stack to the heap by creating a [`Box`]: +//! +//! ``` +//! use bumpalo::{Bump, boxed::Box}; +//! +//! let b = Bump::new(); +//! +//! let val: u8 = 5; +//! let boxed: Box = Box::new_in(val, &b); +//! ``` +//! +//! Move a value from a [`Box`] back to the stack by [dereferencing]: +//! +//! ``` +//! use bumpalo::{Bump, boxed::Box}; +//! +//! let b = Bump::new(); +//! +//! let boxed: Box = Box::new_in(5, &b); +//! let val: u8 = *boxed; +//! ``` +//! +//! Running [`Drop`] implementations on bump-allocated values: +//! +//! ``` +//! use bumpalo::{Bump, boxed::Box}; +//! use std::sync::atomic::{AtomicUsize, Ordering}; +//! +//! static NUM_DROPPED: AtomicUsize = AtomicUsize::new(0); +//! +//! struct CountDrops; +//! +//! impl Drop for CountDrops { +//! fn drop(&mut self) { +//! NUM_DROPPED.fetch_add(1, Ordering::SeqCst); +//! } +//! } +//! +//! // Create a new bump arena. +//! let bump = Bump::new(); +//! +//! // Create a `CountDrops` inside the bump arena. +//! let mut c = Box::new_in(CountDrops, &bump); +//! +//! // No `CountDrops` have been dropped yet. +//! assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 0); +//! +//! // Drop our `Box`. +//! drop(c); +//! +//! // Its `Drop` implementation was run, and so `NUM_DROPS` has been incremented. +//! assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 1); +//! ``` +//! +//! Creating a recursive data structure: +//! +//! ``` +//! use bumpalo::{Bump, boxed::Box}; +//! +//! let b = Bump::new(); +//! +//! #[derive(Debug)] +//! enum List<'a, T> { +//! Cons(T, Box<'a, List<'a, T>>), +//! Nil, +//! } +//! +//! let list: List = List::Cons(1, Box::new_in(List::Cons(2, Box::new_in(List::Nil, &b)), &b)); +//! println!("{:?}", list); +//! ``` +//! +//! This will print `Cons(1, Cons(2, Nil))`. +//! +//! Recursive structures must be boxed, because if the definition of `Cons` +//! looked like this: +//! +//! ```compile_fail,E0072 +//! # enum List { +//! Cons(T, List), +//! # } +//! ``` +//! +//! It wouldn't work. This is because the size of a `List` depends on how many +//! elements are in the list, and so we don't know how much memory to allocate +//! for a `Cons`. By introducing a [`Box<'a, T>`], which has a defined size, we know how +//! big `Cons` needs to be. +//! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the provided [`Bump`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! pointer allocated with the [`Bump`] allocator, given that the +//! [`Layout`] used with the allocator is correct for the type. More precisely, +//! a `value: *mut T` that has been allocated with the [`Bump`] allocator +//! with `Layout::for_value(&*value)` may be converted into a box using +//! [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut +//! T` obtained from [`Box::::into_raw`] will be deallocated by the +//! [`Bump`] allocator with [`Layout::for_value(&*value)`]. +//! +//! Note that roundtrip `Box::from_raw(Box::into_raw(b))` looses the lifetime bound to the +//! [`Bump`] immutable borrow which guarantees that the allocator will not be reset +//! and memory will not be freed. +//! +//! [dereferencing]: https://doc.rust-lang.org/std/ops/trait.Deref.html +//! [`Box`]: struct.Box.html +//! [`Box<'a, T>`]: struct.Box.html +//! [`Box::::from_raw(value)`]: struct.Box.html#method.from_raw +//! [`Box::::into_raw`]: struct.Box.html#method.into_raw +//! [`Bump`]: ../struct.Bump.html +//! [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html +//! [`Layout`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html +//! [`Layout::for_value(&*value)`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.for_value + +use { + crate::Bump, + core::{ + any::Any, + borrow, + cmp::Ordering, + convert::TryFrom, + future::Future, + hash::{Hash, Hasher}, + iter::FusedIterator, + marker::PhantomData, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, + pin::Pin, + ptr::NonNull, + task::{Context, Poll}, + }, + core_alloc::fmt, +}; + +/// An owned pointer to a bump-allocated `T` value, that runs `Drop` +/// implementations. +/// +/// See the [module-level documentation][crate::boxed] for more details. +#[repr(transparent)] +pub struct Box<'a, T: ?Sized>(NonNull, PhantomData<&'a T>); + +impl<'a, T> Box<'a, T> { + /// Allocates memory on the heap and then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let five = Box::new_in(5, &b); + /// ``` + #[inline(always)] + pub fn new_in(x: T, a: &'a Bump) -> Box<'a, T> { + Box(a.alloc(x).into(), PhantomData) + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[inline(always)] + pub fn pin_in(x: T, a: &'a Bump) -> Pin> { + Box(a.alloc(x).into(), PhantomData).into() + } + + /// Consumes the `Box`, returning the wrapped value. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let hello = Box::new_in("hello".to_owned(), &b); + /// assert_eq!(Box::into_inner(hello), "hello"); + /// ``` + pub fn into_inner(b: Box<'a, T>) -> T { + // `Box::into_raw` returns a pointer that is properly aligned and non-null. + // The underlying `Bump` only frees the memory, but won't call the destructor. + unsafe { core::ptr::read(Box::into_raw(b)) } + } +} + +impl<'a, T: ?Sized> Box<'a, T> { + /// Constructs a box from a raw pointer. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the memory layout used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: + /// ``` + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let x = Box::new_in(5, &b); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; // Note that new `x`'s lifetime is unbound. It must be bound to the `b` immutable borrow before `b` is reset. + /// ``` + /// Manually create a `Box` from scratch by using the bump allocator: + /// ``` + /// use std::alloc::{alloc, Layout}; + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// unsafe { + /// let ptr = b.alloc_layout(Layout::new::()).as_ptr() as *mut i32; + /// *ptr = 5; + /// let x = Box::from_raw(ptr); // Note that `x`'s lifetime is unbound. It must be bound to the `b` immutable borrow before `b` is reset. + /// } + /// ``` + #[inline] + pub unsafe fn from_raw(raw: *mut T) -> Self { + // Safety: part of this function's unsafe contract is that the raw + // pointer be non-null. + Box(unsafe { NonNull::new_unchecked(raw) }, PhantomData) + } + + /// Consumes the `Box`, returning a wrapped raw pointer. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// value previously managed by the `Box`. In particular, the + /// caller should properly destroy `T`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: + /// ``` + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let x = Box::new_in(String::from("Hello"), &b); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; // Note that new `x`'s lifetime is unbound. It must be bound to the `b` immutable borrow before `b` is reset. + /// ``` + /// Manual cleanup by explicitly running the destructor: + /// ``` + /// use std::ptr; + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let mut x = Box::new_in(String::from("Hello"), &b); + /// let p = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(p); + /// } + /// ``` + #[inline] + pub fn into_raw(b: Box<'a, T>) -> *mut T { + let b = ManuallyDrop::new(b); + b.0.as_ptr() + } + + /// Consumes and leaks the `Box`, returning a mutable reference, + /// `&'a mut T`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. If this is not acceptable, the reference should first be wrapped + /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can + /// then be dropped which will properly destroy `T` and release the + /// allocated memory. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::leak(b)` instead of `b.leak()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// use bumpalo::{Bump, boxed::Box}; + /// + /// let b = Bump::new(); + /// + /// let x = Box::new_in(41, &b); + /// let reference: &mut usize = Box::leak(x); + /// *reference += 1; + /// assert_eq!(*reference, 42); + /// ``` + /// + ///``` + /// # #[cfg(feature = "collections")] + /// # { + /// use bumpalo::{Bump, boxed::Box, vec}; + /// + /// let b = Bump::new(); + /// + /// let x = vec![in &b; 1, 2, 3].into_boxed_slice(); + /// let reference = Box::leak(x); + /// reference[0] = 4; + /// assert_eq!(*reference, [4, 2, 3]); + /// # } + ///``` + #[inline] + pub fn leak(b: Box<'a, T>) -> &'a mut T { + unsafe { &mut *Box::into_raw(b) } + } +} + +impl<'a, T: ?Sized> Drop for Box<'a, T> { + fn drop(&mut self) { + unsafe { + // `Box` owns value of `T`, but not memory behind it. + core::ptr::drop_in_place(self.0.as_ptr()); + } + } +} + +impl<'a, T> Default for Box<'a, [T]> { + fn default() -> Box<'a, [T]> { + // It should be OK to `drop_in_place` empty slice of anything. + Box( + NonNull::new(&mut []).expect("Reference to empty list is NonNull"), + PhantomData, + ) + } +} + +impl<'a> Default for Box<'a, str> { + fn default() -> Box<'a, str> { + // Empty slice is valid string. + // It should be OK to `drop_in_place` empty str. + unsafe { Box::from_raw(Box::into_raw(Box::<[u8]>::default()) as *mut str) } + } +} + +impl<'a, 'b, T: ?Sized + PartialEq> PartialEq> for Box<'a, T> { + #[inline] + fn eq(&self, other: &Box<'b, T>) -> bool { + PartialEq::eq(&**self, &**other) + } + #[inline] + fn ne(&self, other: &Box<'b, T>) -> bool { + PartialEq::ne(&**self, &**other) + } +} + +impl<'a, 'b, T: ?Sized + PartialOrd> PartialOrd> for Box<'a, T> { + #[inline] + fn partial_cmp(&self, other: &Box<'b, T>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } + #[inline] + fn lt(&self, other: &Box<'b, T>) -> bool { + PartialOrd::lt(&**self, &**other) + } + #[inline] + fn le(&self, other: &Box<'b, T>) -> bool { + PartialOrd::le(&**self, &**other) + } + #[inline] + fn ge(&self, other: &Box<'b, T>) -> bool { + PartialOrd::ge(&**self, &**other) + } + #[inline] + fn gt(&self, other: &Box<'b, T>) -> bool { + PartialOrd::gt(&**self, &**other) + } +} + +impl<'a, T: ?Sized + Ord> Ord for Box<'a, T> { + #[inline] + fn cmp(&self, other: &Box<'a, T>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +impl<'a, T: ?Sized + Eq> Eq for Box<'a, T> {} + +impl<'a, T: ?Sized + Hash> Hash for Box<'a, T> { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +impl<'a, T: ?Sized + Hasher> Hasher for Box<'a, T> { + fn finish(&self) -> u64 { + (**self).finish() + } + fn write(&mut self, bytes: &[u8]) { + (**self).write(bytes) + } + fn write_u8(&mut self, i: u8) { + (**self).write_u8(i) + } + fn write_u16(&mut self, i: u16) { + (**self).write_u16(i) + } + fn write_u32(&mut self, i: u32) { + (**self).write_u32(i) + } + fn write_u64(&mut self, i: u64) { + (**self).write_u64(i) + } + fn write_u128(&mut self, i: u128) { + (**self).write_u128(i) + } + fn write_usize(&mut self, i: usize) { + (**self).write_usize(i) + } + fn write_i8(&mut self, i: i8) { + (**self).write_i8(i) + } + fn write_i16(&mut self, i: i16) { + (**self).write_i16(i) + } + fn write_i32(&mut self, i: i32) { + (**self).write_i32(i) + } + fn write_i64(&mut self, i: i64) { + (**self).write_i64(i) + } + fn write_i128(&mut self, i: i128) { + (**self).write_i128(i) + } + fn write_isize(&mut self, i: isize) { + (**self).write_isize(i) + } +} + +impl<'a, T: ?Sized> From> for Pin> { + /// Converts a `Box` into a `Pin>`. + /// + /// This conversion does not allocate on the heap and happens in place. + fn from(boxed: Box<'a, T>) -> Self { + // It's not possible to move or replace the insides of a `Pin>` + // when `T: !Unpin`, so it's safe to pin it directly without any + // additional requirements. + unsafe { Pin::new_unchecked(boxed) } + } +} + +impl<'a> Box<'a, dyn Any> { + #[inline] + /// Attempt to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Box<'a, dyn Any>> { + if self.is::() { + unsafe { + let raw: *mut dyn Any = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +impl<'a> Box<'a, dyn Any + Send> { + #[inline] + /// Attempt to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Box<'a, dyn Any + Send>> { + if self.is::() { + unsafe { + let raw: *mut (dyn Any + Send) = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +impl<'a, T: fmt::Display + ?Sized> fmt::Display for Box<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Box<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'a, T: ?Sized> fmt::Pointer for Box<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &**self; + fmt::Pointer::fmt(&ptr, f) + } +} + +/// This function tests that box isn't contravariant. +/// +/// ```compile_fail +/// fn _box_is_not_contravariant<'sub, 'sup :'sub>( +/// a: Box<&'sup u32>, +/// b: Box<&'sub u32>, +/// f: impl Fn(Box<&'sup u32>), +/// ) { +/// f(a); +/// f(b); +/// } +/// ``` +/// +/// This function tests that `Box` isn't Send when the inner type isn't Send. +/// ```compile_fail +/// fn _requires_send(_value: T) {} +/// fn _box_inherets_send_not_send(a: Box>) { +/// _requires_send(a); +/// } +/// ``` +/// +/// This function tests that `Box` isn't Sync when the inner type isn't Sync. +/// ```compile_fail +/// fn _requires_sync(_value: T) {} +/// fn _box_inherets_sync_not_sync(a: Box>) { +/// _requires_sync(a); +/// } +/// ``` +#[cfg(doctest)] +fn _doctest_only() {} + +impl<'a, T: ?Sized> Deref for Box<'a, T> { + type Target = T; + + fn deref(&self) -> &T { + // Safety: Our pointer always points to a valid instance of `T` + // allocated within a `Bump` and the `&self` borrow ensures that there + // are no active exclusive borrows. + unsafe { self.0.as_ref() } + } +} + +impl<'a, T: ?Sized> DerefMut for Box<'a, T> { + fn deref_mut(&mut self) -> &mut T { + // Safety: Our pointer always points to a valid instance of `T` + // allocated within a `Bump` and the `&mut self` borrow ensures that + // there are no other active borrows. + unsafe { self.0.as_mut() } + } +} + +impl<'a, I: Iterator + ?Sized> Iterator for Box<'a, I> { + type Item = I::Item; + fn next(&mut self) -> Option { + (**self).next() + } + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + fn nth(&mut self, n: usize) -> Option { + (**self).nth(n) + } + fn last(self) -> Option { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + self.fold(None, some) + } +} + +impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<'a, I> { + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } +} +impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<'a, I> { + fn len(&self) -> usize { + (**self).len() + } +} + +impl<'a, I: FusedIterator + ?Sized> FusedIterator for Box<'a, I> {} + +#[cfg(feature = "collections")] +impl<'a, A> Box<'a, [A]> { + /// Creates a value from an iterator. + /// This method is an adapted version of [`FromIterator::from_iter`][from_iter]. + /// It cannot be made as that trait implementation given different signature. + /// + /// [from_iter]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html#tymethod.from_iter + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// use bumpalo::{Bump, boxed::Box, vec}; + /// + /// let b = Bump::new(); + /// + /// let five_fives = std::iter::repeat(5).take(5); + /// let slice = Box::from_iter_in(five_fives, &b); + /// assert_eq!(vec![in &b; 5, 5, 5, 5, 5], &*slice); + /// ``` + pub fn from_iter_in>(iter: T, a: &'a Bump) -> Self { + use crate::collections::Vec; + let mut vec = Vec::new_in(a); + vec.extend(iter); + vec.into_boxed_slice() + } +} + +impl<'a, T: ?Sized> borrow::Borrow for Box<'a, T> { + fn borrow(&self) -> &T { + &**self + } +} + +impl<'a, T: ?Sized> borrow::BorrowMut for Box<'a, T> { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} + +impl<'a, T: ?Sized> AsRef for Box<'a, T> { + fn as_ref(&self) -> &T { + &**self + } +} + +impl<'a, T: ?Sized> AsMut for Box<'a, T> { + fn as_mut(&mut self) -> &mut T { + &mut **self + } +} + +impl<'a, T: ?Sized> Unpin for Box<'a, T> {} + +// Safety: If T is Send the box is too because Box has exclusive access to its wrapped T. +unsafe impl<'a, T: ?Sized + Send> Send for Box<'a, T> {} + +// Safety: If T is Sync the box is too because Box has exclusive access to its wrapped T. +unsafe impl<'a, T: ?Sized + Sync> Sync for Box<'a, T> {} + +impl<'a, F: ?Sized + Future + Unpin> Future for Box<'a, F> { + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + F::poll(Pin::new(&mut *self), cx) + } +} + +/// This impl replaces unsize coercion. +impl<'a, T, const N: usize> From> for Box<'a, [T]> { + fn from(arr: Box<'a, [T; N]>) -> Box<'a, [T]> { + let mut arr = ManuallyDrop::new(arr); + let ptr = core::ptr::slice_from_raw_parts_mut(arr.as_mut_ptr(), N); + unsafe { Box::from_raw(ptr) } + } +} + +/// This impl replaces unsize coercion. +impl<'a, T, const N: usize> TryFrom> for Box<'a, [T; N]> { + type Error = Box<'a, [T]>; + fn try_from(slice: Box<'a, [T]>) -> Result, Box<'a, [T]>> { + if slice.len() == N { + let mut slice = ManuallyDrop::new(slice); + let ptr = slice.as_mut_ptr() as *mut [T; N]; + Ok(unsafe { Box::from_raw(ptr) }) + } else { + Err(slice) + } + } +} + +#[cfg(feature = "serde")] +mod serialize { + use super::*; + + use serde::{Serialize, Serializer}; + + impl<'a, T> Serialize for Box<'a, T> + where + T: Serialize, + { + fn serialize(&self, serializer: S) -> Result { + T::serialize(self, serializer) + } + } +} diff --git a/anneal/v2/vendor/bumpalo/src/collections/collect_in.rs b/anneal/v2/vendor/bumpalo/src/collections/collect_in.rs new file mode 100644 index 0000000000..3e1adeaeaa --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/collect_in.rs @@ -0,0 +1,152 @@ +#[cfg(feature = "boxed")] +use crate::boxed::Box; +use crate::collections::{String, Vec}; +use crate::Bump; + +/// A trait for types that support being constructed from an iterator, parameterized by an allocator. +pub trait FromIteratorIn { + /// The allocator type + type Alloc; + + /// Similar to [`FromIterator::from_iter`][from_iter], but with a given allocator. + /// + /// [from_iter]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html#tymethod.from_iter + /// + /// ``` + /// # use bumpalo::collections::{FromIteratorIn, Vec}; + /// # use bumpalo::Bump; + /// # + /// let five_fives = std::iter::repeat(5).take(5); + /// let bump = Bump::new(); + /// + /// let v = Vec::from_iter_in(five_fives, &bump); + /// + /// assert_eq!(v, [5, 5, 5, 5, 5]); + /// ``` + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator; +} + +#[cfg(feature = "boxed")] +impl<'bump, T> FromIteratorIn for Box<'bump, [T]> { + type Alloc = &'bump Bump; + + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator, + { + Box::from_iter_in(iter, alloc) + } +} + +impl<'bump, T> FromIteratorIn for Vec<'bump, T> { + type Alloc = &'bump Bump; + + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator, + { + Vec::from_iter_in(iter, alloc) + } +} + +impl> FromIteratorIn> for Option { + type Alloc = V::Alloc; + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator>, + { + iter.into_iter() + .map(|x| x.ok_or(())) + .collect_in::>(alloc) + .ok() + } +} + +impl> FromIteratorIn> for Result { + type Alloc = V::Alloc; + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, a + /// container with the values of each `Result` is returned. + /// + /// Here is an example which increments every integer in a vector, + /// checking for overflow: + /// + /// ``` + /// # use bumpalo::collections::{FromIteratorIn, CollectIn, Vec, String}; + /// # use bumpalo::Bump; + /// # + /// let bump = Bump::new(); + /// + /// let v = vec![1, 2, u32::MAX]; + /// let res: Result, &'static str> = v.iter().take(2).map(|x: &u32| + /// x.checked_add(1).ok_or("Overflow!") + /// ).collect_in(&bump); + /// assert_eq!(res, Ok(bumpalo::vec![in ≎ 2, 3])); + /// + /// let res: Result, &'static str> = v.iter().map(|x: &u32| + /// x.checked_add(1).ok_or("Overflow!") + /// ).collect_in(&bump); + /// assert_eq!(res, Err("Overflow!")); + /// ``` + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator>, + { + let mut iter = iter.into_iter(); + let mut error = None; + let container = core::iter::from_fn(|| match iter.next() { + Some(Ok(x)) => Some(x), + Some(Err(e)) => { + error = Some(e); + None + } + None => None, + }) + .collect_in(alloc); + + match error { + Some(e) => Err(e), + None => Ok(container), + } + } +} + +impl<'bump> FromIteratorIn for String<'bump> { + type Alloc = &'bump Bump; + + fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator, + { + String::from_iter_in(iter, alloc) + } +} + +/// Extension trait for iterators, in order to allow allocator-parameterized collections to be constructed more easily. +pub trait CollectIn: Iterator + Sized { + /// Collect all items from an iterator, into a collection parameterized by an allocator. + /// Similar to [`Iterator::collect`][collect]. + /// + /// [collect]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect + /// + /// ``` + /// # use bumpalo::collections::{FromIteratorIn, CollectIn, Vec, String}; + /// # use bumpalo::Bump; + /// # + /// let bump = Bump::new(); + /// + /// let str = "hello, world!".to_owned(); + /// let bump_str: String = str.chars().collect_in(&bump); + /// assert_eq!(&bump_str, &str); + /// + /// let nums: Vec = (0..=3).collect_in::>(&bump); + /// assert_eq!(&nums, &[0,1,2,3]); + /// ``` + fn collect_in>(self, alloc: C::Alloc) -> C { + C::from_iter_in(self, alloc) + } +} + +impl CollectIn for I {} diff --git a/anneal/v2/vendor/bumpalo/src/collections/mod.rs b/anneal/v2/vendor/bumpalo/src/collections/mod.rs new file mode 100644 index 0000000000..218636c320 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/mod.rs @@ -0,0 +1,93 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Collection types that allocate inside a [`Bump`] arena. +//! +//! [`Bump`]: ../struct.Bump.html + +#![allow(deprecated)] + +mod raw_vec; + +pub mod vec; +pub use self::vec::Vec; + +mod str; +pub mod string; +pub use self::string::String; + +mod collect_in; +pub use collect_in::{CollectIn, FromIteratorIn}; + +// pub mod binary_heap; +// mod btree; +// pub mod linked_list; +// pub mod vec_deque; + +// pub mod btree_map { +// //! A map based on a B-Tree. +// pub use super::btree::map::*; +// } + +// pub mod btree_set { +// //! A set based on a B-Tree. +// pub use super::btree::set::*; +// } + +// #[doc(no_inline)] +// pub use self::binary_heap::BinaryHeap; + +// #[doc(no_inline)] +// pub use self::btree_map::BTreeMap; + +// #[doc(no_inline)] +// pub use self::btree_set::BTreeSet; + +// #[doc(no_inline)] +// pub use self::linked_list::LinkedList; + +// #[doc(no_inline)] +// pub use self::vec_deque::VecDeque; + +use crate::alloc::{AllocErr, LayoutErr}; + +/// Augments `AllocErr` with a `CapacityOverflow` variant. +#[derive(Clone, PartialEq, Eq, Debug)] +// #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +pub enum CollectionAllocErr { + /// Error due to the computed capacity exceeding the collection's maximum + /// (usually `isize::MAX` bytes). + CapacityOverflow, + /// Error due to the allocator (see the documentation for the [`AllocErr`] type). + AllocErr, +} + +// #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +impl From for CollectionAllocErr { + #[inline] + fn from(AllocErr: AllocErr) -> Self { + CollectionAllocErr::AllocErr + } +} + +// #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +impl From for CollectionAllocErr { + #[inline] + fn from(_: LayoutErr) -> Self { + CollectionAllocErr::CapacityOverflow + } +} + +// /// An intermediate trait for specialization of `Extend`. +// #[doc(hidden)] +// trait SpecExtend { +// /// Extends `self` with the contents of the given iterator. +// fn spec_extend(&mut self, iter: I); +// } diff --git a/anneal/v2/vendor/bumpalo/src/collections/raw_vec.rs b/anneal/v2/vendor/bumpalo/src/collections/raw_vec.rs new file mode 100644 index 0000000000..3977ba9a48 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/raw_vec.rs @@ -0,0 +1,781 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unstable_name_collisions)] +#![allow(dead_code)] + +use crate::Bump; + +use core::cmp; +use core::mem; +use core::ptr::{self, NonNull}; + +use crate::alloc::{handle_alloc_error, Alloc, Layout, UnstableLayoutMethods}; +use crate::collections::CollectionAllocErr; +use crate::collections::CollectionAllocErr::*; +// use boxed::Box; + +/// A low-level utility for more ergonomically allocating, reallocating, and deallocating +/// a buffer of memory on the heap without having to worry about all the corner cases +/// involved. This type is excellent for building your own data structures like Vec and VecDeque. +/// In particular: +/// +/// * Produces Unique::empty() on zero-sized types +/// * Produces Unique::empty() on zero-length allocations +/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics) +/// * Guards against 32-bit systems allocating more than isize::MAX bytes +/// * Guards against overflowing your length +/// * Aborts on OOM +/// * Avoids freeing Unique::empty() +/// * Contains a ptr::Unique and thus endows the user with all related benefits +/// +/// This type does not in anyway inspect the memory that it manages. When dropped it *will* +/// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec +/// to handle the actual things *stored* inside of a RawVec. +/// +/// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types. +/// This enables you to use capacity growing logic catch the overflows in your length +/// that might occur with zero-sized types. +/// +/// However this means that you need to be careful when round-tripping this type +/// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`, +/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity +/// field. This allows zero-sized types to not be special-cased by consumers of +/// this type. +#[allow(missing_debug_implementations)] +pub struct RawVec<'a, T> { + ptr: NonNull, + cap: usize, + a: &'a Bump, +} + +impl<'a, T> RawVec<'a, T> { + /// Like `new` but parameterized over the choice of allocator for + /// the returned RawVec. + pub fn new_in(a: &'a Bump) -> Self { + // `cap: 0` means "unallocated". zero-sized types are ignored. + RawVec { + ptr: NonNull::dangling(), + cap: 0, + a, + } + } + + /// Like `with_capacity` but parameterized over the choice of + /// allocator for the returned RawVec. + #[inline] + pub fn with_capacity_in(cap: usize, a: &'a Bump) -> Self { + RawVec::allocate_in(cap, false, a) + } + + /// Like `with_capacity_zeroed` but parameterized over the choice + /// of allocator for the returned RawVec. + #[inline] + pub fn with_capacity_zeroed_in(cap: usize, a: &'a Bump) -> Self { + RawVec::allocate_in(cap, true, a) + } + + fn allocate_in(cap: usize, zeroed: bool, mut a: &'a Bump) -> Self { + unsafe { + let elem_size = mem::size_of::(); + + let alloc_size = cap + .checked_mul(elem_size) + .unwrap_or_else(|| capacity_overflow()); + alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); + + // handles ZSTs and `cap = 0` alike + let ptr = if alloc_size == 0 { + NonNull::::dangling() + } else { + let align = mem::align_of::(); + let layout = Layout::from_size_align(alloc_size, align).unwrap(); + let result = if zeroed { + a.alloc_zeroed(layout) + } else { + Alloc::alloc(&mut a, layout) + }; + match result { + Ok(ptr) => ptr.cast(), + Err(_) => handle_alloc_error(layout), + } + }; + + RawVec { ptr, cap, a } + } + } +} + +impl<'a, T> RawVec<'a, T> { + /// Reconstitutes a RawVec from a pointer, capacity, and allocator. + /// + /// # Undefined Behavior + /// + /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The + /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). + /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed. + pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: &'a Bump) -> Self { + RawVec { + ptr: NonNull::new_unchecked(ptr), + cap, + a, + } + } +} + +impl<'a, T> RawVec<'a, T> { + /// Gets a raw pointer to the start of the allocation. Note that this is + /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must + /// be careful. + pub fn ptr(&self) -> *mut T { + self.ptr.as_ptr() + } + + /// Gets the capacity of the allocation. + /// + /// This will always be `usize::MAX` if `T` is zero-sized. + #[inline(always)] + pub fn cap(&self) -> usize { + if mem::size_of::() == 0 { + !0 + } else { + self.cap + } + } + + /// Returns a shared reference to the allocator backing this RawVec. + pub fn bump(&self) -> &'a Bump { + self.a + } + + fn current_layout(&self) -> Option { + if self.cap == 0 { + None + } else { + // We have an allocated chunk of memory, so we can bypass runtime + // checks to get our current layout. + unsafe { + let align = mem::align_of::(); + let size = mem::size_of::() * self.cap; + Some(Layout::from_size_align_unchecked(size, align)) + } + } + } + + /// Doubles the size of the type's backing allocation. This is common enough + /// to want to do that it's easiest to just have a dedicated method. Slightly + /// more efficient logic can be provided for this than the general case. + /// + /// This function is ideal for when pushing elements one-at-a-time because + /// you don't need to incur the costs of the more general computations + /// reserve needs to do to guard against overflow. You do however need to + /// manually check if your `len == cap`. + /// + /// # Panics + /// + /// * Panics if T is zero-sized on the assumption that you managed to exhaust + /// all `usize::MAX` slots in your imaginary buffer. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM + /// + /// # Examples + /// + /// ```ignore + /// # #![feature(alloc, raw_vec_internals)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; + /// struct MyVec { + /// buf: RawVec, + /// len: usize, + /// } + /// + /// impl MyVec { + /// pub fn push(&mut self, elem: T) { + /// if self.len == self.buf.cap() { self.buf.double(); } + /// // double would have aborted or panicked if the len exceeded + /// // `isize::MAX` so this is safe to do unchecked now. + /// unsafe { + /// ptr::write(self.buf.ptr().add(self.len), elem); + /// } + /// self.len += 1; + /// } + /// } + /// # fn main() { + /// # let mut vec = MyVec { buf: RawVec::new(), len: 0 }; + /// # vec.push(1); + /// # } + /// ``` + #[inline(never)] + #[cold] + pub fn double(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the RawVec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let (new_cap, uniq) = match self.current_layout() { + Some(cur) => { + // Since we guarantee that we never allocate more than + // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as + // a precondition, so this can't overflow. Additionally the + // alignment will never be too large as to "not be + // satisfiable", so `Layout::from_size_align` will always + // return `Some`. + // + // tl;dr; we bypass runtime checks due to dynamic assertions + // in this module, allowing us to use + // `from_size_align_unchecked`. + let new_cap = 2 * self.cap; + let new_size = new_cap * elem_size; + alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); + let ptr_res = self.a.realloc(self.ptr.cast(), cur, new_size); + match ptr_res { + Ok(ptr) => (new_cap, ptr.cast()), + Err(_) => handle_alloc_error(Layout::from_size_align_unchecked( + new_size, + cur.align(), + )), + } + } + None => { + // skip to 4 because tiny Vec's are dumb; but not if that + // would cause overflow + let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; + match self.a.alloc_array::(new_cap) { + Ok(ptr) => (new_cap, ptr), + Err(_) => handle_alloc_error(Layout::array::(new_cap).unwrap()), + } + } + }; + self.ptr = uniq; + self.cap = new_cap; + } + } + + /// Attempts to double the size of the type's backing allocation in place. This is common + /// enough to want to do that it's easiest to just have a dedicated method. Slightly + /// more efficient logic can be provided for this than the general case. + /// + /// Returns true if the reallocation attempt has succeeded, or false otherwise. + /// + /// # Panics + /// + /// * Panics if T is zero-sized on the assumption that you managed to exhaust + /// all `usize::MAX` slots in your imaginary buffer. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + #[inline(never)] + #[cold] + pub fn double_in_place(&mut self) -> bool { + unsafe { + let elem_size = mem::size_of::(); + let old_layout = match self.current_layout() { + Some(layout) => layout, + None => return false, // nothing to double + }; + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the RawVec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + // Since we guarantee that we never allocate more than isize::MAX + // bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so + // this can't overflow. + // + // Similarly like with `double` above we can go straight to + // `Layout::from_size_align_unchecked` as we know this won't + // overflow and the alignment is sufficiently small. + let new_cap = 2 * self.cap; + let new_size = new_cap * elem_size; + alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); + match self.a.grow_in_place(self.ptr.cast(), old_layout, new_size) { + Ok(_) => { + // We can't directly divide `size`. + self.cap = new_cap; + true + } + Err(_) => false, + } + } + } + + /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. + pub fn try_reserve_exact( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + ) -> Result<(), CollectionAllocErr> { + self.fallible_reserve_internal(used_cap, needed_extra_cap, Exact) + } + + /// Ensures that the buffer contains at least enough space to hold + /// `used_cap + needed_extra_cap` elements. If it doesn't already, + /// will reallocate the minimum possible amount of memory necessary. + /// Generally this will be exactly the amount of memory necessary, + /// but in principle the allocator is free to give back more than + /// we asked for. + /// + /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe + /// code *you* write that relies on the behavior of this function may break. + /// + /// # Panics + /// + /// * Panics if the requested capacity exceeds `usize::MAX` bytes. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM + pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { + self.infallible_reserve_internal(used_cap, needed_extra_cap, Exact) + } + + /// Calculates the buffer's new size given that it'll hold `used_cap + + /// needed_extra_cap` elements. This logic is used in amortized reserve methods. + /// Returns `(new_capacity, new_alloc_size)`. + fn amortized_new_size( + &self, + used_cap: usize, + needed_extra_cap: usize, + ) -> Result { + // Nothing we can really do about these checks :( + let required_cap = used_cap + .checked_add(needed_extra_cap) + .ok_or(CapacityOverflow)?; + // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. + let double_cap = self.cap * 2; + // `double_cap` guarantees exponential growth. + Ok(cmp::max(double_cap, required_cap)) + } + + /// The same as `reserve`, but returns on errors instead of panicking or aborting. + pub fn try_reserve( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + ) -> Result<(), CollectionAllocErr> { + self.fallible_reserve_internal(used_cap, needed_extra_cap, Amortized) + } + + /// Ensures that the buffer contains at least enough space to hold + /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// enough capacity, will reallocate enough space plus comfortable slack + /// space to get amortized `O(1)` behavior. Will limit this behavior + /// if it would needlessly cause itself to panic. + /// + /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe + /// code *you* write that relies on the behavior of this function may break. + /// + /// This is ideal for implementing a bulk-push operation like `extend`. + /// + /// # Panics + /// + /// * Panics if the requested capacity exceeds `usize::MAX` bytes. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM + /// + /// # Examples + /// + /// ```ignore + /// # #![feature(alloc, raw_vec_internals)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; + /// struct MyVec { + /// buf: RawVec, + /// len: usize, + /// } + /// + /// impl MyVec { + /// pub fn push_all(&mut self, elems: &[T]) { + /// self.buf.reserve(self.len, elems.len()); + /// // reserve would have aborted or panicked if the len exceeded + /// // `isize::MAX` so this is safe to do unchecked now. + /// for x in elems { + /// unsafe { + /// ptr::write(self.buf.ptr().add(self.len), x.clone()); + /// } + /// self.len += 1; + /// } + /// } + /// } + /// # fn main() { + /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 }; + /// # vector.push_all(&[1, 3, 5, 7, 9]); + /// # } + /// ``` + #[inline(always)] + pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { + self.infallible_reserve_internal(used_cap, needed_extra_cap, Amortized) + } + + /// Attempts to ensure that the buffer contains at least enough space to hold + /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// enough capacity, will reallocate in place enough space plus comfortable slack + /// space to get amortized `O(1)` behavior. Will limit this behaviour + /// if it would needlessly cause itself to panic. + /// + /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe + /// code *you* write that relies on the behavior of this function may break. + /// + /// Returns true if the reallocation attempt has succeeded, or false otherwise. + /// + /// # Panics + /// + /// * Panics if the requested capacity exceeds `usize::MAX` bytes. + /// * Panics on 32-bit platforms if the requested capacity exceeds + /// `isize::MAX` bytes. + pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) -> bool { + unsafe { + // NOTE: we don't early branch on ZSTs here because we want this + // to actually catch "asking for more than usize::MAX" in that case. + // If we make it past the first branch then we are guaranteed to + // panic. + + // Don't actually need any more capacity. If the current `cap` is 0, we can't + // reallocate in place. + // Wrapping in case they give a bad `used_cap` + let old_layout = match self.current_layout() { + Some(layout) => layout, + None => return false, + }; + if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + return false; + } + + let new_cap = self + .amortized_new_size(used_cap, needed_extra_cap) + .unwrap_or_else(|_| capacity_overflow()); + + // Here, `cap < used_cap + needed_extra_cap <= new_cap` + // (regardless of whether `self.cap - used_cap` wrapped). + // Therefore we can safely call grow_in_place. + + let new_layout = Layout::new::().repeat(new_cap).unwrap().0; + // FIXME: may crash and burn on over-reserve + alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow()); + match self + .a + .grow_in_place(self.ptr.cast(), old_layout, new_layout.size()) + { + Ok(_) => { + self.cap = new_cap; + true + } + Err(_) => false, + } + } + } + + /// Shrinks the allocation down to the specified amount. If the given amount + /// is 0, actually completely deallocates. + /// + /// # Panics + /// + /// Panics if the given amount is *larger* than the current capacity. + /// + /// # Aborts + /// + /// Aborts on OOM. + pub fn shrink_to_fit(&mut self, amount: usize) { + let elem_size = mem::size_of::(); + + // Set the `cap` because they might be about to promote to a `Box<[T]>` + if elem_size == 0 { + self.cap = amount; + return; + } + + // This check is my waterloo; it's the only thing Vec wouldn't have to do. + assert!(self.cap >= amount, "Tried to shrink to a larger capacity"); + + if amount == 0 { + // We want to create a new zero-length vector within the + // same allocator. We use ptr::write to avoid an + // erroneous attempt to drop the contents, and we use + // ptr::read to sidestep condition against destructuring + // types that implement Drop. + + unsafe { + let a = self.a; + self.dealloc_buffer(); + ptr::write(self, RawVec::new_in(a)); + } + } else if self.cap != amount { + unsafe { + // We know here that our `amount` is greater than zero. This + // implies, via the assert above, that capacity is also greater + // than zero, which means that we've got a current layout that + // "fits" + // + // We also know that `self.cap` is greater than `amount`, and + // consequently we don't need runtime checks for creating either + // layout + let old_size = elem_size * self.cap; + let new_size = elem_size * amount; + let align = mem::align_of::(); + let old_layout = Layout::from_size_align_unchecked(old_size, align); + match self.a.realloc(self.ptr.cast(), old_layout, new_size) { + Ok(p) => self.ptr = p.cast(), + Err(_) => { + handle_alloc_error(Layout::from_size_align_unchecked(new_size, align)) + } + } + } + self.cap = amount; + } + } +} + +#[cfg(feature = "boxed")] +impl<'a, T> RawVec<'a, T> { + /// Converts the entire buffer into `Box<[T]>`. + /// + /// Note that this will correctly reconstitute any `cap` changes + /// that may have been performed. (See description of type for details.) + /// + /// # Undefined Behavior + /// + /// All elements of `RawVec` must be initialized. Notice that + /// the rules around uninitialized boxed values are not finalized yet, + /// but until they are, it is advisable to avoid them. + pub unsafe fn into_box(self) -> crate::boxed::Box<'a, [T]> { + use crate::boxed::Box; + + // NOTE: not calling `cap()` here; actually using the real `cap` field! + let slice = core::slice::from_raw_parts_mut(self.ptr(), self.cap); + let output: Box<'a, [T]> = Box::from_raw(slice); + mem::forget(self); + output + } +} + +enum Fallibility { + Fallible, + Infallible, +} + +use self::Fallibility::*; + +enum ReserveStrategy { + Exact, + Amortized, +} + +use self::ReserveStrategy::*; + +impl<'a, T> RawVec<'a, T> { + #[inline(always)] + fn fallible_reserve_internal( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + strategy: ReserveStrategy, + ) -> Result<(), CollectionAllocErr> { + // This portion of the method should always be inlined. + if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + return Ok(()); + } + // This portion of the method should never be inlined, and will only be called when + // the check above has confirmed that it is necessary. + self.reserve_internal_or_error(used_cap, needed_extra_cap, Fallible, strategy) + } + + #[inline(always)] + fn infallible_reserve_internal( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + strategy: ReserveStrategy, + ) { + // This portion of the method should always be inlined. + if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + return; + } + // This portion of the method should never be inlined, and will only be called when + // the check above has confirmed that it is necessary. + self.reserve_internal_or_panic(used_cap, needed_extra_cap, strategy) + } + + #[inline(never)] + fn reserve_internal_or_panic( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + strategy: ReserveStrategy, + ) { + // Delegates the call to `reserve_internal_or_error` and panics in the event of an error. + // This allows the method to have a return type of `()`, simplifying the assembly at the + // call site. + match self.reserve_internal(used_cap, needed_extra_cap, Infallible, strategy) { + Err(CapacityOverflow) => capacity_overflow(), + Err(AllocErr) => unreachable!(), + Ok(()) => { /* yay */ } + } + } + + #[inline(never)] + fn reserve_internal_or_error( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + fallibility: Fallibility, + strategy: ReserveStrategy, + ) -> Result<(), CollectionAllocErr> { + // Delegates the call to `reserve_internal`, which can be inlined. + self.reserve_internal(used_cap, needed_extra_cap, fallibility, strategy) + } + + /// Helper method to reserve additional space, reallocating the backing memory. + /// The caller is responsible for confirming that there is not already enough space available. + fn reserve_internal( + &mut self, + used_cap: usize, + needed_extra_cap: usize, + fallibility: Fallibility, + strategy: ReserveStrategy, + ) -> Result<(), CollectionAllocErr> { + unsafe { + use crate::AllocErr; + + // NOTE: we don't early branch on ZSTs here because we want this + // to actually catch "asking for more than usize::MAX" in that case. + // If we make it past the first branch then we are guaranteed to + // panic. + + // Nothing we can really do about these checks :( + let new_cap = match strategy { + Exact => used_cap + .checked_add(needed_extra_cap) + .ok_or(CapacityOverflow)?, + Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?, + }; + let new_layout = Layout::array::(new_cap).map_err(|_| CapacityOverflow)?; + + alloc_guard(new_layout.size())?; + + let res = match self.current_layout() { + Some(layout) => { + debug_assert!(new_layout.align() == layout.align()); + self.a.realloc(self.ptr.cast(), layout, new_layout.size()) + } + None => Alloc::alloc(&mut self.a, new_layout), + }; + + if let (Err(AllocErr), Infallible) = (&res, fallibility) { + handle_alloc_error(new_layout); + } + + self.ptr = res?.cast(); + self.cap = new_cap; + + Ok(()) + } + } +} + +impl<'a, T> RawVec<'a, T> { + /// Frees the memory owned by the RawVec *without* trying to Drop its contents. + pub unsafe fn dealloc_buffer(&mut self) { + let elem_size = mem::size_of::(); + if elem_size != 0 { + if let Some(layout) = self.current_layout() { + self.a.dealloc(self.ptr.cast(), layout); + } + } + } +} + +impl<'a, T> Drop for RawVec<'a, T> { + /// Frees the memory owned by the RawVec *without* trying to Drop its contents. + fn drop(&mut self) { + unsafe { + self.dealloc_buffer(); + } + } +} + +// We need to guarantee the following: +// * We don't ever allocate `> isize::MAX` byte-size objects +// * We don't overflow `usize::MAX` and actually allocate too little +// +// On 64-bit we just need to check for overflow since trying to allocate +// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add +// an extra guard for this in case we're running on a platform which can use +// all 4GB in user-space. e.g. PAE or x32 + +#[inline] +fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { + if mem::size_of::() < 8 && alloc_size > ::core::isize::MAX as usize { + Err(CapacityOverflow) + } else { + Ok(()) + } +} + +// One central function responsible for reporting capacity overflows. This'll +// ensure that the code generation related to these panics is minimal as there's +// only one location which panics rather than a bunch throughout the module. +fn capacity_overflow() -> ! { + panic!("capacity overflow") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn reserve_does_not_overallocate() { + let bump = Bump::new(); + { + let mut v: RawVec = RawVec::new_in(&bump); + // First `reserve` allocates like `reserve_exact` + v.reserve(0, 9); + assert_eq!(9, v.cap()); + } + + { + let mut v: RawVec = RawVec::new_in(&bump); + v.reserve(0, 7); + assert_eq!(7, v.cap()); + // 97 if more than double of 7, so `reserve` should work + // like `reserve_exact`. + v.reserve(7, 90); + assert_eq!(97, v.cap()); + } + + { + let mut v: RawVec = RawVec::new_in(&bump); + v.reserve(0, 12); + assert_eq!(12, v.cap()); + v.reserve(12, 3); + // 3 is less than half of 12, so `reserve` must grow + // exponentially. At the time of writing this test grow + // factor is 2, so new capacity is 24, however, grow factor + // of 1.5 is OK too. Hence `>= 18` in assert. + assert!(v.cap() >= 12 + 12 / 2); + } + } +} diff --git a/anneal/v2/vendor/bumpalo/src/collections/str/lossy.rs b/anneal/v2/vendor/bumpalo/src/collections/str/lossy.rs new file mode 100644 index 0000000000..b1012a4129 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/str/lossy.rs @@ -0,0 +1,209 @@ +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::collections::str as core_str; +use core::char; +use core::fmt; +use core::fmt::Write; +use core::str; + +/// Lossy UTF-8 string. +pub struct Utf8Lossy<'a> { + bytes: &'a [u8], +} + +impl<'a> Utf8Lossy<'a> { + pub fn from_bytes(bytes: &'a [u8]) -> Utf8Lossy<'a> { + Utf8Lossy { bytes } + } + + pub fn chunks(&self) -> Utf8LossyChunksIter<'a> { + Utf8LossyChunksIter { + source: &self.bytes, + } + } +} + +/// Iterator over lossy UTF-8 string +#[allow(missing_debug_implementations)] +pub struct Utf8LossyChunksIter<'a> { + source: &'a [u8], +} + +#[derive(PartialEq, Eq, Debug)] +pub struct Utf8LossyChunk<'a> { + /// Sequence of valid chars. + /// Can be empty between broken UTF-8 chars. + pub valid: &'a str, + /// Single broken char, empty if none. + /// Empty iff iterator item is last. + pub broken: &'a [u8], +} + +impl<'a> Iterator for Utf8LossyChunksIter<'a> { + type Item = Utf8LossyChunk<'a>; + + fn next(&mut self) -> Option> { + if self.source.is_empty() { + return None; + } + + const TAG_CONT_U8: u8 = 128; + fn unsafe_get(xs: &[u8], i: usize) -> u8 { + unsafe { *xs.get_unchecked(i) } + } + fn safe_get(xs: &[u8], i: usize) -> u8 { + if i >= xs.len() { + 0 + } else { + unsafe_get(xs, i) + } + } + + let mut i = 0; + while i < self.source.len() { + let i_ = i; + + let byte = unsafe_get(self.source, i); + i += 1; + + if byte < 128 { + } else { + let w = core_str::utf8_char_width(byte); + + macro_rules! error { + () => {{ + unsafe { + let r = Utf8LossyChunk { + valid: str::from_utf8_unchecked(&self.source[0..i_]), + broken: &self.source[i_..i], + }; + self.source = &self.source[i..]; + return Some(r); + } + }}; + } + + match w { + 2 => { + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 3 => { + match (byte, safe_get(self.source, i)) { + (0xE0, 0xA0..=0xBF) => (), + (0xE1..=0xEC, 0x80..=0xBF) => (), + (0xED, 0x80..=0x9F) => (), + (0xEE..=0xEF, 0x80..=0xBF) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 4 => { + match (byte, safe_get(self.source, i)) { + (0xF0, 0x90..=0xBF) => (), + (0xF1..=0xF3, 0x80..=0xBF) => (), + (0xF4, 0x80..=0x8F) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + _ => { + error!(); + } + } + } + } + + let r = Utf8LossyChunk { + valid: unsafe { str::from_utf8_unchecked(self.source) }, + broken: &[], + }; + self.source = &[]; + Some(r) + } +} + +impl<'a> fmt::Display for Utf8Lossy<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // If we're the empty string then our iterator won't actually yield + // anything, so perform the formatting manually + if self.bytes.is_empty() { + return "".fmt(f); + } + + for Utf8LossyChunk { valid, broken } in self.chunks() { + // If we successfully decoded the whole chunk as a valid string then + // we can return a direct formatting of the string which will also + // respect various formatting flags if possible. + if valid.len() == self.bytes.len() { + assert!(broken.is_empty()); + return valid.fmt(f); + } + + f.write_str(valid)?; + if !broken.is_empty() { + f.write_char(char::REPLACEMENT_CHARACTER)?; + } + } + Ok(()) + } +} + +impl<'a> fmt::Debug for Utf8Lossy<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + for Utf8LossyChunk { valid, broken } in self.chunks() { + // Valid part. + // Here we partially parse UTF-8 again which is suboptimal. + { + let mut from = 0; + for (i, c) in valid.char_indices() { + let esc = c.escape_debug(); + // If char needs escaping, flush backlog so far and write, else skip + if esc.len() != 1 { + f.write_str(&valid[from..i])?; + for c in esc { + f.write_char(c)?; + } + from = i + c.len_utf8(); + } + } + f.write_str(&valid[from..])?; + } + + // Broken parts of string as hex escape. + for &b in broken { + write!(f, "\\x{:02x}", b)?; + } + } + + f.write_char('"') + } +} diff --git a/anneal/v2/vendor/bumpalo/src/collections/str/mod.rs b/anneal/v2/vendor/bumpalo/src/collections/str/mod.rs new file mode 100644 index 0000000000..29f4c6be06 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/str/mod.rs @@ -0,0 +1,43 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! String manipulation +//! +//! For more details, see std::str + +#[allow(missing_docs)] +pub mod lossy; + +// https://tools.ietf.org/html/rfc3629 +#[rustfmt::skip] +static UTF8_CHAR_WIDTH: [u8; 256] = [ +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF +0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF +4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF +]; + +/// Given a first byte, determines how many bytes are in this UTF-8 character. +#[inline] +pub fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} diff --git a/anneal/v2/vendor/bumpalo/src/collections/string.rs b/anneal/v2/vendor/bumpalo/src/collections/string.rs new file mode 100644 index 0000000000..bbc8050fa7 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/string.rs @@ -0,0 +1,2191 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A UTF-8 encoded, growable string. +//! +//! This module contains the [`String`] type and several error types that may +//! result from working with [`String`]s. +//! +//! This module is a fork of the [`std::string`] module, that uses a bump allocator. +//! +//! [`std::string`]: https://doc.rust-lang.org/std/string/index.html +//! +//! # Examples +//! +//! You can create a new [`String`] from a string literal with [`String::from_str_in`]: +//! +//! ``` +//! use bumpalo::{Bump, collections::String}; +//! +//! let b = Bump::new(); +//! +//! let s = String::from_str_in("world", &b); +//! ``` +//! +//! [`String`]: struct.String.html +//! [`String::from_str_in`]: struct.String.html#method.from_str_in +//! +//! If you have a vector of valid UTF-8 bytes, you can make a [`String`] out of +//! it. You can do the reverse too. +//! +//! ``` +//! use bumpalo::{Bump, collections::String}; +//! +//! let b = Bump::new(); +//! +//! let sparkle_heart = bumpalo::vec![in &b; 240, 159, 146, 150]; +//! +//! // We know these bytes are valid, so we'll use `unwrap()`. +//! let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +//! +//! assert_eq!("💖", sparkle_heart); +//! +//! let bytes = sparkle_heart.into_bytes(); +//! +//! assert_eq!(bytes, [240, 159, 146, 150]); +//! ``` + +use crate::collections::str::lossy; +use crate::collections::vec::Vec; +use crate::Bump; +use core::borrow::{Borrow, BorrowMut}; +use core::char::decode_utf16; +use core::fmt; +use core::hash; +use core::iter::FusedIterator; +use core::mem; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds}; +use core::ptr; +use core::str::{self, Chars, Utf8Error}; +use core_alloc::borrow::Cow; + +/// Like the [`format!`] macro, but for creating [`bumpalo::collections::String`]s. +/// +/// [`format!`]: https://doc.rust-lang.org/std/macro.format.html +/// [`bumpalo::collections::String`]: collections/string/struct.String.html +/// +/// # Examples +/// +/// ``` +/// use bumpalo::Bump; +/// +/// let b = Bump::new(); +/// +/// let who = "World"; +/// let s = bumpalo::format!(in &b, "Hello, {}!", who); +/// assert_eq!(s, "Hello, World!") +/// ``` +#[macro_export] +macro_rules! format { + ( in $bump:expr, $fmt:expr, $($args:expr),* ) => {{ + use $crate::core_alloc::fmt::Write; + let bump = $bump; + let mut s = $crate::collections::String::new_in(bump); + let _ = write!(&mut s, $fmt, $($args),*); + s + }}; + + ( in $bump:expr, $fmt:expr, $($args:expr,)* ) => { + $crate::format!(in $bump, $fmt, $($args),*) + }; +} + +/// A UTF-8 encoded, growable string. +/// +/// The `String` type is the most common string type that has ownership over the +/// contents of the string. It has a close relationship with its borrowed +/// counterpart, the primitive [`str`]. +/// +/// [`str`]: https://doc.rust-lang.org/std/primitive.str.html +/// +/// # Examples +/// +/// You can create a `String` from a literal string with [`String::from_str_in`]: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// let hello = String::from_str_in("Hello, world!", &b); +/// ``` +/// +/// You can append a [`char`] to a `String` with the [`push`] method, and +/// append a [`&str`] with the [`push_str`] method: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// let mut hello = String::from_str_in("Hello, ", &b); +/// +/// hello.push('w'); +/// hello.push_str("orld!"); +/// ``` +/// +/// [`char`]: https://doc.rust-lang.org/std/primitive.char.html +/// [`push`]: #method.push +/// [`push_str`]: #method.push_str +/// +/// If you have a vector of UTF-8 bytes, you can create a `String` from it with +/// the [`from_utf8`] method: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// // some bytes, in a vector +/// let sparkle_heart = bumpalo::vec![in &b; 240, 159, 146, 150]; +/// +/// // We know these bytes are valid, so we'll use `unwrap()`. +/// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +/// +/// [`from_utf8`]: #method.from_utf8 +/// +/// # Deref +/// +/// `String`s implement [`Deref`], and so inherit all of [`str`]'s +/// methods. In addition, this means that you can pass a `String` to a +/// function which takes a [`&str`] by using an ampersand (`&`): +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// fn takes_str(s: &str) { } +/// +/// let s = String::from_str_in("Hello", &b); +/// +/// takes_str(&s); +/// ``` +/// +/// This will create a [`&str`] from the `String` and pass it in. This +/// conversion is very inexpensive, and so generally, functions will accept +/// [`&str`]s as arguments unless they need a `String` for some specific +/// reason. +/// +/// In certain cases Rust doesn't have enough information to make this +/// conversion, known as [`Deref`] coercion. In the following example a string +/// slice [`&'a str`][`&str`] implements the trait `TraitExample`, and the function +/// `example_func` takes anything that implements the trait. In this case Rust +/// would need to make two implicit conversions, which Rust doesn't have the +/// means to do. For that reason, the following example will not compile. +/// +/// ```compile_fail,E0277 +/// use bumpalo::{Bump, collections::String}; +/// +/// trait TraitExample {} +/// +/// impl<'a> TraitExample for &'a str {} +/// +/// fn example_func(example_arg: A) {} +/// +/// let b = Bump::new(); +/// let example_string = String::from_str_in("example_string", &b); +/// example_func(&example_string); +/// ``` +/// +/// There are two options that would work instead. The first would be to +/// change the line `example_func(&example_string);` to +/// `example_func(example_string.as_str());`, using the method [`as_str()`] +/// to explicitly extract the string slice containing the string. The second +/// way changes `example_func(&example_string);` to +/// `example_func(&*example_string);`. In this case we are dereferencing a +/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to +/// [`&str`]. The second way is more idiomatic, however both work to do the +/// conversion explicitly rather than relying on the implicit conversion. +/// +/// # Representation +/// +/// A `String` is made up of three components: a pointer to some bytes, a +/// length, and a capacity. The pointer points to an internal buffer `String` +/// uses to store its data. The length is the number of bytes currently stored +/// in the buffer, and the capacity is the size of the buffer in bytes. As such, +/// the length will always be less than or equal to the capacity. +/// +/// This buffer is always stored on the heap. +/// +/// You can look at these with the [`as_ptr`], [`len`], and [`capacity`] +/// methods: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// use std::mem; +/// +/// let b = Bump::new(); +/// +/// let mut story = String::from_str_in("Once upon a time...", &b); +/// +/// let ptr = story.as_mut_ptr(); +/// let len = story.len(); +/// let capacity = story.capacity(); +/// +/// // story has nineteen bytes +/// assert_eq!(19, len); +/// +/// // Now that we have our parts, we throw the story away. +/// mem::forget(story); +/// +/// // We can re-build a String out of ptr, len, and capacity. This is all +/// // unsafe because we are responsible for making sure the components are +/// // valid: +/// let s = unsafe { String::from_raw_parts_in(ptr, len, capacity, &b) } ; +/// +/// assert_eq!(String::from_str_in("Once upon a time...", &b), s); +/// ``` +/// +/// [`as_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_ptr +/// [`len`]: #method.len +/// [`capacity`]: #method.capacity +/// +/// If a `String` has enough capacity, adding elements to it will not +/// re-allocate. For example, consider this program: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// let mut s = String::new_in(&b); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// This will output the following: +/// +/// ```text +/// 0 +/// 5 +/// 10 +/// 20 +/// 20 +/// 40 +/// ``` +/// +/// At first, we have no memory allocated at all, but as we append to the +/// string, it increases its capacity appropriately. If we instead use the +/// [`with_capacity_in`] method to allocate the correct capacity initially: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// let mut s = String::with_capacity_in(25, &b); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// [`with_capacity_in`]: #method.with_capacity_in +/// +/// We end up with a different output: +/// +/// ```text +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// ``` +/// +/// Here, there's no need to allocate more memory inside the loop. +/// +/// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html +/// [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +/// [`as_str()`]: struct.String.html#method.as_str +#[derive(PartialOrd, Eq, Ord)] +pub struct String<'bump> { + vec: Vec<'bump, u8>, +} + +/// A possible error value when converting a `String` from a UTF-8 byte vector. +/// +/// This type is the error type for the [`from_utf8`] method on [`String`]. It +/// is designed in such a way to carefully avoid reallocations: the +/// [`into_bytes`] method will give back the byte vector that was used in the +/// conversion attempt. +/// +/// [`from_utf8`]: struct.String.html#method.from_utf8 +/// [`String`]: struct.String.html +/// [`into_bytes`]: struct.FromUtf8Error.html#method.into_bytes +/// +/// The [`Utf8Error`] type provided by [`std::str`] represents an error that may +/// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's +/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` +/// through the [`utf8_error`] method. +/// +/// [`Utf8Error`]: https://doc.rust-lang.org/std/str/struct.Utf8Error.html +/// [`std::str`]: https://doc.rust-lang.org/std/str/index.html +/// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html +/// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html +/// [`utf8_error`]: #method.utf8_error +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// // some invalid bytes, in a vector +/// let bytes = bumpalo::vec![in &b; 0, 159]; +/// +/// let value = String::from_utf8(bytes); +/// +/// assert!(value.is_err()); +/// assert_eq!(bumpalo::vec![in &b; 0, 159], value.unwrap_err().into_bytes()); +/// ``` +#[derive(Debug)] +pub struct FromUtf8Error<'bump> { + bytes: Vec<'bump, u8>, + error: Utf8Error, +} + +/// A possible error value when converting a `String` from a UTF-16 byte slice. +/// +/// This type is the error type for the [`from_utf16_in`] method on [`String`]. +/// +/// [`from_utf16_in`]: struct.String.html#method.from_utf16_in +/// [`String`]: struct.String.html +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let b = Bump::new(); +/// +/// // 𝄞muic +/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; +/// +/// assert!(String::from_utf16_in(v, &b).is_err()); +/// ``` +#[derive(Debug)] +pub struct FromUtf16Error(()); + +impl<'bump> String<'bump> { + /// Creates a new empty `String`. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity_in`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity_in`]: #method.with_capacity_in + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::new_in(&b); + /// ``` + #[inline] + pub fn new_in(bump: &'bump Bump) -> String<'bump> { + String { + vec: Vec::new_in(bump), + } + } + + /// Creates a new empty `String` with a particular capacity. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold `capacity` bytes. This is useful when you may be + /// appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: #method.capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new_in`] method. + /// + /// [`new_in`]: #method.new + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::with_capacity_in(10, &b); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the vector reallocate + /// s.push('a'); + /// ``` + #[inline] + pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> String<'bump> { + String { + vec: Vec::with_capacity_in(capacity, bump), + } + } + + /// Converts a vector of bytes to a `String`. + /// + /// A string (`String`) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec`]) is made of bytes, so this function converts between the + /// two. Not all byte slices are valid `String`s, however: `String` + /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that + /// the bytes are valid UTF-8, and then does the conversion. + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the validity check, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the check. + /// + /// This method will take care to not copy the vector, for efficiency's + /// sake. + /// + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8`]. + /// + /// The inverse of this method is [`into_bytes`]. + /// + /// # Errors + /// + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the + /// provided bytes are not UTF-8. The vector you moved in is also included. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some bytes, in a vector + /// let sparkle_heart = bumpalo::vec![in &b; 240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so we'll use `unwrap()`. + /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some invalid bytes, in a vector + /// let sparkle_heart = bumpalo::vec![in &b; 0, 159, 146, 150]; + /// + /// assert!(String::from_utf8(sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. + /// + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked + /// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html + /// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html + /// [`Vec`]: ../vec/struct.Vec.html + /// [`str::from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html + /// [`into_bytes`]: struct.String.html#method.into_bytes + /// [`FromUtf8Error`]: struct.FromUtf8Error.html + /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err + #[inline] + pub fn from_utf8(vec: Vec<'bump, u8>) -> Result, FromUtf8Error<'bump>> { + match str::from_utf8(&vec) { + Ok(..) => Ok(String { vec }), + Err(e) => Err(FromUtf8Error { + bytes: vec, + error: e, + }), + } + } + + /// Converts a slice of bytes to a string, including invalid characters. + /// + /// Strings are made of bytes ([`u8`]), and a slice of bytes + /// ([`&[u8]`][slice]) is made of bytes, so this function converts + /// between the two. Not all byte slices are valid strings, however: strings + /// are required to be valid UTF-8. During this conversion, + /// `from_utf8_lossy_in()` will replace any invalid UTF-8 sequences with + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � + /// + /// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html + /// [slice]: https://doc.rust-lang.org/std/primitive.slice.html + /// [U+FFFD]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the conversion, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the checks. + /// + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{collections::String, Bump, vec}; + /// + /// let b = Bump::new(); + /// + /// // some bytes, in a vector + /// let sparkle_heart = bumpalo::vec![in &b; 240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy_in(&sparkle_heart, &b); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// use bumpalo::{collections::String, Bump, vec}; + /// + /// let b = Bump::new(); + /// + /// // some invalid bytes + /// let input = b"Hello \xF0\x90\x80World"; + /// let output = String::from_utf8_lossy_in(input, &b); + /// + /// assert_eq!("Hello �World", output); + /// ``` + pub fn from_utf8_lossy_in(v: &[u8], bump: &'bump Bump) -> String<'bump> { + let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); + + let (first_valid, first_broken) = if let Some(chunk) = iter.next() { + let lossy::Utf8LossyChunk { valid, broken } = chunk; + if valid.len() == v.len() { + debug_assert!(broken.is_empty()); + unsafe { + return String::from_utf8_unchecked(Vec::from_iter_in(v.iter().cloned(), bump)); + } + } + (valid, broken) + } else { + return String::from_str_in("", bump); + }; + + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = String::with_capacity_in(v.len(), bump); + res.push_str(first_valid); + if !first_broken.is_empty() { + res.push_str(REPLACEMENT); + } + + for lossy::Utf8LossyChunk { valid, broken } in iter { + res.push_str(valid); + if !broken.is_empty() { + res.push_str(REPLACEMENT); + } + } + + res + } + + /// Decode a UTF-16 encoded slice `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0x0069, 0x0063]; + /// assert_eq!(String::from_str_in("𝄞music", &b), String::from_utf16_in(v, &b).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; + /// assert!(String::from_utf16_in(v, &b).is_err()); + /// ``` + pub fn from_utf16_in(v: &[u16], bump: &'bump Bump) -> Result, FromUtf16Error> { + let mut ret = String::with_capacity_in(v.len(), bump); + for c in decode_utf16(v.iter().cloned()) { + if let Ok(c) = c { + ret.push(c); + } else { + return Err(FromUtf16Error(())); + } + } + Ok(ret) + } + + /// Construct a new `String<'bump>` from a string slice. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_str_in("hello", &b); + /// assert_eq!(s, "hello"); + /// ``` + #[inline] + pub fn from_str_in(s: &str, bump: &'bump Bump) -> String<'bump> { + let len = s.len(); + let mut t = String::with_capacity_in(len, bump); + // SAFETY: + // * `src` is valid for reads of `s.len()` bytes by virtue of being an allocated `&str`. + // * `dst` is valid for writes of `s.len()` bytes as `String::with_capacity_in(s.len(), bump)` + // above guarantees that. + // * Alignment is not relevant as `u8` has no alignment requirements. + // * Source and destination ranges cannot overlap as we just reserved the destination + // range from the bump. + unsafe { ptr::copy_nonoverlapping(s.as_ptr(), t.vec.as_mut_ptr(), len) }; + // SAFETY: We reserved sufficent capacity for the string above. + // The elements at `0..len` were initialized by `copy_nonoverlapping` above. + unsafe { t.vec.set_len(len) }; + t + } + + /// Construct a new `String<'bump>` from an iterator of `char`s. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_iter_in(['h', 'e', 'l', 'l', 'o'].iter().cloned(), &b); + /// assert_eq!(s, "hello"); + /// ``` + pub fn from_iter_in>(iter: I, bump: &'bump Bump) -> String<'bump> { + let mut s = String::new_in(bump); + for c in iter { + s.push(c); + } + s + } + + /// Creates a new `String` from a length, capacity, and pointer. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `ptr` needs to have been previously allocated by the + /// same allocator the standard library uses. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// use std::mem; + /// + /// let b = Bump::new(); + /// + /// unsafe { + /// let mut s = String::from_str_in("hello", &b); + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// mem::forget(s); + /// + /// let s = String::from_raw_parts_in(ptr, len, capacity, &b); + /// + /// assert_eq!(s, "hello"); + /// } + /// ``` + #[inline] + pub unsafe fn from_raw_parts_in( + buf: *mut u8, + length: usize, + capacity: usize, + bump: &'bump Bump, + ) -> String<'bump> { + String { + vec: Vec::from_raw_parts_in(buf, length, capacity, bump), + } + } + + /// Converts a vector of bytes to a `String` without checking that the + /// string contains valid UTF-8. + /// + /// See the safe version, [`from_utf8`], for more details. + /// + /// [`from_utf8`]: struct.String.html#method.from_utf8 + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, + /// as it is assumed that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some bytes, in a vector + /// let sparkle_heart = bumpalo::vec![in &b; 240, 159, 146, 150]; + /// + /// let sparkle_heart = unsafe { + /// String::from_utf8_unchecked(sparkle_heart) + /// }; + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[inline] + pub unsafe fn from_utf8_unchecked(bytes: Vec<'bump, u8>) -> String<'bump> { + String { vec: bytes } + } + + /// Returns a shared reference to the allocator backing this `String`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// // uses the same allocator as the provided `String` + /// fn copy_string<'bump>(s: &String<'bump>) -> &'bump str { + /// s.bump().alloc_str(s.as_str()) + /// } + /// ``` + #[inline] + #[must_use] + pub fn bump(&self) -> &'bump Bump { + self.vec.bump() + } + + /// Converts a `String` into a byte vector. + /// + /// This consumes the `String`, so we do not need to copy its contents. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_str_in("hello", &b); + /// + /// assert_eq!(s.into_bytes(), [104, 101, 108, 108, 111]); + /// ``` + #[inline] + pub fn into_bytes(self) -> Vec<'bump, u8> { + self.vec + } + + /// Convert this `String<'bump>` into a `&'bump str`. This is analogous to + /// [`std::string::String::into_boxed_str`][into_boxed_str]. + /// + /// [into_boxed_str]: https://doc.rust-lang.org/std/string/struct.String.html#method.into_boxed_str + /// + /// # Example + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_str_in("foo", &b); + /// + /// assert_eq!(s.into_bump_str(), "foo"); + /// ``` + pub fn into_bump_str(self) -> &'bump str { + let s = unsafe { + let s = self.as_str(); + mem::transmute(s) + }; + mem::forget(self); + s + } + + /// Extracts a string slice containing the entire `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_str_in("foo", &b); + /// + /// assert_eq!("foo", s.as_str()); + /// ``` + #[inline] + pub fn as_str(&self) -> &str { + self + } + + /// Converts a `String` into a mutable string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foobar", &b); + /// let s_mut_str = s.as_mut_str(); + /// + /// s_mut_str.make_ascii_uppercase(); + /// + /// assert_eq!("FOOBAR", s_mut_str); + /// ``` + #[inline] + pub fn as_mut_str(&mut self) -> &mut str { + self + } + + /// Appends a given string slice onto the end of this `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foo", &b); + /// + /// s.push_str("bar"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[inline] + pub fn push_str(&mut self, string: &str) { + self.vec.extend_from_slice_copy(string.as_bytes()) + } + + /// Returns this `String`'s capacity, in bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::with_capacity_in(10, &b); + /// + /// assert!(s.capacity() >= 10); + /// ``` + #[inline] + pub fn capacity(&self) -> usize { + self.vec.capacity() + } + + /// Ensures that this `String`'s capacity is at least `additional` bytes + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` bytes if it + /// chooses, to prevent frequent reallocations. + /// + /// If you do not want this "at least" behavior, see the [`reserve_exact`] + /// method. + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// [`reserve_exact`]: struct.String.html#method.reserve_exact + /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::new_in(&b); + /// + /// s.reserve(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::with_capacity_in(10, &b); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.vec.reserve(additional) + } + + /// Ensures that this `String`'s capacity is `additional` bytes + /// larger than its length. + /// + /// Consider using the [`reserve`] method unless you absolutely know + /// better than the allocator. + /// + /// [`reserve`]: #method.reserve + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::new_in(&b); + /// + /// s.reserve_exact(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::with_capacity_in(10, &b); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve_exact(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.vec.reserve_exact(additional) + } + + /// Shrinks the capacity of this `String` to match its length. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foo", &b); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + pub fn shrink_to_fit(&mut self) { + self.vec.shrink_to_fit() + } + + /// Appends the given [`char`] to the end of this `String`. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("abc", &b); + /// + /// s.push('1'); + /// s.push('2'); + /// s.push('3'); + /// + /// assert_eq!("abc123", s); + /// ``` + #[inline] + pub fn push(&mut self, ch: char) { + match ch.len_utf8() { + 1 => self.vec.push(ch as u8), + _ => self + .vec + .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), + } + } + + /// Returns a byte slice of this `String`'s contents. + /// + /// The inverse of this method is [`from_utf8`]. + /// + /// [`from_utf8`]: #method.from_utf8 + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let s = String::from_str_in("hello", &b); + /// + /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); + /// ``` + #[inline] + pub fn as_bytes(&self) -> &[u8] { + &self.vec + } + + /// Shortens this `String` to the specified length. + /// + /// If `new_len` is greater than the string's current length, this has no + /// effect. + /// + /// Note that this method has no effect on the allocated capacity + /// of the string. + /// + /// # Panics + /// + /// Panics if `new_len` does not lie on a [`char`] boundary. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("hello", &b); + /// + /// s.truncate(2); + /// + /// assert_eq!("he", s); + /// ``` + #[inline] + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + self.vec.truncate(new_len) + } + } + + /// Removes the last character from the string buffer and returns it. + /// + /// Returns [`None`] if this `String` is empty. + /// + /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foo", &b); + /// + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('f')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + #[inline] + pub fn pop(&mut self) -> Option { + let ch = self.chars().rev().next()?; + let newlen = self.len() - ch.len_utf8(); + unsafe { + self.vec.set_len(newlen); + } + Some(ch) + } + + /// Removes a [`char`] from this `String` at a byte position and returns it. + /// + /// This is an `O(n)` operation, as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than or equal to the `String`'s length, + /// or if it does not lie on a [`char`] boundary. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foo", &b); + /// + /// assert_eq!(s.remove(0), 'f'); + /// assert_eq!(s.remove(1), 'o'); + /// assert_eq!(s.remove(0), 'o'); + /// ``` + #[inline] + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + unsafe { + ptr::copy( + self.vec.as_ptr().add(next), + self.vec.as_mut_ptr().add(idx), + len - next, + ); + self.vec.set_len(len - (next - idx)); + } + ch + } + + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place and preserves the order of the retained + /// characters. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("f_o_ob_ar", &b); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + #[inline] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(char) -> bool, + { + struct SetLenOnDrop<'a, 'bump> { + s: &'a mut String<'bump>, + idx: usize, + del_bytes: usize, + } + + impl<'a, 'bump> Drop for SetLenOnDrop<'a, 'bump> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } + } + + let len = self.len(); + let mut guard = SetLenOnDrop { + s: self, + idx: 0, + del_bytes: 0, + }; + + while guard.idx < len { + let ch = + // SAFETY: `guard.idx` is positive-or-zero and less that len so the `get_unchecked` + // is in bound. `self` is valid UTF-8 like string and the returned slice starts at + // a unicode code point so the `Chars` always return one character. + unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap_unchecked() }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { + // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of + // bytes that are erased from the string so the resulting `guard.idx - + // guard.del_bytes` always represent a valid unicode code point. + // + // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()` len + // is safe. + ch.encode_utf8(unsafe { + core::slice::from_raw_parts_mut( + guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes), + ch.len_utf8(), + ) + }); + } + + // Point idx to the next char + guard.idx += ch_len; + } + + drop(guard); + } + + /// Inserts a character into this `String` at a byte position. + /// + /// This is an `O(n)` operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::with_capacity_in(3, &b); + /// + /// s.insert(0, 'f'); + /// s.insert(1, 'o'); + /// s.insert(2, 'o'); + /// + /// assert_eq!("foo", s); + /// ``` + #[inline] + pub fn insert(&mut self, idx: usize, ch: char) { + assert!(self.is_char_boundary(idx)); + let mut bits = [0; 4]; + let bits = ch.encode_utf8(&mut bits).as_bytes(); + + unsafe { + self.insert_bytes(idx, bits); + } + } + + unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { + let len = self.len(); + let amt = bytes.len(); + self.vec.reserve(amt); + + ptr::copy( + self.vec.as_ptr().add(idx), + self.vec.as_mut_ptr().add(idx + amt), + len - idx, + ); + ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + self.vec.set_len(len + amt); + } + + /// Inserts a string slice into this `String` at a byte position. + /// + /// This is an `O(n)` operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("bar", &b); + /// + /// s.insert_str(0, "foo"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[inline] + pub fn insert_str(&mut self, idx: usize, string: &str) { + assert!(self.is_char_boundary(idx)); + + unsafe { + self.insert_bytes(idx, string.as_bytes()); + } + } + + /// Returns a mutable reference to the contents of this `String`. + /// + /// # Safety + /// + /// This function is unsafe because the returned `&mut Vec` allows writing + /// bytes which are not valid UTF-8. If this constraint is violated, using + /// the original `String` after dropping the `&mut Vec` may violate memory + /// safety, as it is assumed that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("hello", &b); + /// + /// unsafe { + /// let vec = s.as_mut_vec(); + /// assert_eq!(vec, &[104, 101, 108, 108, 111]); + /// + /// vec.reverse(); + /// } + /// assert_eq!(s, "olleh"); + /// ``` + #[inline] + pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<'bump, u8> { + &mut self.vec + } + + /// Returns the length of this `String`, in bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let a = String::from_str_in("foo", &b); + /// + /// assert_eq!(a.len(), 3); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.vec.len() + } + + /// Returns `true` if this `String` has a length of zero. + /// + /// Returns `false` otherwise. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut v = String::new_in(&b); + /// assert!(v.is_empty()); + /// + /// v.push('a'); + /// assert!(!v.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the string into two at the given index. + /// + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at` is not on a UTF-8 code point boundary, or if it is beyond the last + /// code point of the string. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut hello = String::from_str_in("Hello, World!", &b); + /// let world = hello.split_off(7); + /// assert_eq!(hello, "Hello, "); + /// assert_eq!(world, "World!"); + /// ``` + #[inline] + pub fn split_off(&mut self, at: usize) -> String<'bump> { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); + unsafe { String::from_utf8_unchecked(other) } + } + + /// Truncates this `String`, removing all contents. + /// + /// While this means the `String` will have a length of zero, it does not + /// touch its capacity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("foo", &b); + /// + /// s.clear(); + /// + /// assert!(s.is_empty()); + /// assert_eq!(0, s.len()); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + pub fn clear(&mut self) { + self.vec.clear() + } + + /// Creates a draining iterator that removes the specified range in the `String` + /// and yields the removed `chars`. + /// + /// Note: The element range is removed even if the iterator is not + /// consumed until the end. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("α is alpha, β is beta", &b); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Remove the range up until the β from the string + /// let t = String::from_iter_in(s.drain(..beta_offset), &b); + /// assert_eq!(t, "α is alpha, "); + /// assert_eq!(s, "β is beta"); + /// + /// // A full range clears the string + /// drop(s.drain(..)); + /// assert_eq!(s, ""); + /// ``` + pub fn drain<'a, R>(&'a mut self, range: R) -> Drain<'a, 'bump> + where + R: RangeBounds, + { + // Memory safety + // + // The String version of Drain does not have the memory safety issues + // of the vector version. The data is just plain bytes. + // Because the range removal happens in Drop, if the Drain iterator is leaked, + // the removal will not happen. + let len = self.len(); + let start = match range.start_bound() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end_bound() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self as *mut _; + // slicing does the appropriate bounds checks + let chars_iter = self[start..end].chars(); + + Drain { + start, + end, + iter: chars_iter, + string: self_ptr, + } + } + + /// Removes the specified range in the string, + /// and replaces it with the given string. + /// The given string doesn't need to be the same length as the range. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// [`char`]: https://doc.rust-lang.org/std/primitive.char.html + /// [`Vec::splice`]: ../vec/struct.Vec.html#method.splice + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// let mut s = String::from_str_in("α is alpha, β is beta", &b); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Replace the range up until the β from the string + /// s.replace_range(..beta_offset, "Α is capital alpha; "); + /// assert_eq!(s, "Α is capital alpha; β is beta"); + /// ``` + pub fn replace_range(&mut self, range: R, replace_with: &str) + where + R: RangeBounds, + { + // Memory safety + // + // Replace_range does not have the memory safety issues of a vector Splice. + // of the vector version. The data is just plain bytes. + + match range.start_bound() { + Included(&n) => assert!(self.is_char_boundary(n)), + Excluded(&n) => assert!(self.is_char_boundary(n + 1)), + Unbounded => {} + }; + match range.end_bound() { + Included(&n) => assert!(self.is_char_boundary(n + 1)), + Excluded(&n) => assert!(self.is_char_boundary(n)), + Unbounded => {} + }; + + unsafe { self.as_mut_vec() }.splice(range, replace_with.bytes()); + } +} + +impl<'bump> FromUtf8Error<'bump> { + /// Returns a slice of bytes that were attempted to convert to a `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some invalid bytes, in a vector + /// let bytes = bumpalo::vec![in &b; 0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); + /// ``` + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Returns the bytes that were attempted to convert to a `String`. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some invalid bytes, in a vector + /// let bytes = bumpalo::vec![in &b; 0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(bumpalo::vec![in &b; 0, 159], value.unwrap_err().into_bytes()); + /// ``` + pub fn into_bytes(self) -> Vec<'bump, u8> { + self.bytes + } + + /// Fetch a `Utf8Error` to get more details about the conversion failure. + /// + /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may + /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's + /// an analogue to `FromUtf8Error`. See its documentation for more details + /// on using it. + /// + /// [`Utf8Error`]: https://doc.rust-lang.org/std/str/struct.Utf8Error.html + /// [`std::str`]: https://doc.rust-lang.org/std/str/index.html + /// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html + /// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use bumpalo::{Bump, collections::String}; + /// + /// let b = Bump::new(); + /// + /// // some invalid bytes, in a vector + /// let bytes = bumpalo::vec![in &b; 0, 159]; + /// + /// let error = String::from_utf8(bytes).unwrap_err().utf8_error(); + /// + /// // the first byte is invalid here + /// assert_eq!(1, error.valid_up_to()); + /// ``` + pub fn utf8_error(&self) -> Utf8Error { + self.error + } +} + +impl<'bump> fmt::Display for FromUtf8Error<'bump> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.error, f) + } +} + +impl fmt::Display for FromUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt("invalid utf-16: lone surrogate found", f) + } +} + +impl<'bump> Clone for String<'bump> { + fn clone(&self) -> Self { + String { + vec: self.vec.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.vec.clone_from(&source.vec); + } +} + +impl<'bump> Extend for String<'bump> { + fn extend>(&mut self, iter: I) { + let iterator = iter.into_iter(); + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); + for ch in iterator { + self.push(ch) + } + } +} + +impl<'a, 'bump> Extend<&'a char> for String<'bump> { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } +} + +impl<'a, 'bump> Extend<&'a str> for String<'bump> { + fn extend>(&mut self, iter: I) { + for s in iter { + self.push_str(s) + } + } +} + +impl<'bump> Extend> for String<'bump> { + fn extend>>(&mut self, iter: I) { + for s in iter { + self.push_str(&s) + } + } +} + +impl<'bump> Extend for String<'bump> { + fn extend>(&mut self, iter: I) { + for s in iter { + self.push_str(&s) + } + } +} + +impl<'a, 'bump> Extend> for String<'bump> { + fn extend>>(&mut self, iter: I) { + for s in iter { + self.push_str(&s) + } + } +} + +impl<'bump> PartialEq for String<'bump> { + #[inline] + fn eq(&self, other: &String) -> bool { + PartialEq::eq(&self[..], &other[..]) + } +} + +macro_rules! impl_eq { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'bump> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + } + + impl<'a, 'b, 'bump> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + } + }; +} + +impl_eq! { String<'bump>, str } +impl_eq! { String<'bump>, &'a str } +impl_eq! { Cow<'a, str>, String<'bump> } +impl_eq! { core_alloc::string::String, String<'bump> } + +impl<'bump> fmt::Display for String<'bump> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +impl<'bump> fmt::Debug for String<'bump> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'bump> hash::Hash for String<'bump> { + #[inline] + fn hash(&self, hasher: &mut H) { + (**self).hash(hasher) + } +} + +/// Implements the `+` operator for concatenating two strings. +/// +/// This consumes the `String<'bump>` on the left-hand side and re-uses its buffer (growing it if +/// necessary). This is done to avoid allocating a new `String<'bump>` and copying the entire contents on +/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by +/// repeated concatenation. +/// +/// The string on the right-hand side is only borrowed; its contents are copied into the returned +/// `String<'bump>`. +/// +/// # Examples +/// +/// Concatenating two `String<'bump>`s takes the first by value and borrows the second: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let bump = Bump::new(); +/// +/// let a = String::from_str_in("hello", &bump); +/// let b = String::from_str_in(" world", &bump); +/// let c = a + &b; +/// // `a` is moved and can no longer be used here. +/// ``` +/// +/// If you want to keep using the first `String`, you can clone it and append to the clone instead: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let bump = Bump::new(); +/// +/// let a = String::from_str_in("hello", &bump); +/// let b = String::from_str_in(" world", &bump); +/// let c = a.clone() + &b; +/// // `a` is still valid here. +/// ``` +/// +/// Concatenating `&str` slices can be done by converting the first to a `String`: +/// +/// ``` +/// use bumpalo::{Bump, collections::String}; +/// +/// let bump = Bump::new(); +/// +/// let a = "hello"; +/// let b = " world"; +/// let c = String::from_str_in(a, &bump) + b; +/// ``` +impl<'a, 'bump> Add<&'a str> for String<'bump> { + type Output = String<'bump>; + + #[inline] + fn add(mut self, other: &str) -> String<'bump> { + self.push_str(other); + self + } +} + +/// Implements the `+=` operator for appending to a `String<'bump>`. +/// +/// This has the same behavior as the [`push_str`][String::push_str] method. +impl<'a, 'bump> AddAssign<&'a str> for String<'bump> { + #[inline] + fn add_assign(&mut self, other: &str) { + self.push_str(other); + } +} + +impl<'bump> ops::Index> for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, index: ops::Range) -> &str { + &self[..][index] + } +} +impl<'bump> ops::Index> for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeTo) -> &str { + &self[..][index] + } +} +impl<'bump> ops::Index> for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeFrom) -> &str { + &self[..][index] + } +} +impl<'bump> ops::Index for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, _index: ops::RangeFull) -> &str { + unsafe { str::from_utf8_unchecked(&self.vec) } + } +} +impl<'bump> ops::Index> for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeInclusive) -> &str { + Index::index(&**self, index) + } +} +impl<'bump> ops::Index> for String<'bump> { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeToInclusive) -> &str { + Index::index(&**self, index) + } +} + +impl<'bump> ops::IndexMut> for String<'bump> { + #[inline] + fn index_mut(&mut self, index: ops::Range) -> &mut str { + &mut self[..][index] + } +} +impl<'bump> ops::IndexMut> for String<'bump> { + #[inline] + fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { + &mut self[..][index] + } +} +impl<'bump> ops::IndexMut> for String<'bump> { + #[inline] + fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { + &mut self[..][index] + } +} +impl<'bump> ops::IndexMut for String<'bump> { + #[inline] + fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { + unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } + } +} +impl<'bump> ops::IndexMut> for String<'bump> { + #[inline] + fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { + IndexMut::index_mut(&mut **self, index) + } +} +impl<'bump> ops::IndexMut> for String<'bump> { + #[inline] + fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { + IndexMut::index_mut(&mut **self, index) + } +} + +impl<'bump> ops::Deref for String<'bump> { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + unsafe { str::from_utf8_unchecked(&self.vec) } + } +} + +impl<'bump> ops::DerefMut for String<'bump> { + #[inline] + fn deref_mut(&mut self) -> &mut str { + unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } + } +} + +impl<'bump> AsRef for String<'bump> { + #[inline] + fn as_ref(&self) -> &str { + self + } +} + +impl<'bump> AsRef<[u8]> for String<'bump> { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<'bump> fmt::Write for String<'bump> { + #[inline] + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.push(c); + Ok(()) + } +} + +impl<'bump> Borrow for String<'bump> { + #[inline] + fn borrow(&self) -> &str { + &self[..] + } +} + +impl<'bump> BorrowMut for String<'bump> { + #[inline] + fn borrow_mut(&mut self) -> &mut str { + &mut self[..] + } +} + +/// A draining iterator for `String`. +/// +/// This struct is created by the [`String::drain`] method. See its +/// documentation for more information. +pub struct Drain<'a, 'bump> { + /// Will be used as &'a mut String in the destructor + string: *mut String<'bump>, + /// Start of part to remove + start: usize, + /// End of part to remove + end: usize, + /// Current remaining range to remove + iter: Chars<'a>, +} + +impl<'a, 'bump> fmt::Debug for Drain<'a, 'bump> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Drain { .. }") + } +} + +unsafe impl<'a, 'bump> Sync for Drain<'a, 'bump> {} +unsafe impl<'a, 'bump> Send for Drain<'a, 'bump> {} + +impl<'a, 'bump> Drop for Drain<'a, 'bump> { + fn drop(&mut self) { + unsafe { + // Use Vec::drain. "Reaffirm" the bounds checks to avoid + // panic code being inserted again. + let self_vec = (*self.string).as_mut_vec(); + if self.start <= self.end && self.end <= self_vec.len() { + self_vec.drain(self.start..self.end); + } + } + } +} + +// TODO: implement `AsRef` and `as_str` + +impl<'a, 'bump> Iterator for Drain<'a, 'bump> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, 'bump> DoubleEndedIterator for Drain<'a, 'bump> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +impl<'a, 'bump> FusedIterator for Drain<'a, 'bump> {} + +#[cfg(feature = "serde")] +mod serialize { + use super::*; + + use serde::{Serialize, Serializer}; + + impl<'bump> Serialize for String<'bump> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self) + } + } +} diff --git a/anneal/v2/vendor/bumpalo/src/collections/vec.rs b/anneal/v2/vendor/bumpalo/src/collections/vec.rs new file mode 100644 index 0000000000..52175599ed --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/collections/vec.rs @@ -0,0 +1,3051 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +//! A contiguous growable array type with heap-allocated contents, written +//! [`Vec<'bump, T>`]. +//! +//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and +//! `O(1)` pop (from the end). +//! +//! This module is a fork of the [`std::vec`] module, that uses a bump allocator. +//! +//! [`std::vec`]: https://doc.rust-lang.org/std/vec/index.html +//! +//! # Examples +//! +//! You can explicitly create a [`Vec<'bump, T>`] with [`new_in`]: +//! +//! ``` +//! use bumpalo::{Bump, collections::Vec}; +//! +//! let b = Bump::new(); +//! let v: Vec = Vec::new_in(&b); +//! ``` +//! +//! ... or by using the [`vec!`] macro: +//! +//! ``` +//! use bumpalo::{Bump, collections::Vec}; +//! +//! let b = Bump::new(); +//! +//! let v: Vec = bumpalo::vec![in &b]; +//! +//! let v = bumpalo::vec![in &b; 1, 2, 3, 4, 5]; +//! +//! let v = bumpalo::vec![in &b; 0; 10]; // ten zeroes +//! ``` +//! +//! You can [`push`] values onto the end of a vector (which will grow the vector +//! as needed): +//! +//! ``` +//! use bumpalo::{Bump, collections::Vec}; +//! +//! let b = Bump::new(); +//! +//! let mut v = bumpalo::vec![in &b; 1, 2]; +//! +//! v.push(3); +//! ``` +//! +//! Popping values works in much the same way: +//! +//! ``` +//! use bumpalo::{Bump, collections::Vec}; +//! +//! let b = Bump::new(); +//! +//! let mut v = bumpalo::vec![in &b; 1, 2]; +//! +//! assert_eq!(v.pop(), Some(2)); +//! ``` +//! +//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): +//! +//! ``` +//! use bumpalo::{Bump, collections::Vec}; +//! +//! let b = Bump::new(); +//! +//! let mut v = bumpalo::vec![in &b; 1, 2, 3]; +//! assert_eq!(v[2], 3); +//! v[1] += 5; +//! assert_eq!(v, [1, 7, 3]); +//! ``` +//! +//! [`Vec<'bump, T>`]: struct.Vec.html +//! [`new_in`]: struct.Vec.html#method.new_in +//! [`push`]: struct.Vec.html#method.push +//! [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html +//! [`IndexMut`]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html +//! [`vec!`]: ../../macro.vec.html + +use super::raw_vec::RawVec; +use crate::collections::CollectionAllocErr; +use crate::Bump; +use core::borrow::{Borrow, BorrowMut}; +use core::cmp::Ordering; +use core::fmt; +use core::hash::{self, Hash}; +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::mem; +use core::ops; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Index, IndexMut, RangeBounds}; +use core::ptr; +use core::ptr::NonNull; +use core::slice; +#[cfg(feature = "std")] +use std::io; + +unsafe fn arith_offset(p: *const T, offset: isize) -> *const T { + p.offset(offset) +} + +fn partition_dedup_by(s: &mut [T], mut same_bucket: F) -> (&mut [T], &mut [T]) +where + F: FnMut(&mut T, &mut T) -> bool, +{ + // Although we have a mutable reference to `s`, we cannot make + // *arbitrary* changes. The `same_bucket` calls could panic, so we + // must ensure that the slice is in a valid state at all times. + // + // The way that we handle this is by using swaps; we iterate + // over all the elements, swapping as we go so that at the end + // the elements we wish to keep are in the front, and those we + // wish to reject are at the back. We can then split the slice. + // This operation is still O(n). + // + // Example: We start in this state, where `r` represents "next + // read" and `w` represents "next_write`. + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing s[r] against s[w-1], this is not a duplicate, so + // we swap s[r] and s[w] (no effect as r==w) and then increment both + // r and w, leaving us with: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing s[r] against s[w-1], this value is a duplicate, + // so we increment `r` but leave everything else unchanged: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing s[r] against s[w-1], this is not a duplicate, + // so swap s[r] and s[w] and advance r and w: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 1 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Not a duplicate, repeat: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 3 | 1 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Duplicate, advance r. End of slice. Split at w. + + let len = s.len(); + if len <= 1 { + return (s, &mut []); + } + + let ptr = s.as_mut_ptr(); + let mut next_read: usize = 1; + let mut next_write: usize = 1; + + unsafe { + // Avoid bounds checks by using raw pointers. + while next_read < len { + let ptr_read = ptr.add(next_read); + let prev_ptr_write = ptr.add(next_write - 1); + if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) { + if next_read != next_write { + let ptr_write = prev_ptr_write.offset(1); + mem::swap(&mut *ptr_read, &mut *ptr_write); + } + next_write += 1; + } + next_read += 1; + } + } + + s.split_at_mut(next_write) +} + +unsafe fn offset_from(p: *const T, origin: *const T) -> isize +where + T: Sized, +{ + let pointee_size = mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); + + // This is the same sequence that Clang emits for pointer subtraction. + // It can be neither `nsw` nor `nuw` because the input is treated as + // unsigned but then the output is treated as signed, so neither works. + let d = isize::wrapping_sub(p as _, origin as _); + d / (pointee_size as isize) +} + +/// Creates a [`Vec`] containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a [`Vec`] containing a given list of elements: +/// +/// ``` +/// use bumpalo::Bump; +/// +/// let b = Bump::new(); +/// let v = bumpalo::vec![in &b; 1, 2, 3]; +/// assert_eq!(v, [1, 2, 3]); +/// ``` +/// +/// - Create a [`Vec`] from a given element and size: +/// +/// ``` +/// use bumpalo::Bump; +/// +/// let b = Bump::new(); +/// let v = bumpalo::vec![in &b; 1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions, this syntax supports all elements +/// which implement [`Clone`] and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone` to duplicate an expression, so one should be careful +/// using this with types having a non-standard `Clone` implementation. For +/// example, `bumpalo::vec![in ≎ Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. +/// +/// [`Vec`]: collections/vec/struct.Vec.html +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +#[macro_export] +macro_rules! vec { + (in $bump:expr; $elem:expr; $n:expr) => {{ + let n = $n; + let mut v = $crate::collections::Vec::with_capacity_in(n, $bump); + if n > 0 { + let elem = $elem; + for _ in 0..n - 1 { + v.push(elem.clone()); + } + v.push(elem); + } + v + }}; + (in $bump:expr) => { $crate::collections::Vec::new_in($bump) }; + (in $bump:expr; $($x:expr),*) => {{ + let mut v = $crate::collections::Vec::new_in($bump); + $( v.push($x); )* + v + }}; + (in $bump:expr; $($x:expr,)*) => (bumpalo::vec![in $bump; $($x),*]) +} + +/// A contiguous growable array type, written `Vec<'bump, T>` but pronounced 'vector'. +/// +/// # Examples +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let mut vec = Vec::new_in(&b); +/// vec.push(1); +/// vec.push(2); +/// +/// assert_eq!(vec.len(), 2); +/// assert_eq!(vec[0], 1); +/// +/// assert_eq!(vec.pop(), Some(2)); +/// assert_eq!(vec.len(), 1); +/// +/// vec[0] = 7; +/// assert_eq!(vec[0], 7); +/// +/// vec.extend([1, 2, 3].iter().cloned()); +/// +/// for x in &vec { +/// println!("{}", x); +/// } +/// assert_eq!(vec, [7, 1, 2, 3]); +/// ``` +/// +/// The [`vec!`] macro is provided to make initialization more convenient: +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; +/// vec.push(4); +/// assert_eq!(vec, [1, 2, 3, 4]); +/// ``` +/// +/// It can also initialize each element of a `Vec<'bump, T>` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let vec = bumpalo::vec![in &b; 0; 5]; +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec1 = Vec::with_capacity_in(5, &b); +/// vec1.resize(5, 0); +/// ``` +/// +/// Use a `Vec<'bump, T>` as an efficient stack: +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let mut stack = Vec::new_in(&b); +/// +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); +/// +/// while let Some(top) = stack.pop() { +/// // Prints 3, 2, 1 +/// println!("{}", top); +/// } +/// ``` +/// +/// # Indexing +/// +/// The `Vec` type allows to access values by index, because it implements the +/// [`Index`] trait. An example will be more explicit: +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let v = bumpalo::vec![in &b; 0, 2, 4, 6]; +/// println!("{}", v[1]); // it will display '2' +/// ``` +/// +/// However be careful: if you try to access an index which isn't in the `Vec`, +/// your software will panic! You cannot do this: +/// +/// ```should_panic +/// use bumpalo::{Bump, collections::Vec}; +/// +/// let b = Bump::new(); +/// +/// let v = bumpalo::vec![in &b; 0, 2, 4, 6]; +/// println!("{}", v[6]); // it will panic! +/// ``` +/// +/// In conclusion: always check if the index you want to get really exists +/// before doing it. +/// +/// # Slicing +/// +/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects. +/// To get a slice, use `&`. Example: +/// +/// ``` +/// use bumpalo::{Bump, collections::Vec}; +/// +/// fn read_slice(slice: &[usize]) { +/// // ... +/// } +/// +/// let b = Bump::new(); +/// +/// let v = bumpalo::vec![in &b; 0, 1]; +/// read_slice(&v); +/// +/// // ... and that's all! +/// // you can also do it like this: +/// let x : &[usize] = &v; +/// ``` +/// +/// In Rust, it's more common to pass slices as arguments rather than vectors +/// when you just want to provide a read access. The same goes for [`String`] and +/// [`&str`]. +/// +/// # Capacity and reallocation +/// +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be +/// reallocated. +/// +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity_in`] +/// whenever possible to specify how big the vector is expected to get. +/// +/// # Guarantees +/// +/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees +/// about its design. This ensures that it's as low-overhead as possible in +/// the general case, and can be correctly manipulated in primitive ways +/// by unsafe code. Note that these guarantees refer to an unqualified `Vec<'bump, T>`. +/// If additional type parameters are added (e.g. to support custom allocators), +/// overriding their defaults may change the behavior. +/// +/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) +/// triplet. No more, no less. The order of these fields is completely +/// unspecified, and you should use the appropriate methods to modify these. +/// The pointer will never be null, so this type is null-pointer-optimized. +/// +/// However, the pointer may not actually point to allocated memory. In particular, +/// if you construct a `Vec` with capacity 0 via [`Vec::new_in`], [`bumpalo::vec![in bump]`][`vec!`], +/// [`Vec::with_capacity_in(0)`][`Vec::with_capacity_in`], or by calling [`shrink_to_fit`] +/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized +/// types inside a `Vec`, it will not allocate space for them. *Note that in this case +/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [`mem::size_of::`]\() * capacity() > 0. In general, `Vec`'s allocation +/// details are very subtle — if you intend to allocate memory using a `Vec` +/// and use it for something else (either to pass to unsafe code, or to build your +/// own memory-backed collection), be sure to deallocate this memory by using +/// `from_raw_parts` to recover the `Vec` and then dropping it. +/// +/// If a `Vec` *has* allocated memory, then the memory it points to is +/// in the [`Bump`] arena used to construct it, and its +/// pointer points to [`len`] initialized, contiguous elements in order (what +/// you would see if you coerced it to a slice), followed by [`capacity`] - +/// [`len`] logically uninitialized, contiguous elements. +/// +/// `Vec` will never perform a "small optimization" where elements are actually +/// stored on the stack for two reasons: +/// +/// * It would make it more difficult for unsafe code to correctly manipulate +/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were +/// only moved, and it would be more difficult to determine if a `Vec` had +/// actually allocated memory. +/// +/// * It would penalize the general case, incurring an additional branch +/// on every access. +/// +/// `Vec` will never automatically shrink itself, even if completely empty. This +/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// and then filling it back up to the same [`len`] should incur no calls to +/// the allocator. If you wish to free up unused memory, use +/// [`shrink_to_fit`][`shrink_to_fit`]. +/// +/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is +/// sufficient. [`push`] and [`insert`] *will* (re)allocate if +/// [`len`] == [`capacity`]. That is, the reported capacity is completely +/// accurate, and can be relied on. It can even be used to manually free the memory +/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even +/// when not necessary. +/// +/// `Vec` does not guarantee any particular growth strategy when reallocating +/// when full, nor when [`reserve`] is called. The current strategy is basic +/// and it may prove desirable to use a non-constant growth factor. Whatever +/// strategy is used will of course guarantee `O(1)` amortized [`push`]. +/// +/// `bumpalo::vec![in bump; x; n]`, `bumpalo::vec![in bump; a, b, c, d]`, and +/// [`Vec::with_capacity_in(n)`][`Vec::with_capacity_in`], will all produce a +/// `Vec` with exactly the requested capacity. If [`len`] == [`capacity`], (as +/// is the case for the [`vec!`] macro), then a `Vec<'bump, T>` can be converted +/// to and from a [`Box<[T]>`][owned slice] without reallocating or moving the +/// elements. +/// +/// `Vec` will not specifically overwrite any data that is removed from it, +/// but also won't specifically preserve it. Its uninitialized memory is +/// scratch space that it may use however it wants. It will generally just do +/// whatever is most efficient or otherwise easy to implement. Do not rely on +/// removed data to be erased for security purposes. Even if you drop a `Vec`, its +/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory +/// first, that may not actually happen because the optimizer does not consider +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. +/// +/// `Vec` does not currently guarantee the order in which elements are dropped. +/// The order has changed in the past and may change again. +/// +/// [`vec!`]: ../../macro.vec.html +/// [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html +/// [`String`]: ../string/struct.String.html +/// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html +/// [`Vec::with_capacity_in`]: struct.Vec.html#method.with_capacity_in +/// [`Vec::new_in`]: struct.Vec.html#method.new_in +/// [`shrink_to_fit`]: struct.Vec.html#method.shrink_to_fit +/// [`capacity`]: struct.Vec.html#method.capacity +/// [`mem::size_of::`]: https://doc.rust-lang.org/std/mem/fn.size_of.html +/// [`len`]: struct.Vec.html#method.len +/// [`push`]: struct.Vec.html#method.push +/// [`insert`]: struct.Vec.html#method.insert +/// [`reserve`]: struct.Vec.html#method.reserve +/// [owned slice]: https://doc.rust-lang.org/std/boxed/struct.Box.html +pub struct Vec<'bump, T: 'bump> { + buf: RawVec<'bump, T>, + len: usize, +} + +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// + +impl<'bump, T: 'bump> Vec<'bump, T> { + /// Constructs a new, empty `Vec<'bump, T>`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec: Vec = Vec::new_in(&b); + /// ``` + #[inline] + pub fn new_in(bump: &'bump Bump) -> Vec<'bump, T> { + Vec { + buf: RawVec::new_in(bump), + len: 0, + } + } + + /// Constructs a new, empty `Vec<'bump, T>` with the specified capacity. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = Vec::with_capacity_in(10, &b); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// ``` + #[inline] + pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> Vec<'bump, T> { + Vec { + buf: RawVec::with_capacity_in(capacity, bump), + len: 0, + } + } + + /// Construct a new `Vec` from the given iterator's items. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// use std::iter; + /// + /// let b = Bump::new(); + /// let v = Vec::from_iter_in(iter::repeat(7).take(3), &b); + /// assert_eq!(v, [7, 7, 7]); + /// ``` + pub fn from_iter_in>(iter: I, bump: &'bump Bump) -> Vec<'bump, T> { + let mut v = Vec::new_in(bump); + v.extend(iter); + v + } + + /// Creates a `Vec<'bump, T>` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<'bump, T>` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `ptr`'s `T` needs to have the same size and alignment as it was allocated with. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array and a `size_t`. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec<'bump, T>` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: ../string/struct.String.html + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// use std::ptr; + /// use std::mem; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; 1, 2, 3]; + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Cast `v` into the void: no destructor run, so we are in + /// // complete control of the allocation to which `p` points. + /// mem::forget(v); + /// + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, &b); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + pub unsafe fn from_raw_parts_in( + ptr: *mut T, + length: usize, + capacity: usize, + bump: &'bump Bump, + ) -> Vec<'bump, T> { + Vec { + buf: RawVec::from_raw_parts_in(ptr, capacity, bump), + len: length, + } + } + + /// Returns a shared reference to the allocator backing this `Vec`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// // uses the same allocator as the provided `Vec` + /// fn add_strings<'bump>(vec: &mut Vec<'bump, &'bump str>) { + /// for string in ["foo", "bar", "baz"] { + /// vec.push(vec.bump().alloc_str(string)); + /// } + /// } + /// ``` + #[inline] + #[must_use] + pub fn bump(&self) -> &'bump Bump { + self.buf.bump() + } + + /// Returns the number of elements the vector can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let vec: Vec = Vec::with_capacity_in(10, &b); + /// assert_eq!(vec.capacity(), 10); + /// ``` + #[inline] + pub fn capacity(&self) -> usize { + self.buf.cap() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec<'bump, T>`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); + /// ``` + pub fn reserve(&mut self, additional: usize) { + self.buf.reserve(self.len, additional); + } + + /// Reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec<'bump, T>`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); + /// ``` + pub fn reserve_exact(&mut self, additional: usize) { + self.buf.reserve_exact(self.len, additional); + } + + /// Attempts to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec<'bump, T>`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.try_reserve(10).unwrap(); + /// assert!(vec.capacity() >= 11); + /// ``` + pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.buf.try_reserve(self.len, additional) + } + + /// Attempts to reserve the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec<'bump, T>`. After calling `try_reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `try_reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.try_reserve_exact(10).unwrap(); + /// assert!(vec.capacity() >= 11); + /// ``` + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.buf.try_reserve_exact(self.len, additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator + /// may still inform the vector that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = Vec::with_capacity_in(10, &b); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); + /// ``` + pub fn shrink_to_fit(&mut self) { + if self.capacity() != self.len { + self.buf.shrink_to_fit(self.len); + } + } + + /// Converts the vector into `&'bump [T]`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let v = bumpalo::vec![in &b; 1, 2, 3]; + /// + /// let slice = v.into_bump_slice(); + /// assert_eq!(slice, [1, 2, 3]); + /// ``` + pub fn into_bump_slice(self) -> &'bump [T] { + unsafe { + let ptr = self.as_ptr(); + let len = self.len(); + mem::forget(self); + slice::from_raw_parts(ptr, len) + } + } + + /// Converts the vector into `&'bump mut [T]`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let v = bumpalo::vec![in &b; 1, 2, 3]; + /// + /// let mut slice = v.into_bump_slice_mut(); + /// + /// slice[0] = 3; + /// slice[2] = 1; + /// + /// assert_eq!(slice, [3, 2, 1]); + /// ``` + pub fn into_bump_slice_mut(mut self) -> &'bump mut [T] { + let ptr = self.as_mut_ptr(); + let len = self.len(); + mem::forget(self); + + unsafe { slice::from_raw_parts_mut(ptr, len) } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector's current length, this has no + /// effect. + /// + /// The [`drain`] method can emulate `truncate`, but causes the excess + /// elements to be returned instead of dropped. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// Truncating a five element vector to two elements: + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3, 4, 5]; + /// vec.truncate(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// No truncation occurs when `len` is greater than the vector's current + /// length: + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// vec.truncate(8); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// Truncating when `len == 0` is equivalent to calling the [`clear`] + /// method. + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// vec.truncate(0); + /// assert_eq!(vec, []); + /// ``` + /// + /// [`clear`]: #method.clear + /// [`drain`]: #method.drain + pub fn truncate(&mut self, len: usize) { + let current_len = self.len; + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // drop any extra elements + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); + } + } + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// use std::io::{self, Write}; + /// + /// let b = Bump::new(); + /// + /// let buffer = bumpalo::vec![in &b; 1, 2, 3, 5, 8]; + /// io::sink().write(buffer.as_slice()).unwrap(); + /// ``` + #[inline] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Extracts a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// use std::io::{self, Read}; + /// + /// let b = Bump::new(); + /// let mut buffer = bumpalo::vec![in &b; 0; 3]; + /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); + /// ``` + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Returns a raw pointer to the vector's buffer, or a dangling raw pointer + /// valid for zero sized reads if the vector didn't allocate. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let bump = Bump::new(); + /// + /// let x = bumpalo::vec![in ≎ 1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + if ptr.is_null() { + core::hint::unreachable_unchecked(); + } + } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling + /// raw pointer valid for zero sized reads if the vector didn't allocate. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let bump = Bump::new(); + /// + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity_in(size, &bump); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// x_ptr.add(i).write(i as i32); + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + if ptr.is_null() { + core::hint::unreachable_unchecked(); + } + } + ptr + } + + /// Sets the length of a vector. + /// + /// This will explicitly set the size of the vector, without actually + /// modifying its buffers, so it is up to the caller to ensure that the + /// vector is actually the specified size. + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: struct.Vec.html#method.capacity + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// use std::ptr; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 'r', 'u', 's', 't']; + /// + /// unsafe { + /// ptr::drop_in_place(&mut vec[3]); + /// vec.set_len(3); + /// } + /// assert_eq!(vec, ['r', 'u', 's']); + /// ``` + /// + /// In this example, there is a memory leak since the memory locations + /// owned by the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; + /// bumpalo::vec![in &b; 1, 0, 0], + /// bumpalo::vec![in &b; 0, 1, 0], + /// bumpalo::vec![in &b; 0, 0, 1]]; + /// unsafe { + /// vec.set_len(0); + /// } + /// ``` + /// + /// In this example, the vector gets expanded from zero to four items + /// but we directly initialize uninitialized memory: + /// + // TODO: rely upon `spare_capacity_mut` + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let len = 4; + /// let b = Bump::new(); + /// + /// let mut vec: Vec = Vec::with_capacity_in(len, &b); + /// + /// for i in 0..len { + /// // SAFETY: we initialize memory via `pointer::write` + /// unsafe { vec.as_mut_ptr().add(i).write(b'a') } + /// } + /// + /// unsafe { + /// vec.set_len(len); + /// } + /// + /// assert_eq!(b"aaaa", &*vec); + /// ``` + #[inline] + pub unsafe fn set_len(&mut self, new_len: usize) { + self.len = new_len; + } + + /// Removes an element from the vector and returns it. + /// + /// The removed element is replaced by the last element of the vector. + /// + /// This does not preserve ordering, but is O(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; "foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, ["baz", "qux"]); + /// ``` + #[inline] + pub fn swap_remove(&mut self, index: usize) -> T { + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check on hole succeeds there must be a last element (which + // can be self[index] itself). + let hole: *mut T = &mut self[index]; + let last = ptr::read(self.get_unchecked(self.len - 1)); + self.len -= 1; + ptr::replace(hole, last) + } + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + pub fn insert(&mut self, index: usize, element: T) { + let len = self.len(); + assert!(index <= len); + + // space for the new element + if len == self.buf.cap() { + self.reserve(1); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; 1, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + pub fn remove(&mut self, index: usize) -> T { + let len = self.len(); + assert!(index < len); + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// This method operates in place and preserves the order of the retained + /// elements. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3, 4]; + /// vec.retain(|x: &i32| *x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.drain_filter(|x| !f(x)); + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. + /// This method operates in place and preserves the order of the retained + /// elements. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3, 4]; + /// vec.retain_mut(|x: &mut i32| *x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, + { + self.drain_filter(|x| !f(x)); + } + + /// Creates an iterator that removes the elements in the vector + /// for which the predicate returns `true` and yields the removed items. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::Bump; + /// use bumpalo::collections::{CollectIn, Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut numbers = bumpalo::vec![in &b; 1, 2, 3, 4, 5]; + /// + /// let evens: Vec<_> = numbers.drain_filter(|x| *x % 2 == 0).collect_in(&b); + /// + /// assert_eq!(numbers, &[1, 3, 5]); + /// assert_eq!(evens, &[2, 4]); + /// ``` + pub fn drain_filter<'a, F>(&'a mut self, filter: F) -> DrainFilter<'a, 'bump, T, F> + where + F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + self.set_len(0); + } + + DrainFilter { + vec: self, + idx: 0, + write: 0, + old_len, + pred: filter, + } + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 10, 20, 21, 30, 20]; + /// + /// vec.dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(vec, [10, 20, 30, 20]); + /// ``` + #[inline] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// The `same_bucket` function is passed references to two elements from the vector and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; "foo", "bar", "Bar", "baz", "bar"]; + /// + /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + /// ``` + pub fn dedup_by(&mut self, same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + let len = { + let (dedup, _) = partition_dedup_by(self.as_mut_slice(), same_bucket); + dedup.len() + }; + self.truncate(len); + } + + // Proven specification with verus, converted to comments. + /// # Preconditions + /// + /// - old(self).len() < old(self).capacity(), + /// + /// # Postconditions + /// + /// - self.get_unchecked(old(self).len()) == value, + /// - self.len() == old(self).len() + 1, + /// - self.capacity() == old(self).capacity(), + /// - forall|i: usize| implies( + /// i < old(self).len(), + /// self.get_unchecked(i) == old(self).get_unchecked(i) + /// ) + #[allow(clippy::inline_always)] + #[inline(always)] + unsafe fn push_unchecked(&mut self, value: T) { + debug_assert!(self.len() < self.capacity()); + + // Divergence from verified impl: + // Verified implementation has special handling for ZSTs + // as ZSTs do not play nicely with separation logic. + ptr::write(self.buf.ptr().add(self.len), value); + + self.len = self.len + 1; + } + + /// Appends an element to the back of a vector. + /// + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2]; + /// vec.push(3); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + pub fn push(&mut self, value: T) { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.len == self.buf.cap() { + self.reserve(1); + } + unsafe { + self.push_unchecked(value); + } + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[inline] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + Some(ptr::read(self.as_ptr().add(self.len()))) + } + } + } + + /// Removes and returns the last element from a vector if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the vector + /// is empty (the predicate will not be called in that case). + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3, 4]; + /// let pred = |x: &mut i32| *x % 2 == 0; + /// + /// assert_eq!(vec.pop_if(pred), Some(4)); + /// assert_eq!(vec, [1, 2, 3]); + /// assert_eq!(vec.pop_if(pred), None); + /// ``` + #[inline] + pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option { + let last = self.last_mut()?; + if predicate(last) { + self.pop() + } else { + None + } + } + + /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// let mut vec2 = bumpalo::vec![in &b; 4, 5, 6]; + /// vec.append(&mut vec2); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); + /// ``` + #[inline] + pub fn append(&mut self, other: &mut Self) { + unsafe { + self.append_elements(other.as_slice() as _); + other.set_len(0); + } + } + + /// Appends elements to `Self` from other buffer. + #[inline] + unsafe fn append_elements(&mut self, other: *const [T]) { + let count = (&(*other)).len(); + self.reserve(count); + let len = self.len(); + ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count); + self.len += count; + } + + /// Creates a draining iterator that removes the specified range in the vector + /// and yields the removed items. + /// + /// Note 1: The element range is removed even if the iterator is only + /// partially consumed or not consumed at all. + /// + /// Note 2: It is unspecified how many elements are removed from the vector + /// if the `Drain` value is leaked. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::Bump; + /// use bumpalo::collections::{CollectIn, Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; 1, 2, 3]; + /// + /// let u: Vec<_> = v.drain(1..).collect_in(&b); + /// + /// assert_eq!(v, &[1]); + /// assert_eq!(u, &[2, 3]); + /// + /// // A full range clears the vector + /// v.drain(..); + /// assert_eq!(v, &[]); + /// ``` + pub fn drain<'a, R>(&'a mut self, range: R) -> Drain<'a, 'bump, T> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = match range.start_bound() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end_bound() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; + assert!(start <= end); + assert!(end <= len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + // Use the borrow in the IterMut to indicate borrowing behavior of the + // whole Drain iterator (like &mut T). + let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + vec: NonNull::from(self), + } + } + } + + /// Clears the vector, removing all values. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; 1, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { + self.truncate(0) + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let a = bumpalo::vec![in &b; 1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector contains no elements. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = Vec::new_in(&b); + /// assert!(v.is_empty()); + /// + /// v.push(1); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector. `self` contains elements `[0, at)`, + /// and the returned vector contains elements `[at, len)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[inline] + pub fn split_off(&mut self, at: usize) -> Self { + assert!(at <= self.len(), "`at` out of bounds"); + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.buf.bump()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } +} + +#[cfg(feature = "boxed")] +impl<'bump, T> Vec<'bump, T> { + /// Converts the vector into [`Box<[T]>`][owned slice]. + /// + /// Note that this will drop any excess capacity. + /// + /// [owned slice]: ../../boxed/struct.Box.html + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec, vec}; + /// + /// let b = Bump::new(); + /// + /// let v = vec![in &b; 1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + pub fn into_boxed_slice(mut self) -> crate::boxed::Box<'bump, [T]> { + use crate::boxed::Box; + + // Unlike `alloc::vec::Vec` shrinking here isn't necessary as `bumpalo::boxed::Box` doesn't own memory. + unsafe { + let slice = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len); + let output: Box<'bump, [T]> = Box::from_raw(slice); + mem::forget(self); + output + } + } +} + +impl<'bump, T: 'bump + Clone> Vec<'bump, T> { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires [`Clone`] to be able clone the passed value. If + /// you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`resize_with`]. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; "hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 3, 4]; + /// vec.resize(2, 0); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html + /// [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html + /// [`resize_with`]: #method.resize_with + pub fn resize(&mut self, new_len: usize, value: T) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + } + } + + // Proven specification with verus, converted to comments. + /// # Preconditions + /// + /// - old(self).len() + slice.len() <= old(self).capacity(), + /// + /// # Postconditions + /// + /// - forall|i: usize| implies( + /// i < old(self).len(), + /// self.get_unchecked(i) == old(self).get_unchecked(i) + /// ), + /// - forall|i: usize| implies( + /// i < slice.len(), + /// self.get_unchecked((old(self).len() + i) as usize) + /// == clone(slice.get_unchecked(i)) + /// ), + /// - self.len() == old(self).len() + slice.len(), + /// - self.capacity() == old(self).capacity(), + #[inline] + unsafe fn extend_from_slice_unchecked(&mut self, slice: &[T]) { + // Guaranteed never to overflow for non ZSTs + // size_of::() <= isize::MAX - (isize::MAX % align_of::())) + // isize::MAX + isize::MAX < usize::MAX + debug_assert!( + core::mem::size_of::() == 0 || self.capacity() >= self.len() + slice.len() + ); + debug_assert!( + // is_zst::() ==> capacity >= slen + slice.len() + core::mem::size_of::() != 0 + // Capacity is usize::MAX for ZSTs + || self.len() <= usize::MAX - slice.len() + ); + + let mut pos = 0usize; + + loop + /* + invariants + pos <= slice.len(), + self.len() + (slice.len() - pos) <= old(self).capacity(), + old(self).capacity() == self.capacity(), + + self.len() == old(self).len() + pos, + + forall|i: usize| implies( + i < old(self).len(), + self.get_unchecked(i) == old(self).get_unchecked(i) + ), + forall|i: usize| implies( + i < pos, + self.get_unchecked((old(self).len() + i) as usize) + == clone(slice.get_unchecked(i)) + ) + */ + { + if pos == slice.len() { + /* + pos = slice.len(), + self.len() = old(self).len() + slice.len(), + + forall|i: usize| i < slice.len() implies { + self.get_unchecked((old(self).len() + i) as usize) + == clone(slice.get_unchecked(i)) + } + by { + i < pos + } + */ + return; + } + + /* + pos < slice.len(), + self.len() < self.capacity() + */ + + let elem = slice.get_unchecked(pos); + self.push_unchecked(elem.clone()); + + /* + ghost prev_pos = pos + */ + + pos = pos + 1; + + /* + forall|i: usize| i < pos implies { + self.get_unchecked((old(self).len() + i) as usize) + == clone(slice.get_unchecked(i)) + } + by { + if i < pos - 1 { + // By invariant + } + else { + i == prev_pos + } + } + */ + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. + /// + /// Note that this function is same as [`extend`] except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: #method.extend + pub fn extend_from_slice(&mut self, other: &[T]) { + let capacity = self.capacity(); + + /* + Cannot underflow via invariant of the Vec (capacity >= length). + + This also holds for ZSTs, as capacity is usize::MAX + */ + let remaining_cap = capacity - self.len; + + /* + self.len() + other.len() <= self.capacity(), + <==> + other.len() <= self.capacity() - self.len() + */ + + if other.len() > remaining_cap { + /* + Divergence from verified impl: + Verified implementation's reserve is not the same + as bumpalo's. Verified implementation reserves with + respect to capacity, not length. Thus this is equivalent + to the verified implementation's: + + self.buf.reserve(other.len() - remaining_cap) + + */ + self.reserve(other.len()); + } + + /* + self.capacity() >= self.len() + other.len() + */ + + unsafe { + self.extend_from_slice_unchecked(other); + } + } +} + +impl<'bump, T: 'bump + Copy> Vec<'bump, T> { + /// Helper method to copy all of the items in `other` and append them to the end of `self`. + /// + /// SAFETY: + /// * The caller is responsible for: + /// * calling [`reserve`](Self::reserve) beforehand to guarantee that there is enough + /// capacity to store `other.len()` more items. + /// * guaranteeing that `self` and `other` do not overlap. + unsafe fn extend_from_slice_copy_unchecked(&mut self, other: &[T]) { + let old_len = self.len(); + debug_assert!(old_len + other.len() <= self.capacity()); + + // SAFETY: + // * `src` is valid for reads of `other.len()` values by virtue of being a `&[T]`. + // * `dst` is valid for writes of `other.len()` bytes because the caller of this + // method is required to `reserve` capacity to store at least `other.len()` items + // beforehand. + // * Because `src` is a `&[T]` and dst is a `&[T]` within the `Vec`, + // `copy_nonoverlapping`'s alignment requirements are met. + // * Caller is required to guarantee that the source and destination ranges cannot overlap + unsafe { + let src = other.as_ptr(); + let dst = self.as_mut_ptr().add(old_len); + ptr::copy_nonoverlapping(src, dst, other.len()); + self.set_len(old_len + other.len()); + } + } + + /// Copies all elements in the slice `other` and appends them to the `Vec`. + /// + /// Note that this function is same as [`extend_from_slice`] except that it is optimized for + /// slices of types that implement the `Copy` trait. If and when Rust gets specialization + /// this function will likely be deprecated (but still available). + /// + /// To copy and append the data from multiple source slices at once, see + /// [`extend_from_slices_copy`]. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.extend_from_slice_copy(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 'H' as u8]; + /// vec.extend_from_slice_copy("ello, world!".as_bytes()); + /// assert_eq!(vec, "Hello, world!".as_bytes()); + /// ``` + /// + /// [`extend_from_slice`]: #method.extend_from_slice + /// [`extend_from_slices`]: #method.extend_from_slices + pub fn extend_from_slice_copy(&mut self, other: &[T]) { + // Reserve space in the Vec for the values to be added + self.reserve(other.len()); + + // Copy values into the space that was just reserved + // SAFETY: + // * `self` has enough capacity to store `other.len()` more items as `self.reserve(other.len())` + // above guarantees that. + // * Source and destination data ranges cannot overlap as we just reserved the destination + // range from the bump. + unsafe { + self.extend_from_slice_copy_unchecked(other); + } + } + + /// For each slice in `slices`, copies all elements in the slice and appends them to the `Vec`. + /// + /// This method is equivalent to calling [`extend_from_slice_copy`] in a loop, but is able + /// to precompute the total amount of space to reserve in advance. This reduces the potential + /// maximum number of reallocations needed from one-per-slice to just one. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1]; + /// vec.extend_from_slices_copy(&[&[2, 3], &[], &[4]]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 'H' as u8]; + /// vec.extend_from_slices_copy(&["ello,".as_bytes(), &[], " world!".as_bytes()]); + /// assert_eq!(vec, "Hello, world!".as_bytes()); + /// ``` + /// + /// [`extend_from_slice_copy`]: #method.extend_from_slice_copy + pub fn extend_from_slices_copy(&mut self, slices: &[&[T]]) { + // Reserve the total amount of capacity we'll need to safely append the aggregated contents + // of each slice in `slices`. + let capacity_to_reserve: usize = slices.iter().map(|slice| slice.len()).sum(); + self.reserve(capacity_to_reserve); + + // SAFETY: + // * `dst` is valid for writes of `capacity_to_reserve` items as + // `self.reserve(capacity_to_reserve)` above guarantees that. + // * Source and destination ranges cannot overlap as we just reserved the destination + // range from the bump. + unsafe { + // Copy the contents of each slice onto the end of `self` + slices.iter().for_each(|slice| { + self.extend_from_slice_copy_unchecked(slice); + }); + } + } +} + +// This code generalises `extend_with_{element,default}`. +trait ExtendWith { + fn next(&mut self) -> T; + fn last(self) -> T; +} + +struct ExtendElement(T); +impl ExtendWith for ExtendElement { + fn next(&mut self) -> T { + self.0.clone() + } + fn last(self) -> T { + self.0 + } +} + +impl<'bump, T: 'bump> Vec<'bump, T> { + /// Extend the vector by `n` values, using the given generator. + fn extend_with>(&mut self, n: usize, mut value: E) { + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + // Use SetLenOnDrop to work around bug where compiler + // may not realize the store through `ptr` through self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.next()); + ptr = ptr.offset(1); + // Increment the length in every step in case next() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + ptr::write(ptr, value.last()); + local_len.increment_len(1); + } + + // len set by scope guard + } + } +} + +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { + local_len: *len, + len, + } + } + + #[inline] + fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } + + #[inline] + fn decrement_len(&mut self, decrement: usize) { + self.local_len -= decrement; + } +} + +impl<'a> Drop for SetLenOnDrop<'a> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} + +impl<'bump, T: 'bump + PartialEq> Vec<'bump, T> { + /// Removes consecutive repeated elements in the vector according to the + /// [`PartialEq`] trait implementation. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 1, 2, 2, 3, 2]; + /// + /// vec.dedup(); + /// + /// assert_eq!(vec, [1, 2, 3, 2]); + /// ``` + #[inline] + pub fn dedup(&mut self) { + self.dedup_by(|a, b| a == b) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +impl<'bump, T: 'bump + Clone> Clone for Vec<'bump, T> { + #[cfg(not(test))] + fn clone(&self) -> Vec<'bump, T> { + let mut v = Vec::with_capacity_in(self.len(), self.buf.bump()); + v.extend(self.iter().cloned()); + v + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Vec<'bump, T> { + let mut v = Vec::new_in(self.buf.bump()); + v.extend(self.iter().cloned()); + v + } +} + +impl<'bump, T: 'bump + Hash> Hash for Vec<'bump, T> { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +impl<'bump, T, I> Index for Vec<'bump, T> +where + I: ::core::slice::SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +impl<'bump, T, I> IndexMut for Vec<'bump, T> +where + I: ::core::slice::SliceIndex<[T]>, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +impl<'bump, T: 'bump> ops::Deref for Vec<'bump, T> { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { + let p = self.buf.ptr(); + // assume(!p.is_null()); + slice::from_raw_parts(p, self.len) + } + } +} + +impl<'bump, T: 'bump> ops::DerefMut for Vec<'bump, T> { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + let ptr = self.buf.ptr(); + // assume(!ptr.is_null()); + slice::from_raw_parts_mut(ptr, self.len) + } + } +} + +impl<'bump, T: 'bump> IntoIterator for Vec<'bump, T> { + type Item = T; + type IntoIter = IntoIter<'bump, T>; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let v = bumpalo::vec![in &b; "a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] + fn into_iter(mut self) -> IntoIter<'bump, T> { + unsafe { + let begin = self.as_mut_ptr(); + // assume(!begin.is_null()); + let end = if mem::size_of::() == 0 { + arith_offset(begin as *const i8, self.len() as isize) as *const T + } else { + begin.add(self.len()) as *const T + }; + mem::forget(self); + IntoIter { + phantom: PhantomData, + ptr: begin, + end, + } + } + } +} + +impl<'a, 'bump, T> IntoIterator for &'a Vec<'bump, T> { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +impl<'a, 'bump, T> IntoIterator for &'a mut Vec<'bump, T> { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} + +impl<'bump, T: 'bump> Extend for Vec<'bump, T> { + #[inline] + fn extend>(&mut self, iter: I) { + let iter = iter.into_iter(); + self.reserve(iter.size_hint().0); + + for t in iter { + self.push(t); + } + } +} + +impl<'bump, T: 'bump> Vec<'bump, T> { + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// `replace_with` does not need to be the same length as `range`. + /// + /// Note 1: The element range is removed even if the iterator is not + /// consumed until the end. + /// + /// Note 2: It is unspecified how many elements are removed from the vector, + /// if the `Splice` value is leaked. + /// + /// Note 3: The input iterator `replace_with` is only consumed + /// when the `Splice` value is dropped. + /// + /// Note 4: This is optimal if: + /// + /// * The tail (elements in the vector after `range`) is empty, + /// * or `replace_with` yields fewer elements than `range`’s length + /// * or the lower bound of its `size_hint()` is exact. + /// + /// Otherwise, a temporary vector is allocated and the tail is moved twice. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut v = bumpalo::vec![in &b; 1, 2, 3]; + /// let new = [7, 8]; + /// let u: Vec<_> = Vec::from_iter_in(v.splice(..2, new.iter().cloned()), &b); + /// assert_eq!(v, &[7, 8, 3]); + /// assert_eq!(u, &[1, 2]); + /// ``` + #[inline] + pub fn splice<'a, R, I>( + &'a mut self, + range: R, + replace_with: I, + ) -> Splice<'a, 'bump, I::IntoIter> + where + R: RangeBounds, + I: IntoIterator, + { + Splice { + drain: self.drain(range), + replace_with: replace_with.into_iter(), + } + } +} + +/// Extend implementation that copies elements out of references before pushing them onto the Vec. +/// +/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to +/// append the entire slice at once. +/// +/// [`copy_from_slice`]: https://doc.rust-lang.org/std/primitive.slice.html#method.copy_from_slice +impl<'a, 'bump, T: 'a + Copy> Extend<&'a T> for Vec<'bump, T> { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()) + } +} + +macro_rules! __impl_slice_eq1 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq1! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &$Rhs) -> bool { + self[..] == other[..] + } + } + }; +} + +__impl_slice_eq1! { Vec<'a, A>, Vec<'b, B> } +__impl_slice_eq1! { Vec<'a, A>, &'b [B] } +__impl_slice_eq1! { Vec<'a, A>, &'b mut [B] } +// __impl_slice_eq1! { Cow<'a, [A]>, Vec<'b, B>, Clone } + +macro_rules! __impl_slice_eq1_array { + ($Lhs: ty, $Rhs: ty) => { + impl<'a, 'b, A, B, const N: usize> PartialEq<$Rhs> for $Lhs + where + A: PartialEq, + { + #[inline] + fn eq(&self, other: &$Rhs) -> bool { + self[..] == other[..] + } + } + }; +} + +__impl_slice_eq1_array! { Vec<'a, A>, [B; N] } +__impl_slice_eq1_array! { Vec<'a, A>, &'b [B; N] } +__impl_slice_eq1_array! { Vec<'a, A>, &'b mut [B; N] } + +/// Implements comparison of vectors, lexicographically. +impl<'bump, T: 'bump + PartialOrd> PartialOrd for Vec<'bump, T> { + #[inline] + fn partial_cmp(&self, other: &Vec<'bump, T>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +impl<'bump, T: 'bump + Eq> Eq for Vec<'bump, T> {} + +/// Implements ordering of vectors, lexicographically. +impl<'bump, T: 'bump + Ord> Ord for Vec<'bump, T> { + #[inline] + fn cmp(&self, other: &Vec<'bump, T>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +impl<'bump, T: 'bump + fmt::Debug> fmt::Debug for Vec<'bump, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<'bump, T: 'bump> AsRef> for Vec<'bump, T> { + fn as_ref(&self) -> &Vec<'bump, T> { + self + } +} + +impl<'bump, T: 'bump> AsMut> for Vec<'bump, T> { + fn as_mut(&mut self) -> &mut Vec<'bump, T> { + self + } +} + +impl<'bump, T: 'bump> AsRef<[T]> for Vec<'bump, T> { + fn as_ref(&self) -> &[T] { + self + } +} + +impl<'bump, T: 'bump> AsMut<[T]> for Vec<'bump, T> { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[cfg(feature = "boxed")] +impl<'bump, T: 'bump> From> for crate::boxed::Box<'bump, [T]> { + fn from(v: Vec<'bump, T>) -> crate::boxed::Box<'bump, [T]> { + v.into_boxed_slice() + } +} + +impl<'bump, T: 'bump> Borrow<[T]> for Vec<'bump, T> { + #[inline] + fn borrow(&self) -> &[T] { + &self[..] + } +} + +impl<'bump, T: 'bump> BorrowMut<[T]> for Vec<'bump, T> { + #[inline] + fn borrow_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +impl<'bump, T> Drop for Vec<'bump, T> { + fn drop(&mut self) { + unsafe { + // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) + } + // RawVec handles deallocation + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Clone-on-write +//////////////////////////////////////////////////////////////////////////////// + +// impl<'a, 'bump, T: Clone> From> for Cow<'a, [T]> { +// fn from(v: Vec<'bump, T>) -> Cow<'a, [T]> { +// Cow::Owned(v) +// } +// } + +// impl<'a, 'bump, T: Clone> From<&'a Vec<'bump, T>> for Cow<'a, [T]> { +// fn from(v: &'a Vec<'bump, T>) -> Cow<'a, [T]> { +// Cow::Borrowed(v.as_slice()) +// } +// } + +//////////////////////////////////////////////////////////////////////////////// +// Iterators +//////////////////////////////////////////////////////////////////////////////// + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the [`Vec::into_iter`] method +/// (provided by the [`IntoIterator`] trait). +/// +/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html +pub struct IntoIter<'bump, T> { + phantom: PhantomData<&'bump [T]>, + ptr: *const T, + end: *const T, +} + +impl<'bump, T: fmt::Debug> fmt::Debug for IntoIter<'bump, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl<'bump, T: 'bump> IntoIter<'bump, T> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let vec = bumpalo::vec![in &b; 'a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr, self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let vec = bumpalo::vec![in &b; 'a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } + } +} + +unsafe impl<'bump, T: Send> Send for IntoIter<'bump, T> {} +unsafe impl<'bump, T: Sync> Sync for IntoIter<'bump, T> {} + +impl<'bump, T: 'bump> Iterator for IntoIter<'bump, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + unsafe { + if self.ptr as *const _ == self.end { + None + } else if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T; + + // Make up a value of this ZST. + Some(mem::zeroed()) + } else { + let old = self.ptr; + self.ptr = self.ptr.offset(1); + + Some(ptr::read(old)) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if mem::size_of::() == 0 { + (self.end as usize).wrapping_sub(self.ptr as usize) + } else { + unsafe { offset_from(self.end, self.ptr) as usize } + }; + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } +} + +impl<'bump, T: 'bump> DoubleEndedIterator for IntoIter<'bump, T> { + #[inline] + fn next_back(&mut self) -> Option { + unsafe { + if self.end == self.ptr { + None + } else if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + self.end = arith_offset(self.end as *const i8, -1) as *mut T; + + // Make up a value of this ZST. + Some(mem::zeroed()) + } else { + self.end = self.end.offset(-1); + + Some(ptr::read(self.end)) + } + } + } +} + +impl<'bump, T: 'bump> ExactSizeIterator for IntoIter<'bump, T> {} + +impl<'bump, T: 'bump> FusedIterator for IntoIter<'bump, T> {} + +impl<'bump, T> Drop for IntoIter<'bump, T> { + fn drop(&mut self) { + // drop all remaining elements + self.for_each(drop); + } +} + +/// A draining iterator for `Vec<'bump, T>`. +/// +/// This `struct` is created by the [`Vec::drain`] method. +pub struct Drain<'a, 'bump, T: 'a + 'bump> { + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, T>, + vec: NonNull>, +} + +impl<'a, 'bump, T: 'a + 'bump + fmt::Debug> fmt::Debug for Drain<'a, 'bump, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +unsafe impl<'a, 'bump, T: Sync> Sync for Drain<'a, 'bump, T> {} +unsafe impl<'a, 'bump, T: Send> Send for Drain<'a, 'bump, T> {} + +impl<'a, 'bump, T> Iterator for Drain<'a, 'bump, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter + .next() + .map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, 'bump, T> DoubleEndedIterator for Drain<'a, 'bump, T> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter + .next_back() + .map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +impl<'a, 'bump, T> Drop for Drain<'a, 'bump, T> { + fn drop(&mut self) { + // exhaust self first + self.for_each(drop); + + if self.tail_len > 0 { + unsafe { + let source_vec = self.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.tail_len); + } + source_vec.set_len(start + self.tail_len); + } + } + } +} + +impl<'a, 'bump, T> ExactSizeIterator for Drain<'a, 'bump, T> {} + +impl<'a, 'bump, T> FusedIterator for Drain<'a, 'bump, T> {} + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by the [`Vec::splice`] method. See its +/// documentation for more information. +#[derive(Debug)] +pub struct Splice<'a, 'bump, I> +where + I: Iterator, + I::Item: 'a + 'bump, +{ + drain: Drain<'a, 'bump, I::Item>, + replace_with: I, +} + +impl<'a, 'bump, I: Iterator> Iterator for Splice<'a, 'bump, I> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +impl<'a, 'bump, I: Iterator> DoubleEndedIterator for Splice<'a, 'bump, I> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +impl<'a, 'bump, I: Iterator> ExactSizeIterator for Splice<'a, 'bump, I> {} + +impl<'a, 'bump, I: Iterator> Drop for Splice<'a, 'bump, I> { + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = Vec::new_in(self.drain.vec.as_ref().buf.bump()); + collected.extend(self.replace_with.by_ref()); + let mut collected = collected.into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl<'a, 'bump, T> Drain<'a, 'bump, T> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Return whether we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = self.vec.as_mut(); + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start); + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + ptr::write(place, new_item); + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Make room for inserting more elements before the tail. + unsafe fn move_tail(&mut self, extra_capacity: usize) { + let vec = self.vec.as_mut(); + let used_capacity = self.tail_start + self.tail_len; + vec.buf.reserve(used_capacity, extra_capacity); + + let new_tail_start = self.tail_start + extra_capacity; + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + self.tail_start = new_tail_start; + } +} + +/// An iterator produced by calling [`Vec::drain_filter`]. +#[derive(Debug)] +pub struct DrainFilter<'a, 'bump: 'a, T: 'a + 'bump, F> +where + F: FnMut(&mut T) -> bool, +{ + vec: &'a mut Vec<'bump, T>, + pred: F, + + // Iteration index. + idx: usize, + // Index to write kept items into. + write: usize, + // The original length. + old_len: usize, +} + +impl<'a, 'bump, T, F> Iterator for DrainFilter<'a, 'bump, T, F> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + debug_assert_eq!(self.vec.len(), 0); + debug_assert!(self.write <= self.idx); + unsafe { + while self.idx != self.old_len { + let i = self.idx; + self.idx += 1; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + if (self.pred)(&mut v[i]) { + return Some(ptr::read(&v[i])); + } else { + if i != self.write { + let src: *const T = &v[i]; + let dst: *mut T = &mut v[self.write]; + ptr::copy_nonoverlapping(src, dst, 1); + } + self.write += 1; + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +impl<'a, 'bump, T, F> Drop for DrainFilter<'a, 'bump, T, F> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + /// Guard to shift the trailing items into place if the `DrainFilter`'s + /// predicate panics, leaving it in a valid state. + struct BackshiftOnDrop<'a, 'bump, T> { + vec: &'a mut Vec<'bump, T>, + idx: usize, + write: usize, + old_len: usize, + } + + impl Drop for BackshiftOnDrop<'_, '_, T> { + fn drop(&mut self) { + unsafe { + let tail_len = self.old_len - self.idx; + if tail_len > 0 && self.write < self.idx { + let ptr = self.vec.as_mut_ptr(); + ptr::copy(ptr.add(self.idx), ptr.add(self.write), tail_len); + } + self.vec.set_len(self.write + tail_len); + } + } + } + + let mut guard = BackshiftOnDrop { + vec: self.vec, + idx: self.idx, + write: self.write, + old_len: self.old_len, + }; + + unsafe { + while guard.idx < guard.old_len { + let i = guard.idx; + let v = slice::from_raw_parts_mut(guard.vec.as_mut_ptr(), guard.old_len); + let drained = (self.pred)(&mut v[i]); + guard.idx += 1; + if drained { + ptr::drop_in_place(&mut v[i]); + } else { + if i != guard.write { + let src: *const T = &v[i]; + let dst: *mut T = &mut v[guard.write]; + ptr::copy_nonoverlapping(src, dst, 1); + } + guard.write += 1; + } + } + } + } +} + +#[cfg(feature = "std")] +impl<'bump> io::Write for Vec<'bump, u8> { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.extend_from_slice_copy(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.extend_from_slice_copy(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(feature = "serde")] +mod serialize { + use super::*; + + use serde::{ser::SerializeSeq, Serialize, Serializer}; + + impl<'a, T> Serialize for Vec<'a, T> + where + T: Serialize, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.len))?; + for e in self.iter() { + seq.serialize_element(e)?; + } + seq.end() + } + } +} diff --git a/anneal/v2/vendor/bumpalo/src/lib.rs b/anneal/v2/vendor/bumpalo/src/lib.rs new file mode 100644 index 0000000000..c846ec3828 --- /dev/null +++ b/anneal/v2/vendor/bumpalo/src/lib.rs @@ -0,0 +1,2710 @@ +#![doc = include_str!("../README.md")] +#![deny(missing_debug_implementations)] +#![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "allocator_api", feature(allocator_api))] + +#[doc(hidden)] +pub extern crate alloc as core_alloc; + +#[cfg(feature = "boxed")] +pub mod boxed; +#[cfg(feature = "collections")] +pub mod collections; + +mod alloc; + +use core::cell::Cell; +use core::cmp::Ordering; +use core::fmt::Display; +use core::iter; +use core::marker::PhantomData; +use core::mem; +use core::ptr::{self, NonNull}; +use core::slice; +use core::str; +use core_alloc::alloc::{alloc, dealloc, Layout}; + +#[cfg(feature = "allocator_api")] +use core_alloc::alloc::{AllocError, Allocator}; + +#[cfg(all(feature = "allocator-api2", not(feature = "allocator_api")))] +use allocator_api2::alloc::{AllocError, Allocator}; + +pub use alloc::AllocErr; + +/// An error returned from [`Bump::try_alloc_try_with`]. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum AllocOrInitError { + /// Indicates that the initial allocation failed. + Alloc(AllocErr), + /// Indicates that the initializer failed with the contained error after + /// allocation. + /// + /// It is possible but not guaranteed that the allocated memory has been + /// released back to the allocator at this point. + Init(E), +} +impl From for AllocOrInitError { + fn from(e: AllocErr) -> Self { + Self::Alloc(e) + } +} +impl Display for AllocOrInitError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + AllocOrInitError::Alloc(err) => err.fmt(f), + AllocOrInitError::Init(err) => write!(f, "initialization failed: {}", err), + } + } +} + +/// An RAII guard to rewind an allocation on drop (due to failed initialization +/// of the allocation). +#[derive(Debug)] +struct RewindGuard<'a, const MIN_ALIGN: usize> { + bump: &'a Bump, + + /// The pointer we are guarding. + ptr: NonNull, + + /// The `ChunkFooter` we are rewinding to. + rewind_footer: NonNull, + + /// The bump pointer within that `ChunkFooter` we are rewinding to. + rewind_footer_ptr: NonNull, + + /// Whether the guard is active, and should rewind on drop. + active: bool, +} + +impl<'a, const MIN_ALIGN: usize> RewindGuard<'a, MIN_ALIGN> { + /// # Safety + /// + /// * `ptr` must be the most-recent allocation in `bump` + /// + /// * `ptr` must have been allocated with the given `layout`. + /// + /// * `rewind_footer` must be the `bump`'s chunk footer pointer just before + /// `ptr`'s allocation. + /// + /// * `rewind_footer_ptr` must be the `bump`'s chunk footer's bump pointer + /// just before `ptr`'s allocation. + /// + /// Ownership of `ptr` is moved into this guard, and it must not be used + /// again except through this guard. + unsafe fn new( + bump: &'a Bump, + ptr: NonNull, + rewind_footer: NonNull, + rewind_footer_ptr: NonNull, + ) -> Self { + Self { + bump, + ptr, + rewind_footer, + rewind_footer_ptr, + active: true, + } + } + + /// Finish this guard, yielding ownership of its pointer. + fn finish(mut self) -> NonNull { + self.active = false; + self.ptr + } +} + +impl Drop for RewindGuard<'_, MIN_ALIGN> { + fn drop(&mut self) { + if !self.active || !self.bump.is_last_allocation(self.ptr) { + return; + } + + // When our pointer was the last allocation in the bump, we can reclaim + // its space. In fact, sometimes we can do even better than simply + // calling `dealloc`: we can reclaim any alignment padding we might have + // added (which `dealloc` cannot do) if we didn't allocate a new chunk + // for this result. + unsafe { + let current_footer = self.bump.current_chunk_footer.get(); + if current_footer == self.rewind_footer { + // It's still the same chunk, so rewind the bump pointer to its + // original value (reclaiming any alignment padding we may have + // added). + current_footer.as_ref().ptr.set(self.rewind_footer_ptr); + } else { + // We allocated a new chunk for this pointer. + // + // We know our pointer is the only allocation in this chunk: + // `self.ptr` was the most-recent allocation in `self.bump` + // (guaranteed by `RewindGuard::new` callers) and if control reaches + // here then it is also the last allocation in `self.bump`, and + // therefore it is the only allocation in this chunk. + // + // Because this is the only allocation in this chunk, we can reset + // the chunk's bump pointer to the start of the chunk. + let bump_ptr = + round_mut_ptr_down_to(current_footer.cast::().as_ptr(), MIN_ALIGN); + debug_assert_eq!(bump_ptr as usize % MIN_ALIGN, 0); + let data = current_footer.as_ref().data; + let bump_ptr = NonNull::new_unchecked(bump_ptr); + debug_assert!( + data <= bump_ptr, + "bump pointer {bump_ptr:#p} should still be greater than or equal to the \ + start of the bump chunk {data:#p}" + ); + current_footer.as_ref().ptr.set(bump_ptr); + } + } + } +} + +/// An arena to bump allocate into. +/// +/// ## No `Drop`s +/// +/// Objects that are bump-allocated will never have their [`Drop`] implementation +/// called — unless you do it manually yourself. This makes it relatively +/// easy to leak memory or other resources. +/// +/// If you have a type which internally manages +/// +/// * an allocation from the global heap (e.g. [`Vec`]), +/// * open file descriptors (e.g. [`std::fs::File`]), or +/// * any other resource that must be cleaned up (e.g. an `mmap`) +/// +/// and relies on its `Drop` implementation to clean up the internal resource, +/// then if you allocate that type with a `Bump`, you need to find a new way to +/// clean up after it yourself. +/// +/// Potential solutions are: +/// +/// * Using [`bumpalo::boxed::Box::new_in`] instead of [`Bump::alloc`], that +/// will drop wrapped values similarly to [`std::boxed::Box`]. Note that this +/// requires enabling the `"boxed"` Cargo feature for this crate. **This is +/// often the easiest solution.** +/// +/// * Calling [`drop_in_place`][drop_in_place] or using +/// [`std::mem::ManuallyDrop`][manuallydrop] to manually drop these types. +/// +/// * Using [`bumpalo::collections::Vec`] instead of [`std::vec::Vec`]. +/// +/// * Avoiding allocating these problematic types within a `Bump`. +/// +/// Note that not calling `Drop` is memory safe! Destructors are never +/// guaranteed to run in Rust, you can't rely on them for enforcing memory +/// safety. +/// +/// [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html +/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html +/// [`std::fs::File`]: https://doc.rust-lang.org/std/fs/struct.File.html +/// [drop_in_place]: https://doc.rust-lang.org/std/ptr/fn.drop_in_place.html +/// [manuallydrop]: https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html +/// [`bumpalo::collections::Vec`]: collections/vec/struct.Vec.html +/// [`std::vec::Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html +/// [`bumpalo::boxed::Box::new_in`]: boxed/struct.Box.html#method.new_in +/// [`std::boxed::Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html +/// +/// ## Example +/// +/// ``` +/// use bumpalo::Bump; +/// +/// // Create a new bump arena. +/// let bump = Bump::new(); +/// +/// // Allocate values into the arena. +/// let forty_two = bump.alloc(42); +/// assert_eq!(*forty_two, 42); +/// +/// // Mutable references are returned from allocation. +/// let mut s = bump.alloc("bumpalo"); +/// *s = "the bump allocator; and also is a buffalo"; +/// ``` +/// +/// ## Allocation Methods Come in Many Flavors +/// +/// There are various allocation methods on `Bump`, the simplest being +/// [`alloc`][Bump::alloc]. The others exist to satisfy some combination of +/// fallible allocation and initialization. The allocation methods are +/// summarized in the following table: +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +///
Infallible AllocationFallible Allocation
By Valuealloctry_alloc
Infallible Initializer Functionalloc_withtry_alloc_with
Fallible Initializer Functionalloc_try_withtry_alloc_try_with
+/// +/// ### Fallible Allocation: The `try_alloc_` Method Prefix +/// +/// These allocation methods let you recover from out-of-memory (OOM) +/// scenarios, rather than raising a panic on OOM. +/// +/// ``` +/// use bumpalo::Bump; +/// +/// let bump = Bump::new(); +/// +/// match bump.try_alloc(MyStruct { +/// // ... +/// }) { +/// Ok(my_struct) => { +/// // Allocation succeeded. +/// } +/// Err(e) => { +/// // Out of memory. +/// } +/// } +/// +/// struct MyStruct { +/// // ... +/// } +/// ``` +/// +/// ### Initializer Functions: The `_with` Method Suffix +/// +/// Calling one of the generic `…alloc(x)` methods is essentially equivalent to +/// the matching [`…alloc_with(|| x)`](?search=alloc_with). However if you use +/// `…alloc_with`, then the closure will not be invoked until after allocating +/// space for storing `x` on the heap. +/// +/// This can be useful in certain edge-cases related to compiler optimizations. +/// When evaluating for example `bump.alloc(x)`, semantically `x` is first put +/// on the stack and then moved onto the heap. In some cases, the compiler is +/// able to optimize this into constructing `x` directly on the heap, however +/// in many cases it does not. +/// +/// The `…alloc_with` functions try to help the compiler be smarter. In most +/// cases doing for example `bump.try_alloc_with(|| x)` on release mode will be +/// enough to help the compiler realize that this optimization is valid and +/// to construct `x` directly onto the heap. +/// +/// #### Warning +/// +/// These functions critically depend on compiler optimizations to achieve their +/// desired effect. This means that it is not an effective tool when compiling +/// without optimizations on. +/// +/// Even when optimizations are on, these functions do not **guarantee** that +/// the value is constructed on the heap. To the best of our knowledge no such +/// guarantee can be made in stable Rust as of 1.54. +/// +/// ### Fallible Initialization: The `_try_with` Method Suffix +/// +/// The generic [`…alloc_try_with(|| x)`](?search=_try_with) methods behave +/// like the purely `_with` suffixed methods explained above. However, they +/// allow for fallible initialization by accepting a closure that returns a +/// [`Result`] and will attempt to undo the initial allocation if this closure +/// returns [`Err`]. +/// +/// #### Warning +/// +/// If the inner closure returns [`Ok`], space for the entire [`Result`] remains +/// allocated inside `self`. This can be a problem especially if the [`Err`] +/// variant is larger, but even otherwise there may be overhead for the +/// [`Result`]'s discriminant. +/// +///

Undoing the allocation in the Err case +/// always fails if f successfully made any additional allocations +/// in self. +/// +/// For example, the following will always leak also space for the [`Result`] +/// into this `Bump`, even though the inner reference isn't kept and the [`Err`] +/// payload is returned semantically by value: +/// +/// ```rust +/// let bump = bumpalo::Bump::new(); +/// +/// let r: Result<&mut [u8; 1000], ()> = bump.alloc_try_with(|| { +/// let _ = bump.alloc(0_u8); +/// Err(()) +/// }); +/// +/// assert!(r.is_err()); +/// ``` +/// +///

+/// +/// Since [`Err`] payloads are first placed on the heap and then moved to the +/// stack, `bump.…alloc_try_with(|| x)?` is likely to execute more slowly than +/// the matching `bump.…alloc(x?)` in case of initialization failure. If this +/// happens frequently, using the plain un-suffixed method may perform better. +/// +/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html +/// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok +/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err +/// +/// ### `Bump` Allocation Limits +/// +/// `bumpalo` supports setting a limit on the maximum bytes of memory that can +/// be allocated for use in a particular `Bump` arena. This limit can be set and removed with +/// [`set_allocation_limit`][Bump::set_allocation_limit]. +/// The allocation limit is only enforced when allocating new backing chunks for +/// a `Bump`. Updating the allocation limit will not affect existing allocations +/// or any future allocations within the `Bump`'s current chunk. +/// +/// #### Example +/// +/// ``` +/// let bump = bumpalo::Bump::new(); +/// +/// assert_eq!(bump.allocation_limit(), None); +/// bump.set_allocation_limit(Some(0)); +/// +/// assert!(bump.try_alloc(5).is_err()); +/// +/// bump.set_allocation_limit(Some(6)); +/// +/// assert_eq!(bump.allocation_limit(), Some(6)); +/// +/// bump.set_allocation_limit(None); +/// +/// assert_eq!(bump.allocation_limit(), None); +/// ``` +/// +/// #### Warning +/// +/// Because of backwards compatibility, allocations that fail +/// due to allocation limits will not present differently than +/// errors due to resource exhaustion. +#[derive(Debug)] +pub struct Bump { + // The current chunk we are bump allocating within. + current_chunk_footer: Cell>, + allocation_limit: Cell>, +} + +#[repr(C)] +#[repr(align(16))] +#[derive(Debug)] +struct ChunkFooter { + // Pointer to the start of this chunk allocation. This footer is always at + // the end of the chunk. + data: NonNull, + + // The layout of this chunk's allocation. + layout: Layout, + + // Link to the previous chunk. + // + // Note that the last node in the `prev` linked list is the canonical empty + // chunk, whose `prev` link points to itself. + prev: Cell>, + + // Bump allocation finger that is always in the range `self.data..=self`. + ptr: Cell>, + + // The bytes allocated in all chunks so far, the canonical empty chunk has + // a size of 0 and for all other chunks, `allocated_bytes` will be + // the allocated_bytes of the current chunk plus the allocated bytes + // of the `prev` chunk. + allocated_bytes: usize, +} + +/// A wrapper type for the canonical, statically allocated empty chunk. +/// +/// For the canonical empty chunk to be `static`, its type must be `Sync`, which +/// is the purpose of this wrapper type. This is safe because the empty chunk is +/// immutable and never actually modified. +#[repr(transparent)] +struct EmptyChunkFooter(ChunkFooter); + +unsafe impl Sync for EmptyChunkFooter {} + +static EMPTY_CHUNK: EmptyChunkFooter = EmptyChunkFooter(ChunkFooter { + // This chunk is empty (except the foot itself). + layout: Layout::new::(), + + // The start of the (empty) allocatable region for this chunk is itself. + data: unsafe { NonNull::new_unchecked(&EMPTY_CHUNK as *const EmptyChunkFooter as *mut u8) }, + + // The end of the (empty) allocatable region for this chunk is also itself. + ptr: Cell::new(unsafe { + NonNull::new_unchecked(&EMPTY_CHUNK as *const EmptyChunkFooter as *mut u8) + }), + + // Invariant: the last chunk footer in all `ChunkFooter::prev` linked lists + // is the empty chunk footer, whose `prev` points to itself. + prev: Cell::new(unsafe { + NonNull::new_unchecked(&EMPTY_CHUNK as *const EmptyChunkFooter as *mut ChunkFooter) + }), + + // Empty chunks count as 0 allocated bytes in an arena. + allocated_bytes: 0, +}); + +impl EmptyChunkFooter { + fn get(&'static self) -> NonNull { + NonNull::from(&self.0) + } +} + +impl ChunkFooter { + // Returns the start and length of the currently allocated region of this + // chunk. + fn as_raw_parts(&self) -> (*const u8, usize) { + let data = self.data.as_ptr() as *const u8; + let ptr = self.ptr.get().as_ptr() as *const u8; + debug_assert!(data <= ptr); + debug_assert!(ptr <= self as *const ChunkFooter as *const u8); + let len = unsafe { (self as *const ChunkFooter as *const u8).offset_from(ptr) as usize }; + (ptr, len) + } + + /// Is this chunk the last empty chunk? + fn is_empty(&self) -> bool { + ptr::eq(self, EMPTY_CHUNK.get().as_ptr()) + } +} + +impl Default for Bump { + fn default() -> Self { + Self::with_min_align() + } +} + +impl Drop for Bump { + fn drop(&mut self) { + unsafe { + dealloc_chunk_list(self.current_chunk_footer.get()); + } + } +} + +#[inline] +unsafe fn dealloc_chunk_list(mut footer: NonNull) { + while !footer.as_ref().is_empty() { + let f = footer; + footer = f.as_ref().prev.get(); + dealloc(f.as_ref().data.as_ptr(), f.as_ref().layout); + } +} + +// `Bump`s are safe to send between threads because nothing aliases its owned +// chunks until you start allocating from it. But by the time you allocate from +// it, the returned references to allocations borrow the `Bump` and therefore +// prevent sending the `Bump` across threads until the borrows end. +unsafe impl Send for Bump {} + +#[inline] +fn is_pointer_aligned_to(pointer: *mut T, align: usize) -> bool { + debug_assert!(align.is_power_of_two()); + + let pointer = pointer as usize; + let pointer_aligned = round_down_to(pointer, align); + pointer == pointer_aligned +} + +#[inline] +pub(crate) const fn round_up_to(n: usize, divisor: usize) -> Option { + debug_assert!(divisor > 0); + debug_assert!(divisor.is_power_of_two()); + match n.checked_add(divisor - 1) { + Some(x) => Some(x & !(divisor - 1)), + None => None, + } +} + +/// Like `round_up_to` but turns overflow into undefined behavior rather than +/// returning `None`. +#[inline] +pub(crate) unsafe fn round_up_to_unchecked(n: usize, divisor: usize) -> usize { + match round_up_to(n, divisor) { + Some(x) => x, + None => { + debug_assert!(false, "round_up_to_unchecked failed"); + core::hint::unreachable_unchecked() + } + } +} + +#[inline] +pub(crate) fn round_down_to(n: usize, divisor: usize) -> usize { + debug_assert!(divisor > 0); + debug_assert!(divisor.is_power_of_two()); + n & !(divisor - 1) +} + +/// Same as `round_down_to` but preserves pointer provenance. +#[inline] +pub(crate) fn round_mut_ptr_down_to(ptr: *mut u8, divisor: usize) -> *mut u8 { + debug_assert!(divisor > 0); + debug_assert!(divisor.is_power_of_two()); + ptr.wrapping_sub(ptr as usize & (divisor - 1)) +} + +#[inline] +pub(crate) unsafe fn round_mut_ptr_up_to_unchecked(ptr: *mut u8, divisor: usize) -> *mut u8 { + debug_assert!(divisor > 0); + debug_assert!(divisor.is_power_of_two()); + let aligned = round_up_to_unchecked(ptr as usize, divisor); + let delta = aligned - (ptr as usize); + ptr.add(delta) +} + +// The typical page size these days. +// +// Note that we don't need to exactly match page size for correctness, and it is +// okay if this is smaller than the real page size in practice. It isn't worth +// the portability concerns and lack of const propagation that dynamically +// looking up the actual page size implies. +const TYPICAL_PAGE_SIZE: usize = 0x1000; + +// We only support alignments of up to 16 bytes for iter_allocated_chunks. +const SUPPORTED_ITER_ALIGNMENT: usize = 16; +const CHUNK_ALIGN: usize = SUPPORTED_ITER_ALIGNMENT; +const FOOTER_SIZE: usize = mem::size_of::(); + +// Assert that `ChunkFooter` is at the supported alignment. This will give a +// compile time error if it is not the case +const _FOOTER_ALIGN_ASSERTION: () = { + assert!(mem::align_of::() == CHUNK_ALIGN); +}; + +// Maximum typical overhead per allocation imposed by allocators. +const MALLOC_OVERHEAD: usize = 16; + +// This is the overhead from malloc, footer and alignment. For instance, if +// we want to request a chunk of memory that has at least X bytes usable for +// allocations (where X is aligned to CHUNK_ALIGN), then we expect that the +// after adding a footer, malloc overhead and alignment, the chunk of memory +// the allocator actually sets aside for us is X+OVERHEAD rounded up to the +// nearest suitable size boundary. +const OVERHEAD: usize = match round_up_to(MALLOC_OVERHEAD + FOOTER_SIZE, CHUNK_ALIGN) { + Some(x) => x, + None => panic!(), +}; + +// The target size of our first allocation, including our overhead. The +// available bump capacity will be smaller. +const FIRST_ALLOCATION_GOAL: usize = 1 << 9; + +// The actual size of the first allocation is going to be a bit smaller than the +// goal. We need to make room for the footer, and we also need take the +// alignment into account. We're trying to avoid this kind of situation: +// https://blog.mozilla.org/nnethercote/2011/08/05/clownshoes-available-in-sizes-2101-and-up/ +const DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER: usize = FIRST_ALLOCATION_GOAL - OVERHEAD; + +/// The memory size and alignment details for a potential new chunk +/// allocation. +#[derive(Debug, Clone, Copy)] +struct NewChunkMemoryDetails { + new_size_without_footer: usize, + align: usize, + size: usize, +} + +/// Wrapper around `Layout::from_size_align` that adds debug assertions. +#[inline] +fn layout_from_size_align(size: usize, align: usize) -> Result { + Layout::from_size_align(size, align).map_err(|_| AllocErr) +} + +#[cold] +#[inline(never)] +fn allocation_size_overflow() -> T { + panic!("requested allocation size overflowed") +} + +// NB: We don't have constructors as methods on `impl Bump` that return +// `Self` because then `rustc` can't infer the `N` if it isn't explicitly +// provided, even though it has a default value. There doesn't seem to be a good +// workaround, other than putting constructors on the `Bump`; even +// `std` does this same thing with `HashMap`, for example. +impl Bump<1> { + /// Construct a new arena to bump allocate into. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// # let _ = bump; + /// ``` + pub fn new() -> Self { + Self::with_capacity(0) + } + + /// Attempt to construct a new arena to bump allocate into. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::try_new(); + /// # let _ = bump.unwrap(); + /// ``` + pub fn try_new() -> Result { + Bump::try_with_capacity(0) + } + + /// Construct a new arena with the specified byte capacity to bump allocate + /// into. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::with_capacity(100); + /// # let _ = bump; + /// ``` + /// + /// ## Panics + /// + /// Panics if allocating the initial capacity fails. + pub fn with_capacity(capacity: usize) -> Self { + Self::try_with_capacity(capacity).unwrap_or_else(|_| oom()) + } + + /// Attempt to construct a new arena with the specified byte capacity to + /// bump allocate into. + /// + /// Propagates errors when allocating the initial capacity. + /// + /// ## Example + /// + /// ``` + /// # fn _foo() -> Result<(), bumpalo::AllocErr> { + /// let bump = bumpalo::Bump::try_with_capacity(100)?; + /// # let _ = bump; + /// # Ok(()) + /// # } + /// ``` + pub fn try_with_capacity(capacity: usize) -> Result { + Self::try_with_min_align_and_capacity(capacity) + } +} + +impl Bump { + /// Create a new `Bump` that enforces a minimum alignment. + /// + /// The minimum alignment must be a power of two and no larger than `16`. + /// + /// Enforcing a minimum alignment can speed up allocation of objects with + /// alignment less than or equal to the minimum alignment. This comes at the + /// cost of introducing otherwise-unnecessary padding between allocations of + /// objects with alignment less than the minimum. + /// + /// # Example + /// + /// ``` + /// type BumpAlign8 = bumpalo::Bump<8>; + /// let bump = BumpAlign8::with_min_align(); + /// for x in 0..u8::MAX { + /// let x = bump.alloc(x); + /// assert_eq!((x as *mut _ as usize) % 8, 0, "x is aligned to 8"); + /// } + /// ``` + /// + /// # Panics + /// + /// Panics on invalid minimum alignments. + // + // Because of `rustc`'s poor type inference for default type/const + // parameters (see the comment above the `impl Bump` block with no const + // `MIN_ALIGN` parameter) and because we don't want to force everyone to + // specify a minimum alignment with `Bump::new()` et al, we have a separate + // constructor for specifying the minimum alignment. + pub fn with_min_align() -> Self { + assert!( + MIN_ALIGN.is_power_of_two(), + "MIN_ALIGN must be a power of two; found {MIN_ALIGN}" + ); + assert!( + MIN_ALIGN <= CHUNK_ALIGN, + "MIN_ALIGN may not be larger than {CHUNK_ALIGN}; found {MIN_ALIGN}" + ); + + Bump { + current_chunk_footer: Cell::new(EMPTY_CHUNK.get()), + allocation_limit: Cell::new(None), + } + } + + /// Create a new `Bump` that enforces a minimum alignment and starts with + /// room for at least `capacity` bytes. + /// + /// The minimum alignment must be a power of two and no larger than `16`. + /// + /// Enforcing a minimum alignment can speed up allocation of objects with + /// alignment less than or equal to the minimum alignment. This comes at the + /// cost of introducing otherwise-unnecessary padding between allocations of + /// objects with alignment less than the minimum. + /// + /// # Example + /// + /// ``` + /// type BumpAlign8 = bumpalo::Bump<8>; + /// let mut bump = BumpAlign8::with_min_align_and_capacity(8 * 100); + /// for x in 0..100_u64 { + /// let x = bump.alloc(x); + /// assert_eq!((x as *mut _ as usize) % 8, 0, "x is aligned to 8"); + /// } + /// assert_eq!( + /// bump.iter_allocated_chunks().count(), 1, + /// "initial chunk had capacity for all allocations", + /// ); + /// ``` + /// + /// # Panics + /// + /// Panics on invalid minimum alignments. + /// + /// Panics if allocating the initial capacity fails. + pub fn with_min_align_and_capacity(capacity: usize) -> Self { + Self::try_with_min_align_and_capacity(capacity).unwrap_or_else(|_| oom()) + } + + /// Create a new `Bump` that enforces a minimum alignment and starts with + /// room for at least `capacity` bytes. + /// + /// The minimum alignment must be a power of two and no larger than `16`. + /// + /// Enforcing a minimum alignment can speed up allocation of objects with + /// alignment less than or equal to the minimum alignment. This comes at the + /// cost of introducing otherwise-unnecessary padding between allocations of + /// objects with alignment less than the minimum. + /// + /// # Example + /// + /// ``` + /// # fn _foo() -> Result<(), bumpalo::AllocErr> { + /// type BumpAlign8 = bumpalo::Bump<8>; + /// let mut bump = BumpAlign8::try_with_min_align_and_capacity(8 * 100)?; + /// for x in 0..100_u64 { + /// let x = bump.alloc(x); + /// assert_eq!((x as *mut _ as usize) % 8, 0, "x is aligned to 8"); + /// } + /// assert_eq!( + /// bump.iter_allocated_chunks().count(), 1, + /// "initial chunk had capacity for all allocations", + /// ); + /// # Ok(()) + /// # } + /// ``` + /// + /// # Panics + /// + /// Panics on invalid minimum alignments. + /// + /// Panics if allocating the initial capacity fails. + pub fn try_with_min_align_and_capacity(capacity: usize) -> Result { + assert!( + MIN_ALIGN.is_power_of_two(), + "MIN_ALIGN must be a power of two; found {MIN_ALIGN}" + ); + assert!( + MIN_ALIGN <= CHUNK_ALIGN, + "MIN_ALIGN may not be larger than {CHUNK_ALIGN}; found {MIN_ALIGN}" + ); + + if capacity == 0 { + return Ok(Bump { + current_chunk_footer: Cell::new(EMPTY_CHUNK.get()), + allocation_limit: Cell::new(None), + }); + } + + let layout = layout_from_size_align(capacity, MIN_ALIGN)?; + + let chunk_footer = unsafe { + Self::new_chunk( + Self::new_chunk_memory_details(None, layout).ok_or(AllocErr)?, + layout, + EMPTY_CHUNK.get(), + ) + .ok_or(AllocErr)? + }; + + Ok(Bump { + current_chunk_footer: Cell::new(chunk_footer), + allocation_limit: Cell::new(None), + }) + } + + /// Get this bump arena's minimum alignment. + /// + /// All objects allocated in this arena get aligned to this value. + /// + /// ## Example + /// + /// ``` + /// let bump2 = bumpalo::Bump::<2>::with_min_align(); + /// assert_eq!(bump2.min_align(), 2); + /// + /// let bump4 = bumpalo::Bump::<4>::with_min_align(); + /// assert_eq!(bump4.min_align(), 4); + /// ``` + #[inline] + pub fn min_align(&self) -> usize { + MIN_ALIGN + } + + /// The allocation limit for this arena in bytes. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::with_capacity(0); + /// + /// assert_eq!(bump.allocation_limit(), None); + /// + /// bump.set_allocation_limit(Some(6)); + /// + /// assert_eq!(bump.allocation_limit(), Some(6)); + /// + /// bump.set_allocation_limit(None); + /// + /// assert_eq!(bump.allocation_limit(), None); + /// ``` + pub fn allocation_limit(&self) -> Option { + self.allocation_limit.get() + } + + /// Set the allocation limit in bytes for this arena. + /// + /// The allocation limit is only enforced when allocating new backing chunks for + /// a `Bump`. Updating the allocation limit will not affect existing allocations + /// or any future allocations within the `Bump`'s current chunk. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::with_capacity(0); + /// + /// bump.set_allocation_limit(Some(0)); + /// + /// assert!(bump.try_alloc(5).is_err()); + /// ``` + pub fn set_allocation_limit(&self, limit: Option) { + self.allocation_limit.set(limit); + } + + /// How much headroom an arena has before it hits its allocation + /// limit. + fn allocation_limit_remaining(&self) -> Option { + self.allocation_limit.get().and_then(|allocation_limit| { + let allocated_bytes = self.allocated_bytes(); + if allocated_bytes > allocation_limit { + None + } else { + Some(usize::abs_diff(allocation_limit, allocated_bytes)) + } + }) + } + + /// Whether a request to allocate a new chunk with a given size for a given + /// requested layout will fit under the allocation limit set on a `Bump`. + fn chunk_fits_under_limit( + allocation_limit_remaining: Option, + new_chunk_memory_details: NewChunkMemoryDetails, + ) -> bool { + allocation_limit_remaining + .map(|allocation_limit_left| { + allocation_limit_left >= new_chunk_memory_details.new_size_without_footer + }) + .unwrap_or(true) + } + + /// Determine the memory details including final size, alignment and final + /// size without footer for a new chunk that would be allocated to fulfill + /// an allocation request. + fn new_chunk_memory_details( + new_size_without_footer: Option, + requested_layout: Layout, + ) -> Option { + // We must have `CHUNK_ALIGN` or better alignment... + let align = CHUNK_ALIGN + // and we have to have at least our configured minimum alignment... + .max(MIN_ALIGN) + // and make sure we satisfy the requested allocation's alignment. + .max(requested_layout.align()); + + let mut new_size_without_footer = + new_size_without_footer.unwrap_or(DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER); + + let requested_size = + round_up_to(requested_layout.size(), align).unwrap_or_else(allocation_size_overflow); + new_size_without_footer = new_size_without_footer.max(requested_size); + + // We want our allocations to play nice with the memory allocator, and + // waste as little memory as possible. For small allocations, this means + // that the entire allocation including the chunk footer and mallocs + // internal overhead is as close to a power of two as we can go without + // going over. For larger allocations, we only need to get close to a + // page boundary without going over. + if new_size_without_footer < TYPICAL_PAGE_SIZE { + new_size_without_footer = + (new_size_without_footer + OVERHEAD).next_power_of_two() - OVERHEAD; + } else { + new_size_without_footer = + round_up_to(new_size_without_footer + OVERHEAD, TYPICAL_PAGE_SIZE)? - OVERHEAD; + } + + debug_assert_eq!(align % CHUNK_ALIGN, 0); + debug_assert_eq!(new_size_without_footer % CHUNK_ALIGN, 0); + let size = new_size_without_footer + .checked_add(FOOTER_SIZE) + .unwrap_or_else(allocation_size_overflow); + + Some(NewChunkMemoryDetails { + new_size_without_footer, + size, + align, + }) + } + + /// Allocate a new chunk and return its initialized footer. + /// + /// If given, `layouts` is a tuple of the current chunk size and the + /// layout of the allocation request that triggered us to fall back to + /// allocating a new chunk of memory. + unsafe fn new_chunk( + new_chunk_memory_details: NewChunkMemoryDetails, + requested_layout: Layout, + prev: NonNull, + ) -> Option> { + let NewChunkMemoryDetails { + new_size_without_footer, + align, + size, + } = new_chunk_memory_details; + + let layout = layout_from_size_align(size, align).ok()?; + + debug_assert!(size >= requested_layout.size()); + + let data = alloc(layout); + let data = NonNull::new(data)?; + + // The `ChunkFooter` is at the end of the chunk. + let footer_ptr = data.as_ptr().add(new_size_without_footer); + debug_assert_eq!((data.as_ptr() as usize) % align, 0); + debug_assert_eq!(footer_ptr as usize % CHUNK_ALIGN, 0); + let footer_ptr = footer_ptr as *mut ChunkFooter; + + // The bump pointer is initialized to the end of the range we will bump + // out of, rounded down to the minimum alignment. It is the + // `NewChunkMemoryDetails` constructor's responsibility to ensure that + // even after this rounding we have enough non-zero capacity in the + // chunk. + let ptr = round_mut_ptr_down_to(footer_ptr.cast::(), MIN_ALIGN); + debug_assert_eq!(ptr as usize % MIN_ALIGN, 0); + debug_assert!( + data.as_ptr() <= ptr, + "bump pointer {ptr:#p} should still be greater than or equal to the \ + start of the bump chunk {data:#p}" + ); + debug_assert_eq!( + (ptr as usize) - (data.as_ptr() as usize), + new_size_without_footer + ); + + let ptr = Cell::new(NonNull::new_unchecked(ptr)); + + // The `allocated_bytes` of a new chunk counts the total size + // of the chunks, not how much of the chunks are used. + let allocated_bytes = prev.as_ref().allocated_bytes + new_size_without_footer; + + ptr::write( + footer_ptr, + ChunkFooter { + data, + layout, + prev: Cell::new(prev), + ptr, + allocated_bytes, + }, + ); + + Some(NonNull::new_unchecked(footer_ptr)) + } + + /// Reset this bump allocator. + /// + /// Performs mass deallocation on everything allocated in this arena by + /// resetting the pointer into the underlying chunk of memory to the start + /// of the chunk. Does not run any `Drop` implementations on deallocated + /// objects; see [the top-level documentation](struct.Bump.html) for details. + /// + /// If this arena has allocated multiple chunks to bump allocate into, then + /// the excess chunks are returned to the global allocator. + /// + /// ## Example + /// + /// ``` + /// let mut bump = bumpalo::Bump::new(); + /// + /// // Allocate a bunch of things. + /// { + /// for i in 0..100 { + /// bump.alloc(i); + /// } + /// } + /// + /// // Reset the arena. + /// bump.reset(); + /// + /// // Allocate some new things in the space previously occupied by the + /// // original things. + /// for j in 200..400 { + /// bump.alloc(j); + /// } + ///``` + pub fn reset(&mut self) { + // Takes `&mut self` so `self` must be unique and there can't be any + // borrows active that would get invalidated by resetting. + unsafe { + if self.current_chunk_footer.get().as_ref().is_empty() { + return; + } + + let mut cur_chunk = self.current_chunk_footer.get(); + + // Deallocate all chunks except the current one + let prev_chunk = cur_chunk.as_ref().prev.replace(EMPTY_CHUNK.get()); + dealloc_chunk_list(prev_chunk); + + // Reset the bump finger to the end of the chunk. + debug_assert!( + is_pointer_aligned_to(cur_chunk.as_ptr(), MIN_ALIGN), + "bump pointer {cur_chunk:#p} should be aligned to the minimum alignment of {MIN_ALIGN:#x}" + ); + cur_chunk.as_ref().ptr.set(cur_chunk.cast()); + + // Reset the allocated size of the chunk. + cur_chunk.as_mut().allocated_bytes = cur_chunk.as_ref().layout.size() - FOOTER_SIZE; + + debug_assert!( + self.current_chunk_footer + .get() + .as_ref() + .prev + .get() + .as_ref() + .is_empty(), + "We should only have a single chunk" + ); + debug_assert_eq!( + self.current_chunk_footer.get().as_ref().ptr.get(), + self.current_chunk_footer.get().cast(), + "Our chunk's bump finger should be reset to the start of its allocation" + ); + } + } + + /// Allocate an object in this `Bump` and return an exclusive reference to + /// it. + /// + /// ## Panics + /// + /// Panics if reserving space for `T` fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc("hello"); + /// assert_eq!(*x, "hello"); + /// ``` + #[inline(always)] + pub fn alloc(&self, val: T) -> &mut T { + self.alloc_with(|| val) + } + + /// Try to allocate an object in this `Bump` and return an exclusive + /// reference to it. + /// + /// ## Errors + /// + /// Errors if reserving space for `T` fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.try_alloc("hello"); + /// assert_eq!(x, Ok(&mut "hello")); + /// ``` + #[inline(always)] + pub fn try_alloc(&self, val: T) -> Result<&mut T, AllocErr> { + self.try_alloc_with(|| val) + } + + /// Pre-allocate space for an object in this `Bump`, initializes it using + /// the closure, then returns an exclusive reference to it. + /// + /// See [The `_with` Method Suffix](#initializer-functions-the-_with-method-suffix) for a + /// discussion on the differences between the `_with` suffixed methods and + /// those methods without it, their performance characteristics, and when + /// you might or might not choose a `_with` suffixed method. + /// + /// ## Panics + /// + /// Panics if reserving space for `T` fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_with(|| "hello"); + /// assert_eq!(*x, "hello"); + /// ``` + #[inline(always)] + pub fn alloc_with(&self, f: F) -> &mut T + where + F: FnOnce() -> T, + { + #[inline(always)] + unsafe fn inner_writer(ptr: *mut T, f: F) + where + F: FnOnce() -> T, + { + // This function is translated as: + // - allocate space for a T on the stack + // - call f() with the return value being put onto this stack space + // - memcpy from the stack to the heap + // + // Ideally we want LLVM to always realize that doing a stack + // allocation is unnecessary and optimize the code so it writes + // directly into the heap instead. It seems we get it to realize + // this most consistently if we put this critical line into it's + // own function instead of inlining it into the surrounding code. + ptr::write(ptr, f()); + } + + let layout = Layout::new::(); + + unsafe { + let p = self.alloc_layout(layout); + let p = p.as_ptr() as *mut T; + inner_writer(p, f); + &mut *p + } + } + + /// Tries to pre-allocate space for an object in this `Bump`, initializes + /// it using the closure, then returns an exclusive reference to it. + /// + /// See [The `_with` Method Suffix](#initializer-functions-the-_with-method-suffix) for a + /// discussion on the differences between the `_with` suffixed methods and + /// those methods without it, their performance characteristics, and when + /// you might or might not choose a `_with` suffixed method. + /// + /// ## Errors + /// + /// Errors if reserving space for `T` fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.try_alloc_with(|| "hello"); + /// assert_eq!(x, Ok(&mut "hello")); + /// ``` + #[inline(always)] + pub fn try_alloc_with(&self, f: F) -> Result<&mut T, AllocErr> + where + F: FnOnce() -> T, + { + #[inline(always)] + unsafe fn inner_writer(ptr: *mut T, f: F) + where + F: FnOnce() -> T, + { + // This function is translated as: + // - allocate space for a T on the stack + // - call f() with the return value being put onto this stack space + // - memcpy from the stack to the heap + // + // Ideally we want LLVM to always realize that doing a stack + // allocation is unnecessary and optimize the code so it writes + // directly into the heap instead. It seems we get it to realize + // this most consistently if we put this critical line into it's + // own function instead of inlining it into the surrounding code. + ptr::write(ptr, f()); + } + + //SAFETY: Self-contained: + // `p` is allocated for `T` and then a `T` is written. + let layout = Layout::new::(); + let p = self.try_alloc_layout(layout)?; + let p = p.as_ptr() as *mut T; + + unsafe { + inner_writer(p, f); + Ok(&mut *p) + } + } + + /// Pre-allocates space for a [`Result`] in this `Bump`, initializes it using + /// the closure, then returns an exclusive reference to its `T` if [`Ok`]. + /// + /// Iff the allocation fails, the closure is not run. + /// + /// Iff [`Err`], an allocator rewind is *attempted* and the `E` instance is + /// moved out of the allocator to be consumed or dropped as normal. + /// + /// See [The `_with` Method Suffix](#initializer-functions-the-_with-method-suffix) for a + /// discussion on the differences between the `_with` suffixed methods and + /// those methods without it, their performance characteristics, and when + /// you might or might not choose a `_with` suffixed method. + /// + /// For caveats specific to fallible initialization, see + /// [The `_try_with` Method Suffix](#fallible-initialization-the-_try_with-method-suffix). + /// + /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html + /// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok + /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err + /// + /// ## Errors + /// + /// Iff the allocation succeeds but `f` fails, that error is forwarded by value. + /// + /// ## Panics + /// + /// Panics if reserving space for `Result` fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_try_with(|| Ok("hello"))?; + /// assert_eq!(*x, "hello"); + /// # Result::<_, ()>::Ok(()) + /// ``` + #[inline(always)] + pub fn alloc_try_with(&self, f: F) -> Result<&mut T, E> + where + F: FnOnce() -> Result, + { + match self.try_alloc_try_with(f) { + Ok(x) => Ok(x), + Err(AllocOrInitError::Init(e)) => Err(e), + Err(AllocOrInitError::Alloc(_)) => oom(), + } + } + + /// Tries to pre-allocates space for a [`Result`] in this `Bump`, + /// initializes it using the closure, then returns an exclusive reference + /// to its `T` if all [`Ok`]. + /// + /// Iff the allocation fails, the closure is not run. + /// + /// Iff the closure returns [`Err`], an allocator rewind is *attempted* and + /// the `E` instance is moved out of the allocator to be consumed or dropped + /// as normal. + /// + /// See [The `_with` Method Suffix](#initializer-functions-the-_with-method-suffix) for a + /// discussion on the differences between the `_with` suffixed methods and + /// those methods without it, their performance characteristics, and when + /// you might or might not choose a `_with` suffixed method. + /// + /// For caveats specific to fallible initialization, see + /// [The `_try_with` Method Suffix](#fallible-initialization-the-_try_with-method-suffix). + /// + /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html + /// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok + /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err + /// + /// ## Errors + /// + /// Errors with the [`Alloc`](`AllocOrInitError::Alloc`) variant iff + /// reserving space for `Result` fails. + /// + /// Iff the allocation succeeds but `f` fails, that error is forwarded by + /// value inside the [`Init`](`AllocOrInitError::Init`) variant. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.try_alloc_try_with(|| Ok("hello"))?; + /// assert_eq!(*x, "hello"); + /// # Result::<_, bumpalo::AllocOrInitError<()>>::Ok(()) + /// ``` + #[inline(always)] + pub fn try_alloc_try_with(&self, f: F) -> Result<&mut T, AllocOrInitError> + where + F: FnOnce() -> Result, + { + let rewind_footer = self.current_chunk_footer.get(); + let rewind_footer_ptr = unsafe { rewind_footer.as_ref() }.ptr.get(); + let ptr = self.try_alloc_with(f)?; + let ptr = NonNull::from(ptr).cast::(); + let guard = unsafe { RewindGuard::new(self, ptr, rewind_footer, rewind_footer_ptr) }; + match unsafe { guard.ptr.cast::>().as_mut() } { + Ok(t) => { + guard.finish(); + Ok(unsafe { NonNull::from(t).as_mut() }) + } + Err(e) => unsafe { + // Read the error out and then let the guard rewind. + Err(AllocOrInitError::Init(NonNull::from(e).as_ptr().read())) + }, + } + } + + /// `Copy` a slice into this `Bump` and return an exclusive reference to + /// the copy. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_slice_copy(&[1, 2, 3]); + /// assert_eq!(x, &[1, 2, 3]); + /// ``` + #[inline(always)] + pub fn alloc_slice_copy(&self, src: &[T]) -> &mut [T] + where + T: Copy, + { + let layout = Layout::for_value(src); + let dst = self.alloc_layout(layout).cast::(); + + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), src.len()); + slice::from_raw_parts_mut(dst.as_ptr(), src.len()) + } + } + + /// Like `alloc_slice_copy`, but does not panic in case of allocation failure. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.try_alloc_slice_copy(&[1, 2, 3]); + /// assert_eq!(x, Ok(&mut[1, 2, 3] as &mut [_])); + /// + /// + /// let bump = bumpalo::Bump::new(); + /// bump.set_allocation_limit(Some(4)); + /// let x = bump.try_alloc_slice_copy(&[1, 2, 3, 4, 5, 6]); + /// assert_eq!(x, Err(bumpalo::AllocErr)); // too big + /// ``` + #[inline(always)] + pub fn try_alloc_slice_copy(&self, src: &[T]) -> Result<&mut [T], AllocErr> + where + T: Copy, + { + let layout = Layout::for_value(src); + let dst = self.try_alloc_layout(layout)?.cast::(); + let result = unsafe { + core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), src.len()); + slice::from_raw_parts_mut(dst.as_ptr(), src.len()) + }; + Ok(result) + } + + /// `Clone` a slice into this `Bump` and return an exclusive reference to + /// the clone. Prefer [`alloc_slice_copy`](#method.alloc_slice_copy) if `T` is `Copy`. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// #[derive(Clone, Debug, Eq, PartialEq)] + /// struct Sheep { + /// name: String, + /// } + /// + /// let originals = [ + /// Sheep { name: "Alice".into() }, + /// Sheep { name: "Bob".into() }, + /// Sheep { name: "Cathy".into() }, + /// ]; + /// + /// let bump = bumpalo::Bump::new(); + /// let clones = bump.alloc_slice_clone(&originals); + /// assert_eq!(originals, clones); + /// ``` + #[inline(always)] + pub fn alloc_slice_clone(&self, src: &[T]) -> &mut [T] + where + T: Clone, + { + let layout = Layout::for_value(src); + let dst = self.alloc_layout(layout).cast::(); + + unsafe { + for (i, val) in src.iter().cloned().enumerate() { + ptr::write(dst.as_ptr().add(i), val); + } + + slice::from_raw_parts_mut(dst.as_ptr(), src.len()) + } + } + + /// Like `alloc_slice_clone` but does not panic on failure. + #[inline(always)] + pub fn try_alloc_slice_clone(&self, src: &[T]) -> Result<&mut [T], AllocErr> + where + T: Clone, + { + let layout = Layout::for_value(src); + let dst = self.try_alloc_layout(layout)?.cast::(); + + unsafe { + for (i, val) in src.iter().cloned().enumerate() { + ptr::write(dst.as_ptr().add(i), val); + } + + Ok(slice::from_raw_parts_mut(dst.as_ptr(), src.len())) + } + } + + /// `Copy` a string slice into this `Bump` and return an exclusive reference to it. + /// + /// ## Panics + /// + /// Panics if reserving space for the string fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let hello = bump.alloc_str("hello world"); + /// assert_eq!("hello world", hello); + /// ``` + #[inline(always)] + pub fn alloc_str(&self, src: &str) -> &mut str { + let buffer = self.alloc_slice_copy(src.as_bytes()); + unsafe { + // This is OK, because it already came in as str, so it is guaranteed to be utf8 + str::from_utf8_unchecked_mut(buffer) + } + } + + /// Same as `alloc_str` but does not panic on failure. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let hello = bump.try_alloc_str("hello world").unwrap(); + /// assert_eq!("hello world", hello); + /// + /// + /// let bump = bumpalo::Bump::new(); + /// bump.set_allocation_limit(Some(5)); + /// let hello = bump.try_alloc_str("hello world"); + /// assert_eq!(Err(bumpalo::AllocErr), hello); + /// ``` + #[inline(always)] + pub fn try_alloc_str(&self, src: &str) -> Result<&mut str, AllocErr> { + let buffer = self.try_alloc_slice_copy(src.as_bytes())?; + unsafe { + // This is OK, because it already came in as str, so it is guaranteed to be utf8 + Ok(str::from_utf8_unchecked_mut(buffer)) + } + } + + /// Allocates a new slice of size `len` into this `Bump` and returns an + /// exclusive reference to the copy. + /// + /// The elements of the slice are initialized using the supplied closure. + /// The closure argument is the position in the slice. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_slice_fill_with(5, |i| 5 * (i + 1)); + /// assert_eq!(x, &[5, 10, 15, 20, 25]); + /// ``` + #[inline(always)] + pub fn alloc_slice_fill_with(&self, len: usize, mut f: F) -> &mut [T] + where + F: FnMut(usize) -> T, + { + let layout = Layout::array::(len).unwrap_or_else(|_| oom()); + let guard = self.alloc_layout_with_rewind(layout); + + unsafe { + let mut dst = guard.ptr.cast::(); + for i in 0..len { + ptr::write(dst.as_ptr(), f(i)); + dst = NonNull::new_unchecked(dst.as_ptr().add(1)); + } + + let ptr = guard.finish(); + let result = slice::from_raw_parts_mut(ptr.cast::().as_ptr(), len); + debug_assert_eq!(Layout::for_value(result), layout); + result + } + } + + /// Allocates a new slice of size `len` into this `Bump` and returns an + /// exclusive reference to the copy, failing if the closure return an Err. + /// + /// The elements of the slice are initialized using the supplied closure. + /// The closure argument is the position in the slice. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: Result<&mut [usize], ()> = bump.alloc_slice_try_fill_with(5, |i| Ok(5 * i)); + /// assert_eq!(x, Ok(bump.alloc_slice_copy(&[0, 5, 10, 15, 20]))); + /// ``` + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: Result<&mut [usize], ()> = bump.alloc_slice_try_fill_with( + /// 5, + /// |n| if n == 2 { Err(()) } else { Ok(n) } + /// ); + /// assert_eq!(x, Err(())); + /// ``` + #[inline(always)] + pub fn alloc_slice_try_fill_with(&self, len: usize, mut f: F) -> Result<&mut [T], E> + where + F: FnMut(usize) -> Result, + { + let layout = Layout::array::(len).unwrap_or_else(|_| oom()); + let guard = self.alloc_layout_with_rewind(layout); + + unsafe { + let mut dst = guard.ptr.cast::(); + for i in 0..len { + match f(i) { + Ok(el) => { + ptr::write(dst.as_ptr(), el); + dst = NonNull::new_unchecked(dst.as_ptr().add(1)); + } + Err(e) => return Err(e), + } + } + + let ptr = guard.finish(); + let result = slice::from_raw_parts_mut(ptr.cast::().as_ptr(), len); + debug_assert_eq!(Layout::for_value(result), layout); + Ok(result) + } + } + + /// Allocates a new slice of size `len` into this `Bump` and returns an + /// exclusive reference to the copy. + /// + /// The elements of the slice are initialized using the supplied closure. + /// The closure argument is the position in the slice. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.try_alloc_slice_fill_with(5, |i| 5 * (i + 1)); + /// assert_eq!(x, Ok(&mut[5usize, 10, 15, 20, 25] as &mut [_])); + /// + /// + /// let bump = bumpalo::Bump::new(); + /// bump.set_allocation_limit(Some(4)); + /// let x = bump.try_alloc_slice_fill_with(10, |i| 5 * (i + 1)); + /// assert_eq!(x, Err(bumpalo::AllocErr)); + /// ``` + #[inline(always)] + pub fn try_alloc_slice_fill_with( + &self, + len: usize, + mut f: F, + ) -> Result<&mut [T], AllocErr> + where + F: FnMut(usize) -> T, + { + let layout = Layout::array::(len).map_err(|_| AllocErr)?; + let guard = self.try_alloc_layout_with_rewind(layout)?; + + unsafe { + let mut dst = guard.ptr.cast::(); + for i in 0..len { + ptr::write(dst.as_ptr(), f(i)); + dst = NonNull::new_unchecked(dst.as_ptr().add(1)); + } + + let ptr = guard.finish(); + let result = slice::from_raw_parts_mut(ptr.cast::().as_ptr(), len); + debug_assert_eq!(Layout::for_value(result), layout); + Ok(result) + } + } + + /// Allocates a new slice of size `len` into this `Bump` and returns an + /// exclusive reference to the copy. + /// + /// All elements of the slice are initialized to `value`. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_slice_fill_copy(5, 42); + /// assert_eq!(x, &[42, 42, 42, 42, 42]); + /// ``` + #[inline(always)] + pub fn alloc_slice_fill_copy(&self, len: usize, value: T) -> &mut [T] { + self.alloc_slice_fill_with(len, |_| value) + } + + /// Same as `alloc_slice_fill_copy` but does not panic on failure. + #[inline(always)] + pub fn try_alloc_slice_fill_copy( + &self, + len: usize, + value: T, + ) -> Result<&mut [T], AllocErr> { + self.try_alloc_slice_fill_with(len, |_| value) + } + + /// Allocates a new slice of size `len` slice into this `Bump` and return an + /// exclusive reference to the copy. + /// + /// All elements of the slice are initialized to `value.clone()`. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let s: String = "Hello Bump!".to_string(); + /// let x: &[String] = bump.alloc_slice_fill_clone(2, &s); + /// assert_eq!(x.len(), 2); + /// assert_eq!(&x[0], &s); + /// assert_eq!(&x[1], &s); + /// ``` + #[inline(always)] + pub fn alloc_slice_fill_clone(&self, len: usize, value: &T) -> &mut [T] { + self.alloc_slice_fill_with(len, |_| value.clone()) + } + + /// Like `alloc_slice_fill_clone` but does not panic on failure. + #[inline(always)] + pub fn try_alloc_slice_fill_clone( + &self, + len: usize, + value: &T, + ) -> Result<&mut [T], AllocErr> { + self.try_alloc_slice_fill_with(len, |_| value.clone()) + } + + /// Allocates a new slice of size `len` slice into this `Bump` and return an + /// exclusive reference to the copy. + /// + /// The elements are initialized using the supplied iterator. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails, or if the supplied + /// iterator returns fewer elements than it promised. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: &[i32] = bump.alloc_slice_fill_iter([2, 3, 5].iter().cloned().map(|i| i * i)); + /// assert_eq!(x, [4, 9, 25]); + /// ``` + #[inline(always)] + pub fn alloc_slice_fill_iter(&self, iter: I) -> &mut [T] + where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, + { + let mut iter = iter.into_iter(); + self.alloc_slice_fill_with(iter.len(), |_| { + iter.next().expect("Iterator supplied too few elements") + }) + } + + /// Allocates a new slice of size `len` slice into this `Bump` and return an + /// exclusive reference to the copy, failing if the iterator returns an Err. + /// + /// The elements are initialized using the supplied iterator. + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails, or if the supplied + /// iterator returns fewer elements than it promised. + /// + /// ## Examples + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: Result<&mut [i32], ()> = bump.alloc_slice_try_fill_iter( + /// [2, 3, 5].iter().cloned().map(|i| Ok(i * i)) + /// ); + /// assert_eq!(x, Ok(bump.alloc_slice_copy(&[4, 9, 25]))); + /// ``` + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: Result<&mut [i32], ()> = bump.alloc_slice_try_fill_iter( + /// [Ok(2), Err(()), Ok(5)].iter().cloned() + /// ); + /// assert_eq!(x, Err(())); + /// ``` + #[inline(always)] + pub fn alloc_slice_try_fill_iter(&self, iter: I) -> Result<&mut [T], E> + where + I: IntoIterator>, + I::IntoIter: ExactSizeIterator, + { + let mut iter = iter.into_iter(); + self.alloc_slice_try_fill_with(iter.len(), |_| { + iter.next().expect("Iterator supplied too few elements") + }) + } + + /// Allocates a new slice of size `iter.len()` slice into this `Bump` and return an + /// exclusive reference to the copy. Does not panic on failure. + /// + /// The elements are initialized using the supplied iterator. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x: &[i32] = bump.try_alloc_slice_fill_iter([2, 3, 5] + /// .iter().cloned().map(|i| i * i)).unwrap(); + /// assert_eq!(x, [4, 9, 25]); + /// ``` + #[inline(always)] + pub fn try_alloc_slice_fill_iter(&self, iter: I) -> Result<&mut [T], AllocErr> + where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, + { + let mut iter = iter.into_iter(); + self.try_alloc_slice_fill_with(iter.len(), |_| { + iter.next().expect("Iterator supplied too few elements") + }) + } + + /// Allocates a new slice of size `len` slice into this `Bump` and return an + /// exclusive reference to the copy. + /// + /// All elements of the slice are initialized to [`T::default()`]. + /// + /// [`T::default()`]: https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default + /// + /// ## Panics + /// + /// Panics if reserving space for the slice fails. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let x = bump.alloc_slice_fill_default::(5); + /// assert_eq!(x, &[0, 0, 0, 0, 0]); + /// ``` + #[inline(always)] + pub fn alloc_slice_fill_default(&self, len: usize) -> &mut [T] { + self.alloc_slice_fill_with(len, |_| T::default()) + } + + /// Like `alloc_slice_fill_default` but does not panic on failure. + #[inline(always)] + pub fn try_alloc_slice_fill_default( + &self, + len: usize, + ) -> Result<&mut [T], AllocErr> { + self.try_alloc_slice_fill_with(len, |_| T::default()) + } + + /// Allocate space for an object with the given `Layout`. + /// + /// The returned pointer points at uninitialized memory, and should be + /// initialized with + /// [`std::ptr::write`](https://doc.rust-lang.org/std/ptr/fn.write.html). + /// + /// # Panics + /// + /// Panics if reserving space matching `layout` fails. + #[inline(always)] + pub fn alloc_layout(&self, layout: Layout) -> NonNull { + self.try_alloc_layout(layout).unwrap_or_else(|_| oom()) + } + + /// Attempts to allocate space for an object with the given `Layout` or else returns + /// an `Err`. + /// + /// The returned pointer points at uninitialized memory, and should be + /// initialized with + /// [`std::ptr::write`](https://doc.rust-lang.org/std/ptr/fn.write.html). + /// + /// # Errors + /// + /// Errors if reserving space matching `layout` fails. + #[inline(always)] + pub fn try_alloc_layout(&self, layout: Layout) -> Result, AllocErr> { + if let Some(p) = self.try_alloc_layout_fast(layout) { + Ok(p) + } else { + self.alloc_layout_slow(layout).ok_or(AllocErr) + } + } + + #[inline(always)] + fn try_alloc_layout_fast(&self, layout: Layout) -> Option> { + // We don't need to check for ZSTs here since they will automatically + // be handled properly: the pointer will be bumped by zero bytes, + // modulo alignment. This keeps the fast path optimized for non-ZSTs, + // which are much more common. + unsafe { + let footer_ptr = self.current_chunk_footer.get(); + let footer = footer_ptr.as_ref(); + + let ptr = footer.ptr.get().as_ptr(); + let start = footer.data.as_ptr(); + debug_assert!( + start <= ptr, + "start pointer {start:#p} should be less than or equal to bump pointer {ptr:#p}" + ); + debug_assert!( + ptr <= footer_ptr.cast::().as_ptr(), + "bump pointer {ptr:#p} should be less than or equal to footer pointer {footer_ptr:#p}" + ); + debug_assert!( + is_pointer_aligned_to(ptr, MIN_ALIGN), + "bump pointer {ptr:#p} should be aligned to the minimum alignment of {MIN_ALIGN:#x}" + ); + // This `match` should be boiled away by LLVM: `MIN_ALIGN` is a + // constant and the layout's alignment is also constant in practice + // after inlining. + let aligned_ptr = match layout.align().cmp(&MIN_ALIGN) { + Ordering::Less => { + // We need to round the size up to a multiple of `MIN_ALIGN` + // to preserve the minimum alignment. This might overflow + // since we cannot rely on `Layout`'s guarantees. + let aligned_size = round_up_to(layout.size(), MIN_ALIGN)?; + + let capacity = (ptr as usize) - (start as usize); + if aligned_size > capacity { + return None; + } + + ptr.wrapping_sub(aligned_size) + } + Ordering::Equal => { + // `Layout` guarantees that rounding the size up to its + // align cannot overflow (but does not guarantee that the + // size is initially a multiple of the alignment, which is + // why we need to do this rounding). + let aligned_size = round_up_to_unchecked(layout.size(), layout.align()); + + let capacity = (ptr as usize) - (start as usize); + if aligned_size > capacity { + return None; + } + + ptr.wrapping_sub(aligned_size) + } + Ordering::Greater => { + // `Layout` guarantees that rounding the size up to its + // align cannot overflow (but does not guarantee that the + // size is initially a multiple of the alignment, which is + // why we need to do this rounding). + let aligned_size = round_up_to_unchecked(layout.size(), layout.align()); + + let aligned_ptr = round_mut_ptr_down_to(ptr, layout.align()); + let capacity = (aligned_ptr as usize).wrapping_sub(start as usize); + if aligned_ptr < start || aligned_size > capacity { + return None; + } + + aligned_ptr.wrapping_sub(aligned_size) + } + }; + + debug_assert!( + is_pointer_aligned_to(aligned_ptr, layout.align()), + "pointer {aligned_ptr:#p} should be aligned to layout alignment of {:#}", + layout.align() + ); + debug_assert!( + is_pointer_aligned_to(aligned_ptr, MIN_ALIGN), + "pointer {aligned_ptr:#p} should be aligned to minimum alignment of {:#}", + MIN_ALIGN + ); + debug_assert!( + start <= aligned_ptr && aligned_ptr <= ptr, + "pointer {aligned_ptr:#p} should be in range {start:#p}..{ptr:#p}" + ); + + debug_assert!(!aligned_ptr.is_null()); + let aligned_ptr = NonNull::new_unchecked(aligned_ptr); + + footer.ptr.set(aligned_ptr); + Some(aligned_ptr) + } + } + + /// Gets the remaining capacity in the current chunk (in bytes). + /// + /// ## Example + /// + /// ``` + /// use bumpalo::Bump; + /// + /// let bump = Bump::with_capacity(100); + /// + /// let capacity = bump.chunk_capacity(); + /// assert!(capacity >= 100); + /// ``` + pub fn chunk_capacity(&self) -> usize { + let current_footer = self.current_chunk_footer.get(); + let current_footer = unsafe { current_footer.as_ref() }; + + current_footer.ptr.get().as_ptr() as usize - current_footer.data.as_ptr() as usize + } + + /// Slow path allocation for when we need to allocate a new chunk from the + /// parent bump set because there isn't enough room in our current chunk. + #[inline(never)] + #[cold] + fn alloc_layout_slow(&self, layout: Layout) -> Option> { + unsafe { + let allocation_limit_remaining = self.allocation_limit_remaining(); + + // Get a new chunk from the global allocator. + let current_footer = self.current_chunk_footer.get(); + let current_layout = current_footer.as_ref().layout; + + // By default, we want our new chunk to be about twice as big + // as the previous chunk. If the global allocator refuses it, + // we try to divide it by half until it works or the requested + // size is smaller than the default footer size. + let min_new_chunk_size = layout.size().max(DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER); + let mut base_size = (current_layout.size() - FOOTER_SIZE) + .checked_mul(2)? + .max(min_new_chunk_size); + let chunk_memory_details = iter::from_fn(|| { + let bypass_min_chunk_size_for_small_limits = matches!(self.allocation_limit(), Some(limit) if layout.size() < limit + && base_size >= layout.size() + && limit < DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER + && self.allocated_bytes() == 0); + + if base_size >= min_new_chunk_size || bypass_min_chunk_size_for_small_limits { + let size = base_size; + base_size /= 2; + Self::new_chunk_memory_details(Some(size), layout) + } else { + None + } + }); + + let new_footer = chunk_memory_details + .filter_map(|chunk_memory_details| { + if Self::chunk_fits_under_limit( + allocation_limit_remaining, + chunk_memory_details, + ) { + Self::new_chunk(chunk_memory_details, layout, current_footer) + } else { + None + } + }) + .next()?; + + debug_assert_eq!( + new_footer.as_ref().data.as_ptr() as usize % layout.align(), + 0 + ); + + // Set the new chunk as our new current chunk. + self.current_chunk_footer.set(new_footer); + + // And then we can rely on `try_alloc_layout_fast` to allocate + // space within this chunk. + let ptr = self.try_alloc_layout_fast(layout); + debug_assert!(ptr.is_some()); + ptr + } + } + + #[inline] + fn try_alloc_layout_with_rewind( + &self, + layout: Layout, + ) -> Result, AllocErr> { + let rewind_footer = self.current_chunk_footer.get(); + let rewind_footer_ptr = unsafe { rewind_footer.as_ref().ptr.get() }; + let ptr = self.try_alloc_layout(layout)?; + Ok(unsafe { RewindGuard::new(self, ptr, rewind_footer, rewind_footer_ptr) }) + } + + #[inline] + fn alloc_layout_with_rewind(&self, layout: Layout) -> RewindGuard<'_, MIN_ALIGN> { + self.try_alloc_layout_with_rewind(layout) + .unwrap_or_else(|_| oom()) + } + + /// Returns an iterator over each chunk of allocated memory that + /// this arena has bump allocated into. + /// + /// The chunks are returned ordered by allocation time, with the most + /// recently allocated chunk being returned first, and the least recently + /// allocated chunk being returned last. + /// + /// The values inside each chunk are also ordered by allocation time, with + /// the most recent allocation being earlier in the slice, and the least + /// recent allocation being towards the end of the slice. + /// + /// ## Safety + /// + /// Because this method takes `&mut self`, we know that the bump arena + /// reference is unique and therefore there aren't any active references to + /// any of the objects we've allocated in it either. This potential aliasing + /// of exclusive references is one common footgun for unsafe code that we + /// don't need to worry about here. + /// + /// However, there could be regions of uninitialized memory used as padding + /// between allocations, which is why this iterator has items of type + /// `[MaybeUninit]`, instead of simply `[u8]`. + /// + /// The only way to guarantee that there is no padding between allocations + /// or within allocated objects is if all of these properties hold: + /// + /// 1. Every object allocated in this arena has the same alignment, + /// and that alignment is at most 16. + /// 2. Every object's size is a multiple of its alignment. + /// 3. None of the objects allocated in this arena contain any internal + /// padding. + /// + /// If you want to use this `iter_allocated_chunks` method, it is *your* + /// responsibility to ensure that these properties hold before calling + /// `MaybeUninit::assume_init` or otherwise reading the returned values. + /// + /// Finally, you must also ensure that any values allocated into the bump + /// arena have not had their `Drop` implementations called on them, + /// e.g. after dropping a [`bumpalo::boxed::Box`][crate::boxed::Box]. + /// + /// ## Example + /// + /// ``` + /// let mut bump = bumpalo::Bump::new(); + /// + /// // Allocate a bunch of `i32`s in this bump arena, potentially causing + /// // additional memory chunks to be reserved. + /// for i in 0..10000 { + /// bump.alloc(i); + /// } + /// + /// // Iterate over each chunk we've bump allocated into. This is safe + /// // because we have only allocated `i32`s in this arena, which fulfills + /// // the above requirements. + /// for ch in bump.iter_allocated_chunks() { + /// println!("Used a chunk that is {} bytes long", ch.len()); + /// println!("The first byte is {:?}", unsafe { + /// ch[0].assume_init() + /// }); + /// } + /// + /// // Within a chunk, allocations are ordered from most recent to least + /// // recent. If we allocated 'a', then 'b', then 'c', when we iterate + /// // through the chunk's data, we get them in the order 'c', then 'b', + /// // then 'a'. + /// + /// bump.reset(); + /// bump.alloc(b'a'); + /// bump.alloc(b'b'); + /// bump.alloc(b'c'); + /// + /// assert_eq!(bump.iter_allocated_chunks().count(), 1); + /// let chunk = bump.iter_allocated_chunks().nth(0).unwrap(); + /// assert_eq!(chunk.len(), 3); + /// + /// // Safe because we've only allocated `u8`s in this arena, which + /// // fulfills the above requirements. + /// unsafe { + /// assert_eq!(chunk[0].assume_init(), b'c'); + /// assert_eq!(chunk[1].assume_init(), b'b'); + /// assert_eq!(chunk[2].assume_init(), b'a'); + /// } + /// ``` + pub fn iter_allocated_chunks(&mut self) -> ChunkIter<'_, MIN_ALIGN> { + // Safety: Ensured by mutable borrow of `self`. + let raw = unsafe { self.iter_allocated_chunks_raw() }; + ChunkIter { + raw, + bump: PhantomData, + } + } + + /// Returns an iterator over raw pointers to chunks of allocated memory that + /// this arena has bump allocated into. + /// + /// This is an unsafe version of [`iter_allocated_chunks()`](Bump::iter_allocated_chunks), + /// with the caller responsible for safe usage of the returned pointers as + /// well as ensuring that the iterator is not invalidated by new + /// allocations. + /// + /// ## Safety + /// + /// Allocations from this arena must not be performed while the returned + /// iterator is alive. If reading the chunk data (or casting to a reference) + /// the caller must ensure that there exist no mutable references to + /// previously allocated data. + /// + /// In addition, all of the caveats when reading the chunk data from + /// [`iter_allocated_chunks()`](Bump::iter_allocated_chunks) still apply. + pub unsafe fn iter_allocated_chunks_raw(&self) -> ChunkRawIter<'_, MIN_ALIGN> { + ChunkRawIter { + footer: self.current_chunk_footer.get(), + bump: PhantomData, + } + } + + /// Calculates the number of bytes currently allocated across all chunks in + /// this bump arena. + /// + /// If you allocate types of different alignments or types with + /// larger-than-typical alignment in the same arena, some padding + /// bytes might get allocated in the bump arena. Note that those padding + /// bytes will add to this method's resulting sum, so you cannot rely + /// on it only counting the sum of the sizes of the things + /// you've allocated in the arena. + /// + /// The allocated bytes do not include the size of bumpalo's metadata, + /// so the amount of memory requested from the Rust allocator is higher + /// than the returned value. + /// + /// ## Example + /// + /// ``` + /// let bump = bumpalo::Bump::new(); + /// let _x = bump.alloc_slice_fill_default::(5); + /// let bytes = bump.allocated_bytes(); + /// assert!(bytes >= core::mem::size_of::() * 5); + /// ``` + pub fn allocated_bytes(&self) -> usize { + let footer = self.current_chunk_footer.get(); + + unsafe { footer.as_ref().allocated_bytes } + } + + /// Calculates the number of bytes requested from the Rust allocator for this `Bump`. + /// + /// This number is equal to the [`allocated_bytes()`](Self::allocated_bytes) plus + /// the size of the bump metadata. + pub fn allocated_bytes_including_metadata(&self) -> usize { + let metadata_size = + unsafe { self.iter_allocated_chunks_raw().count() * mem::size_of::() }; + self.allocated_bytes() + metadata_size + } + + #[inline] + fn is_last_allocation(&self, ptr: NonNull) -> bool { + unsafe { + let footer = self.current_chunk_footer.get(); + let footer = footer.as_ref(); + footer.ptr.get() == ptr + } + } + + #[inline] + unsafe fn dealloc(&self, ptr: NonNull, layout: Layout) { + // If the pointer is the last allocation we made, we can reuse the bytes, + // otherwise they are simply leaked -- at least until somebody calls reset(). + if self.is_last_allocation(ptr) { + let ptr = self.current_chunk_footer.get().as_ref().ptr.get(); + let ptr = ptr.as_ptr().add(layout.size()); + + let ptr = round_mut_ptr_up_to_unchecked(ptr, MIN_ALIGN); + debug_assert!( + is_pointer_aligned_to(ptr, MIN_ALIGN), + "bump pointer {ptr:#p} should be aligned to the minimum alignment of {MIN_ALIGN:#x}" + ); + let ptr = NonNull::new_unchecked(ptr); + self.current_chunk_footer.get().as_ref().ptr.set(ptr); + } + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocErr> { + // If the new layout demands greater alignment than the old layout has, + // then either + // + // 1. the pointer happens to satisfy the new layout's alignment, so we + // got lucky and can return the pointer as-is, or + // + // 2. the pointer is not aligned to the new layout's demanded alignment, + // and we are unlucky. + // + // In the case of (2), to successfully "shrink" the allocation, we have + // to allocate a whole new region for the new layout. + if old_layout.align() < new_layout.align() { + return if is_pointer_aligned_to(ptr.as_ptr(), new_layout.align()) { + Ok(ptr) + } else { + let new_ptr = self.try_alloc_layout(new_layout)?; + + // We know that these regions are nonoverlapping because + // `new_ptr` is a fresh allocation. + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), new_layout.size()); + + Ok(new_ptr) + }; + } + + debug_assert!(is_pointer_aligned_to(ptr.as_ptr(), new_layout.align())); + + let old_size = old_layout.size(); + let new_size = new_layout.size(); + + // This is how much space we would *actually* reclaim while satisfying + // the requested alignment. + let delta = round_down_to(old_size - new_size, new_layout.align().max(MIN_ALIGN)); + + if self.is_last_allocation(ptr) + // Only reclaim the excess space (which requires a copy) if it + // is worth it: we are actually going to recover "enough" space + // and we can do a non-overlapping copy. + // + // We do `(old_size + 1) / 2` so division rounds up rather than + // down. Consider when: + // + // old_size = 5 + // new_size = 3 + // + // If we do not take care to round up, this will result in: + // + // delta = 2 + // (old_size / 2) = (5 / 2) = 2 + // + // And the the check will succeed even though we are have + // overlapping ranges: + // + // |--------old-allocation-------| + // |------from-------| + // |-------to--------| + // +-----+-----+-----+-----+-----+ + // | a | b | c | . | . | + // +-----+-----+-----+-----+-----+ + // + // But we MUST NOT have overlapping ranges because we use + // `copy_nonoverlapping` below! Therefore, we round the division + // up to avoid this issue. + && delta >= (old_size + 1) / 2 + { + let footer = self.current_chunk_footer.get(); + let footer = footer.as_ref(); + + // NB: new_ptr is aligned, because ptr *has to* be aligned, and we + // made sure delta is aligned. + let new_ptr = NonNull::new_unchecked(footer.ptr.get().as_ptr().add(delta)); + debug_assert!( + is_pointer_aligned_to(new_ptr.as_ptr(), MIN_ALIGN), + "bump pointer {new_ptr:#p} should be aligned to the minimum alignment of {MIN_ALIGN:#x}" + ); + footer.ptr.set(new_ptr); + + // NB: we know it is non-overlapping because of the size check + // in the `if` condition. + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), new_size); + + return Ok(new_ptr); + } + + // If this wasn't the last allocation, or shrinking wasn't worth it, + // simply return the old pointer as-is. + Ok(ptr) + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocErr> { + let old_size = old_layout.size(); + + let new_size = new_layout.size(); + let new_size = round_up_to(new_size, MIN_ALIGN).ok_or(AllocErr)?; + + let align_is_compatible = old_layout.align() >= new_layout.align(); + + if align_is_compatible && self.is_last_allocation(ptr) { + // Try to allocate the delta size within this same block so we can + // reuse the currently allocated space. + let delta = new_size - old_size; + if let Some(p) = + self.try_alloc_layout_fast(layout_from_size_align(delta, old_layout.align())?) + { + ptr::copy(ptr.as_ptr(), p.as_ptr(), old_size); + return Ok(p); + } + } + + // Fallback: do a fresh allocation and copy the existing data into it. + let new_ptr = self.try_alloc_layout(new_layout)?; + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), old_size); + Ok(new_ptr) + } +} + +/// An iterator over each chunk of allocated memory that +/// an arena has bump allocated into. +/// +/// The chunks are returned ordered by allocation time, with the most recently +/// allocated chunk being returned first. +/// +/// The values inside each chunk are also ordered by allocation time, with the most +/// recent allocation being earlier in the slice. +/// +/// This struct is created by the [`iter_allocated_chunks`] method on +/// [`Bump`]. See that function for a safety description regarding reading from the returned items. +/// +/// [`Bump`]: struct.Bump.html +/// [`iter_allocated_chunks`]: struct.Bump.html#method.iter_allocated_chunks +#[derive(Debug)] +pub struct ChunkIter<'a, const MIN_ALIGN: usize = 1> { + raw: ChunkRawIter<'a, MIN_ALIGN>, + bump: PhantomData<&'a mut Bump>, +} + +impl<'a, const MIN_ALIGN: usize> Iterator for ChunkIter<'a, MIN_ALIGN> { + type Item = &'a [mem::MaybeUninit]; + + fn next(&mut self) -> Option { + unsafe { + let (ptr, len) = self.raw.next()?; + let slice = slice::from_raw_parts(ptr as *const mem::MaybeUninit, len); + Some(slice) + } + } +} + +impl<'a, const MIN_ALIGN: usize> iter::FusedIterator for ChunkIter<'a, MIN_ALIGN> {} + +/// An iterator over raw pointers to chunks of allocated memory that this +/// arena has bump allocated into. +/// +/// See [`ChunkIter`] for details regarding the returned chunks. +/// +/// This struct is created by the [`iter_allocated_chunks_raw`] method on +/// [`Bump`]. See that function for a safety description regarding reading from +/// the returned items. +/// +/// [`Bump`]: struct.Bump.html +/// [`iter_allocated_chunks_raw`]: struct.Bump.html#method.iter_allocated_chunks_raw +#[derive(Debug)] +pub struct ChunkRawIter<'a, const MIN_ALIGN: usize = 1> { + footer: NonNull, + bump: PhantomData<&'a Bump>, +} + +impl Iterator for ChunkRawIter<'_, MIN_ALIGN> { + type Item = (*mut u8, usize); + fn next(&mut self) -> Option<(*mut u8, usize)> { + unsafe { + let foot = self.footer.as_ref(); + if foot.is_empty() { + return None; + } + let (ptr, len) = foot.as_raw_parts(); + self.footer = foot.prev.get(); + Some((ptr as *mut u8, len)) + } + } +} + +impl iter::FusedIterator for ChunkRawIter<'_, MIN_ALIGN> {} + +#[inline(never)] +#[cold] +fn oom() -> ! { + panic!("out of memory") +} + +unsafe impl<'a, const MIN_ALIGN: usize> alloc::Alloc for &'a Bump { + #[inline(always)] + unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + self.try_alloc_layout(layout) + } + + #[inline] + unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { + Bump::::dealloc(self, ptr, layout); + } + + #[inline] + unsafe fn realloc( + &mut self, + ptr: NonNull, + old_layout: Layout, + new_size: usize, + ) -> Result, AllocErr> { + let old_size = old_layout.size(); + let new_layout = layout_from_size_align(new_size, old_layout.align())?; + + if old_size == 0 { + return self.try_alloc_layout(new_layout); + } + + if new_size <= old_size { + Bump::shrink(self, ptr, old_layout, new_layout) + } else { + Bump::grow(self, ptr, old_layout, new_layout) + } + } +} + +/// This function tests that Bump isn't Sync. +/// ```compile_fail +/// use bumpalo::Bump; +/// fn _requires_sync(_value: T) {} +/// fn _bump_not_sync(b: Bump) { +/// _requires_sync(b); +/// } +/// ``` +#[cfg(doctest)] +fn _doctest_only() {} + +#[cfg(any(feature = "allocator_api", feature = "allocator-api2"))] +unsafe impl<'a, const MIN_ALIGN: usize> Allocator for &'a Bump { + #[inline] + fn allocate(&self, layout: Layout) -> Result, AllocError> { + self.try_alloc_layout(layout) + .map(|p| unsafe { + NonNull::new_unchecked(ptr::slice_from_raw_parts_mut(p.as_ptr(), layout.size())) + }) + .map_err(|_| AllocError) + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + Bump::::dealloc(self, ptr, layout) + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + Bump::::shrink(self, ptr, old_layout, new_layout) + .map(|p| unsafe { + NonNull::new_unchecked(ptr::slice_from_raw_parts_mut(p.as_ptr(), new_layout.size())) + }) + .map_err(|_| AllocError) + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + Bump::::grow(self, ptr, old_layout, new_layout) + .map(|p| unsafe { + NonNull::new_unchecked(ptr::slice_from_raw_parts_mut(p.as_ptr(), new_layout.size())) + }) + .map_err(|_| AllocError) + } + + #[inline] + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + let new_ptr = self.grow(ptr, old_layout, new_layout)?; + + // Zero the tail of the new allocation (the bytes past the copied old contents). + // Write through a raw pointer rather than constructing a `&mut [u8]` over the full range, + // because the tail is uninitialized and `&mut [u8]` spanning uninit bytes is UB. + // `old_layout.size() <= new_layout.size()` (invariant of `Allocator` trait), so this cannot underflow. + let tail_len = new_layout.size() - old_layout.size(); + + // SAFETY: `new_ptr` covers `new_layout.size()` bytes. + // `old_layout.size() <= new_layout.size()` (invariant of `Allocator` trait). + // So `tail_len` bytes starting at offset `old_layout.size()` are in bounds. + unsafe { + let dst_ptr = new_ptr.as_ptr().cast::().add(old_layout.size()); + ptr::write_bytes(dst_ptr, 0, tail_len); + } + + Ok(new_ptr) + } +} + +// NB: Only tests which require private types, fields, or methods should be in +// here. Anything that can just be tested via public API surface should be in +// `bumpalo/tests/all/*`. +#[cfg(test)] +mod tests { + use super::*; + + // Uses private type `ChunkFooter`. + #[test] + fn chunk_footer_is_five_words() { + assert_eq!(mem::size_of::(), mem::size_of::() * 6); + } + + // Uses private `DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER` and `FOOTER_SIZE`. + #[test] + fn allocated_bytes() { + let mut b = Bump::with_capacity(1); + + assert_eq!(b.allocated_bytes(), DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER); + assert_eq!( + b.allocated_bytes_including_metadata(), + DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER + FOOTER_SIZE + ); + + b.reset(); + + assert_eq!(b.allocated_bytes(), DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER); + assert_eq!( + b.allocated_bytes_including_metadata(), + DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER + FOOTER_SIZE + ); + } + + // Uses private `alloc` module. + #[test] + fn test_realloc() { + use crate::alloc::Alloc; + + unsafe { + const CAPACITY: usize = DEFAULT_CHUNK_SIZE_WITHOUT_FOOTER; + let mut b = Bump::<1>::with_min_align_and_capacity(CAPACITY); + + // `realloc` doesn't shrink allocations that aren't "worth it". + let layout = Layout::from_size_align(100, 1).unwrap(); + let p = b.alloc_layout(layout); + let q = (&b).realloc(p, layout, 51).unwrap(); + assert_eq!(p, q); + b.reset(); + + // `realloc` will shrink allocations that are "worth it". + let layout = Layout::from_size_align(100, 1).unwrap(); + let p = b.alloc_layout(layout); + let q = (&b).realloc(p, layout, 50).unwrap(); + assert!(p != q); + b.reset(); + + // `realloc` will reuse the last allocation when growing. + let layout = Layout::from_size_align(10, 1).unwrap(); + let p = b.alloc_layout(layout); + let q = (&b).realloc(p, layout, 11).unwrap(); + assert_eq!(q.as_ptr() as usize, p.as_ptr() as usize - 1); + b.reset(); + + // `realloc` will allocate a new chunk when growing the last + // allocation, if need be. + let layout = Layout::from_size_align(1, 1).unwrap(); + let p = b.alloc_layout(layout); + let q = (&b).realloc(p, layout, CAPACITY + 1).unwrap(); + assert_ne!(q.as_ptr() as usize, p.as_ptr() as usize - CAPACITY); + b.reset(); + + // `realloc` will allocate and copy when reallocating anything that + // wasn't the last allocation. + let layout = Layout::from_size_align(1, 1).unwrap(); + let p = b.alloc_layout(layout); + let _ = b.alloc_layout(layout); + let q = (&b).realloc(p, layout, 2).unwrap(); + assert!(q.as_ptr() as usize != p.as_ptr() as usize - 1); + b.reset(); + } + } + + // Uses private `alloc` module. + #[test] + fn realloc_old_size_zero() { + use crate::alloc::Alloc; + + let bump = Bump::new(); + + let old_layout = Layout::from_size_align(0, 1).unwrap(); + let old_ptr = bump.alloc_layout(old_layout); + let new_size = 64; + let new_ptr = unsafe { (&bump).realloc(old_ptr, old_layout, new_size).unwrap() }; + let new_ptr = new_ptr.as_ptr().cast::(); + + // Write to and read from the pointer. If it is invalid, then MIRI will + // complain. + unsafe { + for i in 0..new_size { + *new_ptr.add(i) = 0xAB; + } + for i in 0..new_size { + assert_eq!(*new_ptr.add(i), 0xAB); + } + } + } + + // Uses our private `alloc` module. + #[test] + fn invalid_read() { + use alloc::Alloc; + + let mut b = &Bump::new(); + + unsafe { + let l1 = Layout::from_size_align(12000, 4).unwrap(); + let p1 = Alloc::alloc(&mut b, l1).unwrap(); + + let l2 = Layout::from_size_align(1000, 4).unwrap(); + Alloc::alloc(&mut b, l2).unwrap(); + + let p1 = b.realloc(p1, l1, 24000).unwrap(); + let l3 = Layout::from_size_align(24000, 4).unwrap(); + b.realloc(p1, l3, 48000).unwrap(); + } + } +} diff --git a/anneal/v2/vendor/camino/.cargo-checksum.json b/anneal/v2/vendor/camino/.cargo-checksum.json new file mode 100644 index 0000000000..0278d828bc --- /dev/null +++ b/anneal/v2/vendor/camino/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"cc056c8a56ff215bc64b73abe57cdf8f10cc47845d8bbd8e3cb2cc05646dc770",".claude/settings.json":"fc7557e622b138650d73aec4f47e64e450db5b2e9cd6763656881065e6a01950","CHANGELOG.md":"06ab46d098c6073c616d596578c6a87ed749891f56805dfe424628cd20e616a2","Cargo.lock":"e4abbd5bad2a61b8690462780673d2b23a825f529036f90d6ff1f449a72e2b4a","Cargo.lock.rust161":"f553347679ea8639ef0ce06d919f6b0b1b065d75feb904584df3c1266a11a79b","Cargo.toml":"fc02680883c29f33babec26361e605cefed431f9520c708a9797efe106f0edff","Cargo.toml.orig":"f5d89644fd5b52bcbc9934791c8813c26bc0f511b64916470c75b5d874b893d5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"abbdf9952bf63241cabd641b513231cb7ed31ecae2367398a527775587a5b7a7","build.rs":"5bc29910c9644c320a7cceed121474915f7e832f484f1bf694dec80a45182aa0","clippy.toml":"3a17aa1da8d7ef51201556d0f2fc8c2d2e137ed5a7a998e47a4ee59795a35e49","release.toml":"287514631fde7a1d29a8e8027bc37c585c7e30c173c8254f551b042e38f4bb81","rustfmt.toml":"069dbe6a0d7a6bc933740e5879a4a2bc458eff9e4c7bc1931d1f2550008b9442","src/lib.rs":"4313ca33a44a40756d7e01f315a9ae4161da3eb34eac007a45f7f0050c2a2f4f","src/proptest_impls.rs":"323cc7a5bb2016555a343b0b64404930b52ff0d328473fb91353bd8ccbb97234","src/serde_impls.rs":"831dcdd10bdfbd11296d34c551df59aaa4c1ea29c7429dd7b41340fd82828adf","src/tests.rs":"2cb79e032972ca5eccd9ad95bed1e0314b15e5e7eaa84ecb53acc37636598afe","tests/integration_tests.rs":"56aa396a173d0c255369159b57e4a7db294e607aa6cfb65efebd95d79cc51a04"},"package":"e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48"} \ No newline at end of file diff --git a/anneal/v2/vendor/camino/.cargo_vcs_info.json b/anneal/v2/vendor/camino/.cargo_vcs_info.json new file mode 100644 index 0000000000..64d8e31a1a --- /dev/null +++ b/anneal/v2/vendor/camino/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "0a908a30982268e6b136f472ccfee24c2b652bb7" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/camino/.claude/settings.json b/anneal/v2/vendor/camino/.claude/settings.json new file mode 100644 index 0000000000..5595e45243 --- /dev/null +++ b/anneal/v2/vendor/camino/.claude/settings.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "WebFetch(domain:github.com)", + "WebSearch", + "Bash(cargo build:*)", + "Bash(cargo test:*)", + "Bash(cargo clippy:*)" + ] + } +} diff --git a/anneal/v2/vendor/camino/CHANGELOG.md b/anneal/v2/vendor/camino/CHANGELOG.md new file mode 100644 index 0000000000..875685b6f4 --- /dev/null +++ b/anneal/v2/vendor/camino/CHANGELOG.md @@ -0,0 +1,223 @@ +# Changelog + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.2.2] - 2025-12-14 + +### Added + +On Rust 1.91 and above: + +- `Utf8PathBuf::add_extension` +- `Utf8Path::file_prefix` +- `Utf8Path::with_added_extension` +- `Utf8PathBuf::new` is a const fn. + +## [1.2.1] - 2025-09-29 + +### Fixed + +Replaced obsolete `doc_auto_cfg` with `doc_cfg`, to fix Rust nightly builds with the `doc_cfg` flag enabled. + +## [1.2.0] - 2025-09-14 + +### Changed + +- MSRV updated to Rust 1.61 to support the switch to `serde_core`. +- camino now depends on `serde_core` rather than `serde`. This allows camino's compilation to be parallelized with `serde_derive`. +- `serde` and `proptest` are no longer available as features. This is technically a breaking change, but these features were already no-ops. Instead, use `serde1` and `proptest1` respectively. + +## [1.1.12] - 2025-08-26 + +### Added + +- `Utf8PathBuf::from_os_string` and `Utf8Path::from_os_str` conversions. +- `TryFrom for Utf8PathBuf` and `TryFrom<&OsStr> for &Utf8Path` conversions. + +Thanks to [BenjaminBrienen](https://github.com/BenjaminBrienen) for your first contribution! + +## [1.1.11] - 2025-08-17 + +### Added + +- `Utf8PathBuf::leak` on Rust 1.89 and above. + +## [1.1.10] - 2025-06-02 + +### Changed + +- Hand-write serde implementations, dropping the dependency on `serde_derive`. Thanks to [Enselic](https://github.com/Enselic) for initiating the discussion and for your first contribution! + +## [1.1.9] - 2024-08-17 + +### Added + +- Top-level function `absolute_utf8` wraps `std::path::absolute`, converting paths to UTF-8. + Requires Rust 1.79 and above. + +## [1.1.8] - 2024-08-15 + +### Changed + +- Use `OsStr::as_encoded_bytes` on Rust 1.74 and above, making conversions from `OsStr` to `str` virtually free ([#93](https://github.com/camino-rs/camino/pull/93)). Thanks [@h-a-n-a](https://github.com/h-a-n-a) for your first contribution! + +## [1.1.7] - 2024-05-14 + +### Fixed + +- Resolve `unexpected_cfg` warnings. + +## [1.1.6] - 2023-07-11 + +### Added + +- Implement `Deserialize` for `Box`. + +## [1.1.5] - 2023-07-11 + +(This release was not published due to an internal issue.) + +## [1.1.4] - 2023-03-09 + +### Added + +- Implement `DerefMut` for `Utf8PathBuf` on Rust 1.68 and above. + +## [1.1.3] - 2023-02-21 + +### Added + +- New method `Utf8DirEntry::into_path` to return an owned `Utf8PathBuf`. + +## [1.1.2] - 2022-08-12 + +### Added + +- New convenience methods [`FromPathBufError::into_io_error`] and + [`FromPathError::into_io_error`]. + +## [1.1.1] - 2022-08-12 + +### Fixed + +- Fixed a build regression on older nightlies in the 1.63 series + ([#22](https://github.com/camino-rs/camino/issues/22)). +- Documentation fixes. + +## [1.1.0] - 2022-08-11 + +### Added + +- New methods, mirroring those in recent versions of Rust: + - `Utf8Path::try_exists` checks whether a path exists. Note that while `std::path::Path` only provides this method for Rust 1.58 and above, `camino` backfills the method for all Rust versions it supports. + - `Utf8PathBuf::shrink_to` shrinks a `Utf8PathBuf` to a given size. This was added in, and is gated on, Rust 1.56+. + - `Utf8PathBuf::try_reserve` and `Utf8PathBuf::try_reserve_exact` implement fallible allocations. These were added in, and are gated on, Rust 1.63+. +- A number of `#[must_use]` annotations to APIs, mirroring those added to `Path` and `PathBuf` in recent versions of Rust. The minor version bump is due to this change. + +## [1.0.9] - 2022-05-19 + +### Fixed + +- Documentation fixes. + +## [1.0.8] - 2022-05-09 + +### Added + +- New methods `canonicalize_utf8`, `read_link_utf8` and `read_dir_utf8` return `Utf8PathBuf`s, erroring out if a resulting path is not valid UTF-8. +- New feature `proptest1` introduces proptest `Arbitrary` impls for `Utf8PathBuf` and + `Box` ([#18], thanks [mcronce](https://github.com/mcronce) for your first contribution!) + +[#18]: https://github.com/camino-rs/camino/pull/18 + +## [1.0.7] - 2022-01-16 + +### Added + +- `Utf8Path::is_symlink` checks whether a path is a symlink. Note that while `std::path::Path` only + provides this method for version 1.58 and above, `camino` backfills the method for all Rust versions + it supports. + +### Changed + +- Update repository links to new location [camino-rs/camino](https://github.com/camino-rs/camino). +- Update `structopt` example to clap 3's builtin derive feature. + (camino continues to work with structopt as before.) + +## [1.0.6] - 2022-01-16 + +(This release was yanked due to a publishing issue.) + +## [1.0.5] - 2021-07-27 + +### Added + +- `Utf8PathBuf::into_std_path_buf` converts a `Utf8PathBuf` to a `PathBuf`; equivalent to the + `From for PathBuf` impl, but may aid in type inference. +- `Utf8Path::as_std_path` converts a `Utf8Path` to a `Path`; equivalent to the + `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference. + +## [1.0.4] - 2021-03-19 + +### Fixed + +- `Hash` impls for `Utf8PathBuf` and `Utf8Path` now match as required by the `Borrow` contract ([#9]). + +[#9]: https://github.com/camino-rs/camino/issues/9 + +## [1.0.3] - 2021-03-11 + +### Added + +- `TryFrom for Utf8PathBuf` and `TryFrom<&Path> for &Utf8Path`, both of which return new error types ([#6]). +- `AsRef`, `AsRef`, `AsRef` and `AsRef` impls for `Utf8Components`, `Utf8Component` and + `Iter`. + +[#6]: https://github.com/camino-rs/camino/issues/6 + +## [1.0.2] - 2021-03-02 + +### Added + +- `From` impls for converting a `&Utf8Path` or a `Utf8PathBuf` into `Box`, `Rc`, `Arc` and `Cow<'a, Path>`. +- `PartialEq` and `PartialOrd` implementations comparing `Utf8Path` and `Utf8PathBuf` with `Path`, `PathBuf` and its + variants, and comparing `OsStr`, `OsString` and its variants. + +## [1.0.1] - 2021-02-25 + +### Added + +- More `PartialEq` and `PartialOrd` implementations. +- MSRV lowered to 1.34. + +## [1.0.0] - 2021-02-23 + +Initial release. + +[1.2.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.2.2 +[1.2.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.2.1 +[1.2.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.2.0 +[1.1.12]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.12 +[1.1.11]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.11 +[1.1.10]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.10 +[1.1.9]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.9 +[1.1.8]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.8 +[1.1.7]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.7 +[1.1.6]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.6 +[1.1.5]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.5 +[1.1.4]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.4 +[1.1.3]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.3 +[1.1.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.2 +[1.1.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.1 +[1.1.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.0 +[1.0.9]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.9 +[1.0.8]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.8 +[1.0.7]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.7 +[1.0.6]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.6 +[1.0.5]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.5 +[1.0.4]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.4 +[1.0.3]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.3 +[1.0.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.2 +[1.0.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.1 +[1.0.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.0 diff --git a/anneal/v2/vendor/camino/Cargo.lock b/anneal/v2/vendor/camino/Cargo.lock new file mode 100644 index 0000000000..80afa46bb7 --- /dev/null +++ b/anneal/v2/vendor/camino/Cargo.lock @@ -0,0 +1,379 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "camino" +version = "1.2.2" +dependencies = [ + "bincode", + "proptest", + "serde", + "serde_bytes", + "serde_core", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[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.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/anneal/v2/vendor/camino/Cargo.lock.rust161 b/anneal/v2/vendor/camino/Cargo.lock.rust161 new file mode 100644 index 0000000000..cd799117b0 --- /dev/null +++ b/anneal/v2/vendor/camino/Cargo.lock.rust161 @@ -0,0 +1,516 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "camino" +version = "1.2.1" +dependencies = [ + "bincode", + "proptest", + "serde", + "serde_bytes", + "serde_core", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +dependencies = [ + "bit-set", + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rustix" +version = "0.38.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "serde" +version = "1.0.224" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaeb1e94f53b16384af593c71e20b095e958dab1d26939c1b70645c5cfbcc0b" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.224" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f39390fa6346e24defbcdd3d9544ba8a19985d0af74df8501fbfe9a64341ab" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.224" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ff78ab5e8561c9a675bfc1785cb07ae721f0ee53329a595cefd8c04c2ac4e0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/anneal/v2/vendor/camino/Cargo.toml b/anneal/v2/vendor/camino/Cargo.toml new file mode 100644 index 0000000000..e5d84762fb --- /dev/null +++ b/anneal/v2/vendor/camino/Cargo.toml @@ -0,0 +1,82 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.61.0" +name = "camino" +version = "1.2.2" +authors = [ + "Without Boats ", + "Ashley Williams ", + "Steve Klabnik ", + "Rain ", +] +build = "build.rs" +exclude = [ + ".cargo/**/*", + ".github/**/*", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "UTF-8 paths" +documentation = "https://docs.rs/camino" +readme = "README.md" +keywords = [ + "paths", + "utf8", + "unicode", + "filesystem", +] +categories = [ + "development-tools", + "filesystem", + "os", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/camino-rs/camino" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg=doc_cfg"] + +[features] +proptest1 = ["dep:proptest"] +serde1 = ["dep:serde_core"] + +[lib] +name = "camino" +path = "src/lib.rs" + +[[test]] +name = "integration_tests" +path = "tests/integration_tests.rs" + +[dependencies.proptest] +version = "1.0.0" +optional = true + +[dependencies.serde_core] +version = "1" +optional = true + +[dev-dependencies.bincode] +version = "1" + +[dev-dependencies.serde] +version = "1.0.223" +features = ["derive"] + +[dev-dependencies.serde_bytes] +version = "0.11.8" diff --git a/anneal/v2/vendor/camino/Cargo.toml.orig b/anneal/v2/vendor/camino/Cargo.toml.orig new file mode 100644 index 0000000000..980384b650 --- /dev/null +++ b/anneal/v2/vendor/camino/Cargo.toml.orig @@ -0,0 +1,39 @@ +[workspace] +members = ["."] + +[package] +name = "camino" +description = "UTF-8 paths" +version = "1.2.2" +license = "MIT OR Apache-2.0" +readme = "README.md" +rust-version = "1.61.0" +keywords = ["paths", "utf8", "unicode", "filesystem"] +categories = ["development-tools", "filesystem", "os"] +repository = "https://github.com/camino-rs/camino" +documentation = "https://docs.rs/camino" +authors = [ + "Without Boats ", + "Ashley Williams ", + "Steve Klabnik ", + "Rain ", +] +edition = "2021" +exclude = [".cargo/**/*", ".github/**/*"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg=doc_cfg"] + +[dependencies] +proptest = { version = "1.0.0", optional = true } +serde_core = { version = "1", optional = true } + +[dev-dependencies] +bincode = "1" +serde_bytes = "0.11.8" +serde = { version = "1.0.223", features = ["derive"] } + +[features] +serde1 = ["dep:serde_core"] +proptest1 = ["dep:proptest"] diff --git a/anneal/v2/vendor/camino/LICENSE-APACHE b/anneal/v2/vendor/camino/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/camino/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/camino/LICENSE-MIT b/anneal/v2/vendor/camino/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/anneal/v2/vendor/camino/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/camino/README.md b/anneal/v2/vendor/camino/README.md new file mode 100644 index 0000000000..5c45b5e3ad --- /dev/null +++ b/anneal/v2/vendor/camino/README.md @@ -0,0 +1,135 @@ +# camino - UTF-8 paths + +[![camino on crates.io](https://img.shields.io/crates/v/camino)](https://crates.io/crates/camino) +[![crates.io download count](https://img.shields.io/crates/d/camino)](https://crates.io/crates/camino) +[![Documentation (latest release)](https://img.shields.io/badge/docs-latest%20version-brightgreen.svg)](https://docs.rs/camino) +[![Documentation (main)](https://img.shields.io/badge/docs-main-purple.svg)](https://camino-rs.github.io/camino/rustdoc/camino/) +[![License](https://img.shields.io/badge/license-Apache-green.svg)](LICENSE-APACHE) +[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE-MIT) + +This repository contains the source code for `camino`, an extension of the `std::path` module that adds new +[`Utf8PathBuf`] and [`Utf8Path`] types. + +## What is camino? + +`camino`'s [`Utf8PathBuf`] and [`Utf8Path`] types are like the standard library's [`PathBuf`] and [`Path`] types, except +they are guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +contents as strings, they implement `Display`, etc. + +The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +number of reasons: + +- Unicode is now the dominant encoding for file names. There are still some legacy codebases that store paths in encodings like [Shift JIS], but most have been converted to Unicode at this point. +- Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths + as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 + API boundaries.) +- There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such + system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +- The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) asks: given a + Makefile or other metadata file (such as `Cargo.toml`) that lists the names of other files, how should the names in + the Makefile be matched with the ones on disk? This has _no general, cross-platform solution_ in systems that support + non-UTF-8 paths. However, restricting paths to UTF-8 eliminates this problem. + +[Shift JIS]: https://en.wikipedia.org/wiki/Shift_JIS + +Therefore, many programs that want to manipulate paths _do_ assume they contain UTF-8 data, and convert them to `str`s +as necessary. However, because this invariant is not encoded in the `Path` type, conversions such as +`path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. + +Instead, `camino` allows you to check that your paths are UTF-8 _once_, and then manipulate them +as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +## Examples + +The documentation for [`Utf8PathBuf`] and [`Utf8Path`] contains several examples. + +For examples of how to use `camino` with other libraries like `serde` and `clap`, see the [`camino-examples`] directory. + +## API design + +`camino` is a very thin wrapper around `std::path`. [`Utf8Path`] and [`Utf8PathBuf`] are drop-in replacements +for [`Path`] and [`PathBuf`]. + +Most APIs are the same, but those at the boundary with `str` are different. Some examples: + +- `Path::to_str() -> Option<&str>` has been renamed to `Utf8Path::as_str() -> &str`. +- [`Utf8Path`] implements `Display`, and `Path::display()` has been removed. +- Iterating over a [`Utf8Path`] returns `&str`, not `&OsStr`. + +Every [`Utf8Path`] is a valid [`Path`], so [`Utf8Path`] implements `AsRef`. Any APIs that accept `impl AsRef` +will continue to work with [`Utf8Path`] instances. + +## Should you use camino? + +`camino` trades off some utility for a great deal of simplicity. Whether `camino` is appropriate for a project or not +is ultimately a case-by-case decision. Here are some general guidelines that may help. + +_You should consider using camino if..._ + +- **You're building portable, cross-platform software.** While both Unix and Windows platforms support different kinds + of non-Unicode paths, Unicode is the common subset that's supported across them. +- **Your system has files that contain the names of other files.** If you don't use UTF-8 paths, you will run into the + makefile problem described above, which has no general, cross-platform solution. +- **You're interacting with existing systems that already assume UTF-8 paths.** In that case you won't be adding any new + burdens on downstream consumers. +- **You're building something brand new and are willing to ask your users to rename their paths if necessary.** Projects + that don't have to worry about legacy compatibility have more flexibility in choosing what paths they support. + +In general, using camino is the right choice for most projects. + +_You should **NOT** use camino, if..._ + +- **You're writing a core system utility.** If you're writing, say, an `mv` or `cat` replacement, you should + **not** use camino. Instead, use [`std::path::Path`] and add extensive tests for non-UTF-8 paths. +- **You have legacy compatibility constraints.** For example, Git supports non-UTF-8 paths. If your tool needs to handle + arbitrary Git repositories, it should use its own path type that's a wrapper around `Vec`. + - [`std::path::Path`] supports arbitrary bytestrings [on Unix] but not on Windows. +- **There's some other reason you need to support non-UTF-8 paths.** Some tools like disk recovery utilities need to + handle potentially corrupt filenames: only being able to handle UTF-8 paths would greatly diminish their utility. + +[on Unix]: https://doc.rust-lang.org/std/os/unix/ffi/index.html + +## Optional features + +By default, `camino` has **no dependencies** other than `std`. There are some optional features that enable +dependencies: + +- `serde1` adds serde [`Serialize`] and [`Deserialize`] impls for [`Utf8PathBuf`] and [`Utf8Path`] + (zero-copy). +- `proptest1` adds [proptest](https://altsysrq.github.io/proptest-book/) [`Arbitrary`] + implementations for [`Utf8PathBuf`] and `Box`. + +## Rust version support + +The minimum supported Rust version (MSRV) for `camino` with default features is **1.61**. This project is tested in CI +against the latest stable version of Rust and the MSRV. + +- _Stable APIs_ added in later Rust versions are supported either through conditional compilation in `build.rs`, or through backfills that also work on older versions. +- _Deprecations_ are kept in sync with the version of Rust they're added in. +- _Unstable APIs_ are currently not supported. Please + [file an issue on GitHub](https://github.com/camino-rs/camino/issues/new) if you need an unstable API. + +`camino` is designed to be a core library and has a conservative MSRV policy. MSRV increases will only happen for +a compelling enough reason, and will involve at least a minor version bump. + +Optional features may pull in dependencies that require a newer version of Rust. + +## License + +This project is available under the terms of either the [Apache 2.0 license](LICENSE-APACHE) or the [MIT +license](LICENSE-MIT). + +This project's documentation is adapted from [The Rust Programming Language](https://github.com/rust-lang/rust/), which is +available under the terms of either the [Apache 2.0 license](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) +or the [MIT license](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT). + +[`Utf8PathBuf`]: https://docs.rs/camino/*/camino/struct.Utf8PathBuf.html +[`Utf8Path`]: https://docs.rs/camino/*/camino/struct.Utf8Path.html +[`PathBuf`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html +[`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`Serialize`]: https://docs.rs/serde/1/serde/trait.Serialize.html +[`Deserialize`]: https://docs.rs/serde/1/serde/trait.Deserialize.html +[`camino-examples`]: https://github.com/camino-rs/camino/tree/main/camino-examples +[`Arbitrary`]: https://docs.rs/proptest/1/proptest/arbitrary/trait.Arbitrary.html diff --git a/anneal/v2/vendor/camino/build.rs b/anneal/v2/vendor/camino/build.rs new file mode 100644 index 0000000000..f667f20032 --- /dev/null +++ b/anneal/v2/vendor/camino/build.rs @@ -0,0 +1,104 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Adapted from +//! https://github.com/dtolnay/syn/blob/a54fb0098c6679f1312113ae2eec0305c51c7390/build.rs. + +use std::{env, process::Command, str}; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + // Required by Rust 1.79+. + println!("cargo:rustc-check-cfg=cfg(doc_cfg)"); + println!("cargo:rustc-check-cfg=cfg(path_buf_deref_mut)"); + println!("cargo:rustc-check-cfg=cfg(try_reserve_2)"); + println!("cargo:rustc-check-cfg=cfg(os_str_bytes)"); + println!("cargo:rustc-check-cfg=cfg(os_string_pathbuf_leak)"); + println!("cargo:rustc-check-cfg=cfg(absolute_path)"); + println!("cargo:rustc-check-cfg=cfg(path_add_extension)"); + println!("cargo:rustc-check-cfg=cfg(pathbuf_const_new)"); + + let compiler = match rustc_version() { + Some(compiler) => compiler, + None => return, + }; + + // NOTE: + // Adding a new cfg gated by Rust version MUST be accompanied by an addition to the matrix in + // .github/workflows/ci.yml. + // + // try_reserve_2 was added in a 1.63 nightly. + if (compiler.minor >= 63 + && (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta)) + || compiler.minor >= 64 + { + println!("cargo:rustc-cfg=try_reserve_2"); + } + // path_buf_deref_mut was added in a 1.68 nightly. + if (compiler.minor >= 68 + && (compiler.channel == ReleaseChannel::Stable || compiler.channel == ReleaseChannel::Beta)) + || compiler.minor >= 69 + { + println!("cargo:rustc-cfg=path_buf_deref_mut"); + } + // os_str_bytes was added in 1.74. + if (compiler.minor >= 74 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 75 + { + println!("cargo:rustc-cfg=os_str_bytes"); + } + // absolute_path was added in 1.79. + if (compiler.minor >= 79 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 80 + { + println!("cargo:rustc-cfg=absolute_path"); + } + // os_string_pathbuf_leak was added in 1.89. + if (compiler.minor >= 89 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 90 + { + println!("cargo:rustc-cfg=os_string_pathbuf_leak"); + } + // path_add_extension was added in 1.91. + if (compiler.minor >= 91 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 92 + { + println!("cargo:rustc-cfg=path_add_extension"); + } + // pathbuf_const_new was added in 1.91. + if (compiler.minor >= 91 && compiler.channel == ReleaseChannel::Stable) || compiler.minor >= 92 + { + println!("cargo:rustc-cfg=pathbuf_const_new"); + } +} + +struct Compiler { + minor: u32, + channel: ReleaseChannel, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum ReleaseChannel { + Stable, + Beta, + Nightly, +} + +fn rustc_version() -> Option { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + let minor = pieces.next()?.parse().ok()?; + let channel = if version.contains("nightly") { + ReleaseChannel::Nightly + } else if version.contains("beta") { + ReleaseChannel::Beta + } else { + ReleaseChannel::Stable + }; + Some(Compiler { minor, channel }) +} diff --git a/anneal/v2/vendor/camino/clippy.toml b/anneal/v2/vendor/camino/clippy.toml new file mode 100644 index 0000000000..f5fcb56714 --- /dev/null +++ b/anneal/v2/vendor/camino/clippy.toml @@ -0,0 +1 @@ +msrv = "1.61.0" diff --git a/anneal/v2/vendor/camino/release.toml b/anneal/v2/vendor/camino/release.toml new file mode 100644 index 0000000000..b7977bad50 --- /dev/null +++ b/anneal/v2/vendor/camino/release.toml @@ -0,0 +1,8 @@ +sign-tag = true +# Required for templates below to work +consolidate-commits = false +pre-release-commit-message = "[{{crate_name}}] version {{version}}" +tag-message = "[{{crate_name}}] version {{version}}" +tag-name = "camino-{{version}}" +publish = false +dependent-version = "upgrade" diff --git a/anneal/v2/vendor/camino/rustfmt.toml b/anneal/v2/vendor/camino/rustfmt.toml new file mode 100644 index 0000000000..92ce4f2971 --- /dev/null +++ b/anneal/v2/vendor/camino/rustfmt.toml @@ -0,0 +1,3 @@ +edition = "2021" +style_edition = "2024" +use_field_init_shorthand = true diff --git a/anneal/v2/vendor/camino/src/lib.rs b/anneal/v2/vendor/camino/src/lib.rs new file mode 100644 index 0000000000..4005dcda2b --- /dev/null +++ b/anneal/v2/vendor/camino/src/lib.rs @@ -0,0 +1,3544 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +#![warn(missing_docs)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] + +//! UTF-8 encoded paths. +//! +//! `camino` is an extension of the [`std::path`] module that adds new [`Utf8PathBuf`] and [`Utf8Path`] +//! types. These are like the standard library's [`PathBuf`] and [`Path`] types, except they are +//! guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +//! contents as strings, they implement [`Display`], etc. +//! +//! The [`std::path`] types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +//! since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +//! number of reasons: +//! * Unicode won. There are still some legacy codebases that store paths in encodings like Shift-JIS, but most +//! have been converted to Unicode at this point. +//! * Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths +//! as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 +//! API boundaries.) +//! * There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such +//! system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +//! * The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) +//! (which also applies to `Cargo.toml`, and any other metadata file that lists the names of other files) has *no general, +//! cross-platform solution* in systems that support non-UTF-8 paths. However, restricting paths to UTF-8 eliminates +//! this problem. +//! +//! Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to [`str`]s +//! as necessary. However, because this invariant is not encoded in the [`Path`] type, conversions such as +//! `path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. +//! +//! Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them +//! as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +// General note: we use #[allow(clippy::incompatible_msrv)] for code that's already guarded by a +// version-specific cfg conditional. + +use std::{ + borrow::{Borrow, Cow}, + cmp::Ordering, + convert::{Infallible, TryFrom, TryInto}, + error, + ffi::{OsStr, OsString}, + fmt, + fs::{self, Metadata}, + hash::{Hash, Hasher}, + io, + iter::FusedIterator, + ops::Deref, + path::*, + rc::Rc, + str::FromStr, + sync::Arc, +}; + +#[cfg(feature = "proptest1")] +mod proptest_impls; +#[cfg(feature = "serde1")] +mod serde_impls; +#[cfg(test)] +mod tests; + +/// An owned, mutable UTF-8 path (akin to [`String`]). +/// +/// This type provides methods like [`push`] and [`set_extension`] that mutate +/// the path in place. It also implements [`Deref`] to [`Utf8Path`], meaning that +/// all methods on [`Utf8Path`] slices are available on [`Utf8PathBuf`] values as well. +/// +/// [`push`]: Utf8PathBuf::push +/// [`set_extension`]: Utf8PathBuf::set_extension +/// +/// # Examples +/// +/// You can use [`push`] to build up a [`Utf8PathBuf`] from +/// components: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let mut path = Utf8PathBuf::new(); +/// +/// path.push(r"C:\"); +/// path.push("windows"); +/// path.push("system32"); +/// +/// path.set_extension("dll"); +/// ``` +/// +/// However, [`push`] is best used for dynamic situations. This is a better way +/// to do this when you know all of the components ahead of time: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path: Utf8PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect(); +/// ``` +/// +/// We can still do better than this! Since these are all strings, we can use +/// [`From::from`]: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path = Utf8PathBuf::from(r"C:\windows\system32.dll"); +/// ``` +/// +/// Which method works best depends on what kind of situation you're in. +// NB: Internal PathBuf must only contain utf8 data +#[derive(Clone, Default)] +#[repr(transparent)] +pub struct Utf8PathBuf(PathBuf); + +impl Utf8PathBuf { + /// Allocates an empty [`Utf8PathBuf`]. + /// + /// *On Rust 1.91 or newer, this is a `const fn`.* + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let path = Utf8PathBuf::new(); + /// ``` + #[must_use] + #[cfg(pathbuf_const_new)] + #[expect(clippy::incompatible_msrv)] + pub const fn new() -> Utf8PathBuf { + Utf8PathBuf(PathBuf::new()) + } + + /// Allocates an empty [`Utf8PathBuf`]. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let path = Utf8PathBuf::new(); + /// ``` + #[must_use] + #[cfg(not(pathbuf_const_new))] + pub fn new() -> Utf8PathBuf { + Utf8PathBuf(PathBuf::new()) + } + + /// Creates a new [`Utf8PathBuf`] from a [`PathBuf`] containing valid UTF-8 characters. + /// + /// Errors with the original [`PathBuf`] if it is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], + /// see [`TryFrom<&PathBuf>`][tryfrom]. + /// + /// [tryfrom]: #impl-TryFrom-for-Utf8PathBuf + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::PathBuf; + /// + /// let unicode_path = PathBuf::from("/valid/unicode"); + /// Utf8PathBuf::from_path_buf(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = PathBuf::from(non_unicode_str); + /// # #[cfg(unix)] + /// Utf8PathBuf::from_path_buf(non_unicode_path).expect_err("non-Unicode path failed"); + /// ``` + pub fn from_path_buf(path: PathBuf) -> Result { + match path.into_os_string().into_string() { + Ok(string) => Ok(Utf8PathBuf::from(string)), + Err(os_string) => Err(PathBuf::from(os_string)), + } + } + + /// Creates a new [`Utf8PathBuf`] from an [`OsString`] containing valid UTF-8 characters. + /// + /// Errors with the original [`OsString`] if it is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// [`TryFrom`] impl. + /// + /// [`TryFrom`]: #impl-TryFrom-for-Utf8PathBuf + /// + /// # Examples + /// + /// ``` + /// # #[cfg(osstring_from_str)] { + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// use std::ffi::OsString; + /// use std::convert::TryFrom; + /// use std::str::FromStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// + /// let unicode_string = OsString::from_str("/valid/unicode").unwrap(); + /// Utf8PathBuf::from_os_string(unicode_string).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_string = OsStr::from_bytes(b"\xFF\xFF\xFF").into(); + /// # #[cfg(unix)] + /// Utf8PathBuf::from_os_string(non_unicode_string).expect_err("non-Unicode path failed"); + /// # } + /// ``` + pub fn from_os_string(os_string: OsString) -> Result { + match os_string.into_string() { + Ok(string) => Ok(Utf8PathBuf::from(string)), + Err(os_string) => Err(os_string), + } + } + + /// Converts a [`Utf8PathBuf`] to a [`PathBuf`]. + /// + /// This is equivalent to the [`From for PathBuf`][from] implementation, + /// but may aid in type inference. + /// + /// [from]: #impl-From-for-PathBuf + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::path::PathBuf; + /// + /// let utf8_path_buf = Utf8PathBuf::from("foo.txt"); + /// let std_path_buf = utf8_path_buf.into_std_path_buf(); + /// assert_eq!(std_path_buf.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8PathBuf. + /// let new_utf8_path_buf = Utf8PathBuf::from_path_buf(std_path_buf).unwrap(); + /// assert_eq!(new_utf8_path_buf, "foo.txt"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + pub fn into_std_path_buf(self) -> PathBuf { + self.into() + } + + /// Creates a new [`Utf8PathBuf`] with a given capacity used to create the internal [`PathBuf`]. + /// See [`with_capacity`] defined on [`PathBuf`]. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::with_capacity(10); + /// let capacity = path.capacity(); + /// + /// // This push is done without reallocating + /// path.push(r"C:\"); + /// + /// assert_eq!(capacity, path.capacity()); + /// ``` + /// + /// [`with_capacity`]: PathBuf::with_capacity + #[allow(clippy::incompatible_msrv)] + #[must_use] + pub fn with_capacity(capacity: usize) -> Utf8PathBuf { + Utf8PathBuf(PathBuf::with_capacity(capacity)) + } + + /// Coerces to a [`Utf8Path`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let p = Utf8PathBuf::from("/test"); + /// assert_eq!(Utf8Path::new("/test"), p.as_path()); + /// ``` + #[must_use] + pub fn as_path(&self) -> &Utf8Path { + // SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8 + unsafe { Utf8Path::assume_utf8(&self.0) } + } + + /// Consumes and leaks the [`Utf8PathBuf`], returning a mutable reference to the contents, + /// `&'a mut Utf8Path`. + /// + /// The caller has free choice over the returned lifetime, including 'static. + /// Indeed, this function is ideally used for data that lives for the remainder of + /// the program’s life, as dropping the returned reference will cause a memory leak. + /// + /// It does not reallocate or shrink the [`Utf8PathBuf`], so the leaked allocation may include + /// unused capacity that is not part of the returned slice. If you want to discard excess + /// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead. + /// However, keep in mind that trimming the capacity may result in a reallocation and copy. + /// + /// *Requires Rust 1.89 or newer.* + /// + /// [`into_boxed_path`]: Self::into_boxed_path + #[cfg(os_string_pathbuf_leak)] + #[allow(clippy::incompatible_msrv)] + #[inline] + pub fn leak<'a>(self) -> &'a mut Utf8Path { + // SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8 + unsafe { Utf8Path::assume_utf8_mut(self.0.leak()) } + } + + /// Extends `self` with `path`. + /// + /// If `path` is absolute, it replaces the current path. + /// + /// On Windows: + /// + /// * if `path` has a root but no prefix (e.g., `\windows`), it + /// replaces everything except for the prefix (if any) of `self`. + /// * if `path` has a prefix but no root, it replaces `self`. + /// + /// # Examples + /// + /// Pushing a relative path extends the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("file.bk"); + /// assert_eq!(path, Utf8PathBuf::from("/tmp/file.bk")); + /// ``` + /// + /// Pushing an absolute path replaces the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("/etc"); + /// assert_eq!(path, Utf8PathBuf::from("/etc")); + /// ``` + pub fn push(&mut self, path: impl AsRef) { + self.0.push(&path.as_ref().0) + } + + /// Truncates `self` to [`self.parent`]. + /// + /// Returns `false` and does nothing if [`self.parent`] is [`None`]. + /// Otherwise, returns `true`. + /// + /// [`self.parent`]: Utf8Path::parent + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/spirited/away.rs"); + /// + /// p.pop(); + /// assert_eq!(Utf8Path::new("/spirited"), p); + /// p.pop(); + /// assert_eq!(Utf8Path::new("/"), p); + /// ``` + pub fn pop(&mut self) -> bool { + self.0.pop() + } + + /// Updates [`self.file_name`] to `file_name`. + /// + /// If [`self.file_name`] was [`None`], this is equivalent to pushing + /// `file_name`. + /// + /// Otherwise it is equivalent to calling [`pop`] and then pushing + /// `file_name`. The new path will be a sibling of the original path. + /// (That is, it will have the same parent.) + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`pop`]: Utf8PathBuf::pop + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut buf = Utf8PathBuf::from("/"); + /// assert_eq!(buf.file_name(), None); + /// buf.set_file_name("bar"); + /// assert_eq!(buf, Utf8PathBuf::from("/bar")); + /// assert!(buf.file_name().is_some()); + /// buf.set_file_name("baz.txt"); + /// assert_eq!(buf, Utf8PathBuf::from("/baz.txt")); + /// ``` + pub fn set_file_name(&mut self, file_name: impl AsRef) { + self.0.set_file_name(file_name.as_ref()) + } + + /// Updates [`self.extension`] to `extension`. + /// + /// Returns `false` and does nothing if [`self.file_name`] is [`None`], + /// returns `true` and updates the extension otherwise. + /// + /// If [`self.extension`] is [`None`], the extension is added; otherwise + /// it is replaced. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`self.extension`]: Utf8Path::extension + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/feel/the"); + /// + /// p.set_extension("force"); + /// assert_eq!(Utf8Path::new("/feel/the.force"), p.as_path()); + /// + /// p.set_extension("dark_side"); + /// assert_eq!(Utf8Path::new("/feel/the.dark_side"), p.as_path()); + /// ``` + pub fn set_extension(&mut self, extension: impl AsRef) -> bool { + self.0.set_extension(extension.as_ref()) + } + + /// Appends to [`self.extension`] with `extension`. + /// + /// Returns `false` and does nothing if [`self.file_name`] is [`None`], + /// returns `true` and updates the extension otherwise. + /// + /// *Requires Rust 1.91 or newer.* + /// + /// # Panics + /// + /// Panics if the passed extension contains a path separator (see + /// [`is_separator`]). + /// + /// # Caveats + /// + /// The appended `extension` may contain dots and will be used in its entirety, + /// but only the part after the final dot will be reflected in [`self.extension`]. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`self.extension`]: Utf8Path::extension + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/feel/the"); + /// + /// p.add_extension("formatted"); + /// assert_eq!(Utf8Path::new("/feel/the.formatted"), p.as_path()); + /// + /// p.add_extension("dark.side"); + /// assert_eq!(Utf8Path::new("/feel/the.formatted.dark.side"), p.as_path()); + /// ``` + #[cfg(path_add_extension)] + #[expect(clippy::incompatible_msrv)] + pub fn add_extension>(&mut self, extension: S) -> bool { + self.0.add_extension(extension.as_ref()) + } + + /// Consumes the [`Utf8PathBuf`], yielding its internal [`String`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_string(); + /// assert_eq!(s, "/the/head"); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + pub fn into_string(self) -> String { + self.into_os_string().into_string().unwrap() + } + + /// Consumes the [`Utf8PathBuf`], yielding its internal [`OsString`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_os_string(); + /// assert_eq!(s, OsStr::new("/the/head")); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + pub fn into_os_string(self) -> OsString { + self.0.into_os_string() + } + + /// Converts this [`Utf8PathBuf`] into a [boxed](Box) [`Utf8Path`]. + #[must_use = "`self` will be dropped if the result is not used"] + pub fn into_boxed_path(self) -> Box { + let ptr = Box::into_raw(self.0.into_boxed_path()) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } + + /// Invokes [`capacity`] on the underlying instance of [`PathBuf`]. + /// + /// [`capacity`]: PathBuf::capacity + #[allow(clippy::incompatible_msrv)] + #[must_use] + pub fn capacity(&self) -> usize { + self.0.capacity() + } + + /// Invokes [`clear`] on the underlying instance of [`PathBuf`]. + /// + /// [`clear`]: PathBuf::clear + #[allow(clippy::incompatible_msrv)] + pub fn clear(&mut self) { + self.0.clear() + } + + /// Invokes [`reserve`] on the underlying instance of [`PathBuf`]. + /// + /// [`reserve`]: PathBuf::reserve + #[allow(clippy::incompatible_msrv)] + pub fn reserve(&mut self, additional: usize) { + self.0.reserve(additional) + } + + /// Invokes [`try_reserve`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.63 or newer.* + /// + /// [`try_reserve`]: PathBuf::try_reserve + #[cfg(try_reserve_2)] + #[allow(clippy::incompatible_msrv)] + #[inline] + pub fn try_reserve( + &mut self, + additional: usize, + ) -> Result<(), std::collections::TryReserveError> { + self.0.try_reserve(additional) + } + + /// Invokes [`reserve_exact`] on the underlying instance of [`PathBuf`]. + /// + /// [`reserve_exact`]: PathBuf::reserve_exact + #[allow(clippy::incompatible_msrv)] + pub fn reserve_exact(&mut self, additional: usize) { + self.0.reserve_exact(additional) + } + + /// Invokes [`try_reserve_exact`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.63 or newer.* + /// + /// [`try_reserve_exact`]: PathBuf::try_reserve_exact + #[cfg(try_reserve_2)] + #[allow(clippy::incompatible_msrv)] + #[inline] + pub fn try_reserve_exact( + &mut self, + additional: usize, + ) -> Result<(), std::collections::TryReserveError> { + self.0.try_reserve_exact(additional) + } + + /// Invokes [`shrink_to_fit`] on the underlying instance of [`PathBuf`]. + /// + /// [`shrink_to_fit`]: PathBuf::shrink_to_fit + #[allow(clippy::incompatible_msrv)] + pub fn shrink_to_fit(&mut self) { + self.0.shrink_to_fit() + } + + /// Invokes [`shrink_to`] on the underlying instance of [`PathBuf`]. + /// + /// [`shrink_to`]: PathBuf::shrink_to + #[allow(clippy::incompatible_msrv)] + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.0.shrink_to(min_capacity) + } +} + +impl Deref for Utf8PathBuf { + type Target = Utf8Path; + + fn deref(&self) -> &Utf8Path { + self.as_path() + } +} + +/// *Requires Rust 1.68 or newer.* +#[cfg(path_buf_deref_mut)] +#[allow(clippy::incompatible_msrv)] +impl std::ops::DerefMut for Utf8PathBuf { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { Utf8Path::assume_utf8_mut(&mut self.0) } + } +} + +impl fmt::Debug for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl fmt::Display for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl> Extend

for Utf8PathBuf { + fn extend>(&mut self, iter: I) { + for path in iter { + self.push(path); + } + } +} + +/// A slice of a UTF-8 path (akin to [`str`]). +/// +/// This type supports a number of operations for inspecting a path, including +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. +/// +/// This is an *unsized* type, meaning that it must always be used behind a +/// pointer like `&` or [`Box`]. For an owned version of this type, +/// see [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// // Note: this example does work on Windows +/// let path = Utf8Path::new("./foo/bar.txt"); +/// +/// let parent = path.parent(); +/// assert_eq!(parent, Some(Utf8Path::new("./foo"))); +/// +/// let file_stem = path.file_stem(); +/// assert_eq!(file_stem, Some("bar")); +/// +/// let extension = path.extension(); +/// assert_eq!(extension, Some("txt")); +/// ``` +// NB: Internal Path must only contain utf8 data +#[repr(transparent)] +pub struct Utf8Path(Path); + +impl Utf8Path { + /// Directly wraps a string slice as a [`Utf8Path`] slice. + /// + /// This is a cost-free conversion. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// Utf8Path::new("foo.txt"); + /// ``` + /// + /// You can create [`Utf8Path`]s from [`String`]s, or even other [`Utf8Path`]s: + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let string = String::from("foo.txt"); + /// let from_string = Utf8Path::new(&string); + /// let from_path = Utf8Path::new(&from_string); + /// assert_eq!(from_string, from_path); + /// ``` + pub fn new(s: &(impl AsRef + ?Sized)) -> &Utf8Path { + let path = Path::new(s.as_ref()); + // SAFETY: s is a str which means it is always valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + } + + /// Converts a [`Path`] to a [`Utf8Path`]. + /// + /// Returns [`None`] if the path is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], + /// see [`TryFrom<&Path>`][tryfrom]. + /// + /// [tryfrom]: #impl-TryFrom<%26Path>-for-%26Utf8Path + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::Path; + /// + /// let unicode_path = Path::new("/valid/unicode"); + /// Utf8Path::from_path(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = Path::new(non_unicode_str); + /// # #[cfg(unix)] + /// assert!(Utf8Path::from_path(non_unicode_path).is_none(), "non-Unicode path failed"); + /// ``` + pub fn from_path(path: &Path) -> Option<&Utf8Path> { + path.as_os_str().to_str().map(Utf8Path::new) + } + + /// Converts an [`OsStr`] to a [`Utf8Path`]. + /// + /// Returns [`None`] if the path is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// [`TryFrom<&OsStr>`][tryfrom] impl. + /// + /// [tryfrom]: #impl-TryFrom<%26OsStr>-for-%26Utf8Path + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::Path; + /// + /// let unicode_string = OsStr::new("/valid/unicode"); + /// Utf8Path::from_os_str(unicode_string).expect("valid Unicode string succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// assert!(Utf8Path::from_os_str(non_unicode_str).is_none(), "non-Unicode string failed"); + /// ``` + pub fn from_os_str(path: &OsStr) -> Option<&Utf8Path> { + path.to_str().map(Utf8Path::new) + } + + /// Converts a [`Utf8Path`] to a [`Path`]. + /// + /// This is equivalent to the [`AsRef for Utf8PathBuf`][asref] implementation, + /// but may aid in type inference. + /// + /// [asref]: Utf8PathBuf#impl-AsRef-for-Utf8PathBuf + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::Path; + /// + /// let utf8_path = Utf8Path::new("foo.txt"); + /// let std_path: &Path = utf8_path.as_std_path(); + /// assert_eq!(std_path.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8Path. + /// let new_utf8_path = Utf8Path::from_path(std_path).unwrap(); + /// assert_eq!(new_utf8_path, "foo.txt"); + /// ``` + #[inline] + pub fn as_std_path(&self) -> &Path { + self.as_ref() + } + + /// Yields the underlying [`str`] slice. + /// + /// Unlike [`Path::to_str`], this always returns a slice because the contents + /// of a [`Utf8Path`] are guaranteed to be valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let s = Utf8Path::new("foo.txt").as_str(); + /// assert_eq!(s, "foo.txt"); + /// ``` + /// + /// [`str`]: str + #[inline] + #[must_use] + pub fn as_str(&self) -> &str { + // SAFETY: every Utf8Path constructor ensures that self is valid UTF-8 + unsafe { str_assume_utf8(self.as_os_str()) } + } + + /// Yields the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let os_str = Utf8Path::new("foo.txt").as_os_str(); + /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); + /// ``` + #[inline] + #[must_use] + pub fn as_os_str(&self) -> &OsStr { + self.0.as_os_str() + } + + /// Converts a [`Utf8Path`] to an owned [`Utf8PathBuf`]. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path_buf = Utf8Path::new("foo.txt").to_path_buf(); + /// assert_eq!(path_buf, Utf8PathBuf::from("foo.txt")); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + pub fn to_path_buf(&self) -> Utf8PathBuf { + Utf8PathBuf(self.0.to_path_buf()) + } + + /// Returns `true` if the [`Utf8Path`] is absolute, i.e., if it is independent of + /// the current directory. + /// + /// * On Unix, a path is absolute if it starts with the root, so + /// `is_absolute` and [`has_root`] are equivalent. + /// + /// * On Windows, a path is absolute if it has a prefix and starts with the + /// root: `C:\windows` is absolute, while `C:temp` and `\temp` are not. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(!Utf8Path::new("foo.txt").is_absolute()); + /// ``` + /// + /// [`has_root`]: Utf8Path::has_root + #[inline] + #[must_use] + pub fn is_absolute(&self) -> bool { + self.0.is_absolute() + } + + /// Returns `true` if the [`Utf8Path`] is relative, i.e., not absolute. + /// + /// See [`is_absolute`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("foo.txt").is_relative()); + /// ``` + /// + /// [`is_absolute`]: Utf8Path::is_absolute + #[inline] + #[must_use] + pub fn is_relative(&self) -> bool { + self.0.is_relative() + } + + /// Returns `true` if the [`Utf8Path`] has a root. + /// + /// * On Unix, a path has a root if it begins with `/`. + /// + /// * On Windows, a path has a root if it: + /// * has no prefix and begins with a separator, e.g., `\windows` + /// * has a prefix followed by a separator, e.g., `C:\windows` but not `C:windows` + /// * has any non-disk prefix, e.g., `\\server\share` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("/etc/passwd").has_root()); + /// ``` + #[inline] + #[must_use] + pub fn has_root(&self) -> bool { + self.0.has_root() + } + + /// Returns the [`Path`] without its final component, if there is one. + /// + /// Returns [`None`] if the path terminates in a root or prefix. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/foo/bar"); + /// let parent = path.parent().unwrap(); + /// assert_eq!(parent, Utf8Path::new("/foo")); + /// + /// let grand_parent = parent.parent().unwrap(); + /// assert_eq!(grand_parent, Utf8Path::new("/")); + /// assert_eq!(grand_parent.parent(), None); + /// ``` + #[inline] + #[must_use] + pub fn parent(&self) -> Option<&Utf8Path> { + self.0.parent().map(|path| { + // SAFETY: self is valid UTF-8, so parent is valid UTF-8 as well + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Produces an iterator over [`Utf8Path`] and its ancestors. + /// + /// The iterator will yield the [`Utf8Path`] that is returned if the [`parent`] method is used zero + /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`, + /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns + /// [`None`], the iterator will do likewise. The iterator will always yield at least one value, + /// namely `&self`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut ancestors = Utf8Path::new("/foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/"))); + /// assert_eq!(ancestors.next(), None); + /// + /// let mut ancestors = Utf8Path::new("../foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(".."))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(""))); + /// assert_eq!(ancestors.next(), None); + /// ``` + /// + /// [`parent`]: Utf8Path::parent + #[inline] + pub fn ancestors(&self) -> Utf8Ancestors<'_> { + Utf8Ancestors(self.0.ancestors()) + } + + /// Returns the final component of the [`Utf8Path`], if there is one. + /// + /// If the path is a normal file, this is the file name. If it's the path of a directory, this + /// is the directory name. + /// + /// Returns [`None`] if the path terminates in `..`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!(Some("bin"), Utf8Path::new("/usr/bin/").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("tmp/foo.txt").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.//").file_name()); + /// assert_eq!(None, Utf8Path::new("foo.txt/..").file_name()); + /// assert_eq!(None, Utf8Path::new("/").file_name()); + /// ``` + #[inline] + #[must_use] + pub fn file_name(&self) -> Option<&str> { + self.0.file_name().map(|s| { + // SAFETY: self is valid UTF-8, so file_name is valid UTF-8 as well + unsafe { str_assume_utf8(s) } + }) + } + + /// Returns a path that, when joined onto `base`, yields `self`. + /// + /// # Errors + /// + /// If `base` is not a prefix of `self` (i.e., [`starts_with`] + /// returns `false`), returns [`Err`]. + /// + /// [`starts_with`]: Utf8Path::starts_with + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/test/haha/foo.txt"); + /// + /// assert_eq!(path.strip_prefix("/"), Ok(Utf8Path::new("test/haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Utf8Path::new(""))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Utf8Path::new(""))); + /// + /// assert!(path.strip_prefix("test").is_err()); + /// assert!(path.strip_prefix("/haha").is_err()); + /// + /// let prefix = Utf8PathBuf::from("/test/"); + /// assert_eq!(path.strip_prefix(prefix), Ok(Utf8Path::new("haha/foo.txt"))); + /// ``` + #[inline] + pub fn strip_prefix(&self, base: impl AsRef) -> Result<&Utf8Path, StripPrefixError> { + self.0.strip_prefix(base).map(|path| { + // SAFETY: self is valid UTF-8, and strip_prefix returns a part of self (or an empty + // string), so it is valid UTF-8 as well. + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Determines whether `base` is a prefix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/passwd"); + /// + /// assert!(path.starts_with("/etc")); + /// assert!(path.starts_with("/etc/")); + /// assert!(path.starts_with("/etc/passwd")); + /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay + /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay + /// + /// assert!(!path.starts_with("/e")); + /// assert!(!path.starts_with("/etc/passwd.txt")); + /// + /// assert!(!Utf8Path::new("/etc/foo.rs").starts_with("/etc/foo")); + /// ``` + #[inline] + #[must_use] + pub fn starts_with(&self, base: impl AsRef) -> bool { + self.0.starts_with(base) + } + + /// Determines whether `child` is a suffix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/resolv.conf"); + /// + /// assert!(path.ends_with("resolv.conf")); + /// assert!(path.ends_with("etc/resolv.conf")); + /// assert!(path.ends_with("/etc/resolv.conf")); + /// + /// assert!(!path.ends_with("/resolv.conf")); + /// assert!(!path.ends_with("conf")); // use .extension() instead + /// ``` + #[inline] + #[must_use] + pub fn ends_with(&self, base: impl AsRef) -> bool { + self.0.ends_with(base) + } + + /// Extracts the stem (non-extension) portion of [`self.file_name`]. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// The stem is: + /// + /// * [`None`], if there is no file name; + /// * The entire file name if there is no embedded `.`; + /// * The entire file name if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name before the final `.` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("foo", Utf8Path::new("foo.rs").file_stem().unwrap()); + /// assert_eq!("foo.tar", Utf8Path::new("foo.tar.gz").file_stem().unwrap()); + /// ``` + #[inline] + #[must_use] + pub fn file_stem(&self) -> Option<&str> { + self.0.file_stem().map(|s| { + // SAFETY: self is valid UTF-8, so file_stem is valid UTF-8 as well + unsafe { str_assume_utf8(s) } + }) + } + + /// Extracts the prefix of [`self.file_name`]. + /// + /// The prefix is: + /// + /// * [`None`], if there is no file name; + /// * The entire file name if there is no embedded `.`; + /// * The portion of the file name before the first non-beginning `.`; + /// * The entire file name if the file name begins with `.` and has no other `.`s within; + /// * The portion of the file name before the second `.` if the file name begins with `.` + /// + /// *Requires Rust 1.91 or newer.* + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("foo", Utf8Path::new("foo.rs").file_prefix().unwrap()); + /// assert_eq!("foo", Utf8Path::new("foo.tar.gz").file_prefix().unwrap()); + /// ``` + #[cfg(path_add_extension)] + #[expect(clippy::incompatible_msrv)] + #[inline] + #[must_use] + pub fn file_prefix(&self) -> Option<&str> { + self.0.file_prefix().map(|s| { + // SAFETY: self is valid UTF-8, so file_prefix is valid UTF-8 as well + unsafe { str_assume_utf8(s) } + }) + } + + /// Extracts the extension of [`self.file_name`], if possible. + /// + /// The extension is: + /// + /// * [`None`], if there is no file name; + /// * [`None`], if there is no embedded `.`; + /// * [`None`], if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name after the final `.` + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("rs", Utf8Path::new("foo.rs").extension().unwrap()); + /// assert_eq!("gz", Utf8Path::new("foo.tar.gz").extension().unwrap()); + /// ``` + #[inline] + #[must_use] + pub fn extension(&self) -> Option<&str> { + self.0.extension().map(|s| { + // SAFETY: self is valid UTF-8, so extension is valid UTF-8 as well + unsafe { str_assume_utf8(s) } + }) + } + + /// Creates an owned [`Utf8PathBuf`] with `path` adjoined to `self`. + /// + /// See [`Utf8PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// assert_eq!(Utf8Path::new("/etc").join("passwd"), Utf8PathBuf::from("/etc/passwd")); + /// ``` + #[inline] + #[must_use] + pub fn join(&self, path: impl AsRef) -> Utf8PathBuf { + Utf8PathBuf(self.0.join(&path.as_ref().0)) + } + + /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. + /// + /// See [`PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// assert_eq!(Utf8Path::new("/etc").join_os("passwd"), PathBuf::from("/etc/passwd")); + /// ``` + #[inline] + #[must_use] + pub fn join_os(&self, path: impl AsRef) -> PathBuf { + self.0.join(path) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given file name. + /// + /// See [`Utf8PathBuf::set_file_name`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/tmp/foo.txt"); + /// assert_eq!(path.with_file_name("bar.txt"), Utf8PathBuf::from("/tmp/bar.txt")); + /// + /// let path = Utf8Path::new("/tmp"); + /// assert_eq!(path.with_file_name("var"), Utf8PathBuf::from("/var")); + /// ``` + #[inline] + #[must_use] + pub fn with_file_name(&self, file_name: impl AsRef) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_file_name(file_name.as_ref())) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given extension. + /// + /// See [`Utf8PathBuf::set_extension`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("foo.rs"); + /// assert_eq!(path.with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// + /// let path = Utf8Path::new("foo.tar.gz"); + /// assert_eq!(path.with_extension(""), Utf8PathBuf::from("foo.tar")); + /// assert_eq!(path.with_extension("xz"), Utf8PathBuf::from("foo.tar.xz")); + /// assert_eq!(path.with_extension("").with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// ``` + #[inline] + pub fn with_extension(&self, extension: impl AsRef) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_extension(extension.as_ref())) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the extension added. + /// + /// See [`Utf8PathBuf::add_extension`] for more details. + /// + /// *Requires Rust 1.91 or newer.* + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("foo.rs"); + /// assert_eq!(path.with_added_extension("txt"), Utf8PathBuf::from("foo.rs.txt")); + /// + /// let path = Utf8Path::new("foo.tar.gz"); + /// assert_eq!(path.with_added_extension(""), Utf8PathBuf::from("foo.tar.gz")); + /// assert_eq!(path.with_added_extension("xz"), Utf8PathBuf::from("foo.tar.gz.xz")); + /// ``` + #[cfg(path_add_extension)] + #[expect(clippy::incompatible_msrv)] + #[inline] + pub fn with_added_extension>(&self, extension: S) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_added_extension(extension.as_ref())) + } + + /// Produces an iterator over the [`Utf8Component`]s of the path. + /// + /// When parsing the path, there is a small amount of normalization: + /// + /// * Repeated separators are ignored, so `a/b` and `a//b` both have + /// `a` and `b` as components. + /// + /// * Occurrences of `.` are normalized away, except if they are at the + /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and + /// `a/b` all have `a` and `b` as components, but `./a/b` starts with + /// an additional [`CurDir`] component. + /// + /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. + /// + /// Note that no other normalization takes place; in particular, `a/c` + /// and `a/b/../c` are distinct, to account for the possibility that `b` + /// is a symbolic link (so its parent isn't `a`). + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Component, Utf8Path}; + /// + /// let mut components = Utf8Path::new("/tmp/foo.txt").components(); + /// + /// assert_eq!(components.next(), Some(Utf8Component::RootDir)); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("tmp"))); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("foo.txt"))); + /// assert_eq!(components.next(), None) + /// ``` + /// + /// [`CurDir`]: Utf8Component::CurDir + #[inline] + pub fn components(&self) -> Utf8Components<'_> { + Utf8Components(self.0.components()) + } + + /// Produces an iterator over the path's components viewed as [`str`] + /// slices. + /// + /// For more information about the particulars of how the path is separated + /// into components, see [`components`]. + /// + /// [`components`]: Utf8Path::components + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut it = Utf8Path::new("/tmp/foo.txt").iter(); + /// assert_eq!(it.next(), Some(std::path::MAIN_SEPARATOR.to_string().as_str())); + /// assert_eq!(it.next(), Some("tmp")); + /// assert_eq!(it.next(), Some("foo.txt")); + /// assert_eq!(it.next(), None) + /// ``` + #[inline] + pub fn iter(&self) -> Iter<'_> { + Iter { + inner: self.components(), + } + } + + /// Queries the file system to get information about a file, directory, etc. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. + /// + /// This is an alias to [`fs::metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.metadata().expect("metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + #[inline] + pub fn metadata(&self) -> io::Result { + self.0.metadata() + } + + /// Queries the metadata about a file without following symlinks. + /// + /// This is an alias to [`fs::symlink_metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + #[inline] + pub fn symlink_metadata(&self) -> io::Result { + self.0.symlink_metadata() + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. For a version that returns a [`Utf8PathBuf`], see + /// [`canonicalize_utf8`](Self::canonicalize_utf8). + /// + /// This is an alias to [`fs::canonicalize`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// let path = Utf8Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); + /// ``` + #[inline] + pub fn canonicalize(&self) -> io::Result { + self.0.canonicalize() + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a + /// version that does not attempt to do this conversion, see + /// [`canonicalize`](Self::canonicalize). + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::canonicalize`] + /// documentation for more. + /// + /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to [`InvalidData`](io::ErrorKind::InvalidData) + /// and the payload set to a [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize_utf8().unwrap(), Utf8PathBuf::from("/foo/test/bar.rs")); + /// ``` + pub fn canonicalize_utf8(&self) -> io::Result { + self.canonicalize() + .and_then(|path| path.try_into().map_err(FromPathBufError::into_io_error)) + } + + /// Reads a symbolic link, returning the file that the link points to. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. For a version that returns a [`Utf8PathBuf`], see + /// [`read_link_utf8`](Self::read_link_utf8). + /// + /// This is an alias to [`fs::read_link`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa/sky_castle.rs"); + /// let path_link = path.read_link().expect("read_link call failed"); + /// ``` + #[inline] + pub fn read_link(&self) -> io::Result { + self.0.read_link() + } + + /// Reads a symbolic link, returning the file that the link points to. + /// + /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a + /// version that does not attempt to do this conversion, see [`read_link`](Self::read_link). + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::read_link`] + /// documentation for more. + /// + /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to [`InvalidData`](io::ErrorKind::InvalidData) + /// and the payload set to a [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa/sky_castle.rs"); + /// let path_link = path.read_link_utf8().expect("read_link call failed"); + /// ``` + pub fn read_link_utf8(&self) -> io::Result { + self.read_link() + .and_then(|path| path.try_into().map_err(FromPathBufError::into_io_error)) + } + + /// Returns an iterator over the entries within a directory. + /// + /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New + /// errors may be encountered after an iterator is initially constructed. + /// + /// This is an alias to [`fs::read_dir`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa"); + /// for entry in path.read_dir().expect("read_dir call failed") { + /// if let Ok(entry) = entry { + /// println!("{:?}", entry.path()); + /// } + /// } + /// ``` + #[inline] + pub fn read_dir(&self) -> io::Result { + self.0.read_dir() + } + + /// Returns an iterator over the entries within a directory. + /// + /// The iterator will yield instances of [`io::Result`]`<`[`Utf8DirEntry`]`>`. New + /// errors may be encountered after an iterator is initially constructed. + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::read_dir`] + /// documentation for more. + /// + /// If a directory entry is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to [`InvalidData`](io::ErrorKind::InvalidData) + /// and the payload set to a [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa"); + /// for entry in path.read_dir_utf8().expect("read_dir call failed") { + /// if let Ok(entry) = entry { + /// println!("{}", entry.path()); + /// } + /// } + /// ``` + #[inline] + pub fn read_dir_utf8(&self) -> io::Result { + self.0.read_dir().map(|inner| ReadDirUtf8 { inner }) + } + + /// Returns `true` if the path points at an existing entity. + /// + /// Warning: this method may be error-prone, consider using [`try_exists()`] instead! + /// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert!(!Utf8Path::new("does_not_exist.txt").exists()); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`]. + /// + /// [`try_exists()`]: Self::try_exists + #[must_use] + #[inline] + pub fn exists(&self) -> bool { + self.0.exists() + } + + /// Returns `Ok(true)` if the path points at an existing entity. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `Ok(false)`. + /// + /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors + /// unrelated to the path not existing. (E.g. it will return [`Err`] in case of permission + /// denied on some of the parent directories.) + /// + /// Note that while this avoids some pitfalls of the `exists()` method, it still can not + /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios + /// where those bugs are not an issue. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert!( + /// !Utf8Path::new("does_not_exist.txt") + /// .try_exists() + /// .expect("Can't check existence of file does_not_exist.txt") + /// ); + /// assert!(Utf8Path::new("/root/secret_file.txt").try_exists().is_err()); + /// ``` + /// + /// [`exists()`]: Self::exists + #[inline] + pub fn try_exists(&self) -> io::Result { + match fs::metadata(self) { + Ok(_) => Ok(true), + Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } + } + + /// Returns `true` if the path exists on disk and is pointing at a regular file. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_file(), false); + /// assert_eq!(Utf8Path::new("a_file.txt").is_file(), true); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_file`] if it was [`Ok`]. + /// + /// When the goal is simply to read from (or write to) the source, the most + /// reliable way to test the source can be read (or written to) is to open + /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on + /// a Unix-like system for example. See [`fs::File::open`] or + /// [`fs::OpenOptions::open`] for more information. + #[must_use] + #[inline] + pub fn is_file(&self) -> bool { + self.0.is_file() + } + + /// Returns `true` if the path exists on disk and is pointing at a directory. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_dir(), true); + /// assert_eq!(Utf8Path::new("a_file.txt").is_dir(), false); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_dir`] if it was [`Ok`]. + #[must_use] + #[inline] + pub fn is_dir(&self) -> bool { + self.0.is_dir() + } + + /// Returns `true` if the path exists on disk and is pointing at a symbolic link. + /// + /// This function will not traverse symbolic links. + /// In case of a broken symbolic link this will also return true. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return false. + /// + /// # Examples + /// + #[cfg_attr(unix, doc = "```no_run")] + #[cfg_attr(not(unix), doc = "```ignore")] + /// use camino::Utf8Path; + /// use std::os::unix::fs::symlink; + /// + /// let link_path = Utf8Path::new("link"); + /// symlink("/origin_does_not_exist/", link_path).unwrap(); + /// assert_eq!(link_path.is_symlink(), true); + /// assert_eq!(link_path.exists(), false); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`Utf8Path::symlink_metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_symlink`] if it was [`Ok`]. + #[must_use] + pub fn is_symlink(&self) -> bool { + self.symlink_metadata() + .map(|m| m.file_type().is_symlink()) + .unwrap_or(false) + } + + /// Converts a [`Box`] into a [`Utf8PathBuf`] without copying or allocating. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub fn into_path_buf(self: Box) -> Utf8PathBuf { + let ptr = Box::into_raw(self) as *mut Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path. + // * Utf8Path is marked as #[repr(transparent)] so the conversion from a *mut Utf8Path to a + // *mut Path is valid. + let boxed_path = unsafe { Box::from_raw(ptr) }; + Utf8PathBuf(boxed_path.into_path_buf()) + } + + // invariant: Path must be guaranteed to be utf-8 data + #[inline] + unsafe fn assume_utf8(path: &Path) -> &Utf8Path { + // SAFETY: Utf8Path is marked as #[repr(transparent)] so the conversion from a + // *const Path to a *const Utf8Path is valid. + &*(path as *const Path as *const Utf8Path) + } + + #[cfg(path_buf_deref_mut)] + #[inline] + unsafe fn assume_utf8_mut(path: &mut Path) -> &mut Utf8Path { + &mut *(path as *mut Path as *mut Utf8Path) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + let boxed: Box = self.0.into(); + let ptr = Box::into_raw(boxed) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was created by consuming a Box so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } +} + +impl fmt::Display for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl fmt::Debug for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_str(), f) + } +} + +/// An iterator over [`Utf8Path`] and its ancestors. +/// +/// This `struct` is created by the [`ancestors`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/foo/bar"); +/// +/// for ancestor in path.ancestors() { +/// println!("{}", ancestor); +/// } +/// ``` +/// +/// [`ancestors`]: Utf8Path::ancestors +#[derive(Copy, Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[repr(transparent)] +pub struct Utf8Ancestors<'a>(Ancestors<'a>); + +impl fmt::Debug for Utf8Ancestors<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl<'a> Iterator for Utf8Ancestors<'a> { + type Item = &'a Utf8Path; + + #[inline] + fn next(&mut self) -> Option { + self.0.next().map(|path| { + // SAFETY: Utf8Ancestors was constructed from a Utf8Path, so it is guaranteed to + // be valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + }) + } +} + +impl FusedIterator for Utf8Ancestors<'_> {} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`]. +/// +/// This `struct` is created by the [`components`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// +/// for component in path.components() { +/// println!("{:?}", component); +/// } +/// ``` +/// +/// [`components`]: Utf8Path::components +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Utf8Components<'a>(Components<'a>); + +impl<'a> Utf8Components<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut components = Utf8Path::new("/tmp/foo/bar.txt").components(); + /// components.next(); + /// components.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), components.as_path()); + /// ``` + #[must_use] + #[inline] + pub fn as_path(&self) -> &'a Utf8Path { + // SAFETY: Utf8Components was constructed from a Utf8Path, so it is guaranteed to be valid + // UTF-8 + unsafe { Utf8Path::assume_utf8(self.0.as_path()) } + } +} + +impl<'a> Iterator for Utf8Components<'a> { + type Item = Utf8Component<'a>; + + #[inline] + fn next(&mut self) -> Option { + self.0.next().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl FusedIterator for Utf8Components<'_> {} + +impl DoubleEndedIterator for Utf8Components<'_> { + #[inline] + fn next_back(&mut self) -> Option { + self.0.next_back().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl fmt::Debug for Utf8Components<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl AsRef for Utf8Components<'_> { + #[inline] + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef for Utf8Components<'_> { + #[inline] + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef for Utf8Components<'_> { + #[inline] + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef for Utf8Components<'_> { + #[inline] + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`], as [`str`] slices. +/// +/// This `struct` is created by the [`iter`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// [`iter`]: Utf8Path::iter +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Iter<'a> { + inner: Utf8Components<'a>, +} + +impl fmt::Debug for Iter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DebugHelper<'a>(&'a Utf8Path); + + impl fmt::Debug for DebugHelper<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.0.iter()).finish() + } + } + + f.debug_tuple("Iter") + .field(&DebugHelper(self.as_path())) + .finish() + } +} + +impl<'a> Iter<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut iter = Utf8Path::new("/tmp/foo/bar.txt").iter(); + /// iter.next(); + /// iter.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), iter.as_path()); + /// ``` + #[must_use] + #[inline] + pub fn as_path(&self) -> &'a Utf8Path { + self.inner.as_path() + } +} + +impl AsRef for Iter<'_> { + #[inline] + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef for Iter<'_> { + #[inline] + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef for Iter<'_> { + #[inline] + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef for Iter<'_> { + #[inline] + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.inner.next().map(|component| component.as_str()) + } +} + +impl<'a> DoubleEndedIterator for Iter<'a> { + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.inner.next_back().map(|component| component.as_str()) + } +} + +impl FusedIterator for Iter<'_> {} + +/// A single component of a path. +/// +/// A [`Utf8Component`] roughly corresponds to a substring between path separators +/// (`/` or `\`). +/// +/// This `enum` is created by iterating over [`Utf8Components`], which in turn is +/// created by the [`components`](Utf8Path::components) method on [`Utf8Path`]. +/// +/// # Examples +/// +/// ```rust +/// use camino::{Utf8Component, Utf8Path}; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// let components = path.components().collect::>(); +/// assert_eq!(&components, &[ +/// Utf8Component::RootDir, +/// Utf8Component::Normal("tmp"), +/// Utf8Component::Normal("foo"), +/// Utf8Component::Normal("bar.txt"), +/// ]); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum Utf8Component<'a> { + /// A Windows path prefix, e.g., `C:` or `\\server\share`. + /// + /// There is a large variety of prefix types, see [`Utf8Prefix`]'s documentation + /// for more. + /// + /// Does not occur on Unix. + Prefix(Utf8PrefixComponent<'a>), + + /// The root directory component, appears after any prefix and before anything else. + /// + /// It represents a separator that designates that a path starts from root. + RootDir, + + /// A reference to the current directory, i.e., `.`. + CurDir, + + /// A reference to the parent directory, i.e., `..`. + ParentDir, + + /// A normal component, e.g., `a` and `b` in `a/b`. + /// + /// This variant is the most common one, it represents references to files + /// or directories. + Normal(&'a str), +} + +impl<'a> Utf8Component<'a> { + unsafe fn new(component: Component<'a>) -> Utf8Component<'a> { + match component { + Component::Prefix(prefix) => Utf8Component::Prefix(Utf8PrefixComponent(prefix)), + Component::RootDir => Utf8Component::RootDir, + Component::CurDir => Utf8Component::CurDir, + Component::ParentDir => Utf8Component::ParentDir, + Component::Normal(s) => Utf8Component::Normal(str_assume_utf8(s)), + } + } + + /// Extracts the underlying [`str`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + #[must_use] + #[inline] + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { str_assume_utf8(self.as_os_str()) } + } + + /// Extracts the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + #[must_use] + pub fn as_os_str(&self) -> &'a OsStr { + match *self { + Utf8Component::Prefix(prefix) => prefix.as_os_str(), + Utf8Component::RootDir => Component::RootDir.as_os_str(), + Utf8Component::CurDir => Component::CurDir.as_os_str(), + Utf8Component::ParentDir => Component::ParentDir.as_os_str(), + Utf8Component::Normal(s) => OsStr::new(s), + } + } +} + +impl fmt::Debug for Utf8Component<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_os_str(), f) + } +} + +impl fmt::Display for Utf8Component<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl AsRef for Utf8Component<'_> { + #[inline] + fn as_ref(&self) -> &Utf8Path { + self.as_str().as_ref() + } +} + +impl AsRef for Utf8Component<'_> { + #[inline] + fn as_ref(&self) -> &Path { + self.as_os_str().as_ref() + } +} + +impl AsRef for Utf8Component<'_> { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef for Utf8Component<'_> { + #[inline] + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +/// Windows path prefixes, e.g., `C:` or `\\server\share`. +/// +/// Windows uses a variety of path prefix styles, including references to drive +/// volumes (like `C:`), network shared folders (like `\\server\share`), and +/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with +/// `\\?\`), in which case `/` is *not* treated as a separator and essentially +/// no normalization is performed. +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use camino::Utf8Prefix::*; +/// +/// fn get_path_prefix(s: &str) -> Utf8Prefix { +/// let path = Utf8Path::new(s); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => prefix_component.kind(), +/// _ => panic!(), +/// } +/// } +/// +/// # if cfg!(windows) { +/// assert_eq!(Verbatim("pictures"), get_path_prefix(r"\\?\pictures\kittens")); +/// assert_eq!(VerbatimUNC("server", "share"), get_path_prefix(r"\\?\UNC\server\share")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\C:\")); +/// assert_eq!(DeviceNS("BrainInterface"), get_path_prefix(r"\\.\BrainInterface")); +/// assert_eq!(UNC("server", "share"), get_path_prefix(r"\\server\share")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// # } +/// ``` +#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum Utf8Prefix<'a> { + /// Verbatim prefix, e.g., `\\?\cat_pics`. + /// + /// Verbatim prefixes consist of `\\?\` immediately followed by the given + /// component. + Verbatim(&'a str), + + /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_, + /// e.g., `\\?\UNC\server\share`. + /// + /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the + /// server's hostname and a share name. + VerbatimUNC(&'a str, &'a str), + + /// Verbatim disk prefix, e.g., `\\?\C:`. + /// + /// Verbatim disk prefixes consist of `\\?\` immediately followed by the + /// drive letter and `:`. + VerbatimDisk(u8), + + /// Device namespace prefix, e.g., `\\.\COM42`. + /// + /// Device namespace prefixes consist of `\\.\` immediately followed by the + /// device name. + DeviceNS(&'a str), + + /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g. + /// `\\server\share`. + /// + /// UNC prefixes consist of the server's hostname and a share name. + UNC(&'a str, &'a str), + + /// Prefix `C:` for the given disk drive. + Disk(u8), +} + +impl Utf8Prefix<'_> { + /// Determines if the prefix is verbatim, i.e., begins with `\\?\`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Prefix::*; + /// + /// assert!(Verbatim("pictures").is_verbatim()); + /// assert!(VerbatimUNC("server", "share").is_verbatim()); + /// assert!(VerbatimDisk(b'C').is_verbatim()); + /// assert!(!DeviceNS("BrainInterface").is_verbatim()); + /// assert!(!UNC("server", "share").is_verbatim()); + /// assert!(!Disk(b'C').is_verbatim()); + /// ``` + #[must_use] + pub fn is_verbatim(&self) -> bool { + use Utf8Prefix::*; + matches!(self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..)) + } +} + +/// A structure wrapping a Windows path prefix as well as its unparsed string +/// representation. +/// +/// In addition to the parsed [`Utf8Prefix`] information returned by [`kind`], +/// [`Utf8PrefixComponent`] also holds the raw and unparsed [`str`] slice, +/// returned by [`as_str`]. +/// +/// Instances of this `struct` can be obtained by matching against the +/// [`Prefix` variant] on [`Utf8Component`]. +/// +/// Does not occur on Unix. +/// +/// # Examples +/// +/// ``` +/// # if cfg!(windows) { +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use std::ffi::OsStr; +/// +/// let path = Utf8Path::new(r"C:\you\later\"); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => { +/// assert_eq!(Utf8Prefix::Disk(b'C'), prefix_component.kind()); +/// assert_eq!("C:", prefix_component.as_str()); +/// } +/// _ => unreachable!(), +/// } +/// # } +/// ``` +/// +/// [`as_str`]: Utf8PrefixComponent::as_str +/// [`kind`]: Utf8PrefixComponent::kind +/// [`Prefix` variant]: Utf8Component::Prefix +#[repr(transparent)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Utf8PrefixComponent<'a>(PrefixComponent<'a>); + +impl<'a> Utf8PrefixComponent<'a> { + /// Returns the parsed prefix data. + /// + /// See [`Utf8Prefix`]'s documentation for more information on the different + /// kinds of prefixes. + #[must_use] + pub fn kind(&self) -> Utf8Prefix<'a> { + // SAFETY for all the below unsafe blocks: the path self was originally constructed from was + // UTF-8 so any parts of it are valid UTF-8 + match self.0.kind() { + Prefix::Verbatim(prefix) => Utf8Prefix::Verbatim(unsafe { str_assume_utf8(prefix) }), + Prefix::VerbatimUNC(server, share) => { + let server = unsafe { str_assume_utf8(server) }; + let share = unsafe { str_assume_utf8(share) }; + Utf8Prefix::VerbatimUNC(server, share) + } + Prefix::VerbatimDisk(drive) => Utf8Prefix::VerbatimDisk(drive), + Prefix::DeviceNS(prefix) => Utf8Prefix::DeviceNS(unsafe { str_assume_utf8(prefix) }), + Prefix::UNC(server, share) => { + let server = unsafe { str_assume_utf8(server) }; + let share = unsafe { str_assume_utf8(share) }; + Utf8Prefix::UNC(server, share) + } + Prefix::Disk(drive) => Utf8Prefix::Disk(drive), + } + } + + /// Returns the [`str`] slice for this prefix. + #[must_use] + #[inline] + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8PrefixComponent was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { str_assume_utf8(self.as_os_str()) } + } + + /// Returns the raw [`OsStr`] slice for this prefix. + #[must_use] + #[inline] + pub fn as_os_str(&self) -> &'a OsStr { + self.0.as_os_str() + } +} + +impl fmt::Debug for Utf8PrefixComponent<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Display for Utf8PrefixComponent<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +// --- +// read_dir_utf8 +// --- + +/// Iterator over the entries in a directory. +/// +/// This iterator is returned from [`Utf8Path::read_dir_utf8`] and will yield instances of +/// [io::Result]<[Utf8DirEntry]>. Through a [`Utf8DirEntry`] information like the entry's path +/// and possibly other metadata can be learned. +/// +/// The order in which this iterator returns entries is platform and filesystem +/// dependent. +/// +/// # Errors +/// +/// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent +/// IO error during iteration. +/// +/// If a directory entry is not UTF-8, an [`io::Error`] is returned with the +/// [`ErrorKind`](io::ErrorKind) set to [`InvalidData`][io::ErrorKind::InvalidData] +/// and the payload set to a [`FromPathBufError`]. +#[derive(Debug)] +pub struct ReadDirUtf8 { + inner: fs::ReadDir, +} + +impl Iterator for ReadDirUtf8 { + type Item = io::Result; + + fn next(&mut self) -> Option> { + self.inner + .next() + .map(|entry| entry.and_then(Utf8DirEntry::new)) + } +} + +/// Entries returned by the [`ReadDirUtf8`] iterator. +/// +/// An instance of [`Utf8DirEntry`] represents an entry inside of a directory on the filesystem. Each +/// entry can be inspected via methods to learn about the full path or possibly other metadata. +#[derive(Debug)] +pub struct Utf8DirEntry { + inner: fs::DirEntry, + path: Utf8PathBuf, +} + +impl Utf8DirEntry { + fn new(inner: fs::DirEntry) -> io::Result { + let path = inner + .path() + .try_into() + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + Ok(Self { inner, path }) + } + + /// Returns the full path to the file that this entry represents. + /// + /// The full path is created by joining the original path to `read_dir` + /// with the filename of this entry. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// fn main() -> std::io::Result<()> { + /// for entry in Utf8Path::new(".").read_dir_utf8()? { + /// let dir = entry?; + /// println!("{}", dir.path()); + /// } + /// Ok(()) + /// } + /// ``` + /// + /// This prints output like: + /// + /// ```text + /// ./whatever.txt + /// ./foo.html + /// ./hello_world.rs + /// ``` + /// + /// The exact text, of course, depends on what files you have in `.`. + #[inline] + pub fn path(&self) -> &Utf8Path { + &self.path + } + + /// Returns the metadata for the file that this entry points at. + /// + /// This function will not traverse symlinks if this entry points at a symlink. To traverse + /// symlinks use [`Utf8Path::metadata`] or [`fs::File::metadata`]. + /// + /// # Platform-specific behavior + /// + /// On Windows this function is cheap to call (no extra system calls + /// needed), but on Unix platforms this function is the equivalent of + /// calling `symlink_metadata` on the path. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `Utf8DirEntry`. + /// if let Ok(metadata) = entry.metadata() { + /// // Now let's show our entry's permissions! + /// println!("{}: {:?}", entry.path(), metadata.permissions()); + /// } else { + /// println!("Couldn't get metadata for {}", entry.path()); + /// } + /// } + /// } + /// } + /// ``` + #[inline] + pub fn metadata(&self) -> io::Result { + self.inner.metadata() + } + + /// Returns the file type for the file that this entry points at. + /// + /// This function will not traverse symlinks if this entry points at a + /// symlink. + /// + /// # Platform-specific behavior + /// + /// On Windows and most Unix platforms this function is free (no extra + /// system calls needed), but some Unix platforms may require the equivalent + /// call to `symlink_metadata` to learn about the target file type. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `DirEntry`. + /// if let Ok(file_type) = entry.file_type() { + /// // Now let's show our entry's file type! + /// println!("{}: {:?}", entry.path(), file_type); + /// } else { + /// println!("Couldn't get file type for {}", entry.path()); + /// } + /// } + /// } + /// } + /// ``` + #[inline] + pub fn file_type(&self) -> io::Result { + self.inner.file_type() + } + + /// Returns the bare file name of this directory entry without any other + /// leading path component. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `DirEntry`. + /// println!("{}", entry.file_name()); + /// } + /// } + /// } + /// ``` + pub fn file_name(&self) -> &str { + self.path + .file_name() + .expect("path created through DirEntry must have a filename") + } + + /// Returns the original [`fs::DirEntry`] within this [`Utf8DirEntry`]. + #[inline] + pub fn into_inner(self) -> fs::DirEntry { + self.inner + } + + /// Returns the full path to the file that this entry represents. + /// + /// This is analogous to [`path`], but moves ownership of the path. + /// + /// [`path`]: struct.Utf8DirEntry.html#method.path + #[inline] + #[must_use = "`self` will be dropped if the result is not used"] + pub fn into_path(self) -> Utf8PathBuf { + self.path + } +} + +impl From for Utf8PathBuf { + fn from(string: String) -> Utf8PathBuf { + Utf8PathBuf(string.into()) + } +} + +impl FromStr for Utf8PathBuf { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(Utf8PathBuf(s.into())) + } +} + +// --- +// From impls: borrowed -> borrowed +// --- + +impl<'a> From<&'a str> for &'a Utf8Path { + fn from(s: &'a str) -> &'a Utf8Path { + Utf8Path::new(s) + } +} + +// --- +// From impls: borrowed -> owned +// --- + +impl> From<&T> for Utf8PathBuf { + fn from(s: &T) -> Utf8PathBuf { + Utf8PathBuf::from(s.as_ref().to_owned()) + } +} + +impl> From<&T> for Box { + fn from(s: &T) -> Box { + Utf8PathBuf::from(s).into_boxed_path() + } +} + +impl From<&'_ Utf8Path> for Arc { + fn from(path: &Utf8Path) -> Arc { + let arc: Arc = Arc::from(AsRef::::as_ref(path)); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From<&'_ Utf8Path> for Rc { + fn from(path: &Utf8Path) -> Rc { + let rc: Rc = Rc::from(AsRef::::as_ref(path)); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Utf8Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Utf8Path> { + Cow::Borrowed(path) + } +} + +impl From<&'_ Utf8Path> for Box { + fn from(path: &Utf8Path) -> Box { + AsRef::::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Arc { + fn from(path: &Utf8Path) -> Arc { + AsRef::::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Rc { + fn from(path: &Utf8Path) -> Rc { + AsRef::::as_ref(path).into() + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Path> { + Cow::Borrowed(path.as_ref()) + } +} + +// --- +// From impls: owned -> owned +// --- + +impl From> for Utf8PathBuf { + fn from(path: Box) -> Utf8PathBuf { + path.into_path_buf() + } +} + +impl From for Box { + fn from(path: Utf8PathBuf) -> Box { + path.into_boxed_path() + } +} + +impl<'a> From> for Utf8PathBuf { + fn from(path: Cow<'a, Utf8Path>) -> Utf8PathBuf { + path.into_owned() + } +} + +impl From for String { + fn from(path: Utf8PathBuf) -> String { + path.into_string() + } +} + +impl From for OsString { + fn from(path: Utf8PathBuf) -> OsString { + path.into_os_string() + } +} + +impl<'a> From for Cow<'a, Utf8Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Utf8Path> { + Cow::Owned(path) + } +} + +impl From for Arc { + fn from(path: Utf8PathBuf) -> Arc { + let arc: Arc = Arc::from(path.0); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From for Rc { + fn from(path: Utf8PathBuf) -> Rc { + let rc: Rc = Rc::from(path.0); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl From for PathBuf { + fn from(path: Utf8PathBuf) -> PathBuf { + path.0 + } +} + +impl From for Box { + fn from(path: Utf8PathBuf) -> Box { + PathBuf::from(path).into_boxed_path() + } +} + +impl From for Arc { + fn from(path: Utf8PathBuf) -> Arc { + PathBuf::from(path).into() + } +} + +impl From for Rc { + fn from(path: Utf8PathBuf) -> Rc { + PathBuf::from(path).into() + } +} + +impl<'a> From for Cow<'a, Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Path> { + PathBuf::from(path).into() + } +} + +// --- +// TryFrom impls +// --- + +impl TryFrom for Utf8PathBuf { + type Error = FromPathBufError; + + fn try_from(path: PathBuf) -> Result { + Utf8PathBuf::from_path_buf(path).map_err(|path| FromPathBufError { + path, + error: FromPathError(()), + }) + } +} + +impl TryFrom for Utf8PathBuf { + type Error = FromOsStringError; + + fn try_from(os_string: OsString) -> Result { + Utf8PathBuf::from_os_string(os_string).map_err(|os_string| FromOsStringError { + os_string, + error: FromOsStrError(()), + }) + } +} + +/// Converts a [`Path`] to a [`Utf8Path`]. +/// +/// Returns [`FromPathError`] if the path is not valid UTF-8. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// use std::convert::TryFrom; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::Path; +/// +/// let unicode_path = Path::new("/valid/unicode"); +/// <&Utf8Path>::try_from(unicode_path).expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = Path::new(non_unicode_str); +/// # #[cfg(unix)] +/// assert!(<&Utf8Path>::try_from(non_unicode_path).is_err(), "non-Unicode path failed"); +/// ``` +impl<'a> TryFrom<&'a Path> for &'a Utf8Path { + type Error = FromPathError; + + fn try_from(path: &'a Path) -> Result<&'a Utf8Path, Self::Error> { + Utf8Path::from_path(path).ok_or(FromPathError(())) + } +} + +/// Converts an [`OsStr`] to a [`Utf8Path`]. +/// +/// Returns the original [`OsStr`] if it is not valid UTF-8. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// use std::convert::TryFrom; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::Path; +/// +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// assert!(<&Utf8Path>::try_from(non_unicode_str).is_err(), "non-Unicode string path failed"); +/// ``` +impl<'a> TryFrom<&'a OsStr> for &'a Utf8Path { + type Error = FromOsStrError; + + fn try_from(os_str: &'a OsStr) -> Result<&'a Utf8Path, Self::Error> { + Utf8Path::from_os_str(os_str).ok_or(FromOsStrError(())) + } +} + +/// A possible error value while converting a [`PathBuf`] to a [`Utf8PathBuf`]. +/// +/// Produced by the [`TryFrom<&PathBuf>`][tryfrom] implementation for [`Utf8PathBuf`]. +/// +/// [tryfrom]: Utf8PathBuf#impl-TryFrom-for-Utf8PathBuf +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8PathBuf, FromPathBufError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::PathBuf; +/// +/// let unicode_path = PathBuf::from("/valid/unicode"); +/// let utf8_path_buf: Utf8PathBuf = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = PathBuf::from(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathBufError = Utf8PathBuf::try_from(non_unicode_path.clone()) +/// .expect_err("non-Unicode path failed"); +/// # #[cfg(unix)] +/// assert_eq!(err.as_path(), &non_unicode_path); +/// # #[cfg(unix)] +/// assert_eq!(err.into_path_buf(), non_unicode_path); +/// ``` +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FromPathBufError { + path: PathBuf, + error: FromPathError, +} + +impl FromPathBufError { + /// Returns the [`Path`] slice that was attempted to be converted to [`Utf8PathBuf`]. + #[inline] + pub fn as_path(&self) -> &Path { + &self.path + } + + /// Returns the [`PathBuf`] that was attempted to be converted to [`Utf8PathBuf`]. + #[inline] + pub fn into_path_buf(self) -> PathBuf { + self.path + } + + /// Fetches a [`FromPathError`] for more about the conversion failure. + /// + /// At the moment this struct does not contain any additional information, but is provided for + /// completeness. + #[inline] + pub fn from_path_error(&self) -> FromPathError { + self.error + } + + /// Converts self into a [`std::io::Error`] with kind + /// [`InvalidData`](io::ErrorKind::InvalidData). + /// + /// Many users of [`FromPathBufError`] will want to convert it into an [`io::Error`]. This is a + /// convenience method to do that. + pub fn into_io_error(self) -> io::Error { + // NOTE: we don't currently implement `From for io::Error` because we want + // to ensure the user actually desires that conversion. + io::Error::new(io::ErrorKind::InvalidData, self) + } +} + +impl fmt::Display for FromPathBufError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "PathBuf contains invalid UTF-8: {}", self.path.display()) + } +} + +impl error::Error for FromPathBufError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(&self.error) + } +} + +/// A possible error value while converting a [`Path`] to a [`Utf8Path`]. +/// +/// Produced by the [`TryFrom<&Path>`][tryfrom] implementation for [`&Utf8Path`](Utf8Path). +/// +/// [tryfrom]: Utf8Path#impl-TryFrom<%26Path>-for-%26Utf8Path +/// +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Path, FromPathError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::Path; +/// +/// let unicode_path = Path::new("/valid/unicode"); +/// let utf8_path: &Utf8Path = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = Path::new(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathError = <&Utf8Path>::try_from(non_unicode_path) +/// .expect_err("non-Unicode path failed"); +/// ``` +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct FromPathError(()); + +impl FromPathError { + /// Converts self into a [`std::io::Error`] with kind + /// [`InvalidData`](io::ErrorKind::InvalidData). + /// + /// Many users of [`FromPathError`] will want to convert it into an [`io::Error`]. This is a + /// convenience method to do that. + pub fn into_io_error(self) -> io::Error { + // NOTE: we don't currently implement `From for io::Error` because we want + // to ensure the user actually desires that conversion. + io::Error::new(io::ErrorKind::InvalidData, self) + } +} + +impl fmt::Display for FromPathError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Path contains invalid UTF-8") + } +} + +impl error::Error for FromPathError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + None + } +} + +/// A possible error value while converting a [`OsString`] to a [`Utf8PathBuf`]. +/// +/// Produced by the `TryFrom` implementation for [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(osstring_from_str)] { +/// use camino::{Utf8PathBuf, FromOsStringError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// use std::str::FromStr; +/// use std::ffi::OsString; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// +/// let unicode_string = OsString::from_str("/valid/unicode").unwrap(); +/// let utf8_path_buf: Utf8PathBuf = unicode_string.try_into() +/// .expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_string = OsStr::from_bytes(b"\xFF\xFF\xFF").to_owned(); +/// # #[cfg(unix)] +/// let err: FromOsStringError = Utf8PathBuf::try_from(non_unicode_string.clone()) +/// .expect_err("non-Unicode path failed"); +/// # #[cfg(unix)] +/// assert_eq!(err.as_os_str(), &non_unicode_string); +/// # #[cfg(unix)] +/// assert_eq!(err.into_os_string(), non_unicode_string); +/// # } +/// ``` +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FromOsStringError { + os_string: OsString, + error: FromOsStrError, +} + +impl FromOsStringError { + /// Returns the [`OsStr`] slice that was attempted to be converted to [`Utf8PathBuf`]. + #[inline] + pub fn as_os_str(&self) -> &OsStr { + &self.os_string + } + + /// Returns the [`OsString`] that was attempted to be converted to [`Utf8PathBuf`]. + #[inline] + pub fn into_os_string(self) -> OsString { + self.os_string + } + + /// Fetches a [`FromOsStrError`] for more about the conversion failure. + /// + /// At the moment this struct does not contain any additional information, but is provided for + /// completeness. + #[inline] + pub fn from_os_str_error(&self) -> FromOsStrError { + self.error + } + + /// Converts self into a [`std::io::Error`] with kind + /// [`InvalidData`](io::ErrorKind::InvalidData). + /// + /// Many users of [`FromOsStringError`] will want to convert it into an [`io::Error`]. + /// This is a convenience method to do that. + pub fn into_io_error(self) -> io::Error { + // NOTE: we don't currently implement `From for io::Error` + // because we want to ensure the user actually desires that conversion. + io::Error::new(io::ErrorKind::InvalidData, self) + } +} + +impl fmt::Display for FromOsStringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "OsString contains invalid UTF-8: {}", + // self.os_string.display() // this item is stable since `1.87.0` + PathBuf::from(&self.os_string).display() // msrv hack + ) + } +} + +impl error::Error for FromOsStringError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(&self.error) + } +} + +/// A possible error value while converting a [`OsStr`] to a [`Utf8Path`]. +/// +/// Produced by the `TryFrom<&OsStr>` implementation for [`&Utf8Path`](Utf8Path). +/// +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Path, FromOsStrError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// +/// let unicode_str = OsStr::new("/valid/unicode"); +/// let utf8_path: &Utf8Path = unicode_str.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let err: FromOsStrError = <&Utf8Path>::try_from(non_unicode_str) +/// .expect_err("non-Unicode path failed"); +/// ``` +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct FromOsStrError(()); + +impl FromOsStrError { + /// Converts self into a [`std::io::Error`] with kind + /// [`InvalidData`](io::ErrorKind::InvalidData). + /// + /// Many users of [`FromOsStrError`] will want to convert it into an [`io::Error`]. This is a + /// convenience method to do that. + pub fn into_io_error(self) -> io::Error { + // NOTE: we don't currently implement `From for io::Error` + // because we want to ensure the user actually desires that conversion. + io::Error::new(io::ErrorKind::InvalidData, self) + } +} + +impl fmt::Display for FromOsStrError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "OsStr contains invalid UTF-8") + } +} + +impl error::Error for FromOsStrError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + None + } +} + +// --- +// AsRef impls +// --- + +impl AsRef for Utf8Path { + #[inline] + fn as_ref(&self) -> &Utf8Path { + self + } +} + +impl AsRef for Utf8PathBuf { + #[inline] + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef for str { + #[inline] + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef for String { + #[inline] + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef for Utf8Path { + #[inline] + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl AsRef for Utf8PathBuf { + #[inline] + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl AsRef for Utf8Path { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef for Utf8PathBuf { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef for Utf8Path { + #[inline] + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +impl AsRef for Utf8PathBuf { + #[inline] + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +// --- +// Borrow and ToOwned +// --- + +impl Borrow for Utf8PathBuf { + #[inline] + fn borrow(&self) -> &Utf8Path { + self.as_path() + } +} + +impl ToOwned for Utf8Path { + type Owned = Utf8PathBuf; + + #[inline] + fn to_owned(&self) -> Utf8PathBuf { + self.to_path_buf() + } +} + +impl> std::iter::FromIterator

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + for_both!(self, inner => inner.find(predicate)) + } + + fn find_map(&mut self, f: F) -> Option + where + F: FnMut(Self::Item) -> Option, + { + for_both!(self, inner => inner.find_map(f)) + } + + fn position

(&mut self, predicate: P) -> Option + where + P: FnMut(Self::Item) -> bool, + { + for_both!(self, inner => inner.position(predicate)) + } +} + +impl DoubleEndedIterator for Either +where + L: DoubleEndedIterator, + R: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + for_both!(self, inner => inner.next_back()) + } + + fn nth_back(&mut self, n: usize) -> Option { + for_both!(self, inner => inner.nth_back(n)) + } + + fn rfold(self, init: Acc, f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + for_both!(self, inner => inner.rfold(init, f)) + } + + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + for_both!(self, inner => inner.rfind(predicate)) + } +} + +impl ExactSizeIterator for Either +where + L: ExactSizeIterator, + R: ExactSizeIterator, +{ + fn len(&self) -> usize { + for_both!(self, inner => inner.len()) + } +} + +impl iter::FusedIterator for Either +where + L: iter::FusedIterator, + R: iter::FusedIterator, +{ +} + +impl Iterator for IterEither +where + L: Iterator, + R: Iterator, +{ + type Item = Either; + + fn next(&mut self) -> Option { + Some(map_both!(self.inner, ref mut inner => inner.next()?)) + } + + fn size_hint(&self) -> (usize, Option) { + for_both!(self.inner, ref inner => inner.size_hint()) + } + + fn fold(self, init: Acc, f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + wrap_either!(self.inner => .fold(init, f)) + } + + fn for_each(self, f: F) + where + F: FnMut(Self::Item), + { + wrap_either!(self.inner => .for_each(f)) + } + + fn count(self) -> usize { + for_both!(self.inner, inner => inner.count()) + } + + fn last(self) -> Option { + Some(map_both!(self.inner, inner => inner.last()?)) + } + + fn nth(&mut self, n: usize) -> Option { + Some(map_both!(self.inner, ref mut inner => inner.nth(n)?)) + } + + fn collect(self) -> B + where + B: iter::FromIterator, + { + wrap_either!(self.inner => .collect()) + } + + fn partition(self, f: F) -> (B, B) + where + B: Default + Extend, + F: FnMut(&Self::Item) -> bool, + { + wrap_either!(self.inner => .partition(f)) + } + + fn all(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + wrap_either!(&mut self.inner => .all(f)) + } + + fn any(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + wrap_either!(&mut self.inner => .any(f)) + } + + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + wrap_either!(&mut self.inner => .find(predicate)) + } + + fn find_map(&mut self, f: F) -> Option + where + F: FnMut(Self::Item) -> Option, + { + wrap_either!(&mut self.inner => .find_map(f)) + } + + fn position

(&mut self, predicate: P) -> Option + where + P: FnMut(Self::Item) -> bool, + { + wrap_either!(&mut self.inner => .position(predicate)) + } +} + +impl DoubleEndedIterator for IterEither +where + L: DoubleEndedIterator, + R: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + Some(map_both!(self.inner, ref mut inner => inner.next_back()?)) + } + + fn nth_back(&mut self, n: usize) -> Option { + Some(map_both!(self.inner, ref mut inner => inner.nth_back(n)?)) + } + + fn rfold(self, init: Acc, f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + wrap_either!(self.inner => .rfold(init, f)) + } + + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + wrap_either!(&mut self.inner => .rfind(predicate)) + } +} + +impl ExactSizeIterator for IterEither +where + L: ExactSizeIterator, + R: ExactSizeIterator, +{ + fn len(&self) -> usize { + for_both!(self.inner, ref inner => inner.len()) + } +} + +impl iter::FusedIterator for IterEither +where + L: iter::FusedIterator, + R: iter::FusedIterator, +{ +} diff --git a/anneal/v2/vendor/either/src/lib.rs b/anneal/v2/vendor/either/src/lib.rs new file mode 100644 index 0000000000..ec16cee001 --- /dev/null +++ b/anneal/v2/vendor/either/src/lib.rs @@ -0,0 +1,1826 @@ +//! The enum [`Either`] with variants `Left` and `Right` is a general purpose +//! sum type with two cases. +//! +//! [`Either`]: enum.Either.html +//! +//! **Crate features:** +//! +//! * `"std"` +//! Enabled by default. Disable to make the library `#![no_std]`. +//! +//! * `"serde"` +//! Disabled by default. Enable to `#[derive(Serialize, Deserialize)]` for `Either` +//! + +#![doc(html_root_url = "https://docs.rs/either/1/")] +#![no_std] + +#[cfg(any(test, feature = "std"))] +extern crate std; + +#[cfg(feature = "serde")] +pub mod serde_untagged; + +#[cfg(feature = "serde")] +pub mod serde_untagged_optional; + +use core::convert::{AsMut, AsRef}; +use core::fmt; +use core::future::Future; +use core::ops::Deref; +use core::ops::DerefMut; +use core::pin::Pin; + +#[cfg(any(test, feature = "std"))] +use std::error::Error; +#[cfg(any(test, feature = "std"))] +use std::io::{self, BufRead, Read, Seek, SeekFrom, Write}; + +pub use crate::Either::{Left, Right}; + +/// The enum `Either` with variants `Left` and `Right` is a general purpose +/// sum type with two cases. +/// +/// The `Either` type is symmetric and treats its variants the same way, without +/// preference. +/// (For representing success or error, use the regular `Result` enum instead.) +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Either { + /// A value of type `L`. + Left(L), + /// A value of type `R`. + Right(R), +} + +/// Evaluate the provided expression for both [`Either::Left`] and [`Either::Right`]. +/// +/// This macro is useful in cases where both sides of [`Either`] can be interacted with +/// in the same way even though the don't share the same type. +/// +/// Syntax: +/// +/// - `either::for_both!(` *expression* `,` *pattern* `=>` *expression* `)` +/// - `either::for_both!(` *ident* `=>` *expression* `)` +/// +/// Unlike [`map_both!`], this macro converges both variants to the type returned by the expression. +/// +/// # Example +/// +/// ``` +/// use either::Either; +/// +/// fn length(owned_or_borrowed: Either) -> usize { +/// either::for_both!(owned_or_borrowed, s => s.len()) +/// } +/// +/// fn main() { +/// let borrowed = Either::Right("Hello world!"); +/// let owned = Either::Left("Hello world!".to_owned()); +/// +/// assert_eq!(length(borrowed), 12); +/// assert_eq!(length(owned), 12); +/// } +/// ``` +/// +/// ``` +/// use either::Either; +/// +/// fn length(s: Either>) -> usize { +/// either::for_both!(s => s.len()) +/// } +/// +/// fn main() { +/// let string = Either::Left("Hello world!".to_owned()); +/// let bytes = Either::Right(b"Hello world!".to_vec()); +/// +/// assert_eq!(length(string), 12); +/// assert_eq!(length(bytes), 12); +/// } +/// ``` +#[macro_export] +macro_rules! for_both { + ($value:expr, $pattern:pat => $result:expr) => { + match $value { + $crate::Either::Left($pattern) => $result, + $crate::Either::Right($pattern) => $result, + } + }; + ($name:ident => $result:expr) => { + match $name { + $crate::Either::Left($name) => $result, + $crate::Either::Right($name) => $result, + } + }; +} + +/// Evaluate the provided expression for both [`Either::Left`] and [`Either::Right`], +/// returning an [`Either`] with the results. +/// +/// This macro is useful in cases where both sides of [`Either`] can be interacted with +/// in the same way even though the don't share the same type. +/// +/// Syntax: `either::map_both!(` *expression* `,` *pattern* `=>` *expression* `)` +/// +/// Unlike [`for_both!`], this macro returns an [`Either`] with the results of the expressions. +/// +/// # Example +/// +/// ``` +/// use either::Either; +/// +/// struct Wrapper(T); +/// +/// fn wrap( +/// owned_or_borrowed: Either, +/// ) -> Either, Wrapper<&'static str>> { +/// either::map_both!(owned_or_borrowed, s => Wrapper(s)) +/// } +/// ``` +/// +/// ``` +/// use either::Either; +/// +/// fn widen(x: Either) -> Either { +/// either::map_both!(x => x.into()) +/// } +/// ``` +#[macro_export] +macro_rules! map_both { + ($value:expr, $pattern:pat => $result:expr) => { + match $value { + $crate::Either::Left($pattern) => $crate::Either::Left($result), + $crate::Either::Right($pattern) => $crate::Either::Right($result), + } + }; + ($name:ident => $result:expr) => { + match $name { + $crate::Either::Left($name) => $crate::Either::Left($result), + $crate::Either::Right($name) => $crate::Either::Right($result), + } + }; +} + +/// Macro for unwrapping the left side of an [`Either`], which fails early +/// with the opposite side. Can only be used in functions that return +/// `Either` because of the early return of `Right` that it provides. +/// +/// See also [`try_right!`] for its dual, which applies the same just to the +/// right side. +/// +/// # Example +/// +/// ``` +/// use either::{Either, Left, Right}; +/// +/// fn twice(wrapper: Either) -> Either { +/// let value = either::try_left!(wrapper); +/// Left(value * 2) +/// } +/// +/// fn main() { +/// assert_eq!(twice(Left(2)), Left(4)); +/// assert_eq!(twice(Right("ups")), Right("ups")); +/// } +/// ``` +#[macro_export] +macro_rules! try_left { + ($expr:expr) => { + match $expr { + $crate::Left(val) => val, + $crate::Right(err) => return $crate::Right(::core::convert::From::from(err)), + } + }; +} + +/// Dual to [`try_left!`], see its documentation for more information. +#[macro_export] +macro_rules! try_right { + ($expr:expr) => { + match $expr { + $crate::Left(err) => return $crate::Left(::core::convert::From::from(err)), + $crate::Right(val) => val, + } + }; +} + +mod iterator; +pub use self::iterator::IterEither; + +mod into_either; +pub use self::into_either::IntoEither; + +impl Clone for Either { + fn clone(&self) -> Self { + match self { + Left(inner) => Left(inner.clone()), + Right(inner) => Right(inner.clone()), + } + } + + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (Left(dest), Left(source)) => dest.clone_from(source), + (Right(dest), Right(source)) => dest.clone_from(source), + (dest, source) => *dest = source.clone(), + } + } +} + +impl Either { + /// Return true if the value is the `Left` variant. + /// + /// ``` + /// use either::*; + /// + /// let values = [Left(1), Right("the right value")]; + /// assert_eq!(values[0].is_left(), true); + /// assert_eq!(values[1].is_left(), false); + /// ``` + pub fn is_left(&self) -> bool { + match self { + Left(_) => true, + Right(_) => false, + } + } + + /// Returns `true` if the value is [`Left`] and the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let left0: Either = Left(0); + /// let left2: Either = Left(2); + /// let right: Either = Right(2); + /// + /// assert_eq!(left2.is_left_and(|n| n > 1), true); + /// assert_eq!(left0.is_left_and(|n| n > 1), false); + /// assert_eq!(right.is_left_and(|n| n > 1), false); + /// ``` + pub fn is_left_and(self, f: F) -> bool + where + F: FnOnce(L) -> bool, + { + match self { + Left(left) => f(left), + Right(_) => false, + } + } + + /// Returns `true` if the value is [`Right`] and the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let right0: Either = Right(0); + /// let right2: Either = Right(2); + /// let left: Either = Left(2); + /// + /// assert_eq!(right2.is_right_and(|n| n > 1), true); + /// assert_eq!(right0.is_right_and(|n| n > 1), false); + /// assert_eq!(left.is_right_and(|n| n > 1), false); + /// ``` + pub fn is_right_and(self, f: F) -> bool + where + F: FnOnce(R) -> bool, + { + match self { + Left(_) => false, + Right(right) => f(right), + } + } + + /// Return true if the value is the `Right` variant. + /// + /// ``` + /// use either::*; + /// + /// let values = [Left(1), Right("the right value")]; + /// assert_eq!(values[0].is_right(), false); + /// assert_eq!(values[1].is_right(), true); + /// ``` + pub fn is_right(&self) -> bool { + !self.is_left() + } + + /// Convert the left side of `Either` to an `Option`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, ()> = Left("some value"); + /// assert_eq!(left.left(), Some("some value")); + /// + /// let right: Either<(), _> = Right(321); + /// assert_eq!(right.left(), None); + /// ``` + pub fn left(self) -> Option { + match self { + Left(l) => Some(l), + Right(_) => None, + } + } + + /// Convert the right side of `Either` to an `Option`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, ()> = Left("some value"); + /// assert_eq!(left.right(), None); + /// + /// let right: Either<(), _> = Right(321); + /// assert_eq!(right.right(), Some(321)); + /// ``` + pub fn right(self) -> Option { + match self { + Left(_) => None, + Right(r) => Some(r), + } + } + + /// Convert `&Either` to `Either<&L, &R>`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, ()> = Left("some value"); + /// assert_eq!(left.as_ref(), Left(&"some value")); + /// + /// let right: Either<(), _> = Right("some value"); + /// assert_eq!(right.as_ref(), Right(&"some value")); + /// ``` + pub fn as_ref(&self) -> Either<&L, &R> { + map_both!(self, inner => inner) + } + + /// Convert `&mut Either` to `Either<&mut L, &mut R>`. + /// + /// ``` + /// use either::*; + /// + /// fn mutate_left(value: &mut Either) { + /// if let Some(l) = value.as_mut().left() { + /// *l = 999; + /// } + /// } + /// + /// let mut left = Left(123); + /// let mut right = Right(123); + /// mutate_left(&mut left); + /// mutate_left(&mut right); + /// assert_eq!(left, Left(999)); + /// assert_eq!(right, Right(123)); + /// ``` + pub fn as_mut(&mut self) -> Either<&mut L, &mut R> { + map_both!(self, inner => inner) + } + + /// Convert `Pin<&Either>` to `Either, Pin<&R>>`, + /// pinned projections of the inner variants. + pub fn as_pin_ref(self: Pin<&Self>) -> Either, Pin<&R>> { + // SAFETY: We can use `new_unchecked` because the `inner` parts are + // guaranteed to be pinned, as they come from `self` which is pinned. + unsafe { map_both!(Pin::get_ref(self), inner => Pin::new_unchecked(inner)) } + } + + /// Convert `Pin<&mut Either>` to `Either, Pin<&mut R>>`, + /// pinned projections of the inner variants. + pub fn as_pin_mut(self: Pin<&mut Self>) -> Either, Pin<&mut R>> { + // SAFETY: `get_unchecked_mut` is fine because we don't move anything. + // We can use `new_unchecked` because the `inner` parts are guaranteed + // to be pinned, as they come from `self` which is pinned, and we never + // offer an unpinned `&mut L` or `&mut R` through `Pin<&mut Self>`. We + // also don't have an implementation of `Drop`, nor manual `Unpin`. + unsafe { map_both!(Pin::get_unchecked_mut(self), inner => Pin::new_unchecked(inner)) } + } + + /// Convert `Either` to `Either`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, ()> = Left(123); + /// assert_eq!(left.flip(), Right(123)); + /// + /// let right: Either<(), _> = Right("some value"); + /// assert_eq!(right.flip(), Left("some value")); + /// ``` + pub fn flip(self) -> Either { + match self { + Left(l) => Right(l), + Right(r) => Left(r), + } + } + + /// Apply the function `f` on the value in the `Left` variant if it is present rewrapping the + /// result in `Left`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.map_left(|x| x * 2), Left(246)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.map_left(|x| x * 2), Right(123)); + /// ``` + pub fn map_left(self, f: F) -> Either + where + F: FnOnce(L) -> M, + { + match self { + Left(l) => Left(f(l)), + Right(r) => Right(r), + } + } + + /// Apply the function `f` on the value in the `Right` variant if it is present rewrapping the + /// result in `Right`. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.map_right(|x| x * 2), Left(123)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.map_right(|x| x * 2), Right(246)); + /// ``` + pub fn map_right(self, f: F) -> Either + where + F: FnOnce(R) -> S, + { + match self { + Left(l) => Left(l), + Right(r) => Right(f(r)), + } + } + + /// Returns the provided default (if [`Right`]), or + /// applies a function to the contained value (if [`Left`]). + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let x: Either<_, i32> = Left(123); + /// assert_eq!(x.map_left_or(0, |n| n * 2), 246); + /// + /// let x: Either = Right(123); + /// assert_eq!(x.map_left_or(0, |n| n * 2), 0); + /// ``` + pub fn map_left_or(self, default: S, f: F) -> S + where + F: FnOnce(L) -> S, + { + match self { + Left(left) => f(left), + Right(_) => default, + } + } + + /// Returns the provided default (if [`Left`]), or + /// applies a function to the contained value (if [`Right`]). + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let x: Either<_, i32> = Left(123); + /// assert_eq!(x.map_right_or(0, |n| n * 2), 0); + /// + /// let x: Either = Right(123); + /// assert_eq!(x.map_right_or(0, |n| n * 2), 246); + /// ``` + pub fn map_right_or(self, default: S, f: F) -> S + where + F: FnOnce(R) -> S, + { + match self { + Left(_) => default, + Right(right) => f(right), + } + } + + /// Apply the functions `f` and `g` to the `Left` and `Right` variants + /// respectively. This is equivalent to + /// [bimap](https://hackage.haskell.org/package/bifunctors-5/docs/Data-Bifunctor.html) + /// in functional programming. + /// + /// ``` + /// use either::*; + /// + /// let f = |s: String| s.len(); + /// let g = |u: u8| u.to_string(); + /// + /// let left: Either = Left("loopy".into()); + /// assert_eq!(left.map_either(f, g), Left(5)); + /// + /// let right: Either = Right(42); + /// assert_eq!(right.map_either(f, g), Right("42".into())); + /// ``` + pub fn map_either(self, f: F, g: G) -> Either + where + F: FnOnce(L) -> M, + G: FnOnce(R) -> S, + { + match self { + Left(l) => Left(f(l)), + Right(r) => Right(g(r)), + } + } + + /// Similar to [`map_either`][Self::map_either], with an added context `ctx` accessible to + /// both functions. + /// + /// ``` + /// use either::*; + /// + /// let mut sum = 0; + /// + /// // Both closures want to update the same value, so pass it as context. + /// let mut f = |sum: &mut usize, s: String| { *sum += s.len(); s.to_uppercase() }; + /// let mut g = |sum: &mut usize, u: usize| { *sum += u; u.to_string() }; + /// + /// let left: Either = Left("loopy".into()); + /// assert_eq!(left.map_either_with(&mut sum, &mut f, &mut g), Left("LOOPY".into())); + /// + /// let right: Either = Right(42); + /// assert_eq!(right.map_either_with(&mut sum, &mut f, &mut g), Right("42".into())); + /// + /// assert_eq!(sum, 47); + /// ``` + pub fn map_either_with(self, ctx: Ctx, f: F, g: G) -> Either + where + F: FnOnce(Ctx, L) -> M, + G: FnOnce(Ctx, R) -> S, + { + match self { + Left(l) => Left(f(ctx, l)), + Right(r) => Right(g(ctx, r)), + } + } + + /// Apply one of two functions depending on contents, unifying their result. If the value is + /// `Left(L)` then the first function `f` is applied; if it is `Right(R)` then the second + /// function `g` is applied. + /// + /// ``` + /// use either::*; + /// + /// fn square(n: u32) -> i32 { (n * n) as i32 } + /// fn negate(n: i32) -> i32 { -n } + /// + /// let left: Either = Left(4); + /// assert_eq!(left.either(square, negate), 16); + /// + /// let right: Either = Right(-4); + /// assert_eq!(right.either(square, negate), 4); + /// ``` + pub fn either(self, f: F, g: G) -> T + where + F: FnOnce(L) -> T, + G: FnOnce(R) -> T, + { + match self { + Left(l) => f(l), + Right(r) => g(r), + } + } + + /// Like [`either`][Self::either], but provide some context to whichever of the + /// functions ends up being called. + /// + /// ``` + /// // In this example, the context is a mutable reference + /// use either::*; + /// + /// let mut result = Vec::new(); + /// + /// let values = vec![Left(2), Right(2.7)]; + /// + /// for value in values { + /// value.either_with(&mut result, + /// |ctx, integer| ctx.push(integer), + /// |ctx, real| ctx.push(f64::round(real) as i32)); + /// } + /// + /// assert_eq!(result, vec![2, 3]); + /// ``` + pub fn either_with(self, ctx: Ctx, f: F, g: G) -> T + where + F: FnOnce(Ctx, L) -> T, + G: FnOnce(Ctx, R) -> T, + { + match self { + Left(l) => f(ctx, l), + Right(r) => g(ctx, r), + } + } + + /// Returns `other` if the value is [`Left`], otherwise returns the [`Right`] value of `self`. + /// + /// Arguments passed to `left_and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`left_and_then`], which is + /// lazily evaluated. + /// + /// [`left_and_then`]: Either::left_and_then + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.left_and::<()>(Right(246)), Right(246)); + /// assert_eq!(left.left_and(Left(246)), Left(246)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.left_and::<()>(Right(246)), Right(123)); + /// assert_eq!(right.left_and(Left(246)), Right(123)); + /// ``` + pub fn left_and(self, other: Either) -> Either { + match self { + Left(_) => other, + Right(r) => Right(r), + } + } + + /// Returns `other` if the value is [`Right`], otherwise returns the [`Left`] value of `self`. + /// + /// Arguments passed to `right_and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`right_and_then`], which is + /// lazily evaluated. + /// + /// [`right_and_then`]: Either::right_and_then + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.right_and(Right(246)), Left(123)); + /// assert_eq!(left.right_and::<()>(Left(246)), Left(123)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.right_and(Right(246)), Right(246)); + /// assert_eq!(right.right_and::<()>(Left(246)), Left(246)); + /// ``` + pub fn right_and(self, other: Either) -> Either { + match self { + Left(l) => Left(l), + Right(_) => other, + } + } + + /// Apply the function `f` on the value in the `Left` variant if it is present. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.left_and_then::<_,()>(|x| Right(x * 2)), Right(246)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.left_and_then(|x| Right::<(), _>(x * 2)), Right(123)); + /// ``` + pub fn left_and_then(self, f: F) -> Either + where + F: FnOnce(L) -> Either, + { + match self { + Left(l) => f(l), + Right(r) => Right(r), + } + } + + /// Apply the function `f` on the value in the `Right` variant if it is present. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.right_and_then(|x| Right(x * 2)), Left(123)); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.right_and_then(|x| Right(x * 2)), Right(246)); + /// ``` + pub fn right_and_then(self, f: F) -> Either + where + F: FnOnce(R) -> Either, + { + match self { + Left(l) => Left(l), + Right(r) => f(r), + } + } + + /// Convert the inner value to an iterator. + /// + /// This requires the `Left` and `Right` iterators to have the same item type. + /// See [`factor_into_iter`][Either::factor_into_iter] to iterate different types. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, Vec> = Left(vec![1, 2, 3, 4, 5]); + /// let mut right: Either, _> = Right(vec![]); + /// right.extend(left.into_iter()); + /// assert_eq!(right, Right(vec![1, 2, 3, 4, 5])); + /// ``` + #[allow(clippy::should_implement_trait)] + pub fn into_iter(self) -> Either + where + L: IntoIterator, + R: IntoIterator, + { + map_both!(self, inner => inner.into_iter()) + } + + /// Borrow the inner value as an iterator. + /// + /// This requires the `Left` and `Right` iterators to have the same item type. + /// See [`factor_iter`][Either::factor_iter] to iterate different types. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, &[u32]> = Left(vec![2, 3]); + /// let mut right: Either, _> = Right(&[4, 5][..]); + /// let mut all = vec![1]; + /// all.extend(left.iter()); + /// all.extend(right.iter()); + /// assert_eq!(all, vec![1, 2, 3, 4, 5]); + /// ``` + pub fn iter(&self) -> Either<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter> + where + for<'a> &'a L: IntoIterator, + for<'a> &'a R: IntoIterator::Item>, + { + map_both!(self, inner => inner.into_iter()) + } + + /// Mutably borrow the inner value as an iterator. + /// + /// This requires the `Left` and `Right` iterators to have the same item type. + /// See [`factor_iter_mut`][Either::factor_iter_mut] to iterate different types. + /// + /// ``` + /// use either::*; + /// + /// let mut left: Either<_, &mut [u32]> = Left(vec![2, 3]); + /// for l in left.iter_mut() { + /// *l *= *l + /// } + /// assert_eq!(left, Left(vec![4, 9])); + /// + /// let mut inner = [4, 5]; + /// let mut right: Either, _> = Right(&mut inner[..]); + /// for r in right.iter_mut() { + /// *r *= *r + /// } + /// assert_eq!(inner, [16, 25]); + /// ``` + pub fn iter_mut( + &mut self, + ) -> Either<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter> + where + for<'a> &'a mut L: IntoIterator, + for<'a> &'a mut R: IntoIterator::Item>, + { + map_both!(self, inner => inner.into_iter()) + } + + /// Converts an `Either` of `Iterator`s to be an `Iterator` of `Either`s + /// + /// Unlike [`into_iter`][Either::into_iter], this does not require the + /// `Left` and `Right` iterators to have the same item type. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Vec> = Left(&["hello"]); + /// assert_eq!(left.factor_into_iter().next(), Some(Left(&"hello"))); + /// + /// let right: Either<&[&str], _> = Right(vec![0, 1]); + /// assert_eq!(right.factor_into_iter().collect::>(), vec![Right(0), Right(1)]); + /// + /// ``` + pub fn factor_into_iter(self) -> IterEither + where + L: IntoIterator, + R: IntoIterator, + { + IterEither::new(map_both!(self, inner => inner.into_iter())) + } + + /// Borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s + /// + /// Unlike [`iter`][Either::iter], this does not require the + /// `Left` and `Right` iterators to have the same item type. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Vec> = Left(["hello"]); + /// assert_eq!(left.factor_iter().next(), Some(Left(&"hello"))); + /// + /// let right: Either<[&str; 2], _> = Right(vec![0, 1]); + /// assert_eq!(right.factor_iter().collect::>(), vec![Right(&0), Right(&1)]); + /// + /// ``` + pub fn factor_iter( + &self, + ) -> IterEither<<&L as IntoIterator>::IntoIter, <&R as IntoIterator>::IntoIter> + where + for<'a> &'a L: IntoIterator, + for<'a> &'a R: IntoIterator, + { + IterEither::new(map_both!(self, inner => inner.into_iter())) + } + + /// Mutably borrows an `Either` of `Iterator`s to be an `Iterator` of `Either`s + /// + /// Unlike [`iter_mut`][Either::iter_mut], this does not require the + /// `Left` and `Right` iterators to have the same item type. + /// + /// ``` + /// use either::*; + /// let mut left: Either<_, Vec> = Left(["hello"]); + /// left.factor_iter_mut().for_each(|x| *x.unwrap_left() = "goodbye"); + /// assert_eq!(left, Left(["goodbye"])); + /// + /// let mut right: Either<[&str; 2], _> = Right(vec![0, 1, 2]); + /// right.factor_iter_mut().for_each(|x| if let Right(r) = x { *r = -*r; }); + /// assert_eq!(right, Right(vec![0, -1, -2])); + /// + /// ``` + pub fn factor_iter_mut( + &mut self, + ) -> IterEither<<&mut L as IntoIterator>::IntoIter, <&mut R as IntoIterator>::IntoIter> + where + for<'a> &'a mut L: IntoIterator, + for<'a> &'a mut R: IntoIterator, + { + IterEither::new(map_both!(self, inner => inner.into_iter())) + } + + /// Return left value or given value + /// + /// Arguments passed to `left_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use + /// [`left_or_else`][Self::left_or_else], which is lazily evaluated. + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either<&str, &str> = Left("left"); + /// assert_eq!(left.left_or("foo"), "left"); + /// + /// let right: Either<&str, &str> = Right("right"); + /// assert_eq!(right.left_or("left"), "left"); + /// ``` + pub fn left_or(self, other: L) -> L { + match self { + Either::Left(l) => l, + Either::Right(_) => other, + } + } + + /// Return left or a default + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either = Left("left".to_string()); + /// assert_eq!(left.left_or_default(), "left"); + /// + /// let right: Either = Right(42); + /// assert_eq!(right.left_or_default(), String::default()); + /// ``` + pub fn left_or_default(self) -> L + where + L: Default, + { + match self { + Either::Left(l) => l, + Either::Right(_) => L::default(), + } + } + + /// Returns left value or computes it from a closure + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either = Left("3".to_string()); + /// assert_eq!(left.left_or_else(|_| unreachable!()), "3"); + /// + /// let right: Either = Right(3); + /// assert_eq!(right.left_or_else(|x| x.to_string()), "3"); + /// ``` + pub fn left_or_else(self, f: F) -> L + where + F: FnOnce(R) -> L, + { + match self { + Either::Left(l) => l, + Either::Right(r) => f(r), + } + } + + /// Return right value or given value + /// + /// Arguments passed to `right_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use + /// [`right_or_else`][Self::right_or_else], which is lazily evaluated. + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let right: Either<&str, &str> = Right("right"); + /// assert_eq!(right.right_or("foo"), "right"); + /// + /// let left: Either<&str, &str> = Left("left"); + /// assert_eq!(left.right_or("right"), "right"); + /// ``` + pub fn right_or(self, other: R) -> R { + match self { + Either::Left(_) => other, + Either::Right(r) => r, + } + } + + /// Return right or a default + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either = Left("left".to_string()); + /// assert_eq!(left.right_or_default(), u32::default()); + /// + /// let right: Either = Right(42); + /// assert_eq!(right.right_or_default(), 42); + /// ``` + pub fn right_or_default(self) -> R + where + R: Default, + { + match self { + Either::Left(_) => R::default(), + Either::Right(r) => r, + } + } + + /// Returns right value or computes it from a closure + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either = Left("3".to_string()); + /// assert_eq!(left.right_or_else(|x| x.parse().unwrap()), 3); + /// + /// let right: Either = Right(3); + /// assert_eq!(right.right_or_else(|_| unreachable!()), 3); + /// ``` + pub fn right_or_else(self, f: F) -> R + where + F: FnOnce(L) -> R, + { + match self { + Either::Left(l) => f(l), + Either::Right(r) => r, + } + } + + /// Returns the left value + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either<_, ()> = Left(3); + /// assert_eq!(left.unwrap_left(), 3); + /// ``` + /// + /// # Panics + /// + /// When `Either` is a `Right` value + /// + /// ```should_panic + /// # use either::*; + /// let right: Either<(), _> = Right(3); + /// right.unwrap_left(); + /// ``` + #[track_caller] + pub fn unwrap_left(self) -> L + where + R: core::fmt::Debug, + { + match self { + Either::Left(l) => l, + Either::Right(r) => { + panic!("called `Either::unwrap_left()` on a `Right` value: {:?}", r) + } + } + } + + /// Returns the right value + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let right: Either<(), _> = Right(3); + /// assert_eq!(right.unwrap_right(), 3); + /// ``` + /// + /// # Panics + /// + /// When `Either` is a `Left` value + /// + /// ```should_panic + /// # use either::*; + /// let left: Either<_, ()> = Left(3); + /// left.unwrap_right(); + /// ``` + #[track_caller] + pub fn unwrap_right(self) -> R + where + L: core::fmt::Debug, + { + match self { + Either::Right(r) => r, + Either::Left(l) => panic!("called `Either::unwrap_right()` on a `Left` value: {:?}", l), + } + } + + /// Returns the left value + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let left: Either<_, ()> = Left(3); + /// assert_eq!(left.expect_left("value was Right"), 3); + /// ``` + /// + /// # Panics + /// + /// When `Either` is a `Right` value + /// + /// ```should_panic + /// # use either::*; + /// let right: Either<(), _> = Right(3); + /// right.expect_left("value was Right"); + /// ``` + #[track_caller] + pub fn expect_left(self, msg: &str) -> L + where + R: core::fmt::Debug, + { + match self { + Either::Left(l) => l, + Either::Right(r) => panic!("{}: {:?}", msg, r), + } + } + + /// Returns the right value + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// let right: Either<(), _> = Right(3); + /// assert_eq!(right.expect_right("value was Left"), 3); + /// ``` + /// + /// # Panics + /// + /// When `Either` is a `Left` value + /// + /// ```should_panic + /// # use either::*; + /// let left: Either<_, ()> = Left(3); + /// left.expect_right("value was Right"); + /// ``` + #[track_caller] + pub fn expect_right(self, msg: &str) -> R + where + L: core::fmt::Debug, + { + match self { + Either::Right(r) => r, + Either::Left(l) => panic!("{}: {:?}", msg, l), + } + } + + /// Calls a function with a reference to the contained value if [`Left`]. + /// + /// Returns the original self. + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// # fn foo() -> Either { Right(2) } + /// let x = foo() + /// .inspect_left(|n| println!("left: {n}")) + /// .left_or(0); + /// ``` + pub fn inspect_left(self, f: F) -> Self + where + F: FnOnce(&L), + { + if let Left(ref left) = self { + f(left); + } + + self + } + + /// Calls a function with a reference to the contained value if [`Right`]. + /// + /// Returns the original self. + /// + /// # Examples + /// + /// ``` + /// use either::*; + /// + /// # fn foo() -> Either { Right(2) } + /// let x = foo() + /// .inspect_right(|n| println!("right: {n}")) + /// .left_or(0); + /// ``` + pub fn inspect_right(self, f: F) -> Self + where + F: FnOnce(&R), + { + if let Right(ref right) = self { + f(right); + } + + self + } + + /// Convert the contained value into `T` + /// + /// # Examples + /// + /// ``` + /// # use either::*; + /// // Both u16 and u32 can be converted to u64. + /// let left: Either = Left(3u16); + /// assert_eq!(left.either_into::(), 3u64); + /// let right: Either = Right(7u32); + /// assert_eq!(right.either_into::(), 7u64); + /// ``` + pub fn either_into(self) -> T + where + L: Into, + R: Into, + { + for_both!(self, inner => inner.into()) + } +} + +impl Either, Option> { + /// Factors out `None` from an `Either` of [`Option`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Option> = Left(Some(vec![0])); + /// assert_eq!(left.factor_none(), Some(Left(vec![0]))); + /// + /// let right: Either>, _> = Right(Some(String::new())); + /// assert_eq!(right.factor_none(), Some(Right(String::new()))); + /// ``` + #[doc(alias = "transpose")] + pub fn factor_none(self) -> Option> { + match self { + Left(l) => l.map(Either::Left), + Right(r) => r.map(Either::Right), + } + } +} + +impl Either, Result> { + /// Factors out a homogeneous type from an `Either` of [`Result`]. + /// + /// Here, the homogeneous type is the `Err` type of the [`Result`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Result> = Left(Ok(vec![0])); + /// assert_eq!(left.factor_err(), Ok(Left(vec![0]))); + /// + /// let right: Either, u32>, _> = Right(Ok(String::new())); + /// assert_eq!(right.factor_err(), Ok(Right(String::new()))); + /// ``` + #[doc(alias = "transpose")] + pub fn factor_err(self) -> Result, E> { + match self { + Left(l) => l.map(Either::Left), + Right(r) => r.map(Either::Right), + } + } +} + +impl Either, Result> { + /// Factors out a homogeneous type from an `Either` of [`Result`]. + /// + /// Here, the homogeneous type is the `Ok` type of the [`Result`]. + /// + /// ``` + /// use either::*; + /// let left: Either<_, Result> = Left(Err(vec![0])); + /// assert_eq!(left.factor_ok(), Err(Left(vec![0]))); + /// + /// let right: Either>, _> = Right(Err(String::new())); + /// assert_eq!(right.factor_ok(), Err(Right(String::new()))); + /// ``` + #[doc(alias = "transpose")] + pub fn factor_ok(self) -> Result> { + match self { + Left(l) => l.map_err(Either::Left), + Right(r) => r.map_err(Either::Right), + } + } +} + +impl Either<(T, L), (T, R)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the first element of the pairs. + /// + /// ``` + /// use either::*; + /// let left: Either<_, (u32, String)> = Left((123, vec![0])); + /// assert_eq!(left.factor_first().0, 123); + /// + /// let right: Either<(u32, Vec), _> = Right((123, String::new())); + /// assert_eq!(right.factor_first().0, 123); + /// ``` + pub fn factor_first(self) -> (T, Either) { + match self { + Left((t, l)) => (t, Left(l)), + Right((t, r)) => (t, Right(r)), + } + } +} + +impl Either<(L, T), (R, T)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the second element of the pairs. + /// + /// ``` + /// use either::*; + /// let left: Either<_, (String, u32)> = Left((vec![0], 123)); + /// assert_eq!(left.factor_second().1, 123); + /// + /// let right: Either<(Vec, u32), _> = Right((String::new(), 123)); + /// assert_eq!(right.factor_second().1, 123); + /// ``` + pub fn factor_second(self) -> (Either, T) { + match self { + Left((l, t)) => (Left(l), t), + Right((r, t)) => (Right(r), t), + } + } +} + +impl Either { + /// Extract the value of an either over two equivalent types. + /// + /// ``` + /// use either::*; + /// + /// let left: Either<_, u32> = Left(123); + /// assert_eq!(left.into_inner(), 123); + /// + /// let right: Either = Right(123); + /// assert_eq!(right.into_inner(), 123); + /// ``` + pub fn into_inner(self) -> T { + for_both!(self, inner => inner) + } + + /// Map `f` over the contained value and return the result in the + /// corresponding variant. + /// + /// ``` + /// use either::*; + /// + /// let value: Either<_, i32> = Right(42); + /// + /// let other = value.map(|x| x * 2); + /// assert_eq!(other, Right(84)); + /// ``` + pub fn map(self, f: F) -> Either + where + F: FnOnce(T) -> M, + { + map_both!(self, t => f(t)) + } +} + +impl Either<&L, &R> { + /// Maps an `Either<&L, &R>` to an `Either` by cloning the contents of + /// either branch. + pub fn cloned(self) -> Either + where + L: Clone, + R: Clone, + { + map_both!(self, inner => inner.clone()) + } + + /// Maps an `Either<&L, &R>` to an `Either` by copying the contents of + /// either branch. + pub fn copied(self) -> Either + where + L: Copy, + R: Copy, + { + map_both!(self, inner => *inner) + } +} + +impl Either<&mut L, &mut R> { + /// Maps an `Either<&mut L, &mut R>` to an `Either` by cloning the contents of + /// either branch. + pub fn cloned(self) -> Either + where + L: Clone, + R: Clone, + { + map_both!(self, inner => inner.clone()) + } + + /// Maps an `Either<&mut L, &mut R>` to an `Either` by copying the contents of + /// either branch. + pub fn copied(self) -> Either + where + L: Copy, + R: Copy, + { + map_both!(self, inner => *inner) + } +} + +/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`. +impl From> for Either { + fn from(r: Result) -> Self { + match r { + Err(e) => Left(e), + Ok(o) => Right(o), + } + } +} + +/// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`. +impl From> for Result { + fn from(val: Either) -> Self { + match val { + Left(l) => Err(l), + Right(r) => Ok(r), + } + } +} + +/// `Either` is a future if both `L` and `R` are futures. +impl Future for Either +where + L: Future, + R: Future, +{ + type Output = L::Output; + + fn poll( + self: Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll { + for_both!(self.as_pin_mut(), inner => inner.poll(cx)) + } +} + +#[cfg(any(test, feature = "std"))] +/// `Either` implements `Read` if both `L` and `R` do. +/// +/// Requires crate feature `"std"` +impl Read for Either +where + L: Read, + R: Read, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result { + for_both!(self, inner => inner.read(buf)) + } + + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + for_both!(self, inner => inner.read_exact(buf)) + } + + fn read_to_end(&mut self, buf: &mut std::vec::Vec) -> io::Result { + for_both!(self, inner => inner.read_to_end(buf)) + } + + fn read_to_string(&mut self, buf: &mut std::string::String) -> io::Result { + for_both!(self, inner => inner.read_to_string(buf)) + } +} + +#[cfg(any(test, feature = "std"))] +/// `Either` implements `Seek` if both `L` and `R` do. +/// +/// Requires crate feature `"std"` +impl Seek for Either +where + L: Seek, + R: Seek, +{ + fn seek(&mut self, pos: SeekFrom) -> io::Result { + for_both!(self, inner => inner.seek(pos)) + } +} + +#[cfg(any(test, feature = "std"))] +/// Requires crate feature `"std"` +impl BufRead for Either +where + L: BufRead, + R: BufRead, +{ + fn fill_buf(&mut self) -> io::Result<&[u8]> { + for_both!(self, inner => inner.fill_buf()) + } + + fn consume(&mut self, amt: usize) { + for_both!(self, inner => inner.consume(amt)) + } + + fn read_until(&mut self, byte: u8, buf: &mut std::vec::Vec) -> io::Result { + for_both!(self, inner => inner.read_until(byte, buf)) + } + + fn read_line(&mut self, buf: &mut std::string::String) -> io::Result { + for_both!(self, inner => inner.read_line(buf)) + } +} + +#[cfg(any(test, feature = "std"))] +/// `Either` implements `Write` if both `L` and `R` do. +/// +/// Requires crate feature `"std"` +impl Write for Either +where + L: Write, + R: Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + for_both!(self, inner => inner.write(buf)) + } + + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + for_both!(self, inner => inner.write_all(buf)) + } + + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + for_both!(self, inner => inner.write_fmt(fmt)) + } + + fn flush(&mut self) -> io::Result<()> { + for_both!(self, inner => inner.flush()) + } +} + +impl AsRef for Either +where + L: AsRef, + R: AsRef, +{ + fn as_ref(&self) -> &Target { + for_both!(self, inner => inner.as_ref()) + } +} + +macro_rules! impl_specific_ref_and_mut { + ($t:ty, $($attr:meta),* ) => { + $(#[$attr])* + impl AsRef<$t> for Either + where L: AsRef<$t>, R: AsRef<$t> + { + fn as_ref(&self) -> &$t { + for_both!(self, inner => inner.as_ref()) + } + } + + $(#[$attr])* + impl AsMut<$t> for Either + where L: AsMut<$t>, R: AsMut<$t> + { + fn as_mut(&mut self) -> &mut $t { + for_both!(self, inner => inner.as_mut()) + } + } + }; +} + +impl_specific_ref_and_mut!(str,); +impl_specific_ref_and_mut!( + ::std::path::Path, + cfg(feature = "std"), + doc = "Requires crate feature `std`." +); +impl_specific_ref_and_mut!( + ::std::ffi::OsStr, + cfg(feature = "std"), + doc = "Requires crate feature `std`." +); +impl_specific_ref_and_mut!( + ::std::ffi::CStr, + cfg(feature = "std"), + doc = "Requires crate feature `std`." +); + +impl AsRef<[Target]> for Either +where + L: AsRef<[Target]>, + R: AsRef<[Target]>, +{ + fn as_ref(&self) -> &[Target] { + for_both!(self, inner => inner.as_ref()) + } +} + +impl AsMut for Either +where + L: AsMut, + R: AsMut, +{ + fn as_mut(&mut self) -> &mut Target { + for_both!(self, inner => inner.as_mut()) + } +} + +impl AsMut<[Target]> for Either +where + L: AsMut<[Target]>, + R: AsMut<[Target]>, +{ + fn as_mut(&mut self) -> &mut [Target] { + for_both!(self, inner => inner.as_mut()) + } +} + +impl Deref for Either +where + L: Deref, + R: Deref, +{ + type Target = L::Target; + + fn deref(&self) -> &Self::Target { + for_both!(self, inner => &**inner) + } +} + +impl DerefMut for Either +where + L: DerefMut, + R: DerefMut, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + for_both!(self, inner => &mut *inner) + } +} + +#[cfg(any(test, feature = "std"))] +/// `Either` implements `Error` if *both* `L` and `R` implement it. +/// +/// Requires crate feature `"std"` +impl Error for Either +where + L: Error, + R: Error, +{ + fn source(&self) -> Option<&(dyn Error + 'static)> { + for_both!(self, inner => inner.source()) + } + + #[allow(deprecated)] + fn description(&self) -> &str { + for_both!(self, inner => inner.description()) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + for_both!(self, inner => inner.cause()) + } +} + +impl fmt::Display for Either +where + L: fmt::Display, + R: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for_both!(self, inner => inner.fmt(f)) + } +} + +impl fmt::Write for Either +where + L: fmt::Write, + R: fmt::Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for_both!(self, inner => inner.write_str(s)) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + for_both!(self, inner => inner.write_char(c)) + } + + fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { + for_both!(self, inner => inner.write_fmt(args)) + } +} + +#[test] +fn basic() { + let mut e = Left(2); + let r = Right(2); + assert_eq!(e, Left(2)); + e = r; + assert_eq!(e, Right(2)); + assert_eq!(e.left(), None); + assert_eq!(e.right(), Some(2)); + assert_eq!(e.as_ref().right(), Some(&2)); + assert_eq!(e.as_mut().right(), Some(&mut 2)); +} + +#[test] +fn macros() { + use std::string::String; + + fn a() -> Either { + let x: u32 = try_left!(Right(1337u32)); + Left(x * 2) + } + assert_eq!(a(), Right(1337)); + + fn b() -> Either { + Right(try_right!(Left("foo bar"))) + } + assert_eq!(b(), Left(String::from("foo bar"))); +} + +#[test] +fn deref() { + use std::string::String; + + fn is_str(_: &str) {} + let value: Either = Left(String::from("test")); + is_str(&value); +} + +#[test] +fn iter() { + let x = 3; + let mut iter = match x { + 3 => Left(0..10), + _ => Right(17..), + }; + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.count(), 9); +} + +#[test] +fn seek() { + use std::io; + + let use_empty = false; + let mut mockdata = [0x00; 256]; + for (i, data) in mockdata.iter_mut().enumerate() { + *data = i as u8; + } + + let mut reader = if use_empty { + // Empty didn't impl Seek until Rust 1.51 + Left(io::Cursor::new([])) + } else { + Right(io::Cursor::new(&mockdata[..])) + }; + + let mut buf = [0u8; 16]; + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_eq!(buf, mockdata[..buf.len()]); + + // the first read should advance the cursor and return the next 16 bytes thus the `ne` + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_ne!(buf, mockdata[..buf.len()]); + + // if the seek operation fails it should read 16..31 instead of 0..15 + reader.seek(io::SeekFrom::Start(0)).unwrap(); + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_eq!(buf, mockdata[..buf.len()]); +} + +#[test] +fn read_write() { + use std::io; + + let use_stdio = false; + let mockdata = [0xff; 256]; + + let mut reader = if use_stdio { + Left(io::stdin()) + } else { + Right(&mockdata[..]) + }; + + let mut buf = [0u8; 16]; + assert_eq!(reader.read(&mut buf).unwrap(), buf.len()); + assert_eq!(&buf, &mockdata[..buf.len()]); + + let mut mockbuf = [0u8; 256]; + let mut writer = if use_stdio { + Left(io::stdout()) + } else { + Right(&mut mockbuf[..]) + }; + + let buf = [1u8; 16]; + assert_eq!(writer.write(&buf).unwrap(), buf.len()); +} + +#[test] +fn error() { + let invalid_utf8 = b"\xff"; + #[allow(invalid_from_utf8)] + let res = if let Err(error) = ::std::str::from_utf8(invalid_utf8) { + Err(Left(error)) + } else if let Err(error) = "x".parse::() { + Err(Right(error)) + } else { + Ok(()) + }; + assert!(res.is_err()); + #[allow(deprecated)] + res.unwrap_err().description(); // make sure this can be called +} + +/// A helper macro to check if AsRef and AsMut are implemented for a given type. +macro_rules! check_t { + ($t:ty) => {{ + fn check_ref>() {} + fn propagate_ref, T2: AsRef<$t>>() { + check_ref::>() + } + fn check_mut>() {} + fn propagate_mut, T2: AsMut<$t>>() { + check_mut::>() + } + }}; +} + +// This "unused" method is here to ensure that compilation doesn't fail on given types. +fn _unsized_ref_propagation() { + check_t!(str); + + fn check_array_ref, Item>() {} + fn check_array_mut, Item>() {} + + fn propagate_array_ref, T2: AsRef<[Item]>, Item>() { + check_array_ref::, _>() + } + + fn propagate_array_mut, T2: AsMut<[Item]>, Item>() { + check_array_mut::, _>() + } +} + +// This "unused" method is here to ensure that compilation doesn't fail on given types. +#[cfg(feature = "std")] +fn _unsized_std_propagation() { + check_t!(::std::path::Path); + check_t!(::std::ffi::OsStr); + check_t!(::std::ffi::CStr); +} diff --git a/anneal/v2/vendor/either/src/serde_untagged.rs b/anneal/v2/vendor/either/src/serde_untagged.rs new file mode 100644 index 0000000000..d62dd7d065 --- /dev/null +++ b/anneal/v2/vendor/either/src/serde_untagged.rs @@ -0,0 +1,69 @@ +//! Untagged serialization/deserialization support for `Either`. +//! +//! `Either` uses default, externally-tagged representation. +//! However, sometimes it is useful to support several alternative types. +//! For example, we may have a field which is generally a `HashMap` +//! but in typical cases `Vec` would suffice, too. +//! +//! ```rust +//! # fn main() -> Result<(), Box> { +//! use either::Either; +//! use std::collections::HashMap; +//! +//! #[derive(serde::Serialize, serde::Deserialize, Debug)] +//! #[serde(transparent)] +//! struct IntOrString { +//! #[serde(with = "either::serde_untagged")] +//! inner: Either, HashMap> +//! }; +//! +//! // serialization +//! let data = IntOrString { +//! inner: Either::Left(vec!["Hello".to_string()]) +//! }; +//! // notice: no tags are emitted. +//! assert_eq!(serde_json::to_string(&data)?, r#"["Hello"]"#); +//! +//! // deserialization +//! let data: IntOrString = serde_json::from_str( +//! r#"{"a": 0, "b": 14}"# +//! )?; +//! println!("found {:?}", data); +//! # Ok(()) +//! # } +//! ``` + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(serde::Serialize, serde::Deserialize)] +#[serde(untagged)] +enum Either { + Left(L), + Right(R), +} + +pub fn serialize(this: &super::Either, serializer: S) -> Result +where + S: Serializer, + L: Serialize, + R: Serialize, +{ + let untagged = match this { + super::Either::Left(left) => Either::Left(left), + super::Either::Right(right) => Either::Right(right), + }; + untagged.serialize(serializer) +} + +pub fn deserialize<'de, L, R, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, + L: Deserialize<'de>, + R: Deserialize<'de>, +{ + match Either::deserialize(deserializer) { + Ok(Either::Left(left)) => Ok(super::Either::Left(left)), + Ok(Either::Right(right)) => Ok(super::Either::Right(right)), + Err(error) => Err(error), + } +} diff --git a/anneal/v2/vendor/either/src/serde_untagged_optional.rs b/anneal/v2/vendor/either/src/serde_untagged_optional.rs new file mode 100644 index 0000000000..d1316935c4 --- /dev/null +++ b/anneal/v2/vendor/either/src/serde_untagged_optional.rs @@ -0,0 +1,74 @@ +//! Untagged serialization/deserialization support for `Option>`. +//! +//! `Either` uses default, externally-tagged representation. +//! However, sometimes it is useful to support several alternative types. +//! For example, we may have a field which is generally a `HashMap` +//! but in typical cases `Vec` would suffice, too. +//! +//! ```rust +//! # fn main() -> Result<(), Box> { +//! use either::Either; +//! use std::collections::HashMap; +//! +//! #[derive(serde::Serialize, serde::Deserialize, Debug)] +//! #[serde(transparent)] +//! struct IntOrString { +//! #[serde(with = "either::serde_untagged_optional")] +//! inner: Option, HashMap>> +//! }; +//! +//! // serialization +//! let data = IntOrString { +//! inner: Some(Either::Left(vec!["Hello".to_string()])) +//! }; +//! // notice: no tags are emitted. +//! assert_eq!(serde_json::to_string(&data)?, r#"["Hello"]"#); +//! +//! // deserialization +//! let data: IntOrString = serde_json::from_str( +//! r#"{"a": 0, "b": 14}"# +//! )?; +//! println!("found {:?}", data); +//! # Ok(()) +//! # } +//! ``` + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[derive(Serialize, Deserialize)] +#[serde(untagged)] +enum Either { + Left(L), + Right(R), +} + +pub fn serialize( + this: &Option>, + serializer: S, +) -> Result +where + S: Serializer, + L: Serialize, + R: Serialize, +{ + let untagged = match this { + Some(super::Either::Left(left)) => Some(Either::Left(left)), + Some(super::Either::Right(right)) => Some(Either::Right(right)), + None => None, + }; + untagged.serialize(serializer) +} + +pub fn deserialize<'de, L, R, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, + L: Deserialize<'de>, + R: Deserialize<'de>, +{ + match Option::deserialize(deserializer) { + Ok(Some(Either::Left(left))) => Ok(Some(super::Either::Left(left))), + Ok(Some(Either::Right(right))) => Ok(Some(super::Either::Right(right))), + Ok(None) => Ok(None), + Err(error) => Err(error), + } +} diff --git a/anneal/v2/vendor/encode_unicode/.cargo-checksum.json b/anneal/v2/vendor/encode_unicode/.cargo-checksum.json new file mode 100644 index 0000000000..43658a1e93 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"af46ddb44f387baf3e14a4e0f2d025ea7da570f030d16f8c728319f194ea47be",".cirrus.yml":"7971c090d58cdc63ffa3db104772a221b443313a3588c7e6e1b8fbfc5dc9dcf5","AUTHORS.md":"f2cf336738ad935a482a799be004083ddd07c904513caf80f9e48011888fe1b6","Cargo.lock":"0456988b6573b06b7ebfbcad4457400a51b0fc5b6be72aa22440ff7f54af8314","Cargo.toml":"9954655fa5288b59d81cc2f66c2d20e415b808179c6434de1d9273a67150f3cc","Cargo.toml.orig":"38de48b85fa16a4ee9239e96ffc0447edd851b15a9b12b5aa923261a6f8fb565","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"da23be69ad3ccf7a5823d62152efcd2b15de9482a5014fcb1b02844662d86abd","README.md":"71c99222cb1e62b8f2c2e084caf6405150b57c8bf496c59b1636d63aa2e097d4","RELEASES.md":"2fde9ac9a45170936dcf66085fe7aa362d8536b1390a5f07f59e4f744fbf0d3d","benches/length.rs":"fb509f67ef24377f31c77d0e96ea560c5139307702dfe8cff4d2369176d9ff94","benches/multiiterators.rs":"6589943a33a75d6a56aacf2cc75ef2bb23328a509a57c99589ec078ef77ac7c7","do.sh":"028ba8c5c8e5b4cdc5459fceb025a66c6ad67c1e93c7a41a84bb76c5019716c8","examples/length_distribution.rs":"325ffa59c712d20c257a320a2aa5cd5624a6eb3d67ddc81d6012440e511865ec","src/decoding_iterators.rs":"c36b508273325b8dc589fd28dbd8931ee7de58412e2d0eb8d2da6fcf80803260","src/errors.rs":"d4a71b225c5f8da8bef6673ae5a77064a45c74f57b52a2b1f67685eb0e67b716","src/lib.rs":"e0cf77b9324d619c500d78f406f3be6b7fd10a06fd183397361e3e2381c57c5d","src/traits.rs":"b0b4e6b02834e13d9e1b062f1df540571f25fd290b4bbcd09ec778d7582e5f8f","src/utf16_char.rs":"f1e21f9ba8785441c5afe5e7b78a480c3f6e9b7f5208d56f10ce1421e9309ef1","src/utf16_iterators.rs":"c9967e945d68c5381404451432b889124b431c3eeb7ef72ec64821dfc988094a","src/utf8_char.rs":"2e35014e790d0cabda4e1926724d8ebb83c88215e6a98ed3cb3d7c5ae74454ee","src/utf8_iterators.rs":"114e2fe000a0366251442ece23d842f82828d0b9df0c6f7caed17a51e1a92c25","tests/errs.rs":"f68f76f0b23e51c227db382cfbce38cc401be562079dca73da52fe12dda299a7","tests/exhaustive.rs":"166e397c5d4d636266f33d9fd0fbe4ca9595783a44691ca51e48f54c6a751b76","tests/iterators.rs":"25b75d0cbc086e8605840f66a42b9a2178ee060fdca2b8692616bdfc9e3425b4","tests/oks.rs":"0e3aabfe3cba6105d28b26d7bf3205caa2a345203e424a7c192d53327d7857ac"},"package":"34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"} \ No newline at end of file diff --git a/anneal/v2/vendor/encode_unicode/.cargo_vcs_info.json b/anneal/v2/vendor/encode_unicode/.cargo_vcs_info.json new file mode 100644 index 0000000000..8f80450472 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "b764bc1cec904d2198b052c5a564963a930a0bcb" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/encode_unicode/.cirrus.yml b/anneal/v2/vendor/encode_unicode/.cirrus.yml new file mode 100644 index 0000000000..82641d5a51 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/.cirrus.yml @@ -0,0 +1,90 @@ +task: + name: stable + container: + image: rust + cpu: 1 + memory: 1G + allow_failures: false + env: + RUST_BACKTRACE: 1 + cargo_cache: + folder: $HOME/.cargo/registry + fingerprint_script: cat Cargo.lock 2> /dev/null || true + target_cache: + folder: target + fingerprint_script: cat Cargo.lock 2> /dev/null || true + setup_script: + - rustup component add clippy + info_script: + - rustc --version + check_script: + - cargo check --examples --tests --no-default-features + - cargo check --examples --tests --no-default-features --features std + - cargo check --examples --tests --no-default-features --features ascii + - cargo build --examples --tests --all-features + - cargo clippy --tests --examples --all-features + test_script: + - cargo test --all-features --no-fail-fast -- --test-threads=1 + before_cache_script: + - rm -rf $HOME/.cargo/registry/index + +task: + name: MSRV + container: + image: rust:1.56 + cpu: 1 + memory: 1G + allow_failures: false + env: + RUST_BACKTRACE: 1 + cargo_cache: + folder: $HOME/.cargo/registry + fingerprint_script: cat Cargo.lock 2> /dev/null || true + target_cache: + folder: target + fingerprint_script: cat Cargo.lock 2> /dev/null || true + info_script: + - rustc --version + build_script: + # Lock to the specified minor versions of dependencies + # to test that they work with our MSRV. + # But that doesn't cover recursive dependencies, + # so avoid checking examples and tests because they build dev dependencies. + # Tests and examples don't need to work at MSRV anyway. + - sed -i 's/"^/"~/' Cargo.toml + - cargo check --no-default-features + - cargo check --no-default-features --features std + - cargo check --no-default-features --features ascii + - cargo check --all-features + before_cache_script: + - rm -rf $HOME/.cargo/registry/index + +task: + name: nightly + container: + image: rustlang/rust:nightly + cpu: 1 + memory: 1G + allow_failures: false + cargo_cache: + folder: $HOME/.cargo/registry + fingerprint_script: cat Cargo.lock 2> /dev/null || true + # rustc version is so likely to have changed that build artefacts are not worth caching + setup_script: + - cargo install cargo-fuzz + - rustup component add miri + info_script: + - rustc --version + check_script: + - cargo check --benches --no-default-features + - cargo check --benches --no-default-features --features std + - cargo check --benches --no-default-features --features ascii + - cargo build --benches --all-features + - cargo fuzz build + # fuzz supports feature selection, + # but --no-default-features doesn't seem to have any effect + test_script: + # the doc tets are fast and should cover a lot of code + - cargo miri test --all-features --doc -- --test-threads=1 + before_cache_script: + - rm -rf $HOME/.cargo/registry/index diff --git a/anneal/v2/vendor/encode_unicode/AUTHORS.md b/anneal/v2/vendor/encode_unicode/AUTHORS.md new file mode 100644 index 0000000000..6759605b3d --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/AUTHORS.md @@ -0,0 +1,4 @@ +# The encode_unicode Developers + +* Torbjørn Birch Moltu +* Aljoscha Meyer diff --git a/anneal/v2/vendor/encode_unicode/Cargo.lock b/anneal/v2/vendor/encode_unicode/Cargo.lock new file mode 100644 index 0000000000..338bce949c --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/Cargo.lock @@ -0,0 +1,368 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ascii" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +dependencies = [ + "ascii", + "lazy_static", + "minreq", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "minreq" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c785bc6027fd359756e538541c8624012ba3776d3d3fe123885643092ed4132" +dependencies = [ + "log", + "native-tls", +] + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "openssl" +version = "0.10.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys", +] + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[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-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/anneal/v2/vendor/encode_unicode/Cargo.toml b/anneal/v2/vendor/encode_unicode/Cargo.toml new file mode 100644 index 0000000000..d721ec8358 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/Cargo.toml @@ -0,0 +1,59 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "encode_unicode" +version = "1.0.0" +authors = ["Torbjørn Birch Moltu "] +description = """ +UTF-8 and UTF-16 character types, iterators and related methods for char, u8 and u16. +""" +documentation = "https://docs.rs/encode_unicode/" +readme = "README.md" +keywords = [ + "unicode", + "UTF-8", + "UTF-16", +] +categories = [ + "encoding", + "no-std", +] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/tormol/encode_unicode" +resolver = "2" + +[package.metadata.docs.rs] +features = ["ascii/std"] + +[[bench]] +name = "length" +required-features = ["std"] + +[dependencies.ascii] +version = "^1.0.0" +optional = true +default-features = false + +[dev-dependencies.minreq] +version = "^2.6" +features = ["https-native"] + +[features] +default = ["std"] +std = [] + +[target."cfg(unix)".dev-dependencies.lazy_static] +version = "^1.0" + +[badges.maintenance] +status = "passively-maintained" diff --git a/anneal/v2/vendor/encode_unicode/Cargo.toml.orig b/anneal/v2/vendor/encode_unicode/Cargo.toml.orig new file mode 100644 index 0000000000..3bc0d33d63 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/Cargo.toml.orig @@ -0,0 +1,41 @@ +[package] +name = "encode_unicode" +keywords = ["unicode","UTF-8","UTF-16"] +categories = ["encoding","no-std"] +description = """ +UTF-8 and UTF-16 character types, iterators and related methods for char, u8 and u16. +""" +readme = "README.md" +version = "1.0.0" +license = "Apache-2.0 OR MIT" +repository = "https://github.com/tormol/encode_unicode" +documentation = "https://docs.rs/encode_unicode/" +authors = ["Torbjørn Birch Moltu "] +edition = "2021" + +[dependencies.ascii] +optional = true +version = "^1.0.0" +default-features = false # don't need std for the parts we use + +[target.'cfg(unix)'.dev-dependencies] +lazy_static = "^1.0" + +[dev-dependencies.minreq] +version = "^2.6" +features = ["https-native"] + +[features] +std = [] +default = ["std"] + +[[bench]] +name="length" +required-features = ["std"] + +[badges.maintenance] +status = "passively-maintained" +# Too low activity for is-it-maintained-issue-resolution + +[package.metadata.docs.rs] +features = ["ascii/std"] diff --git a/anneal/v2/vendor/encode_unicode/LICENSE-APACHE b/anneal/v2/vendor/encode_unicode/LICENSE-APACHE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/anneal/v2/vendor/encode_unicode/LICENSE-MIT b/anneal/v2/vendor/encode_unicode/LICENSE-MIT new file mode 100644 index 0000000000..de22e4284a --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/LICENSE-MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/anneal/v2/vendor/encode_unicode/README.md b/anneal/v2/vendor/encode_unicode/README.md new file mode 100644 index 0000000000..aed519d97e --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/README.md @@ -0,0 +1,71 @@ +# encode_unicode + +UTF-8 and UTF-16 character types, iterators and related methods for `char`, `u8` and `u16`. + +[![crates.io page](https://img.shields.io/crates/v/encode_unicode.svg)](https://crates.io/crates/encode_unicode/) ![License: Apache-2 or MIT](https://img.shields.io/crates/l/encode_unicode.svg) [![Documentation on docs.rs](https://docs.rs/encode_unicode/badge.svg)](https://docs.rs/encode_unicode/) [![CI build status](https://api.cirrus-ci.com/github/tormol/encode_unicode.svg)](https://cirrus-ci.com/github/tormol/encode_unicode) + +## Features + +* **[`Utf8Char`](https://docs.rs/encode_unicode/latest/encode_unicode/struct.Utf8Char.html)**: + A `char` stored as UTF-8. Can be borrowed as a `str` or `u8` slice. +* **[`Utf16Char`](https://docs.rs/encode_unicode/latest/encode_unicode/struct.Utf16Char.html)**: + A `char` stored as UTF-16. Can be borrowed as an `u16` slice. +* [Conversion methods on `char`](https://docs.rs/encode_unicode/latest/encode_unicode/trait.CharExt.html): + * to and from UTF-8 as `[u8; 4]` or slice. + * to and from UTF-16 as `(u16, Option)` or slice. +* [Iterator adapters](https://docs.rs/encode_unicode/latest/encode_unicode/trait.IterExt.html) + for converting betwenn `u8`s and `Utf8Char`s or `u16`s and `Utf16Char`s. +* Optimized [slice-based decoding iterators](https://docs.rs/encode_unicode/latest/encode_unicode/trait.SliceExt.html). +* [Precise errors when decoding a char from UTF-8, UTF-16 or `u32` fails](http://docs.rs/encode_unicode/latest/encode_unicode/error/index.html). +* Utility methods on [`u8`](https://docs.rs/encode_unicode/latest/encode_unicode/trait.U8UtfExt.html) + and [`u16`](https://docs.rs/encode_unicode/latest/encode_unicode/trait.U16UtfExt.html). + +## Minimum supported Rust version + +The minimum supported Rust version for 1.0.\* releases is 1.56. +Later 1.y.0 releases might require newer Rust versions, but the three most +recent stable releases at the time of publishing will always be supported. +For example this means that if the current stable Rust version is 1.66 when +encode_unicode 1.1.0 is released, then encode_unicode 1.1.\* will +not require a newer Rust version than 1.63. + +## Optional features + +* `#![no_std]`-mode: There are a few differences: + * `Error` doesn't exist, but `description()` is made available as an inherent impl. + * `Extend`/`FromIterator`-implementations for `String`/`Vec`/`Vec` are missing. + * There is no `io`, so `Utf8Iterator` and `Utf8CharSplitter` doesn't implement `Read`. + This feature is enabled by setting `default-features=false` in `Cargo.toml`: + `encode_unicode = {version="0.3.4", default-features=false}`. +* Integration with the [ascii](https://tomprogrammer.github.io/rust-ascii/ascii/index.html) crate: + Convert `Utf8Char` and `Utf16Char` to and from [ascii::`AsciiChar`](https://tomprogrammer.github.io/rust-ascii/ascii/enum.AsciiChar.html). + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. + +## Developing + +`do.sh` can be used to check all feature combinations, test everything, show output from benchmarks in case setup fails, run fuzz tests for a while and lint everything (except fuzz tests). +It assumes [rustup](https://rustup.rs) is installed and that [`cargo +release`](https://rust-lang.github.io/rustup/concepts/index.html#how-rustup-works) works. +(It is named the way it is to autocomplete fully from the first character after `./`.) + +## History + +The original purpose of this crate was to provide standins for the then +unstable `encode_utf8()` and `encode_utf16()` methods on `char`. +The standins were removed in version 0.3 when Rust 1.15 stabilized the +`encode_` methods, but the other stuff I added, such as iterators like +those `encode_utf{8,16}()` returned for a while, might still be of use. diff --git a/anneal/v2/vendor/encode_unicode/RELEASES.md b/anneal/v2/vendor/encode_unicode/RELEASES.md new file mode 100644 index 0000000000..a73118c95c --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/RELEASES.md @@ -0,0 +1,104 @@ +Version 1.0.0 (2022-08-07) +========================== +* Replace error types `InvalidUtf8Array`, `InvalidUtf8Slice`, `InvalidUtf8FirstByte` and `InvalidUtf8` with `Utf8Error` plus `Utf8ErrorKind`. + Which of the new error kind variants is reported don't map 1:1 to the old enum variants: + For example `Utf8ErrorKind::NonUtf8Byte` is returned for sequences that would previously have been reported as too high codepoint or overlong encoding. +* Rename many other error types for consistency: + * `InvalidCodepoint` -> `CodepointError` + * `InvalidUtf16FirstUnit` -> `Utf16FirstUnitError` + * `InvalidUtf16Array` -> `Utf16ArrayError` + * `InvalidUtf16Slice` -> `Utf16SliceError` + * `1InvalidUtf16Tuple` -> `Utf16TupleError` +* Change return type of `CodepointError::error_range()` to `RangeInclusive`. +* Rename some errors variants: + * `Utf16SliceError::FirstLowSurrogate` -> `FirstIsTrailingSurrogate` + * `Utf16SliceError::SecondNotLowSurrogate` -> `SecondIsNotTrailingSurrogate` + * `Utf16TupleError::InvalidSecond` -> `SecondIsNotTrailingSurrogate` +* Expose the error type of `Utf16Char::from_bmp()` and rename it to `NonBmpError`. +* Remove re-exports of `Utf8CharIterator` and `Utf16CharIterator` from the crate root. + (They are still exposed via the `iterator` module.) +* Remove impls of the deprecated `AsciiExt` trait, + and make the methods available in `#![no_std]`-mode. +* Make many of the previously `AsciiExt` methods take self by value. +* Drop support for pre-1.0 versions of the ascii crate. +* Remove `iter_bytes()` and `iter_units()`. +* Increase minimum Rust version to 1.56 and change the minimum Rust version policy. +* Fix possible UB or panic in `Utf8Char::from_slice_start_unchecked()` when passed an empty slice. + (relates to [#12](https://github.com/tormol/encode_unicode/issues/12).) +* Make many methods `const fn`. +* Add `const fn`s `Utf8Char::new()` and `Utf16Char::new()`. + +Version 0.3.6 (2019-08-23) +========================== +* Fix pointless undefined behavior in `Utf16Char.to_ascii_char()` (which is part of ascii feature) +* Widen ascii version requirement to include 1.\*. +* Add `[u16; 2]` UTF-16 array alternatives to `(u16, Some(u16))` UTF-16 tuple methods. +* Add `Utf16Char.is_bmp()`. + +Version 0.3.5 (2018-10-23) +========================== +* Fix docs.rs build failure + +Version 0.3.4 (2018-10-23) +========================== +* Fix UB in UTF-8 validation which lead to invalid codepoints being accepted in release mode. +* Add fallible decoding iterator adapters `Utf8CharMerger` and `Utf16CharMerger` + and slice-based iterators `Utf8CharDecoder` and `Utf16CharDecoder` +* Widen ascii version requirement from 0.8.\* to 0.8.0 - 0.10.\* +* Implement creating / extending `String`s from `Utf16Char`-producing iterators + +Version 0.3.3 (2018-10-16) +========================== +* Fix UTF-8 overlong check. (`from_array()` and `from_slice()` accepted two-byte encodings of ASCII characters >= '@', which includes all letters) +* Implement `FromStr` for `Utf16Char` +* Add `from_str_start()` to `Utf8Char` and `Utf16Char` +* Add `Utf{8,16}Char{s,Indices}`: `str`-based iterators for `Utf8Char` and `Utf16Char` equivalent to `char`'s `Chars` and `CharIndices`. +* Add `StrExt` with functions to create the above iterators. +* Implement `FromIterator` and `Extend` for `Vec<{u8,u16}>` with reference-producing `Utf{8,16}Char` iterators too. +* Add `Utf8CharSplitter` and `Utf16CharSplitter`: `Utf{8,16}Char`-to-`u{8,16}` iterator adapters. +* Add `IterExt`, `iter_bytes()` and `iter_units()` to create the above splitting iterators. +* Add `Utf8Char::from_ascii()`, `Utf16Char::from_bmp()` with `_unchecked` versions of both. +* Add cross-type `PartialEq` and `PartialOrd` implementations. +* Change the `description()` for a few error types. + +Version 0.3.2 (2018-08-08) +========================== +* Hide `AsciiExt` deprecation warning and add replacement methods. +* Correct documentation for `U8UtfExt::extra_utf8_bytes()`. +* Fix misspellings in some error descriptions. +* Avoid potentially bad transmutes. + +Version 0.3.1 (2017-06-16) +========================== +* Implement `Display` for `Utf8Char` and `Utf16Char`. + +Version 0.3.0 (2017-03-29) +========================== +* Replace the "no_std" feature with opt-out "std". + * Upgrade ascii to v0.8. + * Make tests compile on stable. +* Remove `CharExt::write_utf{8,16}()` because `encode_utf{8,16}()` has been stabilized. +* Return a proper error from `U16UtfExt::utf16_needs_extra_unit()` instead of `None`. +* Rename `U16UtfExt::utf_is_leading_surrogate()` to `is_utf16_leading_surrogate()`. +* Rename `Utf16Char::from_slice()` to `from_slice_start()` and `CharExt::from_utf{8,16}_slice()` + to `from_utf{8,16}_slice_start()` to be consistent with `Utf8Char`. +* Fix a bug where `CharExt::from_slice()` would accept some trailing surrogates + as standalone codepoints. + +Version 0.2.0 (2016-07-24) +========================== +* Change `CharExt::write_utf{8,16}()` to panic instead of returning `None` + if the slice is too short. +* Fix bug where `CharExt::write_utf8()` and `Utf8Char::to_slice()` could change bytes it shouldn't. +* Rename lots of errors with search and replace: + * CodePoint -> Codepoint + * Several -> Multiple +* Update the ascii feature to use [ascii](https://tomprogrammer.github.io/rust-ascii/ascii/index.html) v0.7. +* Support `#[no_std]`; see 70e090ee for differences. +* Ungate impls of `AsciiExt`. (doesn't require ascii or nightly) +* Make the tests compile (and pass) again. + (They still require nightly). + +Version 0.1.* (2016-04-07) +========================== +First release. diff --git a/anneal/v2/vendor/encode_unicode/benches/length.rs b/anneal/v2/vendor/encode_unicode/benches/length.rs new file mode 100644 index 0000000000..dce5fc8cb1 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/benches/length.rs @@ -0,0 +1,282 @@ +/* Copyright 2018-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +// Run with -- --nocapture to show error messages if setup fails. +// (or use ./do.sh) + +#![cfg(feature="std")] +#![feature(test)] +extern crate test; +use test::{Bencher, black_box}; + +use std::fs; +use std::path::Path; +use std::io::ErrorKind; +use std::thread::sleep; +use std::time::Duration; +use std::collections::HashMap; +extern crate minreq; +#[macro_use] extern crate lazy_static; +extern crate encode_unicode; +use encode_unicode::{CharExt, Utf8Char, U8UtfExt, Utf16Char, U16UtfExt}; + +// Setup; need longish strings to make benchmarks representative and +// reduce overhead (might get cache misses now though) +// Therefore we download a few wikipedia articles in different languages. +// Downloading a fixed revision of the articles doesn't prevent the HTML from +// changing due to changes in templates or rendering. + +fn load_wikipedia(language: &str, article: &str, english: &str, revision: usize) -> String { + let cache_path = Path::new("benches").join("texts"); + let cache_path = cache_path.to_str().unwrap(); + let name = format!("{}_{}.html", language, english); + let path = Path::new(cache_path).join(&name); + let path = path.to_str().unwrap(); + match fs::read_to_string(path) { + Ok(content) => return content, + Err(ref e) if e.kind() == ErrorKind::NotFound => {},//continue + Err(ref e) if e.kind() == ErrorKind::InvalidData => { + panic!("{} exists but is not UTF-8", &name); + }, + Err(e) => panic!("{} exists but cannot be read ({})", path, e), + } + let mut article_ascii = String::new(); + for c in article.chars() { + if c.is_ascii() { + article_ascii.push(c); + } else { + let encoded = format!("%{:2X}", c as u32); + article_ascii.push_str(encoded.as_str()); + } + } + let url = format!("https://{}.m.wikipedia.org/w/index.php?title={}&oldid={}", + language, article_ascii, revision + ); + println!("Downloading {} and saving to {}", &url, path); + let response = minreq::get(&url).send().unwrap_or_else(|e| { + panic!("Cannot get {}: {}", url, e); + }); + if response.status_code != 200 { + panic!("Bad URL {}: {} {}", url, response.status_code, response.reason_phrase); + } + let content = String::from_utf8(response.into_bytes()).unwrap_or_else(|_| { + panic!("Response from {} is not UTF-8", url); + }); + if let Err(e) = fs::create_dir_all(cache_path) { + eprintln!("Warning: failed to create directory {}: {}", cache_path, e); + } else if let Err(e) = fs::write(&path, &content) { + eprintln!("Warning: failed to save {}: {}", path, e); + } + sleep(Duration::from_secs(1)); + content +} +const ARTICLES: &[(&str, &str, &str, usize)] = &[ + ("en", "United_Kingdom", "United_Kingdom", 855522252),// 99,7% ASCII + ("es", "España", "Spain", 109861222),// 1,75% 2-byte characters + ("ru", "Россия", "Russia", 94607243),// 36% 2-byte characters + ("zh", "中國", "China", 50868604),// 30% 3-byte characters +]; +lazy_static!{ + static ref STRINGS: HashMap<&'static str, String> = { + let mut content = HashMap::new(); + for &(language, article, english, revision) in ARTICLES { + content.insert(language, load_wikipedia(language, article, english, revision)); + } + // make one string with only ASCII + let only_ascii = content.values() + .map(|v| (v, v.bytes().filter(|b| b.is_ascii() ).count()) ) + .max_by_key(|&(_,len)| len ) + .map(|(v,_)| v.bytes().filter(|b| b.is_ascii() ).map(|b| b as char ).collect() ) + .unwrap(); + content.insert("ascii", only_ascii); + content + }; + static ref EQUAL_CHARS: HashMap<&'static str, &'static str> = { + let (least, chars) = STRINGS.iter() + .map(|(l,s)| (l, s.chars().count()) ) + .min_by_key(|&(_,chars)| chars ) + .unwrap(); + println!("chars: {} (limited by {})", chars, least); + STRINGS.iter().map(|(&language, string)| { + let cut = string.char_indices() + .nth(chars) + .map_or(string.len(), |(i,_)| i ); + let string = &string[..cut]; + assert_eq!(string.chars().count(), chars); + (language, string) + }).collect() + }; + static ref EQUAL_BYTES: HashMap<&'static str, String> = { + let (least, bytes) = STRINGS.iter() + .map(|(l,s)| (l, s.len()) ) + .min_by_key(|&(_,bytes)| bytes ) + .unwrap(); + println!("bytes: {} (limited by {})", bytes, least); + STRINGS.iter().map(|(&language, string)| { + let mut remaining = bytes; + // take just so many characters that their length is exactly $bytes + // slicing won't if !string.is_char_boundary(bytes), + let string = string.chars().filter(|c| { + match remaining.checked_sub(c.len_utf8()) { + Some(after) => {remaining = after; true}, + None => false + } + }).collect::(); + assert_eq!(string.len(), bytes); + (language, string) + }).collect() + }; + static ref EQUAL_UNITS: HashMap<&'static str, String> = { + let (least, units) = STRINGS.iter() + .map(|(l,s)| (l, s.chars().map(|c| c.len_utf16() ).sum::()) ) + .min_by_key(|&(_,units)| units ) + .unwrap(); + println!("units: {} (limited by {})", units, least); + STRINGS.iter().map(|(&language, string)| { + let mut remaining = units; + let string = string.chars().filter(|c| { + match remaining.checked_sub(c.len_utf16()) { + Some(after) => {remaining = after; true}, + None => false + } + }).collect::(); + assert_eq!(string.chars().map(|c| c.len_utf16() ).sum::(), units); + (language, string) + }).collect() + }; +} + + + + /////////////////////////// + // benchmarks begin here // +/////////////////////////// + +fn utf8char_len(language: &str, b: &mut Bencher) { + let string = &EQUAL_BYTES[language]; + let chars: Vec = string.chars().map(|c| c.to_utf8() ).collect(); + let bytes = string.len(); + b.iter(|| { + let sum: usize = black_box(&chars).iter().map(|u8c| u8c.len() ).sum(); + assert_eq!(sum, bytes); + }); +} +#[bench] fn utf8char_len_ascii(b: &mut Bencher) {utf8char_len("ascii", b)} +#[bench] fn utf8char_len_en(b: &mut Bencher) {utf8char_len("en", b)} +#[bench] fn utf8char_len_es(b: &mut Bencher) {utf8char_len("es", b)} +#[bench] fn utf8char_len_ru(b: &mut Bencher) {utf8char_len("ru", b)} +#[bench] fn utf8char_len_zh(b: &mut Bencher) {utf8char_len("zh", b)} + +fn utf8_extra_bytes_unchecked(language: &str, b: &mut Bencher) { + let string = &EQUAL_CHARS[language]; + let chars = string.chars().count(); + let string = string.as_bytes(); + b.iter(|| { + let mut i = 0; + let mut loops = 0; + while i < string.len() { + i += string[i].extra_utf8_bytes_unchecked(); + i += 1; + loops += 1; + } + assert_eq!(loops, chars); + }); +} +#[bench] fn utf8_extra_bytes_unchecked_ascii(b: &mut Bencher) {utf8_extra_bytes_unchecked("ascii", b)} +#[bench] fn utf8_extra_bytes_unchecked_en(b: &mut Bencher) {utf8_extra_bytes_unchecked("en", b)} +#[bench] fn utf8_extra_bytes_unchecked_es(b: &mut Bencher) {utf8_extra_bytes_unchecked("es", b)} +#[bench] fn utf8_extra_bytes_unchecked_ru(b: &mut Bencher) {utf8_extra_bytes_unchecked("ru", b)} +#[bench] fn utf8_extra_bytes_unchecked_zh(b: &mut Bencher) {utf8_extra_bytes_unchecked("zh", b)} + +fn utf8_extra_bytes(language: &str, b: &mut Bencher) { + let string = &EQUAL_CHARS[language]; + let chars = string.chars().count(); + let string = string.as_bytes(); + b.iter(|| { + let mut i = 0; + let mut loops = 0; + let mut errors = 0; + while i < string.len() { + match string[i].extra_utf8_bytes() { + Ok(n) => i += n, + Err(_) => errors += 1, + } + i += 1; + loops += 1; + } + assert_eq!(loops, chars); + assert_eq!(errors, 0); + }); +} +#[bench] fn utf8_extra_bytes_ascii(b: &mut Bencher) {utf8_extra_bytes("ascii", b)} +#[bench] fn utf8_extra_bytes_en(b: &mut Bencher) {utf8_extra_bytes("en", b)} +#[bench] fn utf8_extra_bytes_es(b: &mut Bencher) {utf8_extra_bytes("es", b)} +#[bench] fn utf8_extra_bytes_ru(b: &mut Bencher) {utf8_extra_bytes("ru", b)} +#[bench] fn utf8_extra_bytes_zh(b: &mut Bencher) {utf8_extra_bytes("zh", b)} + + +fn utf16char_len(language: &str, b: &mut Bencher) { + let string = &EQUAL_UNITS[language]; + let chars: Vec = string.chars().map(|c| c.to_utf16() ).collect(); + let units = string.chars().map(|c| c.len_utf16() ).sum::(); + b.iter(|| { + let sum: usize = black_box(&chars).iter().map(|u8c| u8c.len() ).sum(); + assert_eq!(sum, units); + }); +} +#[bench] fn utf16char_len_ascii(b: &mut Bencher) {utf16char_len("ascii", b)} +#[bench] fn utf16char_len_en(b: &mut Bencher) {utf16char_len("en", b)} +#[bench] fn utf16char_len_es(b: &mut Bencher) {utf16char_len("en", b)} +#[bench] fn utf16char_len_ru(b: &mut Bencher) {utf16char_len("ru", b)} +#[bench] fn utf16char_len_zh(b: &mut Bencher) {utf16char_len("zh", b)} + +fn utf16_is_leading_surrogate(language: &str, b: &mut Bencher) { + let string = &EQUAL_UNITS[language]; + let chars = string.chars().count(); + let string: Vec = string.chars().map(|c| c.to_utf16() ).collect(); + b.iter(|| { + let mut i = 0; + let mut loops = 0; + while i < string.len() { + i += if string[i].is_utf16_leading_surrogate() {2} else {1}; + loops += 1; + } + assert_eq!(loops, chars); + }); +} +#[bench] fn utf16_is_leading_surrogate_ascii(b: &mut Bencher) {utf16_is_leading_surrogate("ascii", b)} +#[bench] fn utf16_is_leading_surrogate_en(b: &mut Bencher) {utf16_is_leading_surrogate("en", b)} +#[bench] fn utf16_is_leading_surrogate_es(b: &mut Bencher) {utf16_is_leading_surrogate("es", b)} +#[bench] fn utf16_is_leading_surrogate_ru(b: &mut Bencher) {utf16_is_leading_surrogate("ru", b)} +#[bench] fn utf16_is_leading_surrogate_zh(b: &mut Bencher) {utf16_is_leading_surrogate("zh", b)} + +fn utf16_needs_extra_unit(language: &str, b: &mut Bencher) { + let string = &EQUAL_UNITS[language]; + let chars = string.chars().count(); + let string: Vec = string.chars().map(|c| c.to_utf16() ).collect(); + b.iter(|| { + let mut i = 0; + let mut loops = 0; + let mut errors = 0; + while i < string.len() { + i += match string[i].utf16_needs_extra_unit() { + Ok(true) => 2, + Ok(false) => 1, + Err(_) => {errors+=1; 1} + }; + loops += 1; + } + assert_eq!(loops, chars); + assert_eq!(errors, 0); + }); +} +#[bench] fn utf16_needs_extra_unit_ascii(b: &mut Bencher) {utf16_needs_extra_unit("ascii", b)} +#[bench] fn utf16_needs_extra_unit_en(b: &mut Bencher) {utf16_needs_extra_unit("en", b)} +#[bench] fn utf16_needs_extra_unit_es(b: &mut Bencher) {utf16_needs_extra_unit("es", b)} +#[bench] fn utf16_needs_extra_unit_ru(b: &mut Bencher) {utf16_needs_extra_unit("ru", b)} +#[bench] fn utf16_needs_extra_unit_zh(b: &mut Bencher) {utf16_needs_extra_unit("zh", b)} diff --git a/anneal/v2/vendor/encode_unicode/benches/multiiterators.rs b/anneal/v2/vendor/encode_unicode/benches/multiiterators.rs new file mode 100644 index 0000000000..49530ae8a5 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/benches/multiiterators.rs @@ -0,0 +1,122 @@ +/* Copyright 2018 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +// Run with -- --nocapture to show error messages if setup fails. +// (or use ./do.sh) + +// uses /usr/share/dict/ for text to convert to Vec and iterate over +#![cfg(all(unix, feature="std"))] +#![feature(test)] +extern crate test; +use test::{Bencher, black_box}; +#[macro_use] extern crate lazy_static; +extern crate encode_unicode; +use encode_unicode::{CharExt, Utf8Char, Utf16Char, IterExt}; + +fn read_or_exit(file: &str) -> String { + let mut fd = std::fs::File::open(file).unwrap_or_else(|err| { + if err.kind() == std::io::ErrorKind::NotFound { + eprintln!("{} not found, skipping benchmarks.", file); + std::process::exit(0); + } else { + eprintln!("Failed to open {}: {}.", file, err); + std::process::exit(1); + } + }); + let mut content = String::new(); + std::io::Read::read_to_string(&mut fd, &mut content).unwrap_or_else(|err| { + eprintln!("Failed to read {}: {}.", file, err); + std::process::exit(1); + }); + content +} + +lazy_static!{ + // TODO find a big chinese file; `aptitude search '?provides(wordlist)'` didn't have one + static ref ENGLISH: String = read_or_exit("/usr/share/dict/american-english"); + static ref UTF8CHARS: Vec = ENGLISH.chars().map(|c| c.to_utf8() ).collect(); + static ref UTF16CHARS: Vec = ENGLISH.chars().map(|c| c.to_utf16() ).collect(); +} + + +#[bench] +fn utf16_split_all_single_mulititerator(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF16CHARS).iter().to_units().for_each(|u| assert!(u != 0) ); + }); +} +#[bench] +fn utf16_split_all_single_flatmap(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF16CHARS).iter().cloned().flatten().for_each(|u| assert!(u != 0) ); + }); +} +#[bench] +fn utf16_split_all_single_cloned_flatten(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF16CHARS).iter().cloned().flatten().for_each(|u| assert!(u != 0) ); + }); +} + + +#[bench] +fn utf8_split_mostly_ascii_multiiterator(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF8CHARS).iter().to_bytes().for_each(|b| assert!(b != 0) ); + }); +} +#[bench] +fn utf8_split_mostly_ascii_flatmap(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF8CHARS).iter().cloned().flatten().for_each(|b| assert!(b != 0) ); + }); +} +#[bench] +fn utf8_split_mostly_ascii_cloned_flatten(b: &mut Bencher) { + b.iter(|| { + black_box(&*UTF8CHARS).iter().cloned().flatten().for_each(|b| assert!(b != 0) ); + }); +} + + +#[bench] +fn utf8_extend_mostly_ascii_multiiterator(b: &mut Bencher) { + b.iter(|| { + let vec: Vec = black_box(&*UTF8CHARS).iter().to_bytes().collect(); + assert_eq!(black_box(vec).len(), ENGLISH.len()); + }); +} +#[bench] +fn utf8_extend_mostly_ascii_custom(b: &mut Bencher) { + b.iter(|| { + let vec: Vec = black_box(&*UTF8CHARS).iter().collect(); + assert_eq!(black_box(vec).len(), ENGLISH.len()); + }); +} +#[bench] +fn utf8_extend_mostly_ascii_custom_str(b: &mut Bencher) { + b.iter(|| { + let vec: String = black_box(&*UTF8CHARS).iter().cloned().collect(); + assert_eq!(black_box(vec).len(), ENGLISH.len()); + }); +} + +#[bench] +fn utf16_extend_all_single_multiiterator(b: &mut Bencher) { + b.iter(|| { + let vec: Vec = black_box(&*UTF16CHARS).iter().to_units().collect(); + assert!(black_box(vec).len() < ENGLISH.len()); + }); +} +#[bench] +fn utf16_extend_all_single_custom(b: &mut Bencher) { + b.iter(|| { + let vec: Vec = black_box(&*UTF16CHARS).iter().collect(); + assert!(black_box(vec).len() < ENGLISH.len()); + }); +} diff --git a/anneal/v2/vendor/encode_unicode/do.sh b/anneal/v2/vendor/encode_unicode/do.sh new file mode 100755 index 0000000000..f77ad0e9dd --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/do.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +set -e -o pipefail + +MSRV=1.56.1 +FUZZ_DURATION=60 +FUZZ_PAUSE=2 + +if [[ ${1:0:1} == - || $1 == help ]] || (( $# > 1 )); then + echo "A script to make it easy to check & lint & test everything." >&2 + echo "It assumes rustup is installed and that cargo +release works." >&2 + echo >&2 + echo "Usage: $0 ([setup|MSRV|check|test|ignored|clippy|miri|fuzz|bench|shellcheck|help])" >&2 + echo "If no argument is provided, all parts except ignored and help are run," >&2 + echo "but setup is only done if auto-detection fails." >&2 + exit 1 +fi + +# should have been a Makefile + +# core check, Minimum supported Rust version +if [[ $1 == setup ]] || ! rustup show | grep --silent "$MSRV"; then + rustup install "$MSRV" --no-self-update +fi +if [[ -z $1 || $1 == msrv ]]; then + # FIXME modify Cargo.toml like on CI, and then restore it and Cargo.lock afterwards + cargo "+$MSRV" build --all-features +fi + +# check all feature combinations, stable +if [[ $1 == setup ]] || ! rustup show | grep --silent stable; then + rustup install stable --no-self-update +fi +if [[ -z $1 || $1 == check ]]; then + cargo +stable check --examples --tests --no-default-features + cargo +stable check --examples --tests --no-default-features --features std + cargo +stable check --examples --tests --no-default-features --features ascii + cargo +stable check --examples --tests --all-features +fi + +# tests, stable +if [[ -z $1 || $1 == test ]]; then + cargo +stable test --all-features -- --quiet +elif [[ $1 == ignored ]]; then + cargo +stable test --all-features -- --quiet --ignored +fi + +# clippy, nightly +if [[ $1 == setup ]] || ! rustup show | grep --silent nightly; then + rustup install nightly --no-self-update +fi +if [[ $1 == setup ]] || ! cargo +nightly help clippy >/dev/null 2>/dev/null; then + rustup component add clippy --toolchain nightly +fi +if [[ -z $1 || $1 == clippy ]]; then + cargo +nightly clippy --all-features --tests --benches --examples +fi + +# miri, nightly +if [[ $1 == setup ]] || ! cargo +nightly help miri >/dev/null 2>/dev/null; then + rustup component add miri --toolchain nightly + cargo +nightly miri setup +fi +if [[ -z $1 || $1 == miri ]]; then + cargo +nightly miri test --all-features -- --quiet +fi + +# fuzzing tests, nightly +if [[ $1 == setup ]] || ! command -V cargo-fuzz >/dev/null 2>/dev/null; then + cargo +nightly install cargo-fuzz +fi +if [[ -z $1 || $1 == fuzz ]]; then + cargo +nightly fuzz build + for fuzztest in $(cargo +nightly fuzz list); do + sleep "$FUZZ_PAUSE" + echo "Fuzzing $fuzztest" + timeout "$FUZZ_DURATION" \ + cargo +nightly fuzz run "$fuzztest" \ + || true + echo + done +fi + +# benchmarks, nightly +if [[ -z $1 || $1 == bench ]]; then + cargo +nightly check --benches --no-default-features + cargo +nightly check --benches --no-default-features --features std + cargo +nightly check --benches --no-default-features --features ascii + cargo +nightly check --benches --all-features + # need nocapture to not hide error if setup fails + cargo +nightly bench --all-features -- --nocapture +fi + +if [[ $1 == shellcheck || $1 == selfcheck ]] \ +|| ([[ -z $1 ]] && command -V shellcheck >/dev/null 2>/dev/null); then + shellcheck "$0" +fi diff --git a/anneal/v2/vendor/encode_unicode/examples/length_distribution.rs b/anneal/v2/vendor/encode_unicode/examples/length_distribution.rs new file mode 100644 index 0000000000..746a59d8aa --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/examples/length_distribution.rs @@ -0,0 +1,89 @@ +/* Copyright 2018 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Counts the number of codepoints of each UTF-8 length in files + +use std::env::args_os; +use std::fs::File; +use std::io::{self, Read, stdin}; +use std::borrow::Cow; +extern crate encode_unicode; +use encode_unicode::U8UtfExt; + +#[derive(Default)] +struct Distribution { + bytes: usize, + utf8: [usize; 4], +} + +fn read(file: &mut dyn Read) -> (Distribution, Option) { + let mut r = Distribution::default(); + let mut buf = [0u8; 4096]; + loop { + let read = match file.read(&mut buf) { + Ok(0) => return (r, None), + Ok(n) => n, + Err(e) => return (r, Some(e)), + }; + r.bytes += read; + for (o, &b) in buf[..read].iter().enumerate() { + if let Ok(i) = b.extra_utf8_bytes() { + r.utf8[i] += 1; + if i == 3 { + let min = o.saturating_sub(20); + let max = if o+23 <= read {o+23} else {read}; + println!("{}", String::from_utf8_lossy(&buf[min..max])); + } + } + } + } +} + +fn display(name_pad: usize, name: Cow, + r: Distribution, err: Option) { + let c = r.utf8; + let characters = c[0]+c[1]+c[2]+c[3]; + let s = [c[0], c[1]*2, c[2]*3, c[3]*4]; + let p = [ + (s[0]*100) as f32 / r.bytes as f32, + (s[1]*100) as f32 / r.bytes as f32, + (s[2]*100) as f32 / r.bytes as f32, + (s[3]*100) as f32 / r.bytes as f32, + ]; + println!("{:>6$}: bytes: {:7}, UTF-8 distribution: [{:7}, {:6}, {:6}, {:6}]", + name, r.bytes, s[0], s[1], s[2], s[3], name_pad + ); + println!("{5:6$} chars: {:7}, UTF-8 percentages: [{:>6.2}%, {:>5.2}%, {:>5.2}%, {:>5.2}%]", + characters, p[0], p[1], p[2], p[3], "", name_pad + ); + if let Some(err) = err { + println!("{1:2$} {}", err, "", name_pad); + } +} + +fn main() { + let name_length = args_os().skip(1) + .map(|path| path.to_string_lossy().chars().count() ) + .max(); + for path in args_os().skip(1) { + let name = path.to_string_lossy(); + let (r,err) = match File::open(&path) { + Ok(mut file) => read(&mut file), + Err(err) => { + eprintln!("{}:\t{}", name, err); + continue; + } + }; + display(name_length.unwrap(), name, r, err); + } + if name_length.is_none() { + let stdin = stdin(); + let (r,err) = read(&mut stdin.lock()); + display(0, Cow::Borrowed("stdin"), r, err); + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/decoding_iterators.rs b/anneal/v2/vendor/encode_unicode/src/decoding_iterators.rs new file mode 100644 index 0000000000..92bc06087c --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/decoding_iterators.rs @@ -0,0 +1,490 @@ +/* Copyright 2018-2020 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Iterators that turn multiple `u8`s or `u16`s into `Utf*Char`s, but can fail. +//! +//! To be predictable, all errors consume one element each. +//! +//! The iterator adaptors produce neither offset nor element length to work +//! well with other adaptors, +//! while the slice iterators yield both to make more advanced use cases easy. + +use crate::errors::{Utf16FirstUnitError, Utf16PairError, Utf8Error}; +use crate::errors::Utf16SliceError::*; +use crate::errors::Utf16PairError::*; +use crate::errors::Utf8ErrorKind::*; +use crate::utf8_char::Utf8Char; +use crate::utf16_char::Utf16Char; +use crate::traits::U16UtfExt; +extern crate core; +use core::borrow::Borrow; +use core::fmt::{self, Debug}; +use core::iter::Chain; +use core::option; + + +/// Decodes UTF-8 characters from a byte iterator into `Utf8Char`s. +/// +/// See [`IterExt::to_utf8chars()`](../trait.IterExt.html#tymethod.to_utf8chars) +/// for examples and error handling. +#[derive(Clone, Default)] +pub struct Utf8CharMerger, I:Iterator> { + iter: I, + /// number of bytes that were read before an error was detected + after_err_leftover: u8, + /// stack because it simplifies popping. + after_err_stack: [u8; 3], +} +impl, I:Iterator, T:IntoIterator> +From for Utf8CharMerger { + fn from(t: T) -> Self { + Utf8CharMerger { + iter: t.into_iter(), + after_err_leftover: 0, + after_err_stack: [0; 3], + } + } +} +impl, I:Iterator> Utf8CharMerger { + /// Extract the inner iterator. + /// + /// If the last item produced by `.next()` was an `Err`, + /// up to three following bytes might be missing. + /// The exact number of missing bytes for each error type should not be relied on. + /// + /// # Examples + /// + /// Three bytes swallowed: + /// ``` + /// # use encode_unicode::IterExt; + /// let mut merger = b"\xf4\xa1\xb2FS".iter().to_utf8chars(); + /// assert!(merger.next().unwrap().is_err()); + /// let mut inner: std::slice::Iter = merger.into_inner(); + /// assert_eq!(inner.next(), Some(&b'S')); // b'\xa1', b'\xb2' and b'F' disappeared + /// ``` + /// + /// All bytes present: + /// ``` + /// # use encode_unicode::IterExt; + /// let mut merger = b"\xb0FS".iter().to_utf8chars(); + /// assert!(merger.next().unwrap().is_err()); + /// assert_eq!(merger.into_inner().next(), Some(&b'F')); + /// ``` + /// + /// Two bytes missing: + /// ``` + /// # use encode_unicode::IterExt; + /// let mut merger = b"\xe0\x80\x80FS".iter().to_utf8chars(); + /// assert!(merger.next().unwrap().is_err()); + /// assert_eq!(merger.into_inner().next(), Some(&b'F')); + /// ``` + pub fn into_inner(self) -> I { + self.iter + } + + fn save(&mut self, bytes: &[u8;4], len: usize) { + // forget bytes[0] and push the others onto self.after_err_stack (in reverse). + for &after_err in bytes[1..len].iter().rev() { + self.after_err_stack[self.after_err_leftover as usize] = after_err; + self.after_err_leftover += 1; + } + } + /// Reads len-1 bytes into bytes[1..] + fn extra(&mut self, bytes: &mut[u8;4], len: usize) -> Result<(),Utf8Error> { + // This is the only function that pushes onto after_err_stack, + // and it checks that all bytes are continuation bytes before fetching the next one. + // Therefore only the last byte retrieved can be a non-continuation byte. + // That last byte is also the last to be retrieved from after_err. + // + // Before this function is called, there has been retrieved at least one byte. + // If that byte was a continuation byte, next() produces an error + // and won't call this function. + // Therefore, we know that after_err is empty at this point. + // This means that we can use self.iter directly, and knows where to start pushing + debug_assert_eq!(self.after_err_leftover, 0, "first: {:#02x}, stack: {:?}", bytes[0], self.after_err_stack); + for i in 1..len { + if let Some(extra) = self.iter.next() { + let extra = *extra.borrow(); + bytes[i] = extra; + if extra & 0b1100_0000 != 0b1000_0000 { + // not a continuation byte + self.save(bytes, i+1); + return Err(Utf8Error{ kind: InterruptedSequence }) + } + } else { + self.save(bytes, i); + return Err(Utf8Error{ kind: TooFewBytes }); + } + } + Ok(()) + } +} +impl, I:Iterator> Iterator for Utf8CharMerger { + type Item = Result; + fn next(&mut self) -> Option { + let first: u8; + if self.after_err_leftover != 0 { + self.after_err_leftover -= 1; + first = self.after_err_stack[self.after_err_leftover as usize]; + } else if let Some(next) = self.iter.next() { + first = *next.borrow(); + } else { + return None; + } + + unsafe { + let mut bytes = [first, 0, 0, 0]; + let ok = match first { + 0b0000_0000..=0b0111_1111 => {/*1 and */Ok(())}, + 0b1100_0010..=0b1101_1111 => {//2 and not overlong + self.extra(&mut bytes, 2) // no extra validation required + }, + 0b1110_0000..=0b1110_1111 => {//3 + if let Err(e) = self.extra(&mut bytes, 3) { + Err(e) + } else if bytes[0] == 0b1110_0000 && bytes[1] <= 0b10_011111 { + self.save(&bytes, 3); + Err(Utf8Error{ kind: OverlongEncoding }) + } else if bytes[0] == 0b1110_1101 && bytes[1] & 0b11_100000 == 0b10_100000 { + self.save(&bytes, 3); + Err(Utf8Error{ kind: Utf16ReservedCodepoint }) + } else { + Ok(()) + } + }, + 0b1111_0000..=0b1111_0100 => {//4 + if let Err(e) = self.extra(&mut bytes, 4) { + Err(e) + } else if bytes[0] == 0b11110_000 && bytes[1] <= 0b10_001111 { + self.save(&bytes, 4); + Err(Utf8Error{ kind: OverlongEncoding }) + } else if bytes[0] == 0b11110_100 && bytes[1] > 0b10_001111 { + self.save(&bytes, 4); + Err(Utf8Error{ kind: TooHighCodepoint }) + } else { + Ok(()) + } + }, + 0b1000_0000..=0b1011_1111 => {// continuation byte + Err(Utf8Error{ kind: UnexpectedContinuationByte }) + }, + 0b1100_0000..=0b1100_0001 => {// 2 and overlong + Err(Utf8Error{ kind: NonUtf8Byte }) + }, + 0b1111_0101..=0b1111_0111 => {// 4 and too high codepoint + Err(Utf8Error{ kind: NonUtf8Byte }) + }, + 0b1111_1000..=0b1111_1111 => { + Err(Utf8Error{ kind: NonUtf8Byte }) + }, + }; + Some(ok.map(|()| Utf8Char::from_array_unchecked(bytes) )) + } + } + fn size_hint(&self) -> (usize,Option) { + let (iter_min, iter_max) = self.iter.size_hint(); + // cannot be exact, so KISS + let min = iter_min / 4; // don't bother rounding up or accounting for after_err + // handle edge case of max > usize::MAX-3 just in case. + // Using wrapping_add() wouldn't violate any API contract as the trait isn't unsafe. + let max = iter_max.and_then(|max| { + max.checked_add(self.after_err_leftover as usize) + }); + (min, max) + } +} +impl, I:Iterator+Debug> Debug for Utf8CharMerger { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + let mut in_order = [0u8; 3]; + for i in 0..self.after_err_leftover as usize { + in_order[i] = self.after_err_stack[self.after_err_leftover as usize - i - 1]; + } + fmtr.debug_struct("Utf8CharMerger") + .field("buffered", &&in_order[..self.after_err_leftover as usize]) + .field("inner", &self.iter) + .finish() + } +} + + +/// An [`Utf8CharMerger`](struct.Utf8CharMerger.html) that also produces +/// offsets and lengths, but can only iterate over slices. +/// +/// See [`SliceExt::utf8char_indices()`](../trait.SliceExt.html#tymethod.utf8char_indices) +/// for examples and error handling. +#[derive(Clone, Default)] +pub struct Utf8CharDecoder<'a> { + slice: &'a[u8], + index: usize, +} +impl<'a> From<&'a[u8]> for Utf8CharDecoder<'a> { + fn from(s: &[u8]) -> Utf8CharDecoder { + Utf8CharDecoder { slice: s, index: 0 } + } +} +impl<'a> Utf8CharDecoder<'a> { + /// Extract the remainder of the source slice. + /// + /// # Examples + /// + /// Unlike `Utf8CharMerger::into_inner()`, bytes directly after an error + /// are never swallowed: + /// ``` + /// # use encode_unicode::SliceExt; + /// let mut iter = b"\xf4\xa1\xb2FS".utf8char_indices(); + /// assert!(iter.next().unwrap().1.is_err()); + /// assert_eq!(iter.as_slice(), b"\xa1\xb2FS"); + /// ``` + pub fn as_slice(&self) -> &'a[u8] { + &self.slice[self.index..] + } +} +impl<'a> Iterator for Utf8CharDecoder<'a> { + type Item = (usize, Result, usize); + fn next(&mut self) -> Option { + let start = self.index; + match Utf8Char::from_slice_start(&self.slice[self.index..]) { + Ok((u8c, len)) => { + self.index += len; + Some((start, Ok(u8c), len)) + }, + Err(_) if self.slice.len() <= self.index => None, + Err(e) => { + self.index += 1; + Some((start, Err(e), 1)) + } + } + } + #[inline] + fn size_hint(&self) -> (usize,Option) { + let bytes = self.slice.len() - self.index; + // Cannot be exact, so KISS and don't bother rounding up. + // The slice is unlikely be full of 4-byte codepoints, so buffers + // allocated with the lower bound will have to be grown anyway. + (bytes/4, Some(bytes)) + } +} +impl<'a> DoubleEndedIterator for Utf8CharDecoder<'a> { + fn next_back(&mut self) -> Option { + if self.index < self.slice.len() { + let extras = self.slice.iter() + .rev() + .take_while(|&b| b & 0b1100_0000 == 0b1000_0000 ) + .count(); + let starts = self.slice.len() - (extras+1); + match Utf8Char::from_slice_start(&self.slice[starts..]) { + Ok((u8c,len)) if len == 1+extras => { + self.slice = &self.slice[..starts]; + Some((starts, Ok(u8c), len)) + }, + // This enures errors for every byte in both directions, + // but means overlong and codepoint errors will be turned into + // tooshort errors. + Err(e) if extras == 0 => { + self.slice = &self.slice[..self.slice.len()-1]; + Some((self.slice.len()-1, Err(e), 1)) + }, + _ => { + self.slice = &self.slice[..self.slice.len()-1]; + Some((self.slice.len()-1, Err(Utf8Error{ kind: UnexpectedContinuationByte }), 1)) + }, + } + } else { + None + } + } +} +impl<'a> Debug for Utf8CharDecoder<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + write!(fmtr, "Utf8CharDecoder {{ bytes[{}..]: {:?} }}", self.index, self.as_slice()) + } +} + + + +/// Decodes UTF-16 characters from a `u16` iterator into `Utf16Char`s. +/// +/// See [`IterExt::to_utf16chars()`](../trait.IterExt.html#tymethod.to_utf16chars) +/// for examples and error handling. +#[derive(Clone, Default)] +pub struct Utf16CharMerger, I:Iterator> { + iter: I, + /// Used when a trailing surrogate was expected, the u16 can be any value. + prev: Option, +} +impl, I:Iterator, T:IntoIterator> +From for Utf16CharMerger { + fn from(t: T) -> Self { + Utf16CharMerger { iter: t.into_iter(), prev: None } + } +} +impl, I:Iterator> Utf16CharMerger { + /// Extract the inner iterator. + /// + /// If the last item produced was an `Err`, the first unit might be missing. + /// + /// # Examples + /// + /// Unit right after an error missing + /// ``` + /// # use encode_unicode::IterExt; + /// # use encode_unicode::error::Utf16PairError; + /// let mut merger = [0xd901, 'F' as u16, 'S' as u16].iter().to_utf16chars(); + /// assert_eq!(merger.next(), Some(Err(Utf16PairError::UnmatchedLeadingSurrogate))); + /// let mut inner: std::slice::Iter = merger.into_inner(); + /// assert_eq!(inner.next(), Some('S' as u16).as_ref()); // 'F' was consumed by Utf16CharMerger + /// ``` + /// + /// Error that doesn't swallow any units + /// ``` + /// # use encode_unicode::IterExt; + /// # use encode_unicode::error::Utf16PairError; + /// let mut merger = [0xde00, 'F' as u16, 'S' as u16].iter().to_utf16chars(); + /// assert_eq!(merger.next(), Some(Err(Utf16PairError::UnexpectedTrailingSurrogate))); + /// let mut inner: std::slice::Iter = merger.into_inner(); + /// assert_eq!(inner.next(), Some('F' as u16).as_ref()); // not consumed + /// ``` + pub fn into_inner(self) -> I { + self.iter + } + /// Returns an iterator over the remaining units. + /// Unlike `into_inner()` this will never drop any units. + /// + /// The exact type of the returned iterator should not be depended on. + /// + /// # Examples + /// + /// ``` + /// # use encode_unicode::IterExt; + /// # use encode_unicode::error::Utf16PairError; + /// let slice = [0xd901, 'F' as u16, 'S' as u16]; + /// let mut merger = slice.iter().to_utf16chars(); + /// assert_eq!(merger.next(), Some(Err(Utf16PairError::UnmatchedLeadingSurrogate))); + /// let mut remaining = merger.into_remaining_units(); + /// assert_eq!(remaining.next(), Some('F' as u16).as_ref()); + /// ``` + pub fn into_remaining_units(self) -> Chain,I> { + self.prev.into_iter().chain(self.iter) + } +} +impl, I:Iterator> Iterator for Utf16CharMerger { + type Item = Result; + fn next(&mut self) -> Option { + let first = self.prev.take().or_else(|| self.iter.next() ); + first.map(|first| unsafe { + match first.borrow().utf16_needs_extra_unit() { + Ok(false) => Ok(Utf16Char::from_array_unchecked([*first.borrow(), 0])), + Ok(true) => match self.iter.next() { + Some(second) => match second.borrow().utf16_needs_extra_unit() { + Err(Utf16FirstUnitError) => Ok(Utf16Char::from_tuple_unchecked(( + *first.borrow(), + Some(*second.borrow()) + ))), + Ok(_) => { + self.prev = Some(second); + Err(Utf16PairError::UnmatchedLeadingSurrogate) + } + }, + None => Err(Utf16PairError::Incomplete) + }, + Err(Utf16FirstUnitError) => Err(Utf16PairError::UnexpectedTrailingSurrogate), + } + }) + } + fn size_hint(&self) -> (usize,Option) { + let (iter_min, iter_max) = self.iter.size_hint(); + // cannot be exact, so KISS + let min = iter_min / 2; // don't bother rounding up or accounting for self.prev + let max = match (iter_max, &self.prev) { + (Some(max), &Some(_)) => max.checked_add(1), + (max, _) => max, + }; + (min, max) + } +} +impl, I:Iterator+Debug> Debug for Utf16CharMerger { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.debug_struct("Utf16CharMerger") + .field("buffered", &self.prev.as_ref().map(|b| *b.borrow() )) + .field("inner", &self.iter) + .finish() + } +} + + +/// An [`Utf16CharMerger`](struct.Utf16CharMerger.html) that also produces +/// offsets and lengths, but can only iterate over slices. +/// +/// See [`SliceExt::utf16char_indices()`](../trait.SliceExt.html#tymethod.utf16char_indices) +/// for examples and error handling. +#[derive(Clone, Default)] +pub struct Utf16CharDecoder<'a> { + slice: &'a[u16], + index: usize, +} +impl<'a> From<&'a[u16]> for Utf16CharDecoder<'a> { + fn from(s: &'a[u16]) -> Self { + Utf16CharDecoder{ slice: s, index: 0 } + } +} +impl<'a> Utf16CharDecoder<'a> { + /// Extract the remainder of the source slice. + /// + /// # Examples + /// + /// Unlike `Utf16CharMerger::into_inner()`, the unit after an error is never swallowed: + /// ``` + /// # use encode_unicode::SliceExt; + /// # use encode_unicode::error::Utf16PairError; + /// let mut iter = [0xd901, 'F' as u16, 'S' as u16].utf16char_indices(); + /// assert_eq!(iter.next(), Some((0, Err(Utf16PairError::UnmatchedLeadingSurrogate), 1))); + /// assert_eq!(iter.as_slice(), &['F' as u16, 'S' as u16]); + /// ``` + pub fn as_slice(&self) -> &[u16] { + &self.slice[self.index..] + } +} +impl<'a> Iterator for Utf16CharDecoder<'a> { + type Item = (usize,Result,usize); + #[inline] + fn next(&mut self) -> Option { + let start = self.index; + match Utf16Char::from_slice_start(self.as_slice()) { + Ok((u16c,len)) => { + self.index += len; + Some((start, Ok(u16c), len)) + }, + Err(EmptySlice) => None, + Err(FirstIsTrailingSurrogate) => { + self.index += 1; + Some((start, Err(UnexpectedTrailingSurrogate), 1)) + }, + Err(SecondIsNotTrailingSurrogate) => { + self.index += 1; + Some((start, Err(UnmatchedLeadingSurrogate), 1)) + }, + Err(MissingSecond) => { + self.index = self.slice.len(); + Some((start, Err(Incomplete), 1)) + } + } + } + #[inline] + fn size_hint(&self) -> (usize,Option) { + let units = self.slice.len() - self.index; + // Cannot be exact, so KISS and don't bother rounding up. + // The slice is unlikely be full of surrogate pairs, so buffers + // allocated with the lower bound will have to be grown anyway. + (units/2, Some(units)) + } +} +impl<'a> Debug for Utf16CharDecoder<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + write!(fmtr, "Utf16CharDecoder {{ units[{}..]: {:?} }}", self.index, self.as_slice()) + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/errors.rs b/anneal/v2/vendor/encode_unicode/src/errors.rs new file mode 100644 index 0000000000..13b6ca5fa6 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/errors.rs @@ -0,0 +1,309 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + + +//! Boilerplate-y error types. +//! +//! The discriminant values of the enums might change in minor releases. +//! (to reduce the size of the `Result<>` types they are returned in) + +extern crate core; +use core::fmt::{self,Display,Formatter}; +use core::ops::RangeInclusive; +#[cfg(feature="std")] +use std::error::Error; + + +macro_rules! description {($err:ty, $desc:expr) => { + #[cfg(not(feature="std"))] + impl $err { + #[allow(missing_docs)] + pub fn description(&self) -> &'static str { + ($desc)(self) + } + } + #[cfg(feature="std")] + impl Error for $err { + fn description(&self) -> &'static str { + ($desc)(self) + } + } + impl Display for $err { + fn fmt(&self, fmtr: &mut Formatter) -> fmt::Result { + #![allow(deprecated)] // calling our own function + write!(fmtr, "{}", self.description()) + } + } +}} + + +macro_rules! single_cause {($(#[$doc:meta])* $err:ident => $desc:expr) => { + $(#[$doc])* + #[derive(Clone,Copy, Debug, PartialEq,Eq)] + pub struct $err; + description!{$err, |_| $desc } +}} + + +single_cause!{ + /// Error returned by [`U16UtfExt::utf16_needs_extra_unit()`](../trait.U16UtfExt.html#tymethod.utf16_needs_extra_unit) + /// when called on an `u16` that's a trailing surrogate. + Utf16FirstUnitError => "is a trailing surrogate" +} + +single_cause!{ + /// Error returned by [`Utf8Char::from_ascii()`](../struct.Utf8Char.html#method.from_ascii) + /// for bytes that are not ASCII characters. + NonAsciiError => "not an ASCII character" +} + +single_cause!{ + /// Error returned by [`Utf16Char::from_bmp()`](../struct.Utf16Char.html#method.from_bmp) + /// for units that are not a standalone codepoint. + NonBmpError => "not a codepoint in the basic multilingual plane" +} + +single_cause!{ + /// Error returned by [`Utf8Char::from_str_start()`](../struct.Utf8Char.html#method.from_str_start) + /// and [`Utf16Char::from_str_start()`](../struct.Utf16Char.html#method.from_str_start) + /// when called with an empty string. + EmptyStrError => "is empty" +} + + + +macro_rules! simple {($(#[$tydoc:meta])* $err:ident { + $( $(#[$vardoc:meta])* $variant:ident => $string:expr, )+ + } ) => { + $(#[$tydoc])* + #[derive(Clone,Copy, Debug, PartialEq,Eq)] + pub enum $err { + $( $(#[$vardoc])* $variant, )* + } + description!{$err, |e: &$err| match *e {$($err::$variant => $string),*} } +}} + + +simple!{ + /// Error returned when an `u32` is not a valid unicode codepoint. + CodepointError { + /// It's reserved for UTF-16 surrogate pairs. + Utf16Reserved => "is reserved for UTF-16 surrogate pairs", + /// It's higher than the highest codepoint (which is 0x10ffff). + TooHigh => "is higher than the highest codepoint", + }} +use CodepointError::*; +impl CodepointError { + /// Get the range of values for which this error would be given. + pub const fn error_range(self) -> RangeInclusive {match self { + Utf16Reserved => 0xd8_00..=0xdf_ff, + TooHigh => 0x00_10_ff_ff..=0xff_ff_ff_ff, + }} +} + + +simple!{ + /// Error returned when an `[u16; 2]` doesn't form a valid UTF-16 codepoint. + Utf16ArrayError { + /// The first element is a trailing / low surrogate, which is never valid. + FirstIsTrailingSurrogate => "the first element is a trailing surrogate", + /// The second element is needed, but is not a trailing surrogate. + SecondIsNotTrailingSurrogate => "the second element is needed but is not a trailing surrogate", + }} + +simple!{ + /// Error returned when one or two `u16`s are not valid UTF-16. + /// + /// They are returned in sinking precedence; + /// The condition that causes the first variant to be returned is checked + /// for before the condition the next variant is returned for. + Utf16TupleError { + /// The first unit is a trailing / low surrogate, which is never valid. + FirstIsTrailingSurrogate => "the first unit is a trailing surrogate", + /// The provided second unit is not necessary. + SuperfluousSecond => "the second unit is superfluous", + /// The first and only unit requires a second unit. + MissingSecond => "the first unit requires a second unit", + /// The second unit is needed and was provided, but is not a trailing surrogate. + SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate", + }} + + +simple!{ + /// Error returned when a slice of `u16`s doesn't start with valid UTF-16. + Utf16SliceError { + /// The slice is empty. + EmptySlice => "the slice is empty", + /// The first unit is a trailing surrogate. + FirstIsTrailingSurrogate => "the first unit is a trailing surrogate", + /// The first and only unit requires a second unit. + MissingSecond => "the first and only unit requires a second one", + /// The first unit requires a second one, but it's not a trailing surrogate. + SecondIsNotTrailingSurrogate => "the required second unit is not a trailing surrogate", + }} + +simple!{ + /// Error returned by [`Utf16CharDecoder`](../iterator/struct.Utf16CharMerger.html#impl-Iterator) + /// when it encounters an invalid sequence. + Utf16PairError { + /// A trailing surrogate was not preceeded by a leading surrogate. + UnexpectedTrailingSurrogate => "a trailing surrogate was not preceeded by a leading surrogate", + /// A leading surrogate was followed by an unit that was not a trailing surrogate. + UnmatchedLeadingSurrogate => "a leading surrogate was followed by an unit that was not a trailing surrogate", + /// A trailing surrogate was expected when the end was reached. + Incomplete => "a trailing surrogate was expected when the end was reached", + }} + + +simple!{ + /// Error returned when [`Utf8Char::from_str()`](../struct.Utf8Char.html#impl-FromStr) + /// or [`Utf16Char::from_str()`](../struct.Utf16Char.html#impl-FromStr) fails. + FromStrError { + /// `Utf8Char` and `Utf16Char` cannot store more than a single codepoint. + MultipleCodepoints => "contains more than one codepoint", + /// `Utf8Char` and `Utf16Char` cannot be empty. + Empty => "is empty", + } +} + + + +/// Error returned when an invalid UTF-8 sequence is encountered. +/// +/// See [`Utf8ErrorKind`](enum.Utf8ErrorKind.html) for the types of errors +/// that this type can be returned for. +#[derive(Clone,Copy, Debug, PartialEq,Eq)] +pub struct Utf8Error { + pub(crate) kind: Utf8ErrorKind, +} +impl Utf8Error { + /// Get the type of error. + pub const fn kind(&self) -> Utf8ErrorKind { + self.kind + } + + #[cfg(not(feature="std"))] + #[allow(missing_docs)] + pub const fn description(&self) -> &'static str { + utf8_error_description(self.kind) + } +} +#[cfg(feature="std")] +impl Error for Utf8Error { + fn description(&self) -> &'static str { + utf8_error_description(self.kind) + } +} +impl Display for Utf8Error { + fn fmt(&self, fmtr: &mut Formatter) -> fmt::Result { + fmtr.write_str(utf8_error_description(self.kind)) + } +} + +/// The types of errors that can occur when decoding a UTF-8 codepoint. +/// +/// The variants are more technical than what an end user is likely interested +/// in, but might be useful for deciding how to handle the error. +/// +/// They can be grouped into three categories: +/// * Will happen regularly if decoding chunked or buffered text: `TooFewBytes`. +/// * Input might be binary, a different encoding or corrupted, `UnexpectedContinuationByte` +/// and `InterruptedSequence`. +/// (Broken UTF-8 sequence). +/// * Less likely to happen accidentaly and might be malicious: +/// `OverlongEncoding`, `Utf16ReservedCodepoint` and `TooHighCodepoint`. +/// Note that theese can still be caused by certain valid latin-1 strings +/// such as `"Á©"` (`b"\xC1\xA9"`). +#[derive(Clone,Copy, Debug, PartialEq,Eq)] +pub enum Utf8ErrorKind { + /// There are too few bytes to decode the codepoint. + /// + /// This can happen when a slice is empty or too short, or an iterator + /// returned `None` while in the middle of a codepoint. + /// This error is never produced by functions accepting fixed-size + /// `[u8; 4]` arrays. + /// + /// If decoding text coming chunked (such as in buffers passed to `Read`), + /// the remaing bytes should be carried over into the next chunk or buffer. + /// (including the byte this error was produced for.) + TooFewBytes, + /// A byte which is never used by well-formed UTF-8 was encountered. + /// + /// This means that the input is using a different encoding, + /// is corrupted or binary. + /// + /// This error is returned when a byte in the following ranges + /// is encountered anywhere in an UTF-8 sequence: + /// + /// * `192` and `193` (`0b1100_000x`): Indicates an overlong encoding + /// of a single-byte, ASCII, character, and should therefore never occur. + /// * `248..` (`0b1111_1xxx`): Sequences cannot be longer than 4 bytes. + /// * `245..=247` (`0b1111_0101 | 0b1111_0110`): Indicates a too high + /// codepoint. (above `\u10ffff`) + NonUtf8Byte, + /// The first byte is not a valid start of a codepoint. + /// + /// This might happen as a result of slicing into the middle of a codepoint, + /// the input not being UTF-8 encoded or being corrupted. + /// Errors of this type coming right after another error should probably + /// be ignored, unless returned more than three times in a row. + /// + /// This error is returned when the first byte has a value in the range + /// `128..=191` (`0b1000_0000..=0b1011_1111`). + UnexpectedContinuationByte, + /// The byte at index 1..=3 should be a continuation byte, + /// but doesn't fit the pattern `0b10xx_xxxx`. + /// + /// When the input slice or iterator has too few bytes, + /// [`TooFewBytes`](#Incomplete) is returned instead. + InterruptedSequence, + /// The encoding of the codepoint has so many leading zeroes that it + /// could be a byte shorter. + /// + /// [Successfully decoding this can present a security issue](https://tools.ietf.org/html/rfc3629#section-10): + /// Doing so could allow an attacker to circumvent input validation that + /// only checks for ASCII characters, and input characters or strings that + /// would otherwise be rejected, such as `/../`. + /// + /// This error is only returned for 3 and 4-byte encodings; + /// `NonUtf8Byte` is returned for bytes that start longer or shorter + /// overlong encodings. + OverlongEncoding, + /// The codepoint is reserved for UTF-16 surrogate pairs. + /// + /// (`Utf8Char` cannot be used to work with the + /// [WTF-8](https://simonsapin.github.io/wtf-8) encoding for UCS-2 strings.) + /// + /// This error is returned for codepoints in the range `\ud800`..=`\udfff`. + /// (which are three bytes long as UTF-8) + Utf16ReservedCodepoint, + /// The codepoint is higher than `\u10ffff`, which is the highest codepoint + /// unicode permits. + TooHighCodepoint, +} +const fn utf8_error_description(kind: Utf8ErrorKind) -> &'static str { + match kind { + Utf8ErrorKind::TooFewBytes => "too few bytes", + Utf8ErrorKind::NonUtf8Byte => "not UTF-8", + Utf8ErrorKind::UnexpectedContinuationByte => "not UTF-8", + Utf8ErrorKind::InterruptedSequence => "not UTF-8", + Utf8ErrorKind::OverlongEncoding => "malformed input", + Utf8ErrorKind::Utf16ReservedCodepoint => "malformed input", + Utf8ErrorKind::TooHighCodepoint => "invalid character", + } +} +impl PartialEq for Utf8Error { + fn eq(&self, kind: &Utf8ErrorKind) -> bool { + self.kind == *kind + } +} +impl PartialEq for Utf8ErrorKind { + fn eq(&self, error: &Utf8Error) -> bool { + *self == error.kind + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/lib.rs b/anneal/v2/vendor/encode_unicode/src/lib.rs new file mode 100644 index 0000000000..939125d1c4 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/lib.rs @@ -0,0 +1,89 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * Copyright 2018 Aljoscha Meyer + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + + +/*! +Miscellaneous UTF-8 and UTF-16 types and methods. + +# Optional features: +* `#![no_std]`-mode: There are a few differences: + * `Error` doesn't exist, but `description()` is made available as an inherent impl. + * `Extend`/`FromIterator`-implementations for `String`/`Vec`/`Vec` are missing. + * There is no `io`, so `Utf8Iterator` and `Utf8CharSplitter` doesn't implement `Read`. + + This feature is enabled by setting `default-features=false` in `Cargo.toml`: + `encode_unicode = {version="0.3.4", default-features=false}` +* Integration with the [ascii](https://tomprogrammer.github.io/rust-ascii/ascii/index.html) crate: + Convert `Utf8Char` and `Utf16Char` to and from + [`ascii::AsciiChar`](https://tomprogrammer.github.io/rust-ascii/ascii/enum.AsciiChar.html). + +# Minimum supported Rust version + +The minimum supported Rust version for 1.0.\* releases is 1.56. +Later 1.y.0 releases might require newer Rust versions, but the three most +recent stable releases at the time of publishing will always be supported. +For example this means that if the current stable Rust version is 1.66 when +`encode_unicode` 1.1.0 is released, then `encode_unicode` 1.1.\* will +not require a newer Rust version than 1.63. + +[crates.io page](https://crates.io/crates/encode_unicode) +[github repository](https://github.com/tormol/encode_unicode) + +*/ + +#![cfg_attr(not(feature="std"), no_std)] + +#![warn(missing_docs, unsafe_op_in_unsafe_fn)] +#![allow( + clippy::unusual_byte_groupings,// I sometimes group into UTF-8 control part and codepoint part + clippy::derive_hash_xor_eq,// tested + clippy::len_without_is_empty,// the character types are never empty + clippy::needless_return,// `foo.bar();\n foo` looks unfinished + clippy::redundant_closure_call,// not redundant in macros + clippy::cast_lossless,// the sizes are part of the struct name and so won't change + clippy::many_single_char_names,// the variables are in different scopes + clippy::cmp_owned,// smaller than pointer, and no allocations anyway + clippy::wrong_self_convention,// smaller than pointer + clippy::needless_range_loop,// the suggested iterator chains are less intuitive + clippy::identity_op,// applying a set of opereations with varying arguments to many elements looks nice + clippy::get_first,// .get(0), .get(1) is more readable + clippy::question_mark,// I prefer it very explicit +)] +#![warn(clippy::doc_markdown, clippy::manual_filter_map)] +// opt-in lints that might be interesting to recheck once in a while: +//#![warn(clippy::unwrap_used)] + +mod errors; +mod traits; +mod utf8_char; +mod utf8_iterators; +mod utf16_char; +mod utf16_iterators; +mod decoding_iterators; + +pub use traits::{CharExt, U8UtfExt, U16UtfExt, StrExt, IterExt, SliceExt}; +pub use utf8_char::Utf8Char; +pub use utf16_char::Utf16Char; + +pub mod error {// keeping the public interface in one file + //! Errors returned by various conversion methods in this crate. + pub use crate::errors::{FromStrError, EmptyStrError}; + pub use crate::errors::{CodepointError, NonAsciiError, NonBmpError}; + pub use crate::errors::{Utf8Error, Utf8ErrorKind}; + pub use crate::errors::{Utf16SliceError, Utf16ArrayError, Utf16TupleError}; + pub use crate::errors::{Utf16FirstUnitError, Utf16PairError}; +} + +pub mod iterator { + //! Iterator types that you should rarely need to name + pub use crate::utf8_iterators::{Utf8Iterator, Utf8CharSplitter, Utf8Chars, Utf8CharIndices}; + pub use crate::utf16_iterators::{Utf16Iterator, Utf16CharSplitter, Utf16Chars, Utf16CharIndices}; + pub use crate::decoding_iterators::{Utf8CharMerger, Utf8CharDecoder}; + pub use crate::decoding_iterators::{Utf16CharMerger, Utf16CharDecoder}; +} diff --git a/anneal/v2/vendor/encode_unicode/src/traits.rs b/anneal/v2/vendor/encode_unicode/src/traits.rs new file mode 100644 index 0000000000..53b1211e07 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/traits.rs @@ -0,0 +1,1012 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * Copyright 2018 Aljoscha Meyer + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +use crate::utf8_char::Utf8Char; +use crate::utf16_char::Utf16Char; +use crate::utf8_iterators::*; +use crate::utf16_iterators::*; +use crate::decoding_iterators::*; +use crate::error::*; +use crate::error::Utf8ErrorKind::*; +extern crate core; +use core::{char, u32}; +use core::ops::{Not, Index, RangeFull}; +use core::borrow::Borrow; +#[cfg(feature="ascii")] +extern crate ascii; +#[cfg(feature="ascii")] +use ascii::AsciiStr; + +// TODO better docs and tests + +/// Methods for working with `u8`s as UTF-8 bytes. +pub trait U8UtfExt { + /// How many more bytes will you need to complete this codepoint? + /// + /// # Errors + /// + /// An error is returned if the byte is not a valid start of an UTF-8 + /// codepoint: + /// + /// * `128..192`: [`UnexpectedContinuationByte`](error/enum.Utf8ErrorKind.html#variant.UnexpectedContinuationByte) + /// * `245..`, `192` and `193`: [`NonUtf8Byte`](error/enum.Utf8ErrorKind.html#variant.NonUtf8Byte) + fn extra_utf8_bytes(self) -> Result; + + /// How many more bytes will you need to complete this codepoint? + /// + /// This function assumes that the byte is a valid UTF-8 start, and might + /// return any value otherwise. (but the function is safe to call with any + /// value and will return a consistent result). + fn extra_utf8_bytes_unchecked(self) -> usize; +} + +impl U8UtfExt for u8 { + #[inline] + fn extra_utf8_bytes(self) -> Result { + match self { + 0x00..=0x7f => Ok(0), + 0xc2..=0xdf => Ok(1), + 0xe0..=0xef => Ok(2), + 0xf0..=0xf4 => Ok(3), + 0xc0..=0xc1 | 0xf5..=0xff => Err(Utf8Error{ kind: NonUtf8Byte }),// too big or overlong + 0x80..=0xbf => Err(Utf8Error{ kind: UnexpectedContinuationByte }),// following byte + } + } + #[inline] + fn extra_utf8_bytes_unchecked(self) -> usize { + // For fun I've optimized this function (for x86 instruction count): + // The most straightforward implementation, that lets the compiler do + // the optimizing: + //match self { + // 0b0000_0000...0b0111_1111 => 0, + // 0b1100_0010...0b1101_1111 => 1, + // 0b1110_0000...0b1110_1111 => 2, + // 0b1111_0000...0b1111_0100 => 3, + // _ => whatever() + //} + // Using `unsafe{core::hint::unreachable_unchecked()}` for the + // "don't care" case is a terrible idea: while having the function + // non-deterministically return whatever happens to be in a register + // MIGHT be acceptable, it permits the function to not `ret`urn at all, + // but let execution fall through to whatever comes after it in the + // binary! (in other words completely UB). + // Currently unreachable_unchecked() might trap too, + // which is certainly not what we want. + // I also think `unsafe{mem::unitialized()}` is much more likely to + // explicitly produce whatever happens to be in a register than tell + // the compiler it can ignore this branch but needs to produce a value. + // + // From the bit patterns we see that for non-ASCII values the result is + // (number of leading set bits) - 1 + // The standard library doesn't have a method for counting leading ones, + // but it has leading_zeros(), which can be used after inverting. + // This function can therefore be reduced to the one-liner + //`self.not().leading_zeros().saturating_sub(1) as usize`, which would + // be branchless for architectures with instructions for + // leading_zeros() and saturating_sub(). + + // Shortest version as long as ASCII-ness can be predicted: (especially + // if the BSR instruction which leading_zeros() uses is microcoded or + // doesn't exist) + // u8.leading_zeros() would cast to a bigger type internally, so that's + // free. compensating by shifting left by 24 before inverting lets the + // compiler know that the value passed to leading_zeros() is not zero, + // for which BSR's output is undefined and leading_zeros() normally has + // special case with a branch. + // Shifting one bit too many left acts as a saturating_sub(1). + if self<128 {0} else {((self as u32)<<25).not().leading_zeros() as usize} + + // Branchless but longer version: (9 instructions) + // It's tempting to try (self|0x80).not().leading_zeros().wrapping_sub(1), + // but that produces high lengths for ASCII values 0b01xx_xxxx. + // If we could somehow (branchlessy) clear that bit for ASCII values... + // We can by masking with the value shifted right with sign extension! + // (any nonzero number of bits in range works) + //let extended = self as i8 as i32; + //let ascii_cleared = (extended<<25) & (extended>>25); + //ascii_cleared.not().leading_zeros() as usize + + // cmov version: (7 instructions) + //(((self as u32)<<24).not().leading_zeros() as usize).saturating_sub(1) + } +} + + +/// Methods for working with `u16`s as UTF-16 units. +pub trait U16UtfExt { + /// Will you need an extra unit to complete this codepoint? + /// + /// Returns `Err` for trailing surrogates, `Ok(true)` for leading surrogates, + /// and `Ok(false)` for others. + fn utf16_needs_extra_unit(self) -> Result; + + /// Does this `u16` need another `u16` to complete a codepoint? + /// Returns `(self & 0xfc00) == 0xd800` + /// + /// Is basically an unchecked variant of `utf16_needs_extra_unit()`. + fn is_utf16_leading_surrogate(self) -> bool; +} +impl U16UtfExt for u16 { + #[inline] + fn utf16_needs_extra_unit(self) -> Result { + match self { + // https://en.wikipedia.org/wiki/UTF-16#U.2B10000_to_U.2B10FFFF + 0x00_00..=0xd7_ff | 0xe0_00..=0xff_ff => Ok(false), + 0xd8_00..=0xdb_ff => Ok(true), + _ => Err(Utf16FirstUnitError) + } + } + #[inline] + fn is_utf16_leading_surrogate(self) -> bool { + (self & 0xfc00) == 0xd800// Clear the ten content bytes of a surrogate, + // and see if it's a leading surrogate. + } +} + + + + +/// Extension trait for `char` that adds methods for converting to and from UTF-8 or UTF-16. +pub trait CharExt: Sized { + /// Get the UTF-8 representation of this codepoint. + /// + /// `Utf8Char` is to `[u8;4]` what `char` is to `u32`: + /// a restricted type that cannot be mutated internally. + fn to_utf8(self) -> Utf8Char; + + /// Get the UTF-16 representation of this codepoint. + /// + /// `Utf16Char` is to `[u16;2]` what `char` is to `u32`: + /// a restricted type that cannot be mutated internally. + fn to_utf16(self) -> Utf16Char; + + /// Iterate over or [read](https://doc.rust-lang.org/std/io/trait.Read.html) + /// the one to four bytes in the UTF-8 representation of this codepoint. + /// + /// An identical alternative to the unstable `char.encode_utf8()`. + /// That method somehow still exist on stable, so I have to use a different name. + fn iter_utf8_bytes(self) -> Utf8Iterator; + + /// Iterate over the one or two units in the UTF-16 representation of this codepoint. + /// + /// An identical alternative to the unstable `char.encode_utf16()`. + /// That method somehow still exist on stable, so I have to use a different name. + fn iter_utf16_units(self) -> Utf16Iterator; + + + /// Convert this char to an UTF-8 array, and also return how many bytes of + /// the array are used, + /// + /// The returned array is left-aligned with unused bytes set to zero. + fn to_utf8_array(self) -> ([u8; 4], usize); + + /// Convert this `char` to UTF-16. + /// + /// The second element is non-zero when a surrogate pair is required. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// + /// assert_eq!('@'.to_utf16_array(), ['@' as u16, 0]); + /// assert_eq!('睷'.to_utf16_array(), ['睷' as u16, 0]); + /// assert_eq!('\u{abcde}'.to_utf16_array(), [0xda6f, 0xdcde]); + /// ``` + fn to_utf16_array(self) -> [u16; 2]; + + /// Convert this `char` to UTF-16. + /// The second item is `Some` if a surrogate pair is required. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// + /// assert_eq!('@'.to_utf16_tuple(), ('@' as u16, None)); + /// assert_eq!('睷'.to_utf16_tuple(), ('睷' as u16, None)); + /// assert_eq!('\u{abcde}'.to_utf16_tuple(), (0xda6f, Some(0xdcde))); + /// ``` + fn to_utf16_tuple(self) -> (u16, Option); + + + + /// Create a `char` from the start of an UTF-8 slice, + /// and also return how many bytes were used. + /// + /// # Errors + /// + /// Returns an `Err` if the slice is empty, doesn't start with a valid + /// UTF-8 sequence or is too short for the sequence. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// use encode_unicode::error::Utf8ErrorKind::*; + /// + /// assert_eq!(char::from_utf8_slice_start(&[b'A', b'B', b'C']), Ok(('A',1))); + /// assert_eq!(char::from_utf8_slice_start(&[0xdd, 0xbb]), Ok(('\u{77b}',2))); + /// + /// assert_eq!(char::from_utf8_slice_start(&[]).unwrap_err(), TooFewBytes); + /// assert_eq!(char::from_utf8_slice_start(&[0xf0, 0x99]).unwrap_err(), TooFewBytes); + /// assert_eq!(char::from_utf8_slice_start(&[0xee, b'F', 0x80]).unwrap_err(), InterruptedSequence); + /// assert_eq!(char::from_utf8_slice_start(&[0xee, 0x99, 0x0f]).unwrap_err(), InterruptedSequence); + /// ``` + fn from_utf8_slice_start(src: &[u8]) -> Result<(Self,usize),Utf8Error>; + + /// Create a `char` from the start of an UTF-16 slice, + /// and also return how many units were used. + /// + /// If you want to continue after an error, continue with the next `u16` unit. + fn from_utf16_slice_start(src: &[u16]) -> Result<(Self,usize), Utf16SliceError>; + + + /// Convert an UTF-8 sequence as returned from `.to_utf8_array()` into a `char` + /// + /// The codepoint must start at the first byte, and leftover bytes are ignored. + /// + /// # Errors + /// + /// Returns an `Err` if the array doesn't start with a valid UTF-8 sequence. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// use encode_unicode::error::Utf8ErrorKind::*; + /// + /// assert_eq!(char::from_utf8_array([b'A', 0, 0, 0]), Ok('A')); + /// assert_eq!(char::from_utf8_array([0xf4, 0x8b, 0xbb, 0xbb]), Ok('\u{10befb}')); + /// assert_eq!(char::from_utf8_array([b'A', b'B', b'C', b'D']), Ok('A')); + /// assert_eq!(char::from_utf8_array([0, 0, 0xcc, 0xbb]), Ok('\0')); + /// + /// assert_eq!(char::from_utf8_array([0xef, b'F', 0x80, 0x80]).unwrap_err(), InterruptedSequence); + /// assert_eq!(char::from_utf8_array([0xc1, 0x80, 0, 0]).unwrap_err().kind(), NonUtf8Byte); + /// assert_eq!(char::from_utf8_array([0xe0, 0x9a, 0xbf, 0]).unwrap_err().kind(), OverlongEncoding); + /// assert_eq!(char::from_utf8_array([0xf4, 0xaa, 0x99, 0x88]).unwrap_err(), TooHighCodepoint); + /// ``` + fn from_utf8_array(utf8: [u8; 4]) -> Result; + + /// Convert a UTF-16 pair as returned from `.to_utf16_array()` into a `char`. + /// + /// The second element is ignored when not required. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// use encode_unicode::error::Utf16ArrayError; + /// + /// assert_eq!(char::from_utf16_array(['x' as u16, 'y' as u16]), Ok('x')); + /// assert_eq!(char::from_utf16_array(['睷' as u16, 0]), Ok('睷')); + /// assert_eq!(char::from_utf16_array([0xda6f, 0xdcde]), Ok('\u{abcde}')); + /// assert_eq!(char::from_utf16_array([0xf111, 0xdbad]), Ok('\u{f111}')); + /// assert_eq!(char::from_utf16_array([0xdaaf, 0xdaaf]), Err(Utf16ArrayError::SecondIsNotTrailingSurrogate)); + /// assert_eq!(char::from_utf16_array([0xdcac, 0x9000]), Err(Utf16ArrayError::FirstIsTrailingSurrogate)); + /// ``` + fn from_utf16_array(utf16: [u16; 2]) -> Result; + + /// Convert a UTF-16 pair as returned from `.to_utf16_tuple()` into a `char`. + fn from_utf16_tuple(utf16: (u16, Option)) -> Result; + + + /// Convert an UTF-8 sequence into a char. + /// + /// The length of the slice is taken as length of the sequence; + /// it should be 1,2,3 or 4. + /// + /// # Safety + /// + /// The slice must contain exactly one, valid, UTF-8 sequence. + /// + /// Passing a slice that produces an invalid codepoint is always undefined + /// behavior; Later checks that the codepoint is valid can be removed + /// by the compiler. + /// + /// # Panics + /// + /// If the slice is empty + unsafe fn from_utf8_exact_slice_unchecked(src: &[u8]) -> Self; + + /// Convert a UTF-16 array as returned from `.to_utf16_array()` into a + /// `char`. + /// + /// This function is safe because it avoids creating invalid codepoints, + /// but the returned value might not be what one expectedd. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// + /// // starts with a trailing surrogate - converted as if it was a valid + /// // surrogate pair anyway. + /// assert_eq!(char::from_utf16_array_unchecked([0xdbad, 0xf19e]), '\u{fb59e}'); + /// // missing trailing surrogate - ditto + /// assert_eq!(char::from_utf16_array_unchecked([0xd802, 0]), '\u{10800}'); + /// ``` + fn from_utf16_array_unchecked(utf16: [u16;2]) -> Self; + + /// Convert a UTF-16 tuple as returned from `.to_utf16_tuple()` into a `char`. + /// + /// # Safety + /// + /// If the second element is `None`, the first element must be a codepoint + /// in the basic multilingual pane. + /// (In other words, outside the range`0xd8_00..0xe0_00`.) + /// Violating this results in an invalid `char` in that reserved range + /// being created, which is (or can easily lead to) undefined behavior. + unsafe fn from_utf16_tuple_unchecked(utf16: (u16, Option)) -> Self; + + + /// Produces more detailed errors than `char::from_u32()` + /// + /// # Errors + /// + /// This function will return an error if + /// + /// * the value is greater than 0x10ffff + /// * the value is between 0xd800 and 0xdfff (inclusive) + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::CharExt; + /// use encode_unicode::error::CodepointError; + /// + /// assert_eq!(char::from_u32_detailed(0x41), Ok('A')); + /// assert_eq!(char::from_u32_detailed(0x40_00_00), Err(CodepointError::TooHigh)); + /// assert_eq!(char::from_u32_detailed(0xd951), Err(CodepointError::Utf16Reserved)); + /// assert_eq!(char::from_u32_detailed(0xdddd), Err(CodepointError::Utf16Reserved)); + /// assert_eq!(char::from_u32_detailed(0xdd), Ok('Ý')); + /// assert_eq!(char::from_u32_detailed(0x1f331), Ok('🌱')); + /// ``` + fn from_u32_detailed(c: u32) -> Result; +} + + + +impl CharExt for char { + ///////// + //UTF-8// + ///////// + + fn to_utf8(self) -> Utf8Char { + self.into() + } + fn iter_utf8_bytes(self) -> Utf8Iterator { + self.to_utf8().into_iter() + } + + fn to_utf8_array(self) -> ([u8; 4], usize) { + let len = self.len_utf8(); + let mut c = self as u32; + if len == 1 {// ASCII, the common case + ([c as u8, 0, 0, 0], 1) + } else { + let mut parts = 0;// convert to 6-bit bytes + parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; + parts |= 0x80_80_80_80;// set the most significant bit + parts >>= 8*(4-len);// right-align bytes + // Now, unused bytes are zero, (which matters for Utf8Char.eq()) + // and the rest are 0b10xx_xxxx + + // set header on first byte + parts |= (0xff_00u32 >> len) & 0xff;// store length + parts &= Not::not(1u32 << (7-len));// clear the next bit after it + + (parts.to_le_bytes(), len) + } + } + + + fn from_utf8_slice_start(src: &[u8]) -> Result<(Self,usize),Utf8Error> { + let first = match src.first() { + Some(first) => *first, + None => return Err(Utf8Error{ kind: TooFewBytes }), + }; + let bytes = match first.extra_utf8_bytes() { + Err(e) => return Err(e), + Ok(0) => return Ok((first as char, 1)), + Ok(extra) if extra >= src.len() + => return Err(Utf8Error{ kind: TooFewBytes }), + Ok(extra) => &src[..=extra], + }; + if bytes.iter().skip(1).any(|&b| (b >> 6) != 0b10 ) { + Err(Utf8Error{ kind: InterruptedSequence }) + } else if overlong(bytes[0], bytes[1]) { + Err(Utf8Error{ kind: OverlongEncoding }) + } else { + match char::from_u32_detailed(merge_nonascii_unchecked_utf8(bytes)) { + Ok(c) => Ok((c, bytes.len())), + Err(CodepointError::Utf16Reserved) => { + Err(Utf8Error{ kind: Utf16ReservedCodepoint }) + }, + Err(CodepointError::TooHigh) => Err(Utf8Error{ kind: TooHighCodepoint }), + } + } + } + + fn from_utf8_array(utf8: [u8; 4]) -> Result { + let src = match utf8[0].extra_utf8_bytes() { + Err(error) => return Err(error), + Ok(0) => return Ok(utf8[0] as char), + Ok(extra) => &utf8[..=extra], + }; + if src[1..].iter().any(|&b| (b >> 6) != 0b10 ) { + Err(Utf8Error{ kind: InterruptedSequence }) + } else if overlong(utf8[0], utf8[1]) { + Err(Utf8Error{ kind: OverlongEncoding }) + } else { + match char::from_u32_detailed(merge_nonascii_unchecked_utf8(src)) { + Ok(c) => Ok(c), + Err(CodepointError::Utf16Reserved) => { + Err(Utf8Error{ kind: Utf16ReservedCodepoint }) + }, + Err(CodepointError::TooHigh) => Err(Utf8Error{ kind: TooHighCodepoint }), + } + } + } + + unsafe fn from_utf8_exact_slice_unchecked(src: &[u8]) -> Self { + unsafe { + if src.len() == 1 { + src[0] as char + } else { + char::from_u32_unchecked(merge_nonascii_unchecked_utf8(src)) + } + } + } + + + + ////////// + //UTF-16// + ////////// + + fn to_utf16(self) -> Utf16Char { + Utf16Char::from(self) + } + fn iter_utf16_units(self) -> Utf16Iterator { + self.to_utf16().into_iter() + } + + fn to_utf16_array(self) -> [u16;2] { + let (first, second) = self.to_utf16_tuple(); + [first, second.unwrap_or(0)] + } + fn to_utf16_tuple(self) -> (u16, Option) { + if self <= '\u{ffff}' {// single + (self as u16, None) + } else {// double + let c = self as u32 - 0x_01_00_00; + let high = 0x_d8_00 + (c >> 10); + let low = 0x_dc_00 + (c & 0x_03_ff); + (high as u16, Some(low as u16)) + } + } + + + fn from_utf16_slice_start(src: &[u16]) -> Result<(Self,usize), Utf16SliceError> { + use crate::errors::Utf16SliceError::*; + unsafe {match (src.get(0), src.get(1)) { + (Some(&u @ 0x00_00..=0xd7_ff), _) | + (Some(&u @ 0xe0_00..=0xff_ff), _) + => Ok((char::from_u32_unchecked(u as u32), 1)), + (Some(0xdc_00..=0xdf_ff), _) => Err(FirstIsTrailingSurrogate), + (None, _) => Err(EmptySlice), + (Some(&f @ 0xd8_00..=0xdb_ff), Some(&s @ 0xdc_00..=0xdf_ff)) + => Ok((char::from_utf16_tuple_unchecked((f, Some(s))), 2)), + (Some(0xd8_00..=0xdb_ff), Some(_)) => Err(SecondIsNotTrailingSurrogate), + (Some(0xd8_00..=0xdb_ff), None) => Err(MissingSecond), + }} + } + + fn from_utf16_array(utf16: [u16;2]) -> Result { + use crate::errors::Utf16ArrayError::*; + if let Some(c) = char::from_u32(utf16[0] as u32) { + Ok(c) // single + } else if utf16[0] < 0xdc_00 && utf16[1] & 0xfc_00 == 0xdc_00 { + // correct surrogate pair + Ok(combine_surrogates(utf16[0], utf16[1])) + } else if utf16[0] < 0xdc_00 { + Err(SecondIsNotTrailingSurrogate) + } else { + Err(FirstIsTrailingSurrogate) + } + } + fn from_utf16_tuple(utf16: (u16, Option)) -> Result { + unsafe { + match Utf16Char::validate_tuple(utf16) { + Ok(()) => Ok(Self::from_utf16_tuple_unchecked(utf16)), + Err(e) => Err(e), + } + } + } + + fn from_utf16_array_unchecked(utf16: [u16;2]) -> Self { + // treat any array with a surrogate value in [0] as a surrogate because + // combine_surrogates() is safe. + // `(utf16[0] & 0xf800) == 0xd80` might not be quite as fast as + // `utf16[1] != 0`, but avoiding the potential for UB is worth it + // since the conversion isn't zero-cost in either case. + char::from_u32(utf16[0] as u32) + .unwrap_or_else(|| combine_surrogates(utf16[0], utf16[1]) ) + } + unsafe fn from_utf16_tuple_unchecked(utf16: (u16, Option)) -> Self { + unsafe { + match utf16.1 { + Some(second) => combine_surrogates(utf16.0, second), + None => char::from_u32_unchecked(utf16.0 as u32) + } + } + } + + + fn from_u32_detailed(c: u32) -> Result { + match char::from_u32(c) { + Some(c) => Ok(c), + None if c > 0x10_ff_ff => Err(CodepointError::TooHigh), + None => Err(CodepointError::Utf16Reserved), + } + } +} + +// Adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c +fn overlong(first: u8, second: u8) -> bool { + if first < 0x80 { + false + } else if (first & 0xe0) == 0xc0 { + (first & 0xfe) == 0xc0 + } else if (first & 0xf0) == 0xe0 { + first == 0xe0 && (second & 0xe0) == 0x80 + } else { + first == 0xf0 && (second & 0xf0) == 0x80 + } +} + +/// Decodes the codepoint represented by a multi-byte UTF-8 sequence. +/// +/// Does not check that the codepoint is valid, +/// and returns `u32` because casting invalid codepoints to `char` is insta UB. +fn merge_nonascii_unchecked_utf8(src: &[u8]) -> u32 { + let mut c = src[0] as u32 & (0x7f >> src.len()); + for b in &src[1..] { + c = (c << 6) | (b & 0b0011_1111) as u32; + } + c +} + +/// Create a `char` from a leading and a trailing surrogate. +/// +/// This function is safe because it ignores the six most significant bits of +/// each argument and always produces a codepoint in `0x01_00_00..=0x10_ff_ff`. +fn combine_surrogates(first: u16, second: u16) -> char { + unsafe { + let high = (first & 0x_03_ff) as u32; + let low = (second & 0x_03_ff) as u32; + let c = ((high << 10) | low) + 0x_01_00_00; // no, the constant can't be or'd in + char::from_u32_unchecked(c) + } +} + + + +/// Adds `.utf8chars()` and `.utf16chars()` iterator constructors to `&str`. +pub trait StrExt: AsRef { + /// Equivalent to `.chars()` but produces `Utf8Char`s. + fn utf8chars(&self) -> Utf8Chars; + /// Equivalent to `.chars()` but produces `Utf16Char`s. + fn utf16chars(&self) -> Utf16Chars; + /// Equivalent to `.char_indices()` but produces `Utf8Char`s. + fn utf8char_indices(&self) -> Utf8CharIndices; + /// Equivalent to `.char_indices()` but produces `Utf16Char`s. + fn utf16char_indices(&self) -> Utf16CharIndices; +} + +impl StrExt for str { + fn utf8chars(&self) -> Utf8Chars { + Utf8Chars::from(self) + } + fn utf16chars(&self) -> Utf16Chars { + Utf16Chars::from(self) + } + fn utf8char_indices(&self) -> Utf8CharIndices { + Utf8CharIndices::from(self) + } + fn utf16char_indices(&self) -> Utf16CharIndices { + Utf16CharIndices::from(self) + } +} + +#[cfg(feature="ascii")] +impl StrExt for AsciiStr { + fn utf8chars(&self) -> Utf8Chars { + Utf8Chars::from(self.as_str()) + } + fn utf16chars(&self) -> Utf16Chars { + Utf16Chars::from(self.as_str()) + } + fn utf8char_indices(&self) -> Utf8CharIndices { + Utf8CharIndices::from(self.as_str()) + } + fn utf16char_indices(&self) -> Utf16CharIndices { + Utf16CharIndices::from(self.as_str()) + } +} + + + +/// Iterator methods that convert between `u8`s and `Utf8Char` or `u16`s and `Utf16Char` +/// +/// All the iterator adapters also accept iterators that produce references of +/// the type they convert from. +pub trait IterExt: Iterator+Sized { + /// Converts an iterator of `Utf8Char`s or `&Utf8Char`s to an iterator of + /// `u8`s. + /// + /// Has the same effect as `.flat_map()` or `.flatten()`, but the returned + /// iterator is ~40% faster. + /// + /// The iterator also implements `Read` + /// (when the `std` feature isn't disabled). + /// Reading will never produce an error, and calls to `.read()` and `.next()` + /// can be mixed. + /// + /// The exact number of bytes cannot be known in advance, but `size_hint()` + /// gives the possible range. + /// (min: all remaining characters are ASCII, max: all require four bytes) + /// + /// # Examples + /// + /// From iterator of values: + /// + /// ``` + /// use encode_unicode::{IterExt, StrExt}; + /// + /// let iterator = "foo".utf8chars(); + /// let mut bytes = [0; 4]; + /// iterator.to_bytes().zip(&mut bytes).for_each(|(b,dst)| *dst = b ); + /// assert_eq!(&bytes, b"foo\0"); + /// ``` + /// + /// From iterator of references: + /// + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{IterExt, StrExt, Utf8Char}; + /// + /// let chars: Vec = "💣 bomb 💣".utf8chars().collect(); + /// let bytes: Vec = chars.iter().to_bytes().collect(); + /// let flat_map: Vec = chars.iter().cloned().flatten().collect(); + /// assert_eq!(bytes, flat_map); + /// ``` + /// + /// `Read`ing from it: + /// + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{IterExt, StrExt}; + /// use std::io::Read; + /// + /// let s = "Ååh‽"; + /// assert_eq!(s.len(), 8); + /// let mut buf = [b'E'; 9]; + /// let mut reader = s.utf8chars().to_bytes(); + /// assert_eq!(reader.read(&mut buf[..]).unwrap(), 8); + /// assert_eq!(reader.read(&mut buf[..]).unwrap(), 0); + /// assert_eq!(&buf[..8], s.as_bytes()); + /// assert_eq!(buf[8], b'E'); + /// ``` + fn to_bytes(self) -> Utf8CharSplitter where Self::Item: Borrow; + + /// Converts an iterator of `Utf16Char` (or `&Utf16Char`) to an iterator of + /// `u16`s. + /// + /// Has the same effect as `.flat_map()` or `.flatten()`, but the returned + /// iterator is about twice as fast. + /// + /// The exact number of units cannot be known in advance, but `size_hint()` + /// gives the possible range. + /// + /// # Examples + /// + /// From iterator of values: + /// + /// ``` + /// use encode_unicode::{IterExt, StrExt}; + /// + /// let iterator = "foo".utf16chars(); + /// let mut units = [0; 4]; + /// iterator.to_units().zip(&mut units).for_each(|(u,dst)| *dst = u ); + /// + /// assert_eq!(units, ['f' as u16, 'o' as u16, 'o' as u16, 0]); + /// ``` + /// + /// From iterator of references: + /// + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{IterExt, StrExt, Utf16Char}; + /// + /// // (💣 takes two units) + /// let chars: Vec = "💣 bomb 💣".utf16chars().collect(); + /// let units: Vec = chars.iter().to_units().collect(); + /// let flat_map: Vec = chars.iter().flat_map(|u16c| *u16c ).collect(); + /// + /// assert_eq!(units, flat_map); + /// ``` + fn to_units(self) -> Utf16CharSplitter where Self::Item: Borrow; + + /// Decodes bytes as UTF-8 and groups them into `Utf8Char`s + /// + /// When errors (invalid values or sequences) are encountered, + /// it continues with the byte right after the start of the error sequence. + /// This is neither the most intelligent choiche (sometimes it is guaranteed to + /// produce another error), nor the easiest to implement, but I believe it to + /// be the most predictable. + /// It also means that ASCII characters are never hidden by errors. + /// + /// # Examples + /// + /// Replace all errors with u+FFFD REPLACEMENT_CHARACTER: + /// ``` + /// use encode_unicode::{Utf8Char, IterExt}; + /// + /// let mut buf = [b'\0'; 255]; + /// let len = b"foo\xCFbar".iter() + /// .to_utf8chars() + /// .flat_map(|r| r.unwrap_or(Utf8Char::from('\u{FFFD}')) ) + /// .zip(&mut buf[..]) + /// .map(|(byte, dst)| *dst = byte ) + /// .count(); + /// + /// assert_eq!(&buf[..len], "foo\u{FFFD}bar".as_bytes()); + /// ``` + /// + /// Collect everything up until the first error into a string: + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::iterator::Utf8CharMerger; + /// let mut good = String::new(); + /// for r in Utf8CharMerger::from(b"foo\xcc\xbbbar\xcc\xddbaz") { + /// if let Ok(uc) = r { + /// good.push_str(uc.as_str()); + /// } else { + /// break; + /// } + /// } + /// assert_eq!(good, "foo̻bar"); + /// ``` + /// + /// Abort decoding on error: + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{IterExt, Utf8Char}; + /// use encode_unicode::error::{Utf8Error, Utf8ErrorKind}; + /// + /// let result = b"ab\0\xe0\xbc\xa9 \xf3\x80\x77".iter() + /// .to_utf8chars() + /// .collect::>(); + /// + /// assert_eq!(result.unwrap_err().kind(), Utf8ErrorKind::InterruptedSequence); + /// ``` + fn to_utf8chars(self) -> Utf8CharMerger where Self::Item: Borrow; + + /// Decodes bytes as UTF-16 and groups them into `Utf16Char`s + /// + /// When errors (unmatched leading surrogates or unexpected trailing surrogates) + /// are encountered, an error is produced for every unit. + /// + /// # Examples + /// + /// Replace errors with '�': + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{IterExt, Utf16Char}; + /// + /// let slice = &['a' as u16, 0xdf00, 0xd83c, 0xdca0][..]; + /// let string = slice.iter() + /// .to_utf16chars() + /// .map(|r| r.unwrap_or(Utf16Char::from('\u{fffd}')) ) // REPLACEMENT_CHARACTER + /// .collect::(); + /// + /// assert_eq!(string, "a�🂠"); + /// ``` + /// + /// ``` + /// use encode_unicode::{IterExt, Utf16Char}; + /// use encode_unicode::error::Utf16PairError::*; + /// + /// let slice = [0xdcba, 0xdeff, 0xd8be, 0xdeee, 'Y' as u16, 0xdab1, 0xdab1]; + /// let mut iter = slice.iter().to_utf16chars(); + /// assert_eq!(iter.size_hint(), (3, Some(7))); + /// assert_eq!(iter.next(), Some(Err(UnexpectedTrailingSurrogate))); + /// assert_eq!(iter.next(), Some(Err(UnexpectedTrailingSurrogate))); + /// assert_eq!(iter.next(), Some(Ok(Utf16Char::from('\u{3faee}')))); + /// assert_eq!(iter.next(), Some(Ok(Utf16Char::from('Y')))); + /// assert_eq!(iter.next(), Some(Err(UnmatchedLeadingSurrogate))); + /// assert_eq!(iter.next(), Some(Err(Incomplete))); + /// assert_eq!(iter.into_remaining_units().next(), None); + /// ``` + /// + /// Search for a codepoint and return the codepoint index of the first match: + /// ``` + /// use encode_unicode::{IterExt, Utf16Char}; + /// + /// let position = [0xd875, 0xdd4f, '≈' as u16, '2' as u16].iter() + /// .to_utf16chars() + /// .position(|r| r == Ok(Utf16Char::from('≈')) ); + /// + /// assert_eq!(position, Some(1)); + /// ``` + fn to_utf16chars(self) -> Utf16CharMerger where Self::Item: Borrow; +} + +impl IterExt for I { + fn to_bytes(self) -> Utf8CharSplitter where Self::Item: Borrow { + Utf8CharSplitter::from(self) + } + fn to_units(self) -> Utf16CharSplitter where Self::Item: Borrow { + Utf16CharSplitter::from(self) + } + fn to_utf8chars(self) -> Utf8CharMerger where Self::Item: Borrow { + Utf8CharMerger::from(self) + } + fn to_utf16chars(self) -> Utf16CharMerger where Self::Item: Borrow { + Utf16CharMerger::from(self) + } +} + + +/// Methods for iterating over `u8` and `u16` slices as UTF-8 or UTF-16 characters. +/// +/// The iterators are slightly faster than the similar methods in [`IterExt`](trait.IterExt.html) +/// because they con "push back" items for free after errors and don't need a +/// separate buffer that must be checked on every call to `.next()`. +pub trait SliceExt: Index { + /// Decode `u8` slices as UTF-8 and iterate over the codepoints as `Utf8Char`s, + /// + /// # Examples + /// + /// Get the index and error type of the first error: + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{SliceExt, Utf8Char, error::Utf8ErrorKind}; + /// + /// let slice = b"ab\0\xe0\xbc\xa9 \xf3\x80\x77"; + /// let result = slice.utf8char_indices() + /// .map(|(offset,r,length)| r.map_err(|e| (offset,e.kind(),length) ) ) + /// .collect::>(); + /// + /// assert_eq!(result, Err((7, Utf8ErrorKind::TooFewBytes, 1))); + /// ``` + /// + /// ``` + /// use encode_unicode::{SliceExt, Utf8Char}; + /// use std::error::Error; + /// + /// let slice = b"\xf0\xbf\xbf\xbfXY\xdd\xbb\xe1\x80\x99quux123"; + /// let mut fixed_size = [Utf8Char::default(); 8]; + /// for (cp_i, (byte_index, r, _)) in slice.utf8char_indices().enumerate().take(8) { + /// match r { + /// Ok(u8c) => fixed_size[cp_i] = u8c, + /// Err(e) => panic!("Invalid codepoint at index {} ({})", cp_i, e), + /// } + /// } + /// let chars = ['\u{3ffff}', 'X', 'Y', '\u{77b}', '\u{1019}', 'q', 'u', 'u']; + /// assert_eq!(fixed_size, chars); + /// ``` + /// + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{SliceExt, Utf8Char, error::Utf8ErrorKind}; + /// + /// let bytes = b"\xfa-\xf4\x8f\xee\xa1\x8f-\xed\xa9\x87\xf0\xcc\xbb"; + /// let mut errors = Vec::new(); + /// let mut lengths = Vec::new(); + /// let mut string = String::new(); + /// for (offset,result,length) in bytes.utf8char_indices() { + /// lengths.push((offset,length)); + /// let c = result.unwrap_or_else(|error| { + /// errors.push((offset, error.kind())); + /// Utf8Char::from('\u{fffd}') // replacement character + /// }); + /// string.push_str(c.as_str()); + /// } + /// + /// assert_eq!(string, "�-��\u{e84f}-����\u{33b}"); + /// assert_eq!(lengths, [(0,1), (1,1), (2,1), (3,1), (4,3), (7,1), + /// (8,1), (9,1), (10,1), (11,1), (12,2)]); + /// assert_eq!(errors, [ + /// ( 0, Utf8ErrorKind::NonUtf8Byte), + /// ( 2, Utf8ErrorKind::InterruptedSequence), + /// ( 3, Utf8ErrorKind::UnexpectedContinuationByte), + /// ( 8, Utf8ErrorKind::Utf16ReservedCodepoint), + /// ( 9, Utf8ErrorKind::UnexpectedContinuationByte), + /// (10, Utf8ErrorKind::UnexpectedContinuationByte), + /// (11, Utf8ErrorKind::TooFewBytes), // (but it was not the last element returned!) + /// ]); + /// ``` + fn utf8char_indices(&self) -> Utf8CharDecoder where Self::Output: Borrow<[u8]>; + + + /// Decode `u16` slices as UTF-16 and iterate over the codepoints as `Utf16Char`s, + /// + /// The iterator produces `(usize,Result,usize)`, + /// and the slice is validated as you go. + /// + /// The first `usize` contains the offset from the start of the slice and + /// the last `usize` contains the length of the codepoint or error. + /// The length is either 1 or 2, and always 1 for errors. + /// + /// # Examples + /// + #[cfg_attr(feature="std", doc=" ```")] + #[cfg_attr(not(feature="std"), doc=" ```no_compile")] + /// use encode_unicode::{SliceExt, Utf8Char}; + /// + /// let slice = &['a' as u16, 0xdf00, 0xd83c, 0xdca0][..]; + /// let mut errors = Vec::new(); + /// let string = slice.utf16char_indices().map(|(offset,r,_)| match r { + /// Ok(u16c) => Utf8Char::from(u16c), + /// Err(_) => { + /// errors.push(offset); + /// Utf8Char::from('\u{fffd}') // REPLACEMENT_CHARACTER + /// } + /// }).collect::(); + /// + /// assert_eq!(string, "a�🂠"); + /// assert_eq!(errors, [1]); + /// ``` + /// + /// Search for a codepoint and return its unit and codepoint index. + /// ``` + /// use encode_unicode::{SliceExt, Utf16Char}; + /// + /// let slice = [0xd875,/*'𝕏'*/ 0xdd4f, '≈' as u16, '2' as u16]; + /// let position = slice.utf16char_indices() + /// .enumerate() + /// .find(|&(_,(_,r,_))| r == Ok(Utf16Char::from('≈')) ) + /// .map(|(codepoint, (offset, _, _))| (codepoint, offset) ); + /// + /// assert_eq!(position, Some((1,2))); + /// ``` + /// + /// Error types: + /// ``` + /// use encode_unicode::{SliceExt, Utf16Char}; + /// use encode_unicode::error::Utf16PairError::*; + /// + /// let slice = [0xdcba, 0xdeff, 0xd8be, 0xdeee, 'λ' as u16, 0xdab1, 0xdab1]; + /// let mut iter = slice.utf16char_indices(); + /// assert_eq!(iter.next(), Some((0, Err(UnexpectedTrailingSurrogate), 1))); + /// assert_eq!(iter.next(), Some((1, Err(UnexpectedTrailingSurrogate), 1))); + /// assert_eq!(iter.next(), Some((2, Ok(Utf16Char::from('\u{3faee}')), 2))); + /// assert_eq!(iter.next(), Some((4, Ok(Utf16Char::from('λ')), 1))); + /// assert_eq!(iter.next(), Some((5, Err(UnmatchedLeadingSurrogate), 1))); + /// assert_eq!(iter.next(), Some((6, Err(Incomplete), 1))); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.as_slice(), []) + /// ``` + fn utf16char_indices(&self) -> Utf16CharDecoder where Self::Output: Borrow<[u16]>; +} + +impl> SliceExt for S { + fn utf8char_indices(&self) -> Utf8CharDecoder where Self::Output: Borrow<[u8]> { + Utf8CharDecoder::from(self[..].borrow()) + } + fn utf16char_indices(&self) -> Utf16CharDecoder where Self::Output: Borrow<[u16]> { + Utf16CharDecoder::from(self[..].borrow()) + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/utf16_char.rs b/anneal/v2/vendor/encode_unicode/src/utf16_char.rs new file mode 100644 index 0000000000..a16da7bc4f --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/utf16_char.rs @@ -0,0 +1,692 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +use crate::utf16_iterators::Utf16Iterator; +use crate::traits::{CharExt, U16UtfExt}; +use crate::utf8_char::Utf8Char; +use crate::errors::{Utf16SliceError, Utf16ArrayError, Utf16TupleError}; +use crate::errors::{NonBmpError, EmptyStrError, FromStrError}; +extern crate core; +use core::{hash,fmt}; +use core::cmp::Ordering; +use core::borrow::Borrow; +use core::ops::Deref; +use core::str::FromStr; +#[cfg(feature="std")] +use core::iter::FromIterator; +#[cfg(feature="ascii")] +use core::char; +#[cfg(feature="ascii")] +extern crate ascii; +#[cfg(feature="ascii")] +use ascii::{AsciiChar,ToAsciiChar,ToAsciiCharError}; + + +// I don't think there is any good default value for char, but char does. +#[derive(Default)] +// char doesn't do anything more advanced than u32 for Eq/Ord, so we shouldn't either. +// When it's a single unit, the second is zero, so Eq works. +// #[derive(Ord)] however, breaks on surrogate pairs. +#[derive(PartialEq,Eq)] +#[derive(Clone,Copy)] + + +/// An unicode codepoint stored as UTF-16. +/// +/// It can be borrowed as an `u16` slice, and has the same size as `char`. +pub struct Utf16Char { + units: [u16; 2], +} + + + ///////////////////// + //conversion traits// +///////////////////// +impl FromStr for Utf16Char { + type Err = FromStrError; + /// Create an `Utf16Char` from a string slice. + /// The string must contain exactly one codepoint. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::error::FromStrError::*; + /// use encode_unicode::Utf16Char; + /// use std::str::FromStr; + /// + /// assert_eq!(Utf16Char::from_str("a"), Ok(Utf16Char::from('a'))); + /// assert_eq!(Utf16Char::from_str("🂠"), Ok(Utf16Char::from('🂠'))); + /// assert_eq!(Utf16Char::from_str(""), Err(Empty)); + /// assert_eq!(Utf16Char::from_str("ab"), Err(MultipleCodepoints)); + /// assert_eq!(Utf16Char::from_str("é"), Err(MultipleCodepoints));// 'e'+u301 combining mark + /// ``` + fn from_str(s: &str) -> Result { + match Utf16Char::from_str_start(s) { + Ok((u16c,bytes)) if bytes == s.len() => Ok(u16c), + Ok((_,_)) => Err(FromStrError::MultipleCodepoints), + Err(EmptyStrError) => Err(FromStrError::Empty), + } + } +} +impl From for Utf16Char { + fn from(c: char) -> Self { + let (first, second) = c.to_utf16_tuple(); + Utf16Char{ units: [first, second.unwrap_or(0)] } + } +} +impl From for Utf16Char { + fn from(utf8: Utf8Char) -> Utf16Char { + let (b, utf8_len) = utf8.to_array(); + match utf8_len { + 1 => Utf16Char{ units: [b[0] as u16, 0] }, + 4 => {// need surrogate + let mut first = 0xd800 - (0x01_00_00u32 >> 10) as u16; + first += (b[0] as u16 & 0x07) << 8; + first += (b[1] as u16 & 0x3f) << 2; + first += (b[2] as u16 & 0x30) >> 4; + let mut second = 0xdc00; + second |= (b[2] as u16 & 0x0f) << 6; + second |= b[3] as u16 & 0x3f; + Utf16Char{ units: [first, second] } + }, + _ => { // 2 or 3 + let mut unit = ((b[0] as u16 & 0x1f) << 6) | (b[1] as u16 & 0x3f); + if utf8_len == 3 { + unit = (unit << 6) | (b[2] as u16 & 0x3f); + } + Utf16Char{ units: [unit, 0] } + }, + } + } +} +impl From for char { + fn from(uc: Utf16Char) -> char { + char::from_utf16_array_unchecked(uc.to_array()) + } +} +impl IntoIterator for Utf16Char { + type Item=u16; + type IntoIter=Utf16Iterator; + /// Iterate over the units. + fn into_iter(self) -> Utf16Iterator { + Utf16Iterator::from(self) + } +} + +#[cfg(feature="std")] +impl Extend for Vec { + fn extend>(&mut self, iter: I) { + let iter = iter.into_iter(); + self.reserve(iter.size_hint().0); + for u16c in iter { + self.push(u16c.units[0]); + if u16c.units[1] != 0 { + self.push(u16c.units[1]); + } + } + } +} +#[cfg(feature="std")] +impl<'a> Extend<&'a Utf16Char> for Vec { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()) + } +} +#[cfg(feature="std")] +impl FromIterator for Vec { + fn from_iter>(iter: I) -> Self { + let mut vec = Vec::new(); + vec.extend(iter); + return vec; + } +} +#[cfg(feature="std")] +impl<'a> FromIterator<&'a Utf16Char> for Vec { + fn from_iter>(iter: I) -> Self { + Self::from_iter(iter.into_iter().cloned()) + } +} + +#[cfg(feature="std")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().map(Utf8Char::from)); + } +} +#[cfg(feature="std")] +impl<'a> Extend<&'a Utf16Char> for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } +} +#[cfg(feature="std")] +impl FromIterator for String { + fn from_iter>(iter: I) -> Self { + let mut s = String::new(); + s.extend(iter); + return s; + } +} +#[cfg(feature="std")] +impl<'a> FromIterator<&'a Utf16Char> for String { + fn from_iter>(iter: I) -> Self { + Self::from_iter(iter.into_iter().cloned()) + } +} + + + ///////////////// + //getter traits// +///////////////// +impl AsRef<[u16]> for Utf16Char { + #[inline] + fn as_ref(&self) -> &[u16] { + &self.units[..self.len()] + } +} +impl Borrow<[u16]> for Utf16Char { + #[inline] + fn borrow(&self) -> &[u16] { + self.as_ref() + } +} +impl Deref for Utf16Char { + type Target = [u16]; + #[inline] + fn deref(&self) -> &[u16] { + self.as_ref() + } +} + + + //////////////// + //ascii traits// +//////////////// +#[cfg(feature="ascii")] +/// Requires the feature "ascii". +impl From for Utf16Char { + #[inline] + fn from(ac: AsciiChar) -> Self { + Utf16Char{ units: [ac.as_byte() as u16, 0] } + } +} +#[cfg(feature="ascii")] +/// Requires the feature "ascii". +impl ToAsciiChar for Utf16Char { + #[inline] + fn to_ascii_char(self) -> Result { + self.units[0].to_ascii_char() + } + #[inline] + unsafe fn to_ascii_char_unchecked(self) -> AsciiChar { + unsafe { self.units[0].to_ascii_char_unchecked() } + } +} + + + ///////////////////////////////////////////////////////// + //Genaral traits that cannot be derived to emulate char// +///////////////////////////////////////////////////////// +impl hash::Hash for Utf16Char { + fn hash(&self, state: &mut H) { + self.to_char().hash(state); + } +} +impl fmt::Debug for Utf16Char { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.to_char(), fmtr) + } +} +impl fmt::Display for Utf16Char { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Char::from(*self), fmtr) + } +} +// Cannot derive these impls because two-unit characters must always compare +// greater than one-unit ones. +impl PartialOrd for Utf16Char { + #[inline] + fn partial_cmp(&self, rhs: &Self) -> Option { + Some(self.cmp(rhs)) + } +} +impl Ord for Utf16Char { + #[inline] + fn cmp(&self, rhs: &Self) -> Ordering { + // Shift the first unit by 0xd if surrogate, and 0 otherwise. + // This ensures surrogates are always greater than 0xffff, and + // that the second unit only affect the result when the first are equal. + // Multiplying by a constant factor isn't enough because that factor + // would have to be greater than 1023 and smaller than 5.5. + // This transformation is less complicated than combine_surrogates(). + let lhs = (self.units[0] as u32, self.units[1] as u32); + let rhs = (rhs.units[0] as u32, rhs.units[1] as u32); + let lhs = (lhs.0 << (lhs.1 >> 12)) + lhs.1; + let rhs = (rhs.0 << (rhs.1 >> 12)) + rhs.1; + lhs.cmp(&rhs) + } +} + + + //////////////////////////////// + //Comparisons with other types// +//////////////////////////////// +impl PartialEq for Utf16Char { + fn eq(&self, u32c: &char) -> bool { + *self == Utf16Char::from(*u32c) + } +} +impl PartialEq for char { + fn eq(&self, u16c: &Utf16Char) -> bool { + Utf16Char::from(*self) == *u16c + } +} +impl PartialOrd for Utf16Char { + fn partial_cmp(&self, u32c: &char) -> Option { + self.partial_cmp(&Utf16Char::from(*u32c)) + } +} +impl PartialOrd for char { + fn partial_cmp(&self, u16c: &Utf16Char) -> Option { + Utf16Char::from(*self).partial_cmp(u16c) + } +} + +impl PartialEq for Utf16Char { + fn eq(&self, u8c: &Utf8Char) -> bool { + *self == Utf16Char::from(*u8c) + } +} +impl PartialOrd for Utf16Char { + fn partial_cmp(&self, u8c: &Utf8Char) -> Option { + self.partial_cmp(&Utf16Char::from(*u8c)) + } +} +// The other direction is implemented in utf8_char.rs + +/// Only considers the unit equal if the codepoint of the `Utf16Char` is not +/// made up of a surrogate pair. +/// +/// There is no impl in the opposite direction, as this should only be used to +/// compare `Utf16Char`s against constants. +/// +/// # Examples +/// +/// ``` +/// # use encode_unicode::Utf16Char; +/// assert!(Utf16Char::from('6') == b'6' as u16); +/// assert!(Utf16Char::from('\u{FFFF}') == 0xffff_u16); +/// assert!(Utf16Char::from_tuple((0xd876, Some(0xdef9))).unwrap() != 0xd876_u16); +/// ``` +impl PartialEq for Utf16Char { + fn eq(&self, unit: &u16) -> bool { + self.units[0] == *unit && self.units[1] == 0 + } +} +/// Only considers the byte equal if the codepoint of the `Utf16Char` is <= U+FF. +/// +/// # Examples +/// +/// ``` +/// # use encode_unicode::Utf16Char; +/// assert!(Utf16Char::from('6') == b'6'); +/// assert!(Utf16Char::from('\u{00FF}') == b'\xff'); +/// assert!(Utf16Char::from('\u{0100}') != b'\0'); +/// ``` +impl PartialEq for Utf16Char { + fn eq(&self, byte: &u8) -> bool { + self.units[0] == *byte as u16 + } +} +#[cfg(feature = "ascii")] +/// `Utf16Char`s that are not ASCII never compare equal. +impl PartialEq for Utf16Char { + #[inline] + fn eq(&self, ascii: &AsciiChar) -> bool { + self.units[0] == *ascii as u16 + } +} +#[cfg(feature = "ascii")] +/// `Utf16Char`s that are not ASCII never compare equal. +impl PartialEq for AsciiChar { + #[inline] + fn eq(&self, u16c: &Utf16Char) -> bool { + *self as u16 == u16c.units[0] + } +} +#[cfg(feature = "ascii")] +/// `Utf16Char`s that are not ASCII always compare greater. +impl PartialOrd for Utf16Char { + #[inline] + fn partial_cmp(&self, ascii: &AsciiChar) -> Option { + self.units[0].partial_cmp(&(*ascii as u16)) + } +} +#[cfg(feature = "ascii")] +/// `Utf16Char`s that are not ASCII always compare greater. +impl PartialOrd for AsciiChar { + #[inline] + fn partial_cmp(&self, u16c: &Utf16Char) -> Option { + (*self as u16).partial_cmp(&u16c.units[0]) + } +} + + + /////////////////////////////////////////////////////// + //pub impls that should be together for nicer rustdoc// +/////////////////////////////////////////////////////// +impl Utf16Char { + /// A `const fn` alternative to the trait-based `Utf16Char::from(char)`. + /// + /// # Examples + /// + /// ``` + /// # use encode_unicode::Utf16Char; + /// const REPLACEMENT_CHARACTER: Utf16Char = Utf16Char::new('\u{fffd}'); + /// ``` + pub const fn new(c: char) -> Self { + if c <= '\u{ffff}' { + Utf16Char{ units: [c as u16, 0] } + } else { + let c = (c as u32).wrapping_sub(0x01_00_00); + let first = 0xd8_00 | (c >> 10) as u16; + let second = 0xdc_00 | (c & 0x0_03_ff) as u16; + Utf16Char{ units: [first, second] } + } + } + /// Create an `Utf16Char` from the first codepoint in a string slice, + /// converting from UTF-8 to UTF-16. + /// + /// The returned `usize` is the number of UTF-8 bytes used from the str, + /// and not the number of UTF-16 units. + /// + /// Returns an error if the `str` is empty. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::Utf16Char; + /// + /// assert_eq!(Utf16Char::from_str_start("a"), Ok((Utf16Char::from('a'),1))); + /// assert_eq!(Utf16Char::from_str_start("ab"), Ok((Utf16Char::from('a'),1))); + /// assert_eq!(Utf16Char::from_str_start("🂠 "), Ok((Utf16Char::from('🂠'),4))); + /// assert_eq!(Utf16Char::from_str_start("é"), Ok((Utf16Char::from('e'),1)));// 'e'+u301 combining mark + /// assert!(Utf16Char::from_str_start("").is_err()); + /// ``` + pub const fn from_str_start(s: &str) -> Result<(Self,usize), EmptyStrError> { + if s.is_empty() { + return Err(EmptyStrError); + } + let b = s.as_bytes(); + // Read the last byte first to reduce the number of unnecesary length checks. + match b[0] { + 0..=127 => {// 1 byte => 1 unit + let unit = b[0] as u16;// 0b0000_0000_0xxx_xxxx + Ok((Utf16Char{ units: [unit, 0] }, 1)) + }, + 0b1000_0000..=0b1101_1111 => {// 2 bytes => 1 unit + let unit = (((b[1] & 0x3f) as u16) << 0) // 0b0000_0000_00xx_xxxx + | (((b[0] & 0x1f) as u16) << 6);// 0b0000_0xxx_xx00_0000 + Ok((Utf16Char{ units: [unit, 0] }, 2)) + }, + 0b1110_0000..=0b1110_1111 => {// 3 bytes => 1 unit + let unit = (((b[2] & 0x3f) as u16) << 0) // 0b0000_0000_00xx_xxxx + | (((b[1] & 0x3f) as u16) << 6) // 0b0000_xxxx_xx00_0000 + | (((b[0] & 0x0f) as u16) << 12);// 0bxxxx_0000_0000_0000 + Ok((Utf16Char{ units: [unit, 0] }, 3)) + }, + _ => {// 4 bytes => 2 units + let second = 0xdc00 // 0b1101_1100_0000_0000 + | (((b[3] & 0x3f) as u16) << 0) // 0b0000_0000_00xx_xxxx + | (((b[2] & 0x0f) as u16) << 6);// 0b0000_00xx_xx00_0000 + let first = 0xd800-(0x01_00_00u32>>10) as u16// 0b1101_0111_1100_0000 + + (((b[2] & 0x30) as u16) >> 4) // 0b0000_0000_0000_00xx + + (((b[1] & 0x3f) as u16) << 2) // 0b0000_0000_xxxx_xx00 + + (((b[0] & 0x07) as u16) << 8); // 0b0000_0xxx_0000_0000 + Ok((Utf16Char{ units: [first, second] }, 4)) + } + } + } + /// Validate and store the first UTF-16 codepoint in the slice. + /// Also return how many units were needed. + pub fn from_slice_start(src: &[u16]) -> Result<(Self,usize), Utf16SliceError> { + char::from_utf16_slice_start(src).map(|(_,len)| { + let second = if len==2 {src[1]} else {0}; + (Utf16Char{ units: [src[0], second] }, len) + }) + } + /// Store the first UTF-16 codepoint of the slice. + /// + /// # Safety + /// + /// The slice must be non-empty and start with a valid UTF-16 codepoint. + /// The length of the slice is never checked. + pub unsafe fn from_slice_start_unchecked(src: &[u16]) -> (Self,usize) { + unsafe { + let first = *src.get_unchecked(0); + if first.is_utf16_leading_surrogate() { + (Utf16Char{ units: [first, *src.get_unchecked(1)] }, 2) + } else { + (Utf16Char{ units: [first, 0] }, 1) + } + } + } + /// Validate and store an UTF-16 array as returned from `char.to_utf16_array()`. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::Utf16Char; + /// use encode_unicode::error::Utf16ArrayError; + /// + /// assert_eq!(Utf16Char::from_array(['x' as u16, 'y' as u16]), Ok(Utf16Char::from('x'))); + /// assert_eq!(Utf16Char::from_array(['睷' as u16, 0]), Ok(Utf16Char::from('睷'))); + /// assert_eq!(Utf16Char::from_array([0xda6f, 0xdcde]), Ok(Utf16Char::from('\u{abcde}'))); + /// assert_eq!(Utf16Char::from_array([0xf111, 0xdbad]), Ok(Utf16Char::from('\u{f111}'))); + /// assert_eq!(Utf16Char::from_array([0xdaaf, 0xdaaf]), Err(Utf16ArrayError::SecondIsNotTrailingSurrogate)); + /// assert_eq!(Utf16Char::from_array([0xdcac, 0x9000]), Err(Utf16ArrayError::FirstIsTrailingSurrogate)); + /// ``` + pub const fn from_array(units: [u16; 2]) -> Result { + if (units[0] & 0xf8_00) != 0xd8_00 { + Ok(Utf16Char { units: [units[0], 0] }) + } else if units[0] < 0xdc_00 && (units[1] & 0xfc_00) == 0xdc_00 { + Ok(Utf16Char { units }) + } else if units[0] < 0xdc_00 { + Err(Utf16ArrayError::SecondIsNotTrailingSurrogate) + } else { + Err(Utf16ArrayError::FirstIsTrailingSurrogate) + } + } + /// Create an `Utf16Char` from an array as returned from `char.to_utf16_array()`. + /// + /// # Safety + /// + /// The units must form a valid codepoint, and the second unit must be 0 + /// when a surrogate pair is not required. + /// Violating this can easily lead to undefined behavior, although unlike + /// `char` bad `Utf16Char`s simply existing is not immediately UB. + pub const unsafe fn from_array_unchecked(units: [u16; 2]) -> Self { + Utf16Char { units } + } + pub(crate) const fn validate_tuple(utf16: (u16,Option)) -> Result<(),Utf16TupleError> { + match utf16 { + (0x00_00..=0xd7_ff, None) | // single + (0xe0_00..=0xff_ff, None) | // single + (0xd8_00..=0xdb_ff, Some(0xdc_00..=0xdf_ff)) // correct surrogate + => Ok(()), + (0xd8_00..=0xdb_ff, Some(_)) => Err(Utf16TupleError::SecondIsNotTrailingSurrogate), + (0xd8_00..=0xdb_ff, None ) => Err(Utf16TupleError::MissingSecond), + (0xdc_00..=0xdf_ff, _ ) => Err(Utf16TupleError::FirstIsTrailingSurrogate), + ( _ , Some(_)) => Err(Utf16TupleError::SuperfluousSecond), + } + } + /// Validate and store a UTF-16 pair as returned from `char.to_utf16_tuple()`. + pub const fn from_tuple(utf16: (u16,Option)) -> Result { + unsafe { + match Self::validate_tuple(utf16) { + Ok(()) => Ok(Self::from_tuple_unchecked(utf16)), + Err(e) => Err(e), + } + } + } + /// Create an `Utf16Char` from a tuple as returned from `char.to_utf16_tuple()`. + /// + /// # Safety + /// + /// The units must form a valid codepoint with the second being 0 when a + /// surrogate pair is not required. + /// Violating this can easily lead to undefined behavior. + pub const unsafe fn from_tuple_unchecked(utf16: (u16,Option)) -> Self { + let second = match utf16.1 { + Some(extra) => extra, + None => 0, + }; + Utf16Char { units: [utf16.0, second] } + } + /// Create an `Utf16Char` from a single unit. + /// + /// Codepoints less than `'\u{1_00_00}'` (which fit in an `u16`) + /// are part of the basic multilingual plane + /// unless they are reserved for surrogate pairs. + /// + /// # Errors + /// + /// Returns `NonBmpError` if the unit is in the range `0xd800..0xe000` + /// (which means that it's part of a surrogat pair) + /// + /// # Examples + /// + /// ``` + /// # use encode_unicode::Utf16Char; + /// assert_eq!(Utf16Char::from_bmp(0x40).unwrap(), '@'); + /// assert_eq!(Utf16Char::from_bmp('ø' as u16).unwrap(), 'ø'); + /// assert!(Utf16Char::from_bmp(0xdddd).is_err()); + /// ``` + pub const fn from_bmp(bmp_codepoint: u16) -> Result { + let is_not_bmp = bmp_codepoint & 0xf800 == 0xd800; + let if_good = Utf16Char{ units: [bmp_codepoint, 0] }; + [Ok(if_good), Err(NonBmpError)][is_not_bmp as usize] + } + /// Create an `Utf16Char` from a single unit without checking that it's a + /// valid codepoint on its own. + /// + /// # Safety + /// + /// The unit must be less than 0xd800 or greater than 0xdfff. + /// In other words, not part of a surrogate pair. + /// Violating this can easily lead to undefined behavior. + #[inline] + pub const unsafe fn from_bmp_unchecked(bmp_codepoint: u16) -> Self { + Utf16Char{ units: [bmp_codepoint, 0] } + } + /// Checks that the codepoint is in the basic multilingual plane. + /// + /// # Examples + /// ``` + /// # use encode_unicode::Utf16Char; + /// assert_eq!(Utf16Char::from('e').is_bmp(), true); + /// assert_eq!(Utf16Char::from('€').is_bmp(), true); + /// assert_eq!(Utf16Char::from('𝔼').is_bmp(), false); + /// ``` + #[inline] + pub const fn is_bmp(self) -> bool { + self.units[1] == 0 + } + + /// The number of units this character is made up of. + /// + /// Is either 1 or 2 and identical to `.as_char().len_utf16()` + /// or `.as_ref().len()`. + #[inline] + pub const fn len(self) -> usize { + 1 + (self.units[1] as usize >> 15) + } + // There is no `.is_emty()` because it would always return false. + + /// Checks that the codepoint is an ASCII character. + #[inline] + pub const fn is_ascii(self) -> bool { + self.units[0] <= 127 + } + /// Checks that two characters are an ASCII case-insensitive match. + /// + /// Is equivalent to `a.to_ascii_lowercase() == b.to_ascii_lowercase()`. + pub const fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + if self.is_ascii() && other.is_ascii() { + (self.units[0] as u8).eq_ignore_ascii_case(&(other.units[0] as u8)) + } else { + self.units[0] == other.units[0] && self.units[1] == other.units[1] + } + } + /// Converts the character to its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + pub const fn to_ascii_uppercase(self) -> Self { + let n = self.units[0].wrapping_sub(b'a' as u16); + if n < 26 {Utf16Char{ units: [n+b'A' as u16, 0] }} + else {self} + } + /// Converts the character to its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + pub const fn to_ascii_lowercase(self) -> Self { + let n = self.units[0].wrapping_sub(b'A' as u16); + if n < 26 {Utf16Char{ units: [n+b'a' as u16, 0] }} + else {self} + } + /// Converts the character to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + pub fn make_ascii_uppercase(&mut self) { + *self = self.to_ascii_uppercase() + } + /// Converts the character to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + pub fn make_ascii_lowercase(&mut self) { + *self = self.to_ascii_lowercase(); + } + + /// Convert from UTF-16 to UTF-32 + pub fn to_char(self) -> char { + self.into() + } + /// Write the internal representation to a slice, + /// and then returns the number of `u16`s written. + /// + /// # Panics + /// Will panic the buffer is too small; + /// You can get the required length from `.len()`, + /// but a buffer of length two is always large enough. + pub fn to_slice(self, dst: &mut[u16]) -> usize { + // Write the last unit first to avoid repeated length checks. + let extra = self.units[1] as usize >> 15; + match dst.get_mut(extra) { + Some(first) => *first = self.units[extra], + None => panic!("The provided buffer is too small.") + } + if extra != 0 {dst[0] = self.units[0];} + extra+1 + } + /// Get the character represented as an array of two units. + /// + /// The second `u16` is zero for codepoints that fit in one unit. + #[inline] + pub const fn to_array(self) -> [u16;2] { + self.units + } + /// The second `u16` is used for surrogate pairs. + #[inline] + pub const fn to_tuple(self) -> (u16,Option) { + (self.units[0], [None, Some(self.units[1])][self.units[1] as usize >> 15]) + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/utf16_iterators.rs b/anneal/v2/vendor/encode_unicode/src/utf16_iterators.rs new file mode 100644 index 0000000000..30dcd80dbd --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/utf16_iterators.rs @@ -0,0 +1,265 @@ +/* Copyright 2018-2019 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +use crate::traits::CharExt; +use crate::utf16_char::Utf16Char; +use crate::errors::EmptyStrError; +extern crate core; +use core::fmt; +use core::borrow::Borrow; + +// Invalid values that says the field is consumed or empty. +const FIRST_USED: u16 = 0x_dc_00; +const SECOND_USED: u16 = 0; + +/// Iterate over the units of the UTF-16 representation of a codepoint. +#[derive(Clone)] +pub struct Utf16Iterator { + first: u16, + second: u16, +} +impl From for Utf16Iterator { + fn from(c: char) -> Self { + Self::from(c.to_utf16()) + } +} +impl From for Utf16Iterator { + fn from(uc: Utf16Char) -> Self { + let (first, second) = uc.to_tuple(); + let second = second.unwrap_or(SECOND_USED); + Utf16Iterator{first, second} + } +} +impl Iterator for Utf16Iterator { + type Item=u16; + fn next(&mut self) -> Option { + match (self.first, self.second) { + (FIRST_USED, SECOND_USED) => { None }, + (FIRST_USED, second ) => {self.second = SECOND_USED; Some(second)}, + (first , _ ) => {self.first = FIRST_USED; Some(first )}, + } + } + fn size_hint(&self) -> (usize, Option) { + (self.len(), Some(self.len())) + } +} +impl ExactSizeIterator for Utf16Iterator { + fn len(&self) -> usize { + (if self.first == FIRST_USED {0} else {1}) + + (if self.second == SECOND_USED {0} else {1}) + } +} +impl fmt::Debug for Utf16Iterator { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + let mut clone = self.clone(); + match (clone.next(), clone.next()) { + (Some(one), None) => write!(fmtr, "[{}]", one), + (Some(a), Some(b)) => write!(fmtr, "[{}, {}]", a, b), + (None, _) => write!(fmtr, "[]"), + } + } +} + + + +/// Converts an iterator of `Utf16Char` (or `&Utf16Char`) +/// to an iterator of `u16`s. +/// +/// Is equivalent to calling `.flatten()` or `.flat_map()` on the original iterator, +/// but the returned iterator is about twice as fast. +/// +/// The exact number of units cannot be known in advance, but `size_hint()` +/// gives the possible range. +/// +/// # Examples +/// +/// From iterator of values: +/// +/// ``` +/// use encode_unicode::{IterExt, CharExt}; +/// +/// let iterator = "foo".chars().map(|c| c.to_utf16() ); +/// let mut units = [0; 4]; +/// iterator.to_units().zip(&mut units).for_each(|(u,dst)| *dst = u ); +/// assert_eq!(units, ['f' as u16, 'o' as u16, 'o' as u16, 0]); +/// ``` +/// +/// From iterator of references: +/// +#[cfg_attr(feature="std", doc=" ```")] +#[cfg_attr(not(feature="std"), doc=" ```no_compile")] +/// use encode_unicode::{IterExt, CharExt, Utf16Char}; +/// +/// // (💣 takes two units) +/// let chars: Vec = "💣 bomb 💣".chars().map(|c| c.to_utf16() ).collect(); +/// let units: Vec = chars.iter().to_units().collect(); +/// let flat_map: Vec = chars.iter().cloned().flatten().collect(); +/// assert_eq!(units, flat_map); +/// ``` +#[derive(Clone)] +pub struct Utf16CharSplitter, I:Iterator> { + inner: I, + prev_second: u16, +} +impl, I:IntoIterator> +From for Utf16CharSplitter { + fn from(iterable: I) -> Self { + Utf16CharSplitter { inner: iterable.into_iter(), prev_second: 0 } + } +} +impl, I:Iterator> Utf16CharSplitter { + /// Extracts the source iterator. + /// + /// Note that `iter.into_inner().to_units()` is not a no-op: + /// If the last returned unit from `next()` was a leading surrogate, + /// the trailing surrogate is lost. + pub fn into_inner(self) -> I { + self.inner + } +} +impl, I:Iterator> Iterator for Utf16CharSplitter { + type Item = u16; + fn next(&mut self) -> Option { + if self.prev_second == 0 { + self.inner.next().map(|u16c| { + let units = u16c.borrow().to_array(); + self.prev_second = units[1]; + units[0] + }) + } else { + let prev_second = self.prev_second; + self.prev_second = 0; + Some(prev_second) + } + } + fn size_hint(&self) -> (usize,Option) { + // Doesn't need to handle unlikely overflows correctly because + // size_hint() cannot be relied upon anyway. (the trait isn't unsafe) + let (min, max) = self.inner.size_hint(); + let add = if self.prev_second == 0 {0} else {1}; + (min.wrapping_add(add), max.map(|max| max.wrapping_mul(2).wrapping_add(add) )) + } +} + + + +/// An iterator over the codepoints in a `str` represented as `Utf16Char`. +#[derive(Clone)] +pub struct Utf16CharIndices<'a>{ + str: &'a str, + index: usize, +} +impl<'a> From<&'a str> for Utf16CharIndices<'a> { + fn from(s: &str) -> Utf16CharIndices { + Utf16CharIndices{str: s, index: 0} + } +} +impl<'a> Utf16CharIndices<'a> { + /// Extract the remainder of the source `str`. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::{StrExt, Utf16Char}; + /// let mut iter = "abc".utf16char_indices(); + /// assert_eq!(iter.next_back(), Some((2, Utf16Char::from('c')))); + /// assert_eq!(iter.next(), Some((0, Utf16Char::from('a')))); + /// assert_eq!(iter.as_str(), "b"); + /// ``` + pub fn as_str(&self) -> &'a str { + &self.str[self.index..] + } +} +impl<'a> Iterator for Utf16CharIndices<'a> { + type Item = (usize,Utf16Char); + fn next(&mut self) -> Option<(usize,Utf16Char)> { + match Utf16Char::from_str_start(&self.str[self.index..]) { + Ok((u16c, bytes)) => { + let item = (self.index, u16c); + self.index += bytes; + Some(item) + }, + Err(EmptyStrError) => None + } + } + fn size_hint(&self) -> (usize,Option) { + let len = self.str.len() - self.index; + // For len+3 to overflow, the slice must fill all but two bytes of + // addressable memory, and size_hint() doesn't need to be correct. + (len.wrapping_add(3)/4, Some(len)) + } +} +impl<'a> DoubleEndedIterator for Utf16CharIndices<'a> { + fn next_back(&mut self) -> Option<(usize,Utf16Char)> { + if self.index < self.str.len() { + let rev = self.str.bytes().rev(); + let len = 1 + rev.take_while(|b| b & 0b1100_0000 == 0b1000_0000 ).count(); + let starts = self.str.len() - len; + let (u16c,_) = Utf16Char::from_str_start(&self.str[starts..]).unwrap(); + self.str = &self.str[..starts]; + Some((starts, u16c)) + } else { + None + } + } +} +impl<'a> fmt::Debug for Utf16CharIndices<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.debug_tuple("Utf16CharIndices") + .field(&self.index) + .field(&self.as_str()) + .finish() + } +} + + +/// An iterator over the codepoints in a `str` represented as `Utf16Char`. +#[derive(Clone)] +pub struct Utf16Chars<'a>(Utf16CharIndices<'a>); +impl<'a> From<&'a str> for Utf16Chars<'a> { + fn from(s: &str) -> Utf16Chars { + Utf16Chars(Utf16CharIndices::from(s)) + } +} +impl<'a> Utf16Chars<'a> { + /// Extract the remainder of the source `str`. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::{StrExt, Utf16Char}; + /// let mut iter = "abc".utf16chars(); + /// assert_eq!(iter.next(), Some(Utf16Char::from('a'))); + /// assert_eq!(iter.next_back(), Some(Utf16Char::from('c'))); + /// assert_eq!(iter.as_str(), "b"); + /// ``` + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} +impl<'a> Iterator for Utf16Chars<'a> { + type Item = Utf16Char; + fn next(&mut self) -> Option { + self.0.next().map(|(_,u16c)| u16c ) + } + fn size_hint(&self) -> (usize,Option) { + self.0.size_hint() + } +} +impl<'a> DoubleEndedIterator for Utf16Chars<'a> { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(_,u16c)| u16c ) + } +} +impl<'a> fmt::Debug for Utf16Chars<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.debug_tuple("Utf16Chars") + .field(&self.as_str()) + .finish() + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/utf8_char.rs b/anneal/v2/vendor/encode_unicode/src/utf8_char.rs new file mode 100644 index 0000000000..58eef04fcd --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/utf8_char.rs @@ -0,0 +1,647 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +use crate::errors::{FromStrError, EmptyStrError, NonAsciiError, Utf8Error}; +use crate::utf8_iterators::Utf8Iterator; +use crate::traits::{CharExt, U8UtfExt}; +use crate::utf16_char::Utf16Char; +extern crate core; +use core::{hash, fmt, str, ptr}; +use core::cmp::Ordering; +use core::borrow::Borrow; +use core::ops::Deref; +#[cfg(feature="std")] +use core::iter::FromIterator; +#[cfg(feature="ascii")] +extern crate ascii; +#[cfg(feature="ascii")] +use ascii::{AsciiChar,ToAsciiChar,ToAsciiCharError}; + + +// I don't think there is any good default value for char, but char does. +#[derive(Default)] +// char doesn't do anything more advanced than u32 for Eq/Ord, so we shouldn't either. +// The default impl of Ord for arrays works out because longer codepoints +// start with more ones, so if they're equal, the length is the same, +// breaks down for values above 0x1f_ff_ff but those can only be created by unsafe code. +#[derive(PartialEq,Eq, PartialOrd,Ord)] + +#[derive(Clone,Copy)] + + +/// An unicode codepoint stored as UTF-8. +/// +/// It can be borrowed as a `str`, and has the same size as `char`. +pub struct Utf8Char { + bytes: [u8; 4], +} + + + ///////////////////// + //conversion traits// +///////////////////// +impl str::FromStr for Utf8Char { + type Err = FromStrError; + /// Create an `Utf8Char` from a string slice. + /// The string must contain exactly one codepoint. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::error::FromStrError::*; + /// use encode_unicode::Utf8Char; + /// use std::str::FromStr; + /// + /// assert_eq!(Utf8Char::from_str("a"), Ok(Utf8Char::from('a'))); + /// assert_eq!(Utf8Char::from_str("🂠"), Ok(Utf8Char::from('🂠'))); + /// assert_eq!(Utf8Char::from_str(""), Err(Empty)); + /// assert_eq!(Utf8Char::from_str("ab"), Err(MultipleCodepoints)); + /// assert_eq!(Utf8Char::from_str("é"), Err(MultipleCodepoints));// 'e'+u301 combining mark + /// ``` + fn from_str(s: &str) -> Result { + if s.is_empty() { + Err(FromStrError::Empty) + } else if s.len() != 1+s.as_bytes()[0].extra_utf8_bytes_unchecked() { + Err(FromStrError::MultipleCodepoints) + } else { + let mut bytes = [0; 4]; + bytes[..s.len()].copy_from_slice(s.as_bytes()); + Ok(Utf8Char{bytes}) + } + } +} +impl From for Utf8Char { + fn from(utf16: Utf16Char) -> Utf8Char { + match utf16.to_tuple() { + (ascii @ 0..=0x00_7f, _) => { + Utf8Char{ bytes: [ascii as u8, 0, 0, 0] } + }, + (unit @ 0..=0x07_ff, _) => { + let byte2 = 0x80 | (unit & 0x00_3f) as u8; + let byte1 = 0xc0 | ((unit & 0x07_c0) >> 6) as u8; + Utf8Char{ bytes: [byte1, byte2, 0, 0] } + }, + (unit, None) => { + let byte3 = 0x80 | (unit & 0x00_3f) as u8; + let byte2 = 0x80 | ((unit & 0x0f_c0) >> 6) as u8; + let byte1 = 0xe0 | ((unit & 0xf0_00) >> 12) as u8; + Utf8Char{ bytes: [byte1, byte2, byte3, 0] } + }, + (first, Some(second)) => { + let first = first + (0x01_00_00u32 >> 10) as u16; + let byte4 = 0x80 | (second & 0x00_3f) as u8; + let byte3 = 0x80 | ((second & 0x03_c0) >> 6) as u8 + | (( first & 0x00_03) << 4) as u8; + let byte2 = 0x80 | (( first & 0x00_fc) >> 2) as u8; + let byte1 = 0xf0 | (( first & 0x07_00) >> 8) as u8; + Utf8Char{ bytes: [byte1, byte2, byte3, byte4] } + } + } + } +} +impl From for Utf8Char { + fn from(c: char) -> Self { + Utf8Char::new(c) + } +} +impl From for char { + fn from(uc: Utf8Char) -> char { + uc.to_char() + } +} +impl IntoIterator for Utf8Char { + type Item=u8; + type IntoIter=Utf8Iterator; + /// Iterate over the byte values. + fn into_iter(self) -> Utf8Iterator { + Utf8Iterator::from(self) + } +} + +#[cfg(feature="std")] +impl Extend for Vec { + fn extend>(&mut self, iter: I) { + let iter = iter.into_iter(); + self.reserve(iter.size_hint().0); + for u8c in iter { + // twice as fast as self.extend_from_slice(u8c.as_bytes()); + self.push(u8c.bytes[0]); + for &extra in &u8c.bytes[1..] { + if extra != 0 { + self.push(extra); + } + } + } + } +} +#[cfg(feature="std")] +impl<'a> Extend<&'a Utf8Char> for Vec { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()) + } +} +#[cfg(feature="std")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + unsafe { self.as_mut_vec().extend(iter) } + } +} +#[cfg(feature="std")] +impl<'a> Extend<&'a Utf8Char> for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()) + } +} +#[cfg(feature="std")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut string = String::new(); + string.extend(iter); + return string; + } +} +#[cfg(feature="std")] +impl<'a> FromIterator<&'a Utf8Char> for String { + fn from_iter>(iter: I) -> String { + iter.into_iter().cloned().collect() + } +} +#[cfg(feature="std")] +impl FromIterator for Vec { + fn from_iter>(iter: I) -> Self { + iter.into_iter().collect::().into_bytes() + } +} +#[cfg(feature="std")] +impl<'a> FromIterator<&'a Utf8Char> for Vec { + fn from_iter>(iter: I) -> Self { + iter.into_iter().cloned().collect::().into_bytes() + } +} + + + ///////////////// + //getter traits// +///////////////// +impl AsRef<[u8]> for Utf8Char { + fn as_ref(&self) -> &[u8] { + &self.bytes[..self.len()] + } +} +impl AsRef for Utf8Char { + fn as_ref(&self) -> &str { + unsafe{ str::from_utf8_unchecked( self.as_ref() ) } + } +} +impl Borrow<[u8]> for Utf8Char { + fn borrow(&self) -> &[u8] { + self.as_ref() + } +} +impl Borrow for Utf8Char { + fn borrow(&self) -> &str { + self.as_ref() + } +} +impl Deref for Utf8Char { + type Target = str; + fn deref(&self) -> &Self::Target { + self.as_ref() + } +} + + + //////////////// + //ascii traits// +//////////////// +#[cfg(feature="ascii")] +/// Requires the feature "ascii". +impl From for Utf8Char { + fn from(ac: AsciiChar) -> Self { + Utf8Char{ bytes: [ac.as_byte(),0,0,0] } + } +} +#[cfg(feature="ascii")] +/// Requires the feature "ascii". +impl ToAsciiChar for Utf8Char { + fn to_ascii_char(self) -> Result { + self.bytes[0].to_ascii_char() + } + unsafe fn to_ascii_char_unchecked(self) -> AsciiChar { + unsafe { self.bytes[0].to_ascii_char_unchecked() } + } +} + + + ///////////////////////////////////////////////////////// + //Genaral traits that cannot be derived to emulate char// +///////////////////////////////////////////////////////// +impl hash::Hash for Utf8Char { + fn hash(&self, state: &mut H) { + self.to_char().hash(state); + } +} +impl fmt::Debug for Utf8Char { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.to_char(), fmtr) + } +} +impl fmt::Display for Utf8Char { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.write_str(self.as_str()) + } +} + + + //////////////////////////////// + //Comparisons with other types// +//////////////////////////////// +impl PartialEq for Utf8Char { + fn eq(&self, u32c: &char) -> bool { + *self == Utf8Char::from(*u32c) + } +} +impl PartialEq for char { + fn eq(&self, u8c: &Utf8Char) -> bool { + Utf8Char::from(*self) == *u8c + } +} +impl PartialOrd for Utf8Char { + fn partial_cmp(&self, u32c: &char) -> Option { + self.partial_cmp(&Self::from(*u32c)) + } +} +impl PartialOrd for char { + fn partial_cmp(&self, u8c: &Utf8Char) -> Option { + Utf8Char::from(*self).partial_cmp(u8c) + } +} + +impl PartialEq for Utf8Char { + fn eq(&self, u16c: &Utf16Char) -> bool { + *self == Self::from(*u16c) + } +} +impl PartialOrd for Utf8Char { + fn partial_cmp(&self, u16c: &Utf16Char) -> Option { + self.partial_cmp(&Self::from(*u16c)) + } +} +// The other direction is implemented in utf16_char.rs + +/// Only considers the byte equal if both it and the `Utf8Char` represents ASCII characters. +/// +/// There is no impl in the opposite direction, as this should only be used to +/// compare `Utf8Char`s against constants. +/// +/// # Examples +/// +/// ``` +/// # use encode_unicode::Utf8Char; +/// assert!(Utf8Char::from('8') == b'8'); +/// assert!(Utf8Char::from_array([0xf1,0x80,0x80,0x80]).unwrap() != 0xf1); +/// assert!(Utf8Char::from('\u{ff}') != 0xff); +/// assert!(Utf8Char::from('\u{80}') != 0x80); +/// ``` +impl PartialEq for Utf8Char { + fn eq(&self, byte: &u8) -> bool { + self.bytes[0] == *byte && self.bytes[1] == 0 + } +} +#[cfg(feature = "ascii")] +/// `Utf8Char`s that are not ASCII never compare equal. +impl PartialEq for Utf8Char { + #[inline] + fn eq(&self, ascii: &AsciiChar) -> bool { + self.bytes[0] == *ascii as u8 + } +} +#[cfg(feature = "ascii")] +/// `Utf8Char`s that are not ASCII never compare equal. +impl PartialEq for AsciiChar { + #[inline] + fn eq(&self, u8c: &Utf8Char) -> bool { + u8c == self + } +} +#[cfg(feature = "ascii")] +/// `Utf8Char`s that are not ASCII always compare greater. +impl PartialOrd for Utf8Char { + #[inline] + fn partial_cmp(&self, ascii: &AsciiChar) -> Option { + self.bytes[0].partial_cmp(ascii) + } +} +#[cfg(feature = "ascii")] +/// `Utf8Char`s that are not ASCII always compare greater. +impl PartialOrd for AsciiChar { + #[inline] + fn partial_cmp(&self, u8c: &Utf8Char) -> Option { + self.partial_cmp(&u8c.bytes[0]) + } +} + + + /////////////////////////////////////////////////////// + //pub impls that should be together for nicer rustdoc// +/////////////////////////////////////////////////////// +impl Utf8Char { + /// A `const fn` alternative to the trait-based `Utf8Char::from(char)`. + /// + /// # Example + /// + /// ``` + /// # use encode_unicode::Utf8Char; + /// const REPLACEMENT_CHARACTER: Utf8Char = Utf8Char::new('\u{fffd}'); + /// ``` + pub const fn new(c: char) -> Self { + if c.is_ascii() { + Utf8Char{bytes: [c as u8, 0, 0, 0]} + } else { + // How many extra UTF-8 bytes that are needed to represent an + // UTF-32 codepoint with a number of bits. + // Stored as a bit-packed array using two bits per value. + // 0..=7 bits = no extra bytes + // +4 = 8..=11 bits = one xtra byte (5+6 bits) + // +5 = 12..=16 bits = two extra bytes (4+6+6 bits) + // +5 = 17..=21 bits = three extra bytes (3+6+6+6 bits) + const EXTRA_BYTES: u64 = 0b11_11_11_11_11__10_10_10_10_10__01_01_01_01__00_00_00_00_00_00_00__00; + let bits_used = 32 - (c as u32).leading_zeros(); + let len = 1 + ((EXTRA_BYTES >> (bits_used*2)) & 0b11); + // copied from CharExt::to_utf8_array() + let mut c = c as u32; + let mut parts = 0;// convert to 6-bit bytes + parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; c>>=6; + parts<<=8; parts |= c & 0x3f; + parts |= 0x80_80_80_80;// set the most significant bit + parts >>= 8*(4-len);// right-align bytes + // Now, unused bytes are zero, (which matters for Utf8Char.eq()) + // and the rest are 0b10xx_xxxx + + // set header on first byte + parts |= (0xff_00u32 >> len) & 0xff;// store length + parts &= !(1u32 << (7-len));// clear the next bit after it + + Utf8Char {bytes: parts.to_le_bytes()} + } + } + + /// Create an `Utf8Char` from the first codepoint in a `str`. + /// + /// Returns an error if the `str` is empty. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::Utf8Char; + /// + /// assert_eq!(Utf8Char::from_str_start("a"), Ok((Utf8Char::from('a'),1))); + /// assert_eq!(Utf8Char::from_str_start("ab"), Ok((Utf8Char::from('a'),1))); + /// assert_eq!(Utf8Char::from_str_start("🂠 "), Ok((Utf8Char::from('🂠'),4))); + /// assert_eq!(Utf8Char::from_str_start("é"), Ok((Utf8Char::from('e'),1)));// 'e'+u301 combining mark + /// assert!(Utf8Char::from_str_start("").is_err()); + /// ``` + pub fn from_str_start(src: &str) -> Result<(Self,usize),EmptyStrError> { + unsafe { + if src.is_empty() { + Err(EmptyStrError) + } else { + Ok(Utf8Char::from_slice_start_unchecked(src.as_bytes())) + } + } + } + /// Create an `Utf8Char` of the first codepoint in an UTF-8 slice. + /// Also returns the length of the UTF-8 sequence for the codepoint. + /// + /// If the slice is from a `str`, use `::from_str_start()` to skip UTF-8 validation. + /// + /// # Errors + /// + /// Returns an `Err` if the slice is empty, doesn't start with a valid + /// UTF-8 sequence or is too short for the sequence. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::Utf8Char; + /// use encode_unicode::error::Utf8ErrorKind::*; + /// + /// assert_eq!(Utf8Char::from_slice_start(&[b'A', b'B', b'C']), Ok((Utf8Char::from('A'),1))); + /// assert_eq!(Utf8Char::from_slice_start(&[0xdd, 0xbb]), Ok((Utf8Char::from('\u{77b}'),2))); + /// + /// assert_eq!(Utf8Char::from_slice_start(&[]).unwrap_err().kind(), TooFewBytes); + /// assert_eq!(Utf8Char::from_slice_start(&[0xf0, 0x99]).unwrap_err().kind(), TooFewBytes); + /// assert_eq!(Utf8Char::from_slice_start(&[0xee, b'F', 0x80]).unwrap_err().kind(), InterruptedSequence); + /// assert_eq!(Utf8Char::from_slice_start(&[0xee, 0x99, 0x0f]).unwrap_err().kind(), InterruptedSequence); + /// ``` + pub fn from_slice_start(src: &[u8]) -> Result<(Self,usize),Utf8Error> { + char::from_utf8_slice_start(src).map(|(_,len)| { + let mut bytes = [0; 4]; + bytes[..len].copy_from_slice(&src[..len]); + (Utf8Char{bytes}, len) + }) + } + /// A `from_slice_start()` that doesn't validate the codepoint. + /// + /// # Safety + /// + /// The slice must be non-empty and start with a valid UTF-8 codepoint. + /// Invalid or incomplete values might cause reads of uninitalized memory. + pub unsafe fn from_slice_start_unchecked(src: &[u8]) -> (Self,usize) { + unsafe { + let len = 1+src.get_unchecked(0).extra_utf8_bytes_unchecked(); + let mut bytes = [0; 4]; + ptr::copy_nonoverlapping(src.as_ptr(), bytes.as_mut_ptr() as *mut u8, len); + (Utf8Char{bytes}, len) + } + } + /// Create an `Utf8Char` from a byte array after validating it. + /// + /// The codepoint must start at the first byte. + /// Unused bytes are set to zero by this function and so can be anything. + /// + /// # Errors + /// + /// Returns an `Err` if the array doesn't start with a valid UTF-8 sequence. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::Utf8Char; + /// use encode_unicode::error::Utf8ErrorKind::*; + /// + /// assert_eq!(Utf8Char::from_array([b'A', 0, 0, 0]), Ok(Utf8Char::from('A'))); + /// assert_eq!(Utf8Char::from_array([0xf4, 0x8b, 0xbb, 0xbb]), Ok(Utf8Char::from('\u{10befb}'))); + /// assert_eq!(Utf8Char::from_array([b'A', b'B', b'C', b'D']), Ok(Utf8Char::from('A'))); + /// assert_eq!(Utf8Char::from_array([0, 0, 0xcc, 0xbb]), Ok(Utf8Char::from('\0'))); + /// + /// assert_eq!(Utf8Char::from_array([0xef, b'F', 0x80, 0x80]).unwrap_err().kind(), InterruptedSequence); + /// assert_eq!(Utf8Char::from_array([0xc1, 0x80, 0, 0]).unwrap_err().kind(), NonUtf8Byte); + /// assert_eq!(Utf8Char::from_array([0xe0, 0x9a, 0xbf, 0]).unwrap_err().kind(), OverlongEncoding); + /// assert_eq!(Utf8Char::from_array([0xf4, 0xaa, 0x99, 0x88]).unwrap_err().kind(), TooHighCodepoint); + /// ``` + pub fn from_array(utf8: [u8;4]) -> Result { + // perform all validation + char::from_utf8_array(utf8)?; + let extra = utf8[0].extra_utf8_bytes_unchecked() as u32; + // zero unused bytes in one operation by transmuting the arrary to + // u32, apply an endian-corrected mask and transmute back + let mask = u32::from_le(0xff_ff_ff_ff >> (8*(3-extra))); + let unused_zeroed = mask & u32::from_ne_bytes(utf8); // native endian + Ok(Utf8Char{ bytes: unused_zeroed.to_ne_bytes() }) + } + /// Zero-cost constructor. + /// + /// # Safety + /// + /// Must contain a valid codepoint starting at the first byte, with the + /// unused bytes zeroed. + /// Bad values can easily lead to undefined behavior. + #[inline] + pub const unsafe fn from_array_unchecked(utf8: [u8;4]) -> Self { + Utf8Char{ bytes: utf8 } + } + /// Create an `Utf8Char` from a single byte. + /// + /// The byte must be an ASCII character. + /// + /// # Errors + /// + /// Returns `NonAsciiError` if the byte greater than 127. + /// + /// # Examples + /// + /// ``` + /// # use encode_unicode::Utf8Char; + /// assert_eq!(Utf8Char::from_ascii(b'a').unwrap(), 'a'); + /// assert!(Utf8Char::from_ascii(128).is_err()); + /// ``` + pub const fn from_ascii(ascii: u8) -> Result { + [Ok(Utf8Char{ bytes: [ascii, 0, 0, 0] }), Err(NonAsciiError)][(ascii >> 7) as usize] + } + /// Create an `Utf8Char` from a single byte without checking that it's a + /// valid codepoint on its own, which is only true for ASCII characters. + /// + /// # Safety + /// + /// The byte must be less than 128. + #[inline] + pub const unsafe fn from_ascii_unchecked(ascii: u8) -> Self { + Utf8Char{ bytes: [ascii, 0, 0, 0] } + } + + /// The number of bytes this character needs. + /// + /// Is between 1 and 4 (inclusive) and identical to `.as_ref().len()` or + /// `.as_char().len_utf8()`. + #[inline] + pub const fn len(self) -> usize { + // Invariants of the extra bytes enambles algorithms that + // `u8.extra_utf8_bytes_unchecked()` cannot use. + // Some of them turned out to require fewer x86 instructions: + + // Exploits that unused bytes are zero and calculates the number of + // trailing zero bytes. + // Setting a bit in the first byte prevents the function from returning + // 0 for '\0' (which has 32 leading zeros). + // trailing and leading is swapped below to optimize for little-endian + // architectures. + (4 - (u32::from_le_bytes(self.bytes)|1).leading_zeros()/8) as usize + + // Exploits that the extra bytes have their most significant bit set if + // in use. + // Takes fewer instructions than the one above if popcnt can be used, + // (which it cannot by default, + // set RUSTFLAGS='-C target-cpu=native' to enable) + //let all = u32::from_ne_bytes(self.bytes); + //let msb_mask = u32::from_be(0x00808080); + //let add_one = u32::from_be(0x80000000); + //((all & msb_mask) | add_one).count_ones() as usize + } + // There is no .is_emty() because this type is never empty. + + /// Checks that the codepoint is an ASCII character. + pub const fn is_ascii(self) -> bool { + self.bytes[0].is_ascii() + } + /// Checks that two characters are an ASCII case-insensitive match. + /// + /// Is equivalent to `a.to_ascii_lowercase() == b.to_ascii_lowercase()`. + pub const fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + if self.is_ascii() { + self.bytes[0].eq_ignore_ascii_case(&other.bytes[0]) + } else { + // [u8; 4] can't be const compared as of Rust 1.60, but u32 can + u32::from_le_bytes(self.bytes) == u32::from_le_bytes(other.bytes) + } + } + /// Converts the character to its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + pub const fn to_ascii_uppercase(mut self) -> Self { + self.bytes[0] = self.bytes[0].to_ascii_uppercase(); + self + } + /// Converts the character to its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + pub const fn to_ascii_lowercase(mut self) -> Self { + self.bytes[0] = self.bytes[0].to_ascii_lowercase(); + self + } + /// Converts the character to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.bytes[0].make_ascii_uppercase() + } + /// Converts the character to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.bytes[0].make_ascii_lowercase(); + } + + /// Convert from UTF-8 to UTF-32 + pub fn to_char(self) -> char { + unsafe { char::from_utf8_exact_slice_unchecked(&self.bytes[..self.len()]) } + } + /// Write the internal representation to a slice, + /// and then returns the number of bytes written. + /// + /// # Panics + /// + /// Will panic the buffer is too small; + /// You can get the required length from `.len()`, + /// but a buffer of length four is always large enough. + pub fn to_slice(self, dst: &mut[u8]) -> usize { + if self.len() > dst.len() { + panic!("The provided buffer is too small."); + } + dst[..self.len()].copy_from_slice(&self.bytes[..self.len()]); + self.len() + } + /// Expose the internal array and the number of used bytes. + pub const fn to_array(self) -> ([u8;4],usize) { + (self.bytes, self.len()) + } + /// Return a `str` view of the array the codepoint is stored as. + /// + /// Is an unambiguous version of `.as_ref()`. + pub fn as_str(&self) -> &str { + self.deref() + } +} diff --git a/anneal/v2/vendor/encode_unicode/src/utf8_iterators.rs b/anneal/v2/vendor/encode_unicode/src/utf8_iterators.rs new file mode 100644 index 0000000000..b37c687733 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/src/utf8_iterators.rs @@ -0,0 +1,346 @@ +/* Copyright 2018-2020 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +use crate::utf8_char::Utf8Char; +use crate::errors::EmptyStrError; +extern crate core; +use core::{u32, u64}; +use core::ops::Not; +use core::fmt; +use core::borrow::Borrow; +#[cfg(feature="std")] +use std::io::{Read, Error as ioError}; + + + +/// Read or iterate over the bytes of the UTF-8 representation of a codepoint. +#[derive(Clone)] +pub struct Utf8Iterator (u32); + +impl From for Utf8Iterator { + fn from(uc: Utf8Char) -> Self { + let used = u32::from_le_bytes(uc.to_array().0); + // uses u64 because shifting an u32 by 32 bits is a no-op. + let unused_set = (u64::MAX << (uc.len() as u64*8)) as u32; + Utf8Iterator(used | unused_set) + } +} +impl From for Utf8Iterator { + fn from(c: char) -> Self { + Self::from(Utf8Char::from(c)) + } +} +impl Iterator for Utf8Iterator { + type Item=u8; + fn next(&mut self) -> Option { + let next = self.0 as u8; + if next == 0xff { + None + } else { + self.0 = (self.0 >> 8) | 0xff_00_00_00; + Some(next) + } + } + fn size_hint(&self) -> (usize, Option) { + (self.len(), Some(self.len())) + } +} +impl ExactSizeIterator for Utf8Iterator { + fn len(&self) -> usize {// not straightforward, but possible + let unused_bytes = self.0.not().leading_zeros() / 8; + 4 - unused_bytes as usize + } +} +#[cfg(feature="std")] +impl Read for Utf8Iterator { + /// Always returns Ok + fn read(&mut self, buf: &mut[u8]) -> Result { + // Cannot call self.next() until I know I can write the result. + for (i, dst) in buf.iter_mut().enumerate() { + match self.next() { + Some(b) => *dst = b, + None => return Ok(i), + } + } + Ok(buf.len()) + } +} +impl fmt::Debug for Utf8Iterator { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + let mut content = [0; 4]; + let mut i = 0; + for b in self.clone() { + content[i] = b; + i += 1; + } + write!(fmtr, "{:?}", &content[..i]) + } +} + + + +/// Converts an iterator of `Utf8Char` (or `&Utf8Char`) +/// to an iterator of `u8`s. +/// +/// Is equivalent to calling `.flatten()` or `.flat_map()` on the original iterator, +/// but the returned iterator is ~40% faster. +/// +/// The iterator also implements `Read` (if the `std` feature isn't disabled). +/// Reading will never produce an error, and calls to `.read()` and `.next()` +/// can be mixed. +/// +/// The exact number of bytes cannot be known in advance, but `size_hint()` +/// gives the possible range. +/// (min: all remaining characters are ASCII, max: all require four bytes) +/// +/// # Examples +/// +/// From iterator of values: +/// +/// ``` +/// use encode_unicode::{IterExt, CharExt}; +/// +/// let iterator = "foo".chars().map(|c| c.to_utf8() ); +/// let mut bytes = [0; 4]; +/// iterator.to_bytes().zip(&mut bytes).for_each(|(b,dst)| *dst = b ); +/// assert_eq!(&bytes, b"foo\0"); +/// ``` +/// +/// From iterator of references: +/// +#[cfg_attr(feature="std", doc=" ```")] +#[cfg_attr(not(feature="std"), doc=" ```no_compile")] +/// use encode_unicode::{IterExt, CharExt, Utf8Char}; +/// +/// let chars: Vec = "💣 bomb 💣".chars().map(|c| c.to_utf8() ).collect(); +/// let bytes: Vec = chars.iter().to_bytes().collect(); +/// let flat_map: Vec = chars.iter().cloned().flatten().collect(); +/// assert_eq!(bytes, flat_map); +/// ``` +/// +/// `Read`ing from it: +/// +#[cfg_attr(feature="std", doc=" ```")] +#[cfg_attr(not(feature="std"), doc=" ```no_compile")] +/// use encode_unicode::{IterExt, CharExt}; +/// use std::io::Read; +/// +/// let s = "Ååh‽"; +/// assert_eq!(s.len(), 8); +/// let mut buf = [b'E'; 9]; +/// let mut reader = s.chars().map(|c| c.to_utf8() ).to_bytes(); +/// assert_eq!(reader.read(&mut buf[..]).unwrap(), 8); +/// assert_eq!(reader.read(&mut buf[..]).unwrap(), 0); +/// assert_eq!(&buf[..8], s.as_bytes()); +/// assert_eq!(buf[8], b'E'); +/// ``` +#[derive(Clone)] +pub struct Utf8CharSplitter, I:Iterator> { + inner: I, + prev: u32, +} +impl, I:IntoIterator> +From for Utf8CharSplitter { + fn from(iterable: I) -> Self { + Utf8CharSplitter { inner: iterable.into_iter(), prev: 0 } + } +} +impl, I:Iterator> Utf8CharSplitter { + /// Extracts the source iterator. + /// + /// Note that `iter.into_inner().to_bytes()` is not a no-op: + /// If the last returned byte from `next()` was not an ASCII character, + /// the remaining bytes of that codepoint is lost. + pub fn into_inner(self) -> I { + self.inner + } +} +impl, I:Iterator> Iterator for Utf8CharSplitter { + type Item = u8; + fn next(&mut self) -> Option { + if self.prev == 0 { + self.inner.next().map(|u8c| { + let array = u8c.borrow().to_array().0; + self.prev = u32::from_le_bytes(array) >> 8; + array[0] + }) + } else { + let next = self.prev as u8; + self.prev >>= 8; + Some(next) + } + } + fn size_hint(&self) -> (usize,Option) { + // Doesn't need to handle unlikely overflows correctly because + // size_hint() cannot be relied upon anyway. (the trait isn't unsafe) + let (min, max) = self.inner.size_hint(); + let add = 4 - (self.prev.leading_zeros() / 8) as usize; + (min.wrapping_add(add), max.map(|max| max.wrapping_mul(4).wrapping_add(add) )) + } +} +#[cfg(feature="std")] +impl, I:Iterator> Read for Utf8CharSplitter { + /// Always returns `Ok` + fn read(&mut self, buf: &mut[u8]) -> Result { + let mut i = 0; + // write remaining bytes of previous codepoint + while self.prev != 0 && i < buf.len() { + buf[i] = self.prev as u8; + self.prev >>= 8; + i += 1; + } + // write whole characters + while i < buf.len() { + let bytes = match self.inner.next() { + Some(u8c) => u8c.borrow().to_array().0, + None => break + }; + buf[i] = bytes[0]; + i += 1; + if bytes[1] != 0 { + let len = bytes[0].not().leading_zeros() as usize; + let mut written = 1; + while written < len { + if i < buf.len() { + buf[i] = bytes[written]; + i += 1; + written += 1; + } else { + let bytes_as_u32 = u32::from_le_bytes(bytes); + self.prev = bytes_as_u32 >> (8*written); + return Ok(i); + } + } + } + } + Ok(i) + } +} + + + +/// An iterator over the `Utf8Char` of a string slice, and their positions. +/// +/// This struct is created by the `utf8char_indices()` method from [`StrExt`](../trait.StrExt.html) +/// trait. See its documentation for more. +#[derive(Clone)] +pub struct Utf8CharIndices<'a>{ + str: &'a str, + index: usize, +} +impl<'a> From<&'a str> for Utf8CharIndices<'a> { + fn from(s: &str) -> Utf8CharIndices { + Utf8CharIndices{str: s, index: 0} + } +} +impl<'a> Utf8CharIndices<'a> { + /// Extract the remainder of the source `str`. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::{StrExt, Utf8Char}; + /// let mut iter = "abc".utf8char_indices(); + /// assert_eq!(iter.next_back(), Some((2, Utf8Char::from('c')))); + /// assert_eq!(iter.next(), Some((0, Utf8Char::from('a')))); + /// assert_eq!(iter.as_str(), "b"); + /// ``` + pub fn as_str(&self) -> &'a str { + &self.str[self.index..] + } +} +impl<'a> Iterator for Utf8CharIndices<'a> { + type Item = (usize,Utf8Char); + fn next(&mut self) -> Option<(usize,Utf8Char)> { + match Utf8Char::from_str_start(&self.str[self.index..]) { + Ok((u8c, len)) => { + let item = (self.index, u8c); + self.index += len; + Some(item) + }, + Err(EmptyStrError) => None + } + } + fn size_hint(&self) -> (usize,Option) { + let len = self.str.len() - self.index; + // For len+3 to overflow, the slice must fill all but two bytes of + // addressable memory, and size_hint() doesn't need to be correct. + (len.wrapping_add(3)/4, Some(len)) + } +} +impl<'a> DoubleEndedIterator for Utf8CharIndices<'a> { + fn next_back(&mut self) -> Option<(usize,Utf8Char)> { + // Cannot refactor out the unwrap without switching to ::from_slice() + // since slicing the str panics if not on a boundary. + if self.index < self.str.len() { + let rev = self.str.bytes().rev(); + let len = 1 + rev.take_while(|b| b & 0b1100_0000 == 0b1000_0000 ).count(); + let starts = self.str.len() - len; + let (u8c,_) = Utf8Char::from_str_start(&self.str[starts..]).unwrap(); + self.str = &self.str[..starts]; + Some((starts, u8c)) + } else { + None + } + } +} +impl<'a> fmt::Debug for Utf8CharIndices<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.debug_tuple("Utf8CharIndices") + .field(&self.index) + .field(&self.as_str()) + .finish() + } +} + + +/// An iterator over the codepoints in a `str` represented as `Utf8Char`. +#[derive(Clone)] +pub struct Utf8Chars<'a>(Utf8CharIndices<'a>); +impl<'a> From<&'a str> for Utf8Chars<'a> { + fn from(s: &str) -> Utf8Chars { + Utf8Chars(Utf8CharIndices::from(s)) + } +} +impl<'a> Utf8Chars<'a> { + /// Extract the remainder of the source `str`. + /// + /// # Examples + /// + /// ``` + /// use encode_unicode::{StrExt, Utf8Char}; + /// let mut iter = "abc".utf8chars(); + /// assert_eq!(iter.next(), Some(Utf8Char::from('a'))); + /// assert_eq!(iter.next_back(), Some(Utf8Char::from('c'))); + /// assert_eq!(iter.as_str(), "b"); + /// ``` + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} +impl<'a> Iterator for Utf8Chars<'a> { + type Item = Utf8Char; + fn next(&mut self) -> Option { + self.0.next().map(|(_,u8c)| u8c ) + } + fn size_hint(&self) -> (usize,Option) { + self.0.size_hint() + } +} +impl<'a> DoubleEndedIterator for Utf8Chars<'a> { + fn next_back(&mut self) -> Option { + self.0.next_back().map(|(_,u8c)| u8c ) + } +} +impl<'a> fmt::Debug for Utf8Chars<'a> { + fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { + fmtr.debug_tuple("Utf8CharIndices") + .field(&self.as_str()) + .finish() + } +} diff --git a/anneal/v2/vendor/encode_unicode/tests/errs.rs b/anneal/v2/vendor/encode_unicode/tests/errs.rs new file mode 100644 index 0000000000..94e5119c58 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/tests/errs.rs @@ -0,0 +1,227 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * Copyright 2018 Aljoscha Meyer + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Test that methods gives the correct error. +//! Some also test a bit more because it's easy. + +extern crate core; +use core::char; +extern crate encode_unicode; +use encode_unicode::*; +use encode_unicode::error::*; +use encode_unicode::error::CodepointError::*; +use encode_unicode::error::Utf8ErrorKind::*; + + +#[test] fn from_u32() { + for c in 0xd800..0xe000 { + assert_eq!(char::from_u32_detailed(c), Err(Utf16Reserved)); + } + let mut c = 0x11_00_00; + loop { + assert_eq!(char::from_u32_detailed(c), Err(TooHigh)); + // Don't test every value. (Range.step_by() is unstable) + match c.checked_add(0x10_11_11) { + Some(next) => c = next, + None => break, + } + } +} + +fn kind(result: Result) -> Result { + result.map_err(|e| e.kind() ) +} + + +#[test] fn utf8_extra_bytes() { + for c in 0..256 { + assert_eq!( kind((c as u8).extra_utf8_bytes()), match c { + 0b_1000_0000..=0b_1011_1111 => Err(UnexpectedContinuationByte), + 0b_1100_0000..=0b_1100_0001 => Err(NonUtf8Byte), + 0b_1111_0101..=0b_1111_0111 => Err(NonUtf8Byte), + 0b_1111_1000..=0b_1111_1111 => Err(NonUtf8Byte), + 0b_0000_0000..=0b_0111_1111 => Ok(0), + 0b_1100_0010..=0b_1101_1111 => Ok(1), + 0b_1110_0000..=0b_1110_1111 => Ok(2), + 0b_1111_0000..=0b_1111_0100 => Ok(3), + _ => unreachable!(), + }); + } + + for c in 0..256 { + assert_eq!((c as u8).extra_utf8_bytes_unchecked(), match c { + 0b_0000_0000..=0b_0111_1111 => 0, + 0b_1100_0000..=0b_1101_1111 => 1, + 0b_1110_0000..=0b_1110_1111 => 2, + 0b_1111_0000..=0b_1111_0111 => 3, + 0b_1000_0000..=0b_1011_1111 => 0, + 0b_1111_1111 => 7, + _ => continue, + }); + } +} + +#[test] +#[cfg_attr(miri, ignore)] +fn utf16_extra_unit() { + for c in 0..0x1_00_00 { + assert_eq!( (c as u16).utf16_needs_extra_unit(), match c { + 0b_0000_0000_0000_0000..=0b_1101_0111_1111_1111 => Ok(false), + 0b_1101_1000_0000_0000..=0b_1101_1011_1111_1111 => Ok(true), + 0b_1101_1100_0000_0000..=0b_1101_1111_1111_1111 => Err(Utf16FirstUnitError), + 0b_1110_0000_0000_0000..=0b_1111_1111_1111_1111 => Ok(false), + _ => unreachable!(), + }); + } +} + + +#[test] +#[cfg_attr(miri, ignore)] +fn from_utf16_tuple() { + use encode_unicode::error::Utf16TupleError::*; + for u in 0xdc00..0xe000 { + let close = if u%3==0 {u-100} else {u+100}; + let doesnt_matter = if u%2==0 {Some(close)} else {None}; + assert_eq!(char::from_utf16_tuple((u,doesnt_matter)), Err(FirstIsTrailingSurrogate)); + } + for u in (0..0xd800).chain(0xe000..0x10000) { + assert_eq!( + char::from_utf16_tuple((u as u16, Some((0x100+u) as u16))), + Err(SuperfluousSecond) + ); + } + for u in 0xd800..0xdc00 { + assert_eq!(char::from_utf16_tuple((u,None)), Err(MissingSecond)); + assert_eq!(char::from_utf16_tuple((u,Some(u - 0x2ff))), Err(SecondIsNotTrailingSurrogate)); + } +} + +#[test] fn from_utf16_slice_start() { + use encode_unicode::error::Utf16SliceError::*; + assert_eq!(char::from_utf16_slice_start(&[]), Err(EmptySlice)); + let mut buf = [0; 6]; + for u in 0xd800..0xdc00 { + buf[0] = u; + assert_eq!(char::from_utf16_slice_start(&buf[..1]), Err(MissingSecond)); + buf[1] = u; + let pass = 2 + (u as usize % (buf.len()-2)); + assert_eq!(char::from_utf16_slice_start(&buf[..pass]), Err(SecondIsNotTrailingSurrogate)); + } + for u in 0xdc00..0xe000 { + buf[0] = u; + let close = if u%3==0 {u-100} else {u+100}; + let pass = 1 + (u as usize % (buf.len()-1)); + buf[pass] = close; + assert_eq!(char::from_utf16_slice_start(&buf[..pass]), Err(FirstIsTrailingSurrogate)); + } +} + +#[test] fn utf8_overlong() { + let overlongs = [ + [0xf0,0x8f], [0xf0,0x87], [0xf0,0x80], // 4-byte + [0xe0,0x9f], [0xe0,0x8f], [0xe0,0x80], // 3-byte + ]; + for o in overlongs.iter() { + for &last in &[0x80, 0xbf] { + let arr = [o[0], o[1], last, last]; + assert_eq!(kind(char::from_utf8_slice_start(&arr)), Err(OverlongEncoding)); + assert_eq!(kind(char::from_utf8_array(arr)), Err(OverlongEncoding)); + assert_eq!(kind(Utf8Char::from_slice_start(&arr)), Err(OverlongEncoding)); + assert_eq!(kind(Utf8Char::from_array(arr)), Err(OverlongEncoding)); + } + } + + let non_utf8 = [ + [0xc1,0xbf], [0xc1,0x92], [0xc1,0x80], // 2-byte + [0xc0,0xbf], [0xc0,0x9f], [0xc0,0x80], // 2-byte + ]; + for non in non_utf8.iter() { + for &last in &[0x80, 0xbf] { + let arr = [non[0], non[1], last, last]; + assert_eq!(kind(char::from_utf8_slice_start(&arr)), Err(NonUtf8Byte)); + assert_eq!(kind(char::from_utf8_array(arr)), Err(NonUtf8Byte)); + assert_eq!(kind(Utf8Char::from_slice_start(&arr)), Err(NonUtf8Byte)); + assert_eq!(kind(Utf8Char::from_array(arr)), Err(NonUtf8Byte)); + } + } +} + +#[test] fn from_str_start() { + assert_eq!(Utf8Char::from_str_start(""), Err(EmptyStrError)); + assert_eq!(Utf16Char::from_str_start(""), Err(EmptyStrError)); +} + +#[test] fn utf8_codepoint_is_too_high() { + assert_eq!(kind(Utf8Char::from_array([0xf4, 0x90, 0x80, 0x80])), Err(TooHighCodepoint)); + assert_eq!(kind(char::from_utf8_array([0xf4, 0x90, 0x80, 0x80])), Err(TooHighCodepoint)); + assert_eq!(kind(Utf8Char::from_slice_start(&[0xf4, 0x90, 0x80, 0x80])), Err(TooHighCodepoint)); + assert_eq!(kind(char::from_utf8_slice_start(&[0xf4, 0x90, 0x80, 0x80])), Err(TooHighCodepoint)); + + assert_eq!(kind(Utf8Char::from_array([0xf4, 0xa4, 0xb0, 0x9f])), Err(TooHighCodepoint)); + assert_eq!(kind(char::from_utf8_array([0xf4, 0xa4, 0xb0, 0x9f])), Err(TooHighCodepoint)); + assert_eq!(kind(Utf8Char::from_slice_start(&[0xf4, 0xa4, 0xb0, 0x9f])), Err(TooHighCodepoint)); + assert_eq!(kind(char::from_utf8_slice_start(&[0xf4, 0xa4, 0xb8, 0x9f])), Err(TooHighCodepoint)); + + assert_eq!(kind(Utf8Char::from_array([0xf5, 0x88, 0x99, 0xaa])), Err(NonUtf8Byte)); + assert_eq!(kind(char::from_utf8_array([0xf5, 0xaa, 0xbb, 0x88])), Err(NonUtf8Byte)); + assert_eq!(kind(Utf8Char::from_slice_start(&[0xf5, 0x99, 0xaa, 0xbb])), Err(NonUtf8Byte)); + assert_eq!(kind(char::from_utf8_slice_start(&[0xf5, 0xbb, 0x88, 0x99])), Err(NonUtf8Byte)); +} + +#[test] fn utf8_codepoint_is_utf16_reserved() { + assert_eq!(kind(Utf8Char::from_array([0xed, 0xa0, 0x80, 0xff])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(char::from_utf8_array([0xed, 0xa0, 0x8f, 0x00])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(Utf8Char::from_slice_start(&[0xed, 0xa0, 0xbe, 0xa5])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(char::from_utf8_slice_start(&[0xed, 0xa0, 0xbf])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(Utf8Char::from_array([0xed, 0xbf, 0x80, 0xff])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(char::from_utf8_array([0xed, 0xbf, 0x8f, 0x00])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(Utf8Char::from_slice_start(&[0xed, 0xbf, 0xbe, 0xa5])), Err(Utf16ReservedCodepoint)); + assert_eq!(kind(char::from_utf8_slice_start(&[0xed, 0xbf, 0xbf])), Err(Utf16ReservedCodepoint)); +} + +#[test] fn utf8_first_is_continuation_byte() { + for first in 0x80..0xc0 { + let arr = [first, first<<2, first<<4, first<<6]; + assert_eq!(kind(Utf8Char::from_array(arr)), Err(UnexpectedContinuationByte)); + assert_eq!(kind(char::from_utf8_array(arr)), Err(UnexpectedContinuationByte)); + let len = (1 + first%3) as usize; + assert_eq!(kind(Utf8Char::from_slice_start(&arr[..len])), Err(UnexpectedContinuationByte)); + assert_eq!(kind(char::from_utf8_slice_start(&arr[..len])), Err(UnexpectedContinuationByte)); + } +} + +#[test] fn utf8_too_long() { + for first in 0xf8..0x100 { + let arr = [first as u8, 0x88, 0x80, 0x80]; + assert_eq!(kind(Utf8Char::from_array(arr)), Err(NonUtf8Byte)); + assert_eq!(kind(char::from_utf8_array(arr)), Err(NonUtf8Byte)); + let arr = [first as u8, 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80]; + let slice = &arr[..if first&1 == 0 {1} else {8}]; + assert_eq!(kind(Utf8Char::from_slice_start(slice)), Err(NonUtf8Byte)); + assert_eq!(kind(char::from_utf8_slice_start(slice)), Err(NonUtf8Byte)); + } +} + +#[test] fn utf8_not_continuation_byte() { + for first in 0xc2..0xf4 { + let mut arr = [first, 0x90, 0xa0, 0xb0]; + let extra = first.extra_utf8_bytes().unwrap(); + for corrupt in (1..extra).rev() { + for &bad in &[0x00, 0x3f, 0x40, 0x7f, 0xc0, 0xff] { + arr[corrupt] = bad; + assert_eq!(kind(Utf8Char::from_array(arr)), Err(InterruptedSequence), "{:?}", arr); + assert_eq!(kind(char::from_utf8_array(arr)), Err(InterruptedSequence)); + let slice = if first&1 == 0 {&arr[..1+extra]} else {&arr}; + assert_eq!(kind(Utf8Char::from_slice_start(slice)), Err(InterruptedSequence), "{:?}", slice); + assert_eq!(kind(char::from_utf8_slice_start(slice)), Err(InterruptedSequence)); + } + } + } +} diff --git a/anneal/v2/vendor/encode_unicode/tests/exhaustive.rs b/anneal/v2/vendor/encode_unicode/tests/exhaustive.rs new file mode 100644 index 0000000000..237cd78d74 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/tests/exhaustive.rs @@ -0,0 +1,35 @@ +/* Copyright 2018-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Tests that try all possible values for at least one parameter / byte / unit +//! of the tested function. + +use core::char; +extern crate encode_unicode; +use encode_unicode::*; + +#[test] +fn from_ascii() { + for cp in 0u32..256 { + assert_eq!(Utf8Char::from_ascii(cp as u8).is_ok(), cp & 0x80 == 0); + if let Ok(u8c) = Utf8Char::from_ascii(cp as u8) { + assert_eq!(u8c, Utf8Char::from(cp as u8 as char)); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] +fn from_bmp() { + for cp in 0u32..0x1_00_00 { + assert_eq!( + Utf16Char::from_bmp(cp as u16).ok(), + char::from_u32(cp).map(Utf16Char::from) + ); + } +} diff --git a/anneal/v2/vendor/encode_unicode/tests/iterators.rs b/anneal/v2/vendor/encode_unicode/tests/iterators.rs new file mode 100644 index 0000000000..6d6533bbf7 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/tests/iterators.rs @@ -0,0 +1,186 @@ +/* Copyright 2018-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Iterator tests + +#![cfg(feature="std")] + +#![allow( + clippy::needless_collect,// test oee thing at a time +)] + +extern crate encode_unicode; + +use encode_unicode::{IterExt, SliceExt, CharExt, Utf8Char}; +use encode_unicode::iterator::Utf8CharSplitter; +use encode_unicode::error::Utf8ErrorKind::*; +use encode_unicode::error::Utf16PairError::*; +use std::io::Read; +use std::cmp::min; + +#[test] fn utf8charmerger() { + let slice = b"\xf0\xa1\x92X\xcc\xbb"; + let mut iter = slice.iter().to_utf8chars(); + assert_eq!(iter.size_hint(), (1, Some(6))); + assert_eq!(format!("{:?}", &iter), + format!("Utf8CharMerger {{ buffered: [], inner: {:?} }}", slice.iter())); + + assert_eq!(iter.next().map(|v| v.map_err(|e| e.kind() ) ), Some(Err(InterruptedSequence))); + assert_eq!(iter.size_hint(), (0, Some(5))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharMerger {{ buffered: [161, 146, 88], inner: {:?} }}", slice[4..].iter()) + ); + + assert_eq!(iter.next().map(|v| v.map_err(|e| e.kind() ) ), Some(Err(UnexpectedContinuationByte))); + assert_eq!(iter.into_inner().next(), Some(&b'\xcc')); +} + +#[test] fn utf8chardecoder() { + let slice = b"\xf4\xbf\x80\x80XY\xcc\xbbZ_"; + let mut iter = slice.utf8char_indices(); + assert_eq!(iter.size_hint(), (2, Some(10))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharDecoder {{ bytes[0..]: {:?} }}", &slice) + ); + + match iter.next() { + Some((0, Err(e), 1)) => assert_eq!(e.kind(), TooHighCodepoint), + wrong => panic!("Expected Some((0, Err(TooHighCodepoint), 1), got {:?}", wrong), + } + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharDecoder {{ bytes[1..]: {:?} }}", &slice[1..]) + ); + assert_eq!(iter.size_hint(), (2, Some(9))); + assert_eq!(iter.count(), 8); +} + +#[test] fn utf16charmerger() { + let slice = [0xd800, 'x' as u16, 0xd900, 0xdfff, 'λ' as u16]; + let mut iter = slice.iter().to_utf16chars(); + assert_eq!(iter.size_hint(), (2, Some(5))); + assert_eq!(format!("{:?}", &iter), + format!("Utf16CharMerger {{ buffered: None, inner: {:?} }}", slice.iter())); + + assert_eq!(iter.next(), Some(Err(UnmatchedLeadingSurrogate))); + assert_eq!(iter.size_hint(), (1, Some(4))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharMerger {{ buffered: Some(120), inner: {:?} }}", slice[2..].iter()) + ); + + assert_eq!(iter.into_inner().next(), Some(&0xd900)); +} + +#[test] fn utf16chardecoder() { + let slice = [0xd800, 'x' as u16, 0xd900, 0xdfff, 'λ' as u16]; + let mut iter = slice.utf16char_indices(); + assert_eq!(iter.size_hint(), (2, Some(5))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharDecoder {{ units[0..]: {:?} }}", &slice) + ); + + assert_eq!(iter.next(), Some((0, Err(UnmatchedLeadingSurrogate), 1))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharDecoder {{ units[1..]: {:?} }}", &slice[1..]) + ); + assert_eq!(iter.size_hint(), (2, Some(4))); + assert_eq!(iter.count(), 3); +} + + + +/// Tests for ensuring that iterators which also implement Read support +/// interleaving calls of `read()` and `next()`, and that they implement Read +/// correctly (support any buffer size at any time). + +#[test] fn read_single_ascii() { + let uc = 'a'.to_utf8(); + assert_eq!(uc.len(), 1); + for chunk in 1..5 { + let mut buf = [b'E'; 6]; + let mut iter = uc.into_iter(); + let mut written = 0; + for _ in 0..4 { + assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0); + let wrote = iter.read(&mut buf[written..written+chunk]).unwrap(); + assert_eq!(wrote, min(1-written, chunk)); + written += wrote; + for &b in &buf[written..] {assert_eq!(b, b'E');} + assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]); + } + assert_eq!(written, 1); + } +} + +#[test] fn read_single_nonascii() { + let uc = 'ä'.to_utf8(); + assert_eq!(uc.len(), 2); + for chunk in 1..5 { + let mut buf = [b'E'; 6]; + let mut iter = uc.into_iter(); + let mut written = 0; + for _ in 0..4 { + assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0); + let wrote = iter.read(&mut buf[written..written+chunk]).unwrap(); + assert_eq!(wrote, min(2-written, chunk)); + written += wrote; + for &b in &buf[written..] {assert_eq!(b, b'E');} + assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]); + } + assert_eq!(written, 2); + } +} + + +#[test] fn utf8charsplitter_read_all_sizes() { + let s = "1111\u{104444}\u{222}1\u{833}1111\u{100004}"; + assert!(s.len()%3 == 1); + let mut buf = vec![b'E'; s.len()+6]; + for size in 2..6 {//s.len()+4 { + let mut reader = Utf8CharSplitter::from(s.chars().map(|c| c.to_utf8() )); + for (offset, part) in s.as_bytes().chunks(size).enumerate() { + let read_to = if part.len() == size {(offset+1)*size} else {buf.len()}; + assert_eq!(reader.read(&mut buf[offset*size..read_to]).unwrap(), part.len()); + assert_eq!(&buf[..offset*size+part.len()], &s.as_bytes()[..offset*size+part.len()]); + } + assert_eq!(reader.read(&mut buf[..]).unwrap(), 0); + assert!(buf[s.len()..].iter().all(|&b| b==b'E' )); + } +} + +#[test] fn utf8charsplitter_alternate_iter_read() { + let s = "1111\u{104444}\u{222}1\u{833}1111\u{100004}"; + let mut buf = [b'0'; 10]; + for n in 0..2 { + // need to collect to test size_hint() + // because chars().size_hint() returns ((bytes+3)/4, Some(bytes)) + let u8chars = s.chars().map(|c| c.to_utf8() ).collect::>(); + let mut iter = Utf8CharSplitter::from(u8chars.into_iter()); + for (i, byte) in s.bytes().enumerate() { + let until_next = s.as_bytes()[i..].iter().take_while(|&b| (b>>6)==0b10u8 ).count(); + let remaining_chars = s[i+until_next..].chars().count(); + println!("{}. run: byte {:02} of {}, remaining: {:02}+{}: 0b{:08b} = {:?}", + n, i, s.len(), remaining_chars, until_next, byte, byte as char); + assert_eq!(iter.read(&mut[][..]).unwrap(), 0); + if i % 2 == n { + assert_eq!(iter.next(), Some(byte)); + } else { + assert_eq!(iter.read(&mut buf[..1]).unwrap(), 1); + assert_eq!(buf[0], byte); + } + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.read(&mut buf[..]).unwrap(), 0); + } +} diff --git a/anneal/v2/vendor/encode_unicode/tests/oks.rs b/anneal/v2/vendor/encode_unicode/tests/oks.rs new file mode 100644 index 0000000000..956f2b98b2 --- /dev/null +++ b/anneal/v2/vendor/encode_unicode/tests/oks.rs @@ -0,0 +1,311 @@ +/* Copyright 2016-2022 Torbjørn Birch Moltu + * + * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Test that every method gives the correct result for valid values. +//! Except iterators, which are stateful. + +#![cfg(feature="std")] +#![allow( + clippy::eq_op, // testing the comparison +)] + +use std::char; +use std::str::{self,FromStr}; +use std::cmp::Ordering; +use std::hash::{Hash,Hasher}; +use std::collections::hash_map::DefaultHasher; +use std::iter::FromIterator; +extern crate encode_unicode; +use encode_unicode::*; + + +#[test] +fn equal_defaults() { + assert_eq!(Utf8Char::default().to_char(), char::default()); + assert_eq!(Utf16Char::default().to_char(), char::default()); +} + +#[test] +fn same_size_as_char() { + use std::mem::size_of; + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); +} + +#[test] +fn utf16chars_to_string() { + let s = "aå\u{10ffff}‽\u{100000}\u{fee1}"; + let u16cs = s.chars().map(Utf16Char::from).collect::>(); + + let mut from_refs: String = u16cs.iter().collect(); + assert_eq!(&from_refs, s); + from_refs.extend(&u16cs); + assert_eq!(&from_refs[s.len()..], s); + + let mut from_vals: String = u16cs.iter().cloned().collect(); + assert_eq!(&from_vals, s); + from_vals.extend(u16cs); + assert_eq!(&from_vals[s.len()..], s); +} + + +const EDGES_AND_BETWEEN: [char;19] = [ + '\u{0}',// min + '\u{3b}',// middle ASCII + 'A',// min ASCII uppercase + 'N',// middle ASCII uppercase + 'Z',// max ASCII uppercase + 'a',// min ASCII lowercase + 'm',// middle ASCII lowercase + 'z',// max ASCII lowercase + '\u{7f}',// max ASCII and 1-byte UTF-8 + '\u{80}',// min 2-byte UTF-8 + '\u{111}',// middle + '\u{7ff}',// max 2-byte UTF-8 + '\u{800}',// min 3-byte UTF-8 + '\u{d7ff}',// before reserved + '\u{e000}',// after reserved + '\u{ffff}',// max UTF-16 single and 3-byte UTF-8 + '\u{10000}',// min UTF-16 surrogate and 4-byte UTF-8 + '\u{abcde}',// middle + '\u{10ffff}',// max +]; + +fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) { + fn hash(v: T) -> u64 { + #[allow(deprecated)] + let mut hasher = DefaultHasher::new(); + v.hash(&mut hasher); + hasher.finish() + } + let u8c = c.to_utf8(); + assert_eq!(u8c.to_char(), c); + assert_eq!(u8c, u8c); + assert_eq!(hash(u8c), hash(u8c)); + assert_eq!(u8c.cmp(&u8c), Ordering::Equal); + assert!(u8c.eq_ignore_ascii_case(&u8c)); + let u16c = c.to_utf16(); + assert_eq!(u16c.to_char(), c); + assert_eq!(u16c, u16c); + assert_eq!(hash(u16c), hash(c)); + assert_eq!(u16c.cmp(&u16c), Ordering::Equal); + assert!(u16c.eq_ignore_ascii_case(&u16c)); + + assert_eq!(u8c, c); + assert_eq!(c, u8c); + assert_eq!(u16c, c); + assert_eq!(c, u16c); + assert_eq!(u8c, u16c); + assert_eq!(u16c, u8c); + assert_eq!(u8c == c as u8, c <= '\u{7F}'); + assert_eq!(u16c == c as u8, c <= '\u{FF}'); + assert_eq!(u16c == c as u16, c <= '\u{FFFF}'); + + assert_eq!(u8c.partial_cmp(&c), Some(Ordering::Equal)); + assert_eq!(c.partial_cmp(&u8c), Some(Ordering::Equal)); + assert_eq!(u16c.partial_cmp(&c), Some(Ordering::Equal)); + assert_eq!(c.partial_cmp(&u16c), Some(Ordering::Equal)); + assert_eq!(u8c.partial_cmp(&u16c), Some(Ordering::Equal)); + assert_eq!(u16c.partial_cmp(&u8c), Some(Ordering::Equal)); + + + for &other in &EDGES_AND_BETWEEN { + let u8other = other.to_utf8(); + assert_eq!(u8c == u8other, c == other); + assert_eq!(hash(u8c)==hash(u8other), hash(c)==hash(other)); + assert_eq!(u8c.cmp(&u8other), c.cmp(&other)); + assert_eq!(u8c.eq_ignore_ascii_case(&u8other), c.eq_ignore_ascii_case(&other)); + assert_eq!(u8c.partial_cmp(&other), c.partial_cmp(&other)); + assert_eq!(c.partial_cmp(&u8other), c.partial_cmp(&other)); + assert_eq!(u8other.partial_cmp(&c), other.partial_cmp(&c)); + assert_eq!(other.partial_cmp(&u8c), other.partial_cmp(&c)); + assert_eq!(u8c == other as u8, other as u8 <= 127 && c == other as u8 as char); + + let u16other = other.to_utf16(); + assert_eq!(u16c == u16other, c == other); + assert_eq!(hash(u16c)==hash(u16other), hash(c)==hash(other)); + assert_eq!(u16c.cmp(&u16other), c.cmp(&other)); + assert_eq!(u16c.eq_ignore_ascii_case(&u16other), c.eq_ignore_ascii_case(&other)); + assert_eq!(u16c.partial_cmp(&other), c.partial_cmp(&other)); + assert_eq!(c.partial_cmp(&u16other), c.partial_cmp(&other)); + assert_eq!(u16other.partial_cmp(&c), other.partial_cmp(&c)); + assert_eq!(other.partial_cmp(&u16c), other.partial_cmp(&c)); + assert_eq!(u16c == other as u8, c == other as u8 as char); + assert_eq!(u16c == other as u16, c as u32 == other as u16 as u32); + + assert_eq!(u8c == u16other, c == other); + assert_eq!(u16c == u8other, c == other); + assert_eq!(u8c.partial_cmp(&u16other), c.partial_cmp(&other)); + assert_eq!(u16c.partial_cmp(&u8other), c.partial_cmp(&other)); + assert_eq!(u8other.partial_cmp(&u16c), other.partial_cmp(&c)); + assert_eq!(u16other.partial_cmp(&u8c), other.partial_cmp(&c)); + } + (u8c, u16c) +} + +fn iterators(c: char) { + let mut iter = c.iter_utf8_bytes(); + let mut buf = [0; 4]; + let mut iter_ref = c.encode_utf8(&mut buf[..]).as_bytes().iter(); + for _ in 0..6 { + assert_eq!(iter.size_hint(), iter_ref.size_hint()); + assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice())); + assert_eq!(iter.next(), iter_ref.next().cloned()); + } + + let mut iter = c.iter_utf16_units(); + let mut buf = [0; 2]; + let mut iter_ref = c.encode_utf16(&mut buf[..]).iter(); + for _ in 0..4 { + assert_eq!(iter.size_hint(), iter_ref.size_hint()); + assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice())); + assert_eq!(iter.next(), iter_ref.next().cloned()); + } +} + +fn test(c: char) { + assert_eq!(char::from_u32(c as u32), Some(c)); + assert_eq!(char::from_u32_detailed(c as u32), Ok(c)); + assert_eq!(unsafe{ char::from_u32_unchecked(c as u32) }, c); + let (u8c, u16c) = eq_cmp_hash(c); + iterators(c); + assert_eq!(Utf16Char::from(u8c), u16c); + assert_eq!(Utf8Char::from(u16c), u8c); + let utf8_len = c.len_utf8(); + let utf16_len = c.len_utf16(); + let mut as_str = c.to_string(); + + // UTF-8 + let mut buf = [0; 4]; + let reference = c.encode_utf8(&mut buf[..]).as_bytes(); + let len = reference.len(); // short name because it is used in many places. + assert_eq!(len, utf8_len); + assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1)); + assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1); + assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference); + + let (arr,arrlen) = u8c.to_array(); + assert_eq!(arrlen, len); + assert_eq!(Utf8Char::from_array(arr), Ok(u8c)); + assert_eq!(Utf8Char::new(c), u8c); + assert_eq!(c.to_utf8_array(), (arr, len)); + + let str_ = str::from_utf8(reference).unwrap(); + let ustr = Utf8Char::from_str(str_).unwrap(); + assert_eq!(ustr.to_array().0, arr);// bitwise equality + assert_eq!(char::from_utf8_array(arr), Ok(c)); + let mut longer = [0xff; 5]; // 0xff is never valid + longer[..len].copy_from_slice(reference); + assert_eq!(char::from_utf8_slice_start(reference), Ok((c,len))); + assert_eq!(char::from_utf8_slice_start(&longer), Ok((c,len))); + assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len))); + assert_eq!(Utf8Char::from_slice_start(&longer), Ok((u8c,len))); + for other in &mut longer[len..] {*other = b'?'} + assert_eq!(Utf8Char::from_str(str_), Ok(u8c)); + assert_eq!(Utf8Char::from_str_start(str_), Ok((u8c,len))); + assert_eq!(Utf8Char::from_str_start(str::from_utf8(&longer).unwrap()), Ok((u8c,len))); + unsafe { + // Hopefully make bugs easier to catch by making reads into unallocated memory by filling + // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes. + // I have no idea whether this works. + let mut boxed = Box::new([0xffu8; 16]); + let start = boxed.len()-len; // reach the end + boxed[start..].copy_from_slice(reference); + let slice = &boxed[start..]; + assert_eq!(Utf8Char::from_slice_start_unchecked(slice), (u8c,len)); + } + assert_eq!(&Vec::::from_iter(Some(u8c))[..], reference); + assert_eq!(&String::from_iter(Some(u8c))[..], str_); + assert_eq!(format!("{:?}", u8c), format!("{:?}", c)); + assert_eq!(format!("{}", u8c), format!("{}", c)); + assert_eq!(u8c.is_ascii(), c.is_ascii()); + assert_eq!(u8c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase()); + assert_eq!(u8c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase()); + + // UTF-16 + let mut buf = [0; 2]; + let reference = c.encode_utf16(&mut buf[..]); + let len = reference.len(); + assert_eq!(len, utf16_len); + assert_eq!(reference[0].utf16_needs_extra_unit(), Ok(len==2)); + assert_eq!(reference[0].is_utf16_leading_surrogate(), len==2); + assert_eq!(u16c.as_ref(), reference); + assert_eq!(Utf16Char::new(c), u16c); + let mut longer = [0; 3]; + longer[..len].copy_from_slice(reference); + assert_eq!(char::from_utf16_slice_start(reference), Ok((c,len))); + assert_eq!(char::from_utf16_slice_start(&longer), Ok((c,len))); + assert_eq!(Utf16Char::from_slice_start(reference), Ok((u16c,len))); + assert_eq!(Utf16Char::from_slice_start(&longer), Ok((u16c,len))); + assert_eq!(Utf16Char::from_str(&as_str), Ok(u16c)); + as_str.push(c); + assert_eq!(Utf16Char::from_str_start(&as_str), Ok((u16c,utf8_len))); + unsafe { + // Hopefully make bugs easier to catch by making reads into unallocated memory by filling + // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes. + // I have no idea whether this works. + let mut boxed = Box::new([0u16; 8]); + let start = boxed.len()-len; // reach the end + boxed[start..].copy_from_slice(reference); + let slice = &boxed[start..]; + assert_eq!(Utf16Char::from_slice_start_unchecked(slice), (u16c,len)); + } + let array = c.to_utf16_array(); + let tuple = c.to_utf16_tuple(); + assert_eq!(&array[..reference.len()], reference); + assert_eq!(tuple, (reference[0],reference.get(1).cloned())); + assert_eq!(char::from_utf16_array(array), Ok(c)); + assert_eq!(char::from_utf16_tuple(tuple), Ok(c)); + assert_eq!(c.to_utf16().to_char(), c); + assert_eq!(&Vec::::from_iter(Some(u16c))[..], reference); + assert_eq!(format!("{:?}", u16c), format!("{:?}", c)); + assert_eq!(format!("{}", u16c), format!("{}", c)); + assert_eq!(u16c.is_ascii(), c.is_ascii()); + assert_eq!(u16c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase()); + assert_eq!(u16c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase()); +} + + +#[test] +fn edges_and_middle() { + for &c in &EDGES_AND_BETWEEN { + test(c); + } +} + + +// Test EVERY codepoint. +// By splitting into multiple tests we get multithreading for free. +macro_rules! test_codepoint_range {($name:ident, $range:expr) => { + #[test] + #[ignore] + fn $name() { + for cp in $range { + let c = char::from_u32(cp).expect("not a valid char"); + test(c); + } + } +}} +test_codepoint_range!{all_0000_d800, 0x0000..0xd800} +test_codepoint_range!{all_e000_10000, 0xe000..0x10000} +test_codepoint_range!{all_10000_20000, 0x10000..0x20000} +test_codepoint_range!{all_20000_30000, 0x20000..0x30000} +test_codepoint_range!{all_30000_40000, 0x30000..0x40000} +test_codepoint_range!{all_40000_50000, 0x40000..0x50000} +test_codepoint_range!{all_50000_60000, 0x50000..0x60000} +test_codepoint_range!{all_60000_70000, 0x60000..0x70000} +test_codepoint_range!{all_70000_80000, 0x70000..0x80000} +test_codepoint_range!{all_80000_90000, 0x80000..0x90000} +test_codepoint_range!{all_90000_a0000, 0x90000..0xa0000} +test_codepoint_range!{all_a0000_b0000, 0xa0000..0xb0000} +test_codepoint_range!{all_b0000_c0000, 0xb0000..0xc0000} +test_codepoint_range!{all_c0000_d0000, 0xc0000..0xd0000} +test_codepoint_range!{all_d0000_e0000, 0xd0000..0xe0000} +test_codepoint_range!{all_e0000_f0000, 0xe0000..0xf0000} +test_codepoint_range!{all_f0000_100000, 0xf0000..0x100000} +test_codepoint_range!{all_100000_110000, 0x100000..0x110000} diff --git a/anneal/v2/vendor/fs2/.appveyor.yml b/anneal/v2/vendor/fs2/.appveyor.yml new file mode 100644 index 0000000000..a54c426af5 --- /dev/null +++ b/anneal/v2/vendor/fs2/.appveyor.yml @@ -0,0 +1,18 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + - TARGET: i686-pc-windows-msvc + - TARGET: x86_64-pc-windows-gnu + - TARGET: i686-pc-windows-gnu + +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" -FileName "rust-nightly.exe" + - ps: .\rust-nightly.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null + - ps: $env:PATH="$env:PATH;C:\rust\bin" + +build_script: + - cargo build -v + +test_script: + - SET RUST_BACKTRACE=1 + - cargo test -v diff --git a/anneal/v2/vendor/fs2/.cargo-checksum.json b/anneal/v2/vendor/fs2/.cargo-checksum.json new file mode 100644 index 0000000000..f5d5bda304 --- /dev/null +++ b/anneal/v2/vendor/fs2/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".appveyor.yml":"15c5548159ad6ebcc02960bb6a3269e729e772df2733b7d4c7cc1583c413ae45",".travis.yml":"5733d01f7cd27cbdd17a46399103e83eca528727e6cad7f355f6748e772ef916","Cargo.toml":"c47bb59c1d58dc1eb439331bb140e3a4174370f83b0f0b702d41eb64b27cda3f","Cargo.toml.orig":"d7f0effff89f0f78b46f0c007ea6c8c37e532c57e1c6cdb32543c68b2eb3d36a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"4dda80a0599cc235f8eaf56c33117fcc7cbeb48aece7f7b262f374ee12e3f1f4","src/lib.rs":"38e0f03bb81d76ac8d71b73b00fae648359aa7e1c1b9ba7159cb1b19eb12b987","src/unix.rs":"67f0244c118cff918f01b6c164dfe604039ce9160a099ba6e4ff86dcf8ec0097","src/windows.rs":"4178e02fe48c1148a4d0edcdac6cec8fecf016e636064843b60e7a1d78c817a7"},"package":"9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"} \ No newline at end of file diff --git a/anneal/v2/vendor/fs2/.travis.yml b/anneal/v2/vendor/fs2/.travis.yml new file mode 100644 index 0000000000..3e8a024f94 --- /dev/null +++ b/anneal/v2/vendor/fs2/.travis.yml @@ -0,0 +1,21 @@ +language: rust + +rust: +- 1.8.0 +- stable +- nightly + +os: + - linux + - osx + +env: + matrix: + - ARCH=x86_64 + - ARCH=i686 + +script: + - cargo build --verbose + - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then + env RUST_BACKTRACE=1 cargo test -v; + fi diff --git a/anneal/v2/vendor/fs2/Cargo.toml b/anneal/v2/vendor/fs2/Cargo.toml new file mode 100644 index 0000000000..4c6aded51f --- /dev/null +++ b/anneal/v2/vendor/fs2/Cargo.toml @@ -0,0 +1,33 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "fs2" +version = "0.4.3" +authors = ["Dan Burkert "] +description = "Cross-platform file locks and file duplication." +documentation = "https://docs.rs/fs2" +keywords = ["file", "file-system", "lock", "duplicate", "flock"] +license = "MIT/Apache-2.0" +repository = "https://github.com/danburkert/fs2-rs" +[dev-dependencies.tempdir] +version = "0.3" +[target."cfg(unix)".dependencies.libc] +version = "0.2.30" +[target."cfg(windows)".dependencies.winapi] +version = "0.3" +features = ["handleapi", "processthreadsapi", "winerror", "fileapi", "winbase", "std"] +[badges.appveyor] +repository = "danburkert/fs2-rs" + +[badges.travis-ci] +repository = "danburkert/fs2-rs" diff --git a/anneal/v2/vendor/fs2/Cargo.toml.orig b/anneal/v2/vendor/fs2/Cargo.toml.orig new file mode 100644 index 0000000000..2fac260ff0 --- /dev/null +++ b/anneal/v2/vendor/fs2/Cargo.toml.orig @@ -0,0 +1,23 @@ +[package] +name = "fs2" +# NB: When modifying, also modify html_root_url in lib.rs +version = "0.4.3" +authors = ["Dan Burkert "] +license = "MIT/Apache-2.0" +repository = "https://github.com/danburkert/fs2-rs" +documentation = "https://docs.rs/fs2" +description = "Cross-platform file locks and file duplication." +keywords = ["file", "file-system", "lock", "duplicate", "flock"] + +[badges] +travis-ci = { repository = "danburkert/fs2-rs" } +appveyor = { repository = "danburkert/fs2-rs" } + +[target.'cfg(unix)'.dependencies] +libc = "0.2.30" + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["handleapi", "processthreadsapi", "winerror", "fileapi", "winbase", "std"] } + +[dev-dependencies] +tempdir = "0.3" diff --git a/anneal/v2/vendor/fs2/LICENSE-APACHE b/anneal/v2/vendor/fs2/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/fs2/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/fs2/LICENSE-MIT b/anneal/v2/vendor/fs2/LICENSE-MIT new file mode 100644 index 0000000000..e69282e381 --- /dev/null +++ b/anneal/v2/vendor/fs2/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2015 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/fs2/README.md b/anneal/v2/vendor/fs2/README.md new file mode 100644 index 0000000000..c10459a684 --- /dev/null +++ b/anneal/v2/vendor/fs2/README.md @@ -0,0 +1,50 @@ +# fs2 + +Extended utilities for working with files and filesystems in Rust. `fs2` +requires Rust stable 1.8 or greater. + +[![Build Status](https://travis-ci.org/danburkert/fs2-rs.svg?branch=master)](https://travis-ci.org/danburkert/fs2-rs) +[![Windows Build status](https://ci.appveyor.com/api/projects/status/iuvjv1aaaml0rntt/branch/master?svg=true)](https://ci.appveyor.com/project/danburkert/fs2-rs/branch/master) +[![Documentation](https://docs.rs/fs2/badge.svg)](https://docs.rs/memmap) +[![Crate](https://img.shields.io/crates/v/fs2.svg)](https://crates.io/crates/memmap) + +## Features + +- [x] file descriptor duplication. +- [x] file locks. +- [x] file (pre)allocation. +- [x] file allocation information. +- [x] filesystem space usage information. + +## Platforms + +`fs2` should work on any platform supported by +[`libc`](https://github.com/rust-lang-nursery/libc#platforms-and-documentation). + +`fs2` is continuously tested on: + * `x86_64-unknown-linux-gnu` (Linux) + * `i686-unknown-linux-gnu` + * `x86_64-apple-darwin` (OSX) + * `i686-apple-darwin` + * `x86_64-pc-windows-msvc` (Windows) + * `i686-pc-windows-msvc` + * `x86_64-pc-windows-gnu` + * `i686-pc-windows-gnu` + +## Benchmarks + +Simple benchmarks are provided for the methods provided. Many of these +benchmarks use files in a temporary directory. On many modern Linux distros the +default temporary directory, `/tmp`, is mounted on a tempfs filesystem, which +will have different performance characteristics than a disk-backed filesystem. +The temporary directory is configurable at runtime through the environment (see +[`env::temp_dir`](https://doc.rust-lang.org/stable/std/env/fn.temp_dir.html)). + +## License + +`fs2` is primarily distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details. + +Copyright (c) 2015 Dan Burkert. diff --git a/anneal/v2/vendor/fs2/src/lib.rs b/anneal/v2/vendor/fs2/src/lib.rs new file mode 100644 index 0000000000..51b22db6ac --- /dev/null +++ b/anneal/v2/vendor/fs2/src/lib.rs @@ -0,0 +1,458 @@ +//! Extended utilities for working with files and filesystems in Rust. + +#![doc(html_root_url = "https://docs.rs/fs2/0.4.3")] + +#![cfg_attr(test, feature(test))] + +#[cfg(windows)] +extern crate winapi; + +#[cfg(unix)] +mod unix; +#[cfg(unix)] +use unix as sys; + +#[cfg(windows)] +mod windows; +#[cfg(windows)] +use windows as sys; + +use std::fs::File; +use std::io::{Error, Result}; +use std::path::Path; + +/// Extension trait for `std::fs::File` which provides allocation, duplication and locking methods. +/// +/// ## Notes on File Locks +/// +/// This library provides whole-file locks in both shared (read) and exclusive +/// (read-write) varieties. +/// +/// File locks are a cross-platform hazard since the file lock APIs exposed by +/// operating system kernels vary in subtle and not-so-subtle ways. +/// +/// The API exposed by this library can be safely used across platforms as long +/// as the following rules are followed: +/// +/// * Multiple locks should not be created on an individual `File` instance +/// concurrently. +/// * Duplicated files should not be locked without great care. +/// * Files to be locked should be opened with at least read or write +/// permissions. +/// * File locks may only be relied upon to be advisory. +/// +/// See the tests in `lib.rs` for cross-platform lock behavior that may be +/// relied upon; see the tests in `unix.rs` and `windows.rs` for examples of +/// platform-specific behavior. File locks are implemented with +/// [`flock(2)`](http://man7.org/linux/man-pages/man2/flock.2.html) on Unix and +/// [`LockFile`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365202(v=vs.85).aspx) +/// on Windows. +pub trait FileExt { + + /// Returns a duplicate instance of the file. + /// + /// The returned file will share the same file position as the original + /// file. + /// + /// If using rustc version 1.9 or later, prefer using `File::try_clone` to this. + /// + /// # Notes + /// + /// This is implemented with + /// [`dup(2)`](http://man7.org/linux/man-pages/man2/dup.2.html) on Unix and + /// [`DuplicateHandle`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx) + /// on Windows. + fn duplicate(&self) -> Result; + + /// Returns the amount of physical space allocated for a file. + fn allocated_size(&self) -> Result; + + /// Ensures that at least `len` bytes of disk space are allocated for the + /// file, and the file size is at least `len` bytes. After a successful call + /// to `allocate`, subsequent writes to the file within the specified length + /// are guaranteed not to fail because of lack of disk space. + fn allocate(&self, len: u64) -> Result<()>; + + /// Locks the file for shared usage, blocking if the file is currently + /// locked exclusively. + fn lock_shared(&self) -> Result<()>; + + /// Locks the file for exclusive usage, blocking if the file is currently + /// locked. + fn lock_exclusive(&self) -> Result<()>; + + /// Locks the file for shared usage, or returns a an error if the file is + /// currently locked (see `lock_contended_error`). + fn try_lock_shared(&self) -> Result<()>; + + /// Locks the file for shared usage, or returns a an error if the file is + /// currently locked (see `lock_contended_error`). + fn try_lock_exclusive(&self) -> Result<()>; + + /// Unlocks the file. + fn unlock(&self) -> Result<()>; +} + +impl FileExt for File { + fn duplicate(&self) -> Result { + sys::duplicate(self) + } + fn allocated_size(&self) -> Result { + sys::allocated_size(self) + } + fn allocate(&self, len: u64) -> Result<()> { + sys::allocate(self, len) + } + fn lock_shared(&self) -> Result<()> { + sys::lock_shared(self) + } + fn lock_exclusive(&self) -> Result<()> { + sys::lock_exclusive(self) + } + fn try_lock_shared(&self) -> Result<()> { + sys::try_lock_shared(self) + } + fn try_lock_exclusive(&self) -> Result<()> { + sys::try_lock_exclusive(self) + } + fn unlock(&self) -> Result<()> { + sys::unlock(self) + } +} + +/// Returns the error that a call to a try lock method on a contended file will +/// return. +pub fn lock_contended_error() -> Error { + sys::lock_error() +} + +/// `FsStats` contains some common stats about a file system. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct FsStats { + free_space: u64, + available_space: u64, + total_space: u64, + allocation_granularity: u64, +} + +impl FsStats { + /// Returns the number of free bytes in the file system containing the provided + /// path. + pub fn free_space(&self) -> u64 { + self.free_space + } + + /// Returns the available space in bytes to non-priveleged users in the file + /// system containing the provided path. + pub fn available_space(&self) -> u64 { + self.available_space + } + + /// Returns the total space in bytes in the file system containing the provided + /// path. + pub fn total_space(&self) -> u64 { + self.total_space + } + + /// Returns the filesystem's disk space allocation granularity in bytes. + /// The provided path may be for any file in the filesystem. + /// + /// On Posix, this is equivalent to the filesystem's block size. + /// On Windows, this is equivalent to the filesystem's cluster size. + pub fn allocation_granularity(&self) -> u64 { + self.allocation_granularity + } +} + +/// Get the stats of the file system containing the provided path. +pub fn statvfs

(path: P) -> Result where P: AsRef { + sys::statvfs(path.as_ref()) +} + +/// Returns the number of free bytes in the file system containing the provided +/// path. +pub fn free_space

(path: P) -> Result where P: AsRef { + statvfs(path).map(|stat| stat.free_space) +} + +/// Returns the available space in bytes to non-priveleged users in the file +/// system containing the provided path. +pub fn available_space

(path: P) -> Result where P: AsRef { + statvfs(path).map(|stat| stat.available_space) +} + +/// Returns the total space in bytes in the file system containing the provided +/// path. +pub fn total_space

(path: P) -> Result where P: AsRef { + statvfs(path).map(|stat| stat.total_space) +} + +/// Returns the filesystem's disk space allocation granularity in bytes. +/// The provided path may be for any file in the filesystem. +/// +/// On Posix, this is equivalent to the filesystem's block size. +/// On Windows, this is equivalent to the filesystem's cluster size. +pub fn allocation_granularity

(path: P) -> Result where P: AsRef { + statvfs(path).map(|stat| stat.allocation_granularity) +} + +#[cfg(test)] +mod test { + + extern crate tempdir; + extern crate test; + + use std::fs; + use super::*; + use std::io::{Read, Seek, SeekFrom, Write}; + + /// Tests file duplication. + #[test] + fn duplicate() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let mut file1 = + fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let mut file2 = file1.duplicate().unwrap(); + + // Write into the first file and then drop it. + file1.write_all(b"foo").unwrap(); + drop(file1); + + let mut buf = vec![]; + + // Read from the second file; since the position is shared it will already be at EOF. + file2.read_to_end(&mut buf).unwrap(); + assert_eq!(0, buf.len()); + + // Rewind and read. + file2.seek(SeekFrom::Start(0)).unwrap(); + file2.read_to_end(&mut buf).unwrap(); + assert_eq!(&buf, &b"foo"); + } + + /// Tests shared file lock operations. + #[test] + fn lock_shared() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file3 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + // Concurrent shared access is OK, but not shared and exclusive. + file1.lock_shared().unwrap(); + file2.lock_shared().unwrap(); + assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(), + lock_contended_error().kind()); + file1.unlock().unwrap(); + assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(), + lock_contended_error().kind()); + + // Once all shared file locks are dropped, an exclusive lock may be created; + file2.unlock().unwrap(); + file3.lock_exclusive().unwrap(); + } + + /// Tests exclusive file lock operations. + #[test] + fn lock_exclusive() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + // No other access is possible once an exclusive lock is created. + file1.lock_exclusive().unwrap(); + assert_eq!(file2.try_lock_exclusive().unwrap_err().kind(), + lock_contended_error().kind()); + assert_eq!(file2.try_lock_shared().unwrap_err().kind(), + lock_contended_error().kind()); + + // Once the exclusive lock is dropped, the second file is able to create a lock. + file1.unlock().unwrap(); + file2.lock_exclusive().unwrap(); + } + + /// Tests that a lock is released after the file that owns it is dropped. + #[test] + fn lock_cleanup() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + file1.lock_exclusive().unwrap(); + assert_eq!(file2.try_lock_shared().unwrap_err().kind(), + lock_contended_error().kind()); + + // Drop file1; the lock should be released. + drop(file1); + file2.lock_shared().unwrap(); + } + + /// Tests file allocation. + #[test] + fn allocate() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let blksize = allocation_granularity(&path).unwrap(); + + // New files are created with no allocated size. + assert_eq!(0, file.allocated_size().unwrap()); + assert_eq!(0, file.metadata().unwrap().len()); + + // Allocate space for the file, checking that the allocated size steps + // up by block size, and the file length matches the allocated size. + + file.allocate(2 * blksize - 1).unwrap(); + assert_eq!(2 * blksize, file.allocated_size().unwrap()); + assert_eq!(2 * blksize - 1, file.metadata().unwrap().len()); + + // Truncate the file, checking that the allocated size steps down by + // block size. + + file.set_len(blksize + 1).unwrap(); + assert_eq!(2 * blksize, file.allocated_size().unwrap()); + assert_eq!(blksize + 1, file.metadata().unwrap().len()); + } + + /// Checks filesystem space methods. + #[test] + fn filesystem_space() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let total_space = total_space(&tempdir.path()).unwrap(); + let free_space = free_space(&tempdir.path()).unwrap(); + let available_space = available_space(&tempdir.path()).unwrap(); + + assert!(total_space > free_space); + assert!(total_space > available_space); + assert!(available_space <= free_space); + } + + /// Benchmarks creating and removing a file. This is a baseline benchmark + /// for comparing against the truncate and allocate benchmarks. + #[bench] + fn bench_file_create(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("file"); + + b.iter(|| { + fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path) + .unwrap(); + fs::remove_file(&path).unwrap(); + }); + } + + /// Benchmarks creating a file, truncating it to 32MiB, and deleting it. + #[bench] + fn bench_file_truncate(b: &mut test::Bencher) { + let size = 32 * 1024 * 1024; + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("file"); + + b.iter(|| { + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path) + .unwrap(); + file.set_len(size).unwrap(); + fs::remove_file(&path).unwrap(); + }); + } + + /// Benchmarks creating a file, allocating 32MiB for it, and deleting it. + #[bench] + fn bench_file_allocate(b: &mut test::Bencher) { + let size = 32 * 1024 * 1024; + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("file"); + + b.iter(|| { + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path) + .unwrap(); + file.allocate(size).unwrap(); + fs::remove_file(&path).unwrap(); + }); + } + + /// Benchmarks creating a file, allocating 32MiB for it, and deleting it. + #[bench] + fn bench_allocated_size(b: &mut test::Bencher) { + let size = 32 * 1024 * 1024; + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("file"); + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path) + .unwrap(); + file.allocate(size).unwrap(); + + b.iter(|| { + file.allocated_size().unwrap(); + }); + } + + /// Benchmarks duplicating a file descriptor or handle. + #[bench] + fn bench_duplicate(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + b.iter(|| test::black_box(file.duplicate().unwrap())); + } + + /// Benchmarks locking and unlocking a file lock. + #[bench] + fn bench_lock_unlock(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + b.iter(|| { + file.lock_exclusive().unwrap(); + file.unlock().unwrap(); + }); + } + + /// Benchmarks the free space method. + #[bench] + fn bench_free_space(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + b.iter(|| { + test::black_box(free_space(&tempdir.path()).unwrap()); + }); + } + + /// Benchmarks the available space method. + #[bench] + fn bench_available_space(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + b.iter(|| { + test::black_box(available_space(&tempdir.path()).unwrap()); + }); + } + + /// Benchmarks the total space method. + #[bench] + fn bench_total_space(b: &mut test::Bencher) { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + b.iter(|| { + test::black_box(total_space(&tempdir.path()).unwrap()); + }); + } +} diff --git a/anneal/v2/vendor/fs2/src/unix.rs b/anneal/v2/vendor/fs2/src/unix.rs new file mode 100644 index 0000000000..91867f7e3f --- /dev/null +++ b/anneal/v2/vendor/fs2/src/unix.rs @@ -0,0 +1,250 @@ +extern crate libc; + +use std::ffi::CString; +use std::fs::File; +use std::io::{Error, ErrorKind, Result}; +use std::mem; +use std::os::unix::ffi::OsStrExt; +use std::os::unix::fs::MetadataExt; +use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::path::Path; + +use FsStats; + +pub fn duplicate(file: &File) -> Result { + unsafe { + let fd = libc::dup(file.as_raw_fd()); + + if fd < 0 { + Err(Error::last_os_error()) + } else { + Ok(File::from_raw_fd(fd)) + } + } +} + +pub fn lock_shared(file: &File) -> Result<()> { + flock(file, libc::LOCK_SH) +} + +pub fn lock_exclusive(file: &File) -> Result<()> { + flock(file, libc::LOCK_EX) +} + +pub fn try_lock_shared(file: &File) -> Result<()> { + flock(file, libc::LOCK_SH | libc::LOCK_NB) +} + +pub fn try_lock_exclusive(file: &File) -> Result<()> { + flock(file, libc::LOCK_EX | libc::LOCK_NB) +} + +pub fn unlock(file: &File) -> Result<()> { + flock(file, libc::LOCK_UN) +} + +pub fn lock_error() -> Error { + Error::from_raw_os_error(libc::EWOULDBLOCK) +} + +#[cfg(not(target_os = "solaris"))] +fn flock(file: &File, flag: libc::c_int) -> Result<()> { + let ret = unsafe { libc::flock(file.as_raw_fd(), flag) }; + if ret < 0 { Err(Error::last_os_error()) } else { Ok(()) } +} + +/// Simulate flock() using fcntl(); primarily for Oracle Solaris. +#[cfg(target_os = "solaris")] +fn flock(file: &File, flag: libc::c_int) -> Result<()> { + let mut fl = libc::flock { + l_whence: 0, + l_start: 0, + l_len: 0, + l_type: 0, + l_pad: [0; 4], + l_pid: 0, + l_sysid: 0, + }; + + // In non-blocking mode, use F_SETLK for cmd, F_SETLKW otherwise, and don't forget to clear + // LOCK_NB. + let (cmd, operation) = match flag & libc::LOCK_NB { + 0 => (libc::F_SETLKW, flag), + _ => (libc::F_SETLK, flag & !libc::LOCK_NB), + }; + + match operation { + libc::LOCK_SH => fl.l_type |= libc::F_RDLCK, + libc::LOCK_EX => fl.l_type |= libc::F_WRLCK, + libc::LOCK_UN => fl.l_type |= libc::F_UNLCK, + _ => return Err(Error::from_raw_os_error(libc::EINVAL)), + } + + let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &fl) }; + match ret { + // Translate EACCES to EWOULDBLOCK + -1 => match Error::last_os_error().raw_os_error() { + Some(libc::EACCES) => return Err(lock_error()), + _ => return Err(Error::last_os_error()) + }, + _ => Ok(()) + } +} + +pub fn allocated_size(file: &File) -> Result { + file.metadata().map(|m| m.blocks() as u64 * 512) +} + +#[cfg(any(target_os = "linux", + target_os = "freebsd", + target_os = "android", + target_os = "nacl"))] +pub fn allocate(file: &File, len: u64) -> Result<()> { + let ret = unsafe { libc::posix_fallocate(file.as_raw_fd(), 0, len as libc::off_t) }; + if ret == 0 { Ok(()) } else { Err(Error::last_os_error()) } +} + +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub fn allocate(file: &File, len: u64) -> Result<()> { + let stat = try!(file.metadata()); + + if len > stat.blocks() as u64 * 512 { + let mut fstore = libc::fstore_t { + fst_flags: libc::F_ALLOCATECONTIG, + fst_posmode: libc::F_PEOFPOSMODE, + fst_offset: 0, + fst_length: len as libc::off_t, + fst_bytesalloc: 0, + }; + + let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) }; + if ret == -1 { + // Unable to allocate contiguous disk space; attempt to allocate non-contiguously. + fstore.fst_flags = libc::F_ALLOCATEALL; + let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) }; + if ret == -1 { + return Err(Error::last_os_error()); + } + } + } + + if len > stat.size() as u64 { + file.set_len(len) + } else { + Ok(()) + } +} + +#[cfg(any(target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly", + target_os = "solaris", + target_os = "haiku"))] +pub fn allocate(file: &File, len: u64) -> Result<()> { + // No file allocation API available, just set the length if necessary. + if len > try!(file.metadata()).len() as u64 { + file.set_len(len) + } else { + Ok(()) + } +} + +pub fn statvfs(path: &Path) -> Result { + let cstr = match CString::new(path.as_os_str().as_bytes()) { + Ok(cstr) => cstr, + Err(..) => return Err(Error::new(ErrorKind::InvalidInput, "path contained a null")), + }; + + unsafe { + let mut stat: libc::statvfs = mem::zeroed(); + // danburkert/fs2-rs#1: cast is necessary for platforms where c_char != u8. + if libc::statvfs(cstr.as_ptr() as *const _, &mut stat) != 0 { + Err(Error::last_os_error()) + } else { + Ok(FsStats { + free_space: stat.f_frsize as u64 * stat.f_bfree as u64, + available_space: stat.f_frsize as u64 * stat.f_bavail as u64, + total_space: stat.f_frsize as u64 * stat.f_blocks as u64, + allocation_granularity: stat.f_frsize as u64, + }) + } + } +} + +#[cfg(test)] +mod test { + extern crate tempdir; + extern crate libc; + + use std::fs::{self, File}; + use std::os::unix::io::AsRawFd; + + use {FileExt, lock_contended_error}; + + /// The duplicate method returns a file with a new file descriptor. + #[test] + fn duplicate_new_fd() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + assert!(file1.as_raw_fd() != file2.as_raw_fd()); + } + + /// The duplicate method should preservesthe close on exec flag. + #[test] + fn duplicate_cloexec() { + + fn flags(file: &File) -> libc::c_int { + unsafe { libc::fcntl(file.as_raw_fd(), libc::F_GETFL, 0) } + } + + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + + assert_eq!(flags(&file1), flags(&file2)); + } + + /// Tests that locking a file descriptor will replace any existing locks + /// held on the file descriptor. + #[test] + fn lock_replace() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let file2 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + + // Creating a shared lock will drop an exclusive lock. + file1.lock_exclusive().unwrap(); + file1.lock_shared().unwrap(); + file2.lock_shared().unwrap(); + + // Attempting to replace a shared lock with an exclusive lock will fail + // with multiple lock holders, and remove the original shared lock. + assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + file1.lock_shared().unwrap(); + } + + /// Tests that locks are shared among duplicated file descriptors. + #[test] + fn lock_duplicate() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + let file3 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + + // Create a lock through fd1, then replace it through fd2. + file1.lock_shared().unwrap(); + file2.lock_exclusive().unwrap(); + assert_eq!(file3.try_lock_shared().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + // Either of the file descriptors should be able to unlock. + file1.unlock().unwrap(); + file3.lock_shared().unwrap(); + } +} diff --git a/anneal/v2/vendor/fs2/src/windows.rs b/anneal/v2/vendor/fs2/src/windows.rs new file mode 100644 index 0000000000..0e37c66579 --- /dev/null +++ b/anneal/v2/vendor/fs2/src/windows.rs @@ -0,0 +1,279 @@ +use std::fs::File; +use std::io::{Error, Result}; +use std::mem; +use std::os::windows::ffi::OsStrExt; +use std::os::windows::io::{AsRawHandle, FromRawHandle}; +use std::path::Path; +use std::ptr; + +use winapi::shared::minwindef::{BOOL, DWORD}; +use winapi::shared::winerror::ERROR_LOCK_VIOLATION; +use winapi::um::fileapi::{FILE_ALLOCATION_INFO, FILE_STANDARD_INFO, GetDiskFreeSpaceW}; +use winapi::um::fileapi::{GetVolumePathNameW, LockFileEx, UnlockFile, SetFileInformationByHandle}; +use winapi::um::handleapi::DuplicateHandle; +use winapi::um::minwinbase::{FileAllocationInfo, FileStandardInfo}; +use winapi::um::minwinbase::{LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK}; +use winapi::um::processthreadsapi::GetCurrentProcess; +use winapi::um::winbase::GetFileInformationByHandleEx; +use winapi::um::winnt::DUPLICATE_SAME_ACCESS; + +use FsStats; + +pub fn duplicate(file: &File) -> Result { + unsafe { + let mut handle = ptr::null_mut(); + let current_process = GetCurrentProcess(); + let ret = DuplicateHandle(current_process, + file.as_raw_handle(), + current_process, + &mut handle, + 0, + true as BOOL, + DUPLICATE_SAME_ACCESS); + if ret == 0 { + Err(Error::last_os_error()) + } else { + Ok(File::from_raw_handle(handle)) + } + } +} + +pub fn allocated_size(file: &File) -> Result { + unsafe { + let mut info: FILE_STANDARD_INFO = mem::zeroed(); + + let ret = GetFileInformationByHandleEx( + file.as_raw_handle(), + FileStandardInfo, + &mut info as *mut _ as *mut _, + mem::size_of::() as DWORD); + + if ret == 0 { + Err(Error::last_os_error()) + } else { + Ok(*info.AllocationSize.QuadPart() as u64) + } + } +} + +pub fn allocate(file: &File, len: u64) -> Result<()> { + if try!(allocated_size(file)) < len { + unsafe { + let mut info: FILE_ALLOCATION_INFO = mem::zeroed(); + *info.AllocationSize.QuadPart_mut() = len as i64; + let ret = SetFileInformationByHandle( + file.as_raw_handle(), + FileAllocationInfo, + &mut info as *mut _ as *mut _, + mem::size_of::() as DWORD); + if ret == 0 { + return Err(Error::last_os_error()); + } + } + } + if try!(file.metadata()).len() < len { + file.set_len(len) + } else { + Ok(()) + } +} + +pub fn lock_shared(file: &File) -> Result<()> { + lock_file(file, 0) +} + +pub fn lock_exclusive(file: &File) -> Result<()> { + lock_file(file, LOCKFILE_EXCLUSIVE_LOCK) +} + +pub fn try_lock_shared(file: &File) -> Result<()> { + lock_file(file, LOCKFILE_FAIL_IMMEDIATELY) +} + +pub fn try_lock_exclusive(file: &File) -> Result<()> { + lock_file(file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY) +} + +pub fn unlock(file: &File) -> Result<()> { + unsafe { + let ret = UnlockFile(file.as_raw_handle(), 0, 0, !0, !0); + if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) } + } +} + +pub fn lock_error() -> Error { + Error::from_raw_os_error(ERROR_LOCK_VIOLATION as i32) +} + +fn lock_file(file: &File, flags: DWORD) -> Result<()> { + unsafe { + let mut overlapped = mem::zeroed(); + let ret = LockFileEx(file.as_raw_handle(), flags, 0, !0, !0, &mut overlapped); + if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) } + } +} + +fn volume_path(path: &Path, volume_path: &mut [u16]) -> Result<()> { + let path_utf8: Vec = path.as_os_str().encode_wide().chain(Some(0)).collect(); + unsafe { + let ret = GetVolumePathNameW(path_utf8.as_ptr(), + volume_path.as_mut_ptr(), + volume_path.len() as DWORD); + if ret == 0 { Err(Error::last_os_error()) } else { Ok(()) + } + } +} + +pub fn statvfs(path: &Path) -> Result { + let root_path: &mut [u16] = &mut [0; 261]; + try!(volume_path(path, root_path)); + unsafe { + + let mut sectors_per_cluster = 0; + let mut bytes_per_sector = 0; + let mut number_of_free_clusters = 0; + let mut total_number_of_clusters = 0; + let ret = GetDiskFreeSpaceW(root_path.as_ptr(), + &mut sectors_per_cluster, + &mut bytes_per_sector, + &mut number_of_free_clusters, + &mut total_number_of_clusters); + if ret == 0 { + Err(Error::last_os_error()) + } else { + let bytes_per_cluster = sectors_per_cluster as u64 * bytes_per_sector as u64; + let free_space = bytes_per_cluster * number_of_free_clusters as u64; + let total_space = bytes_per_cluster * total_number_of_clusters as u64; + Ok(FsStats { + free_space: free_space, + available_space: free_space, + total_space: total_space, + allocation_granularity: bytes_per_cluster, + }) + } + } +} + +#[cfg(test)] +mod test { + + extern crate tempdir; + + use std::fs; + use std::os::windows::io::AsRawHandle; + + use {FileExt, lock_contended_error}; + + /// The duplicate method returns a file with a new file handle. + #[test] + fn duplicate_new_handle() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + assert!(file1.as_raw_handle() != file2.as_raw_handle()); + } + + /// A duplicated file handle does not have access to the original handle's locks. + #[test] + fn lock_duplicate_handle_independence() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + + // Locking the original file handle will block the duplicate file handle from opening a lock. + file1.lock_shared().unwrap(); + assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + // Once the original file handle is unlocked, the duplicate handle can proceed with a lock. + file1.unlock().unwrap(); + file2.lock_exclusive().unwrap(); + } + + /// A file handle may not be exclusively locked multiple times, or exclusively locked and then + /// shared locked. + #[test] + fn lock_non_reentrant() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + // Multiple exclusive locks fails. + file.lock_exclusive().unwrap(); + assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + file.unlock().unwrap(); + + // Shared then Exclusive locks fails. + file.lock_shared().unwrap(); + assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + } + + /// A file handle can hold an exclusive lock and any number of shared locks, all of which must + /// be unlocked independently. + #[test] + fn lock_layering() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + // Open two shared locks on the file, and then try and fail to open an exclusive lock. + file.lock_exclusive().unwrap(); + file.lock_shared().unwrap(); + file.lock_shared().unwrap(); + assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + // Pop one of the shared locks and try again. + file.unlock().unwrap(); + assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + // Pop the second shared lock and try again. + file.unlock().unwrap(); + assert_eq!(file.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + // Pop the exclusive lock and finally succeed. + file.unlock().unwrap(); + file.lock_exclusive().unwrap(); + } + + /// A file handle with multiple open locks will have all locks closed on drop. + #[test] + fn lock_layering_cleanup() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + + // Open two shared locks on the file, and then try and fail to open an exclusive lock. + file1.lock_shared().unwrap(); + assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + + drop(file1); + file2.lock_exclusive().unwrap(); + } + + /// A file handle's locks will not be released until the original handle and all of its + /// duplicates have been closed. This on really smells like a bug in Windows. + #[test] + fn lock_duplicate_cleanup() { + let tempdir = tempdir::TempDir::new("fs2").unwrap(); + let path = tempdir.path().join("fs2"); + let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap(); + let file2 = file1.duplicate().unwrap(); + + // Open a lock on the original handle, then close it. + file1.lock_shared().unwrap(); + drop(file1); + + // Attempting to create a lock on the file with the duplicate handle will fail. + assert_eq!(file2.try_lock_exclusive().unwrap_err().raw_os_error(), + lock_contended_error().raw_os_error()); + } +} diff --git a/anneal/v2/vendor/futures-core/.cargo-checksum.json b/anneal/v2/vendor/futures-core/.cargo-checksum.json new file mode 100644 index 0000000000..f00a9f1f12 --- /dev/null +++ b/anneal/v2/vendor/futures-core/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"69b2d02e5db8288df704d7a276ef0bfb27017f5ba1657efddd33135076f82ba0","Cargo.lock":"fbeac5791a2d97ac81be504c9436354ec6f4d2fa43172945f9bbac1097d84faf","Cargo.toml":"8e1fc1b21e82013b3accf43c8fc1bcdddeb3d41c810110fb83a61558a49742c3","Cargo.toml.orig":"be1d2616172fb5ae584491a8cf34dd5e4f330a70a1056286cbde6bf4f358c9f8","LICENSE-APACHE":"275c491d6d1160553c32fd6127061d7f9606c3ea25abfad6ca3f6ed088785427","LICENSE-MIT":"6652c868f35dfe5e8ef636810a4e576b9d663f3a17fb0f5613ad73583e1b88fd","README.md":"e8258273fed6f1796485777655118f2369fd3f000191e9d8cdbd10bf052946a9","src/future.rs":"bdbe034548271aef0c3dd8a6d087a5861e5920848c9e33a8949dbc40407c0ca7","src/lib.rs":"e545004177a7cd13257a3a562d2d44a5e0cff45687fc912b69e3d510fa397396","src/stream.rs":"11f0b4360287dd870c1b674db84f2452ddc38fbaf475cca27d374b65211af72d","src/task/__internal/atomic_waker.rs":"67d3e3177332e95696bc727420beadc1af44b5c96da78ac8f97f9f5bae4fb143","src/task/__internal/mod.rs":"1cc15fd61942a29ea558c5f4d5782e46adcfd914cab82be084a6882fa9afc122","src/task/mod.rs":"e213602a2fe5ae78ad5f1ca20e6d32dcbab17aba5b6b072fb927a72da99b4a11","src/task/poll.rs":"3732f2e489b107ef76ba0cd9b30efd197d445dcea67f2c65783a388893f310b6"},"package":"7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-core/.cargo_vcs_info.json b/anneal/v2/vendor/futures-core/.cargo_vcs_info.json new file mode 100644 index 0000000000..25469f1419 --- /dev/null +++ b/anneal/v2/vendor/futures-core/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d9bba94c239daa1175a5bb2958f37a5c72db3f6a" + }, + "path_in_vcs": "futures-core" +} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-core/Cargo.lock b/anneal/v2/vendor/futures-core/Cargo.lock new file mode 100644 index 0000000000..28c88e3010 --- /dev/null +++ b/anneal/v2/vendor/futures-core/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "futures-core" +version = "0.3.32" +dependencies = [ + "portable-atomic 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum portable-atomic 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" diff --git a/anneal/v2/vendor/futures-core/Cargo.toml b/anneal/v2/vendor/futures-core/Cargo.toml new file mode 100644 index 0000000000..2afd7b5046 --- /dev/null +++ b/anneal/v2/vendor/futures-core/Cargo.toml @@ -0,0 +1,66 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.36" +name = "futures-core" +version = "0.3.32" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +The core traits and types in for the `futures` library. +""" +homepage = "https://rust-lang.github.io/futures-rs" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +alloc = [] +cfg-target-has-atomic = [] +default = ["std"] +std = ["alloc"] +unstable = [] + +[lib] +name = "futures_core" +path = "src/lib.rs" + +[dependencies.portable-atomic] +version = "1.3" +features = ["require-cas"] +optional = true +default-features = false + +[dev-dependencies] + +[lints.rust] +missing_debug_implementations = "warn" +rust_2018_idioms = "warn" +single_use_lifetimes = "warn" +unreachable_pub = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(futures_sanitizer)"] diff --git a/anneal/v2/vendor/futures-core/Cargo.toml.orig b/anneal/v2/vendor/futures-core/Cargo.toml.orig new file mode 100644 index 0000000000..273665b637 --- /dev/null +++ b/anneal/v2/vendor/futures-core/Cargo.toml.orig @@ -0,0 +1,35 @@ +[package] +name = "futures-core" +version = "0.3.32" +edition = "2018" +# NB: Sync with "Usage" section in README.md and core-msrv job in .github/workflows/ci.yml +rust-version = "1.36" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" +homepage = "https://rust-lang.github.io/futures-rs" +description = """ +The core traits and types in for the `futures` library. +""" + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +# These features are no longer used. +# TODO: remove in the next major version. +unstable = [] +cfg-target-has-atomic = [] + +[dependencies] +portable-atomic = { version = "1.3", optional = true, default-features = false, features = ["require-cas"] } + +[dev-dependencies] +futures = { path = "../futures" } + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true diff --git a/anneal/v2/vendor/futures-core/LICENSE-APACHE b/anneal/v2/vendor/futures-core/LICENSE-APACHE new file mode 100644 index 0000000000..9eb0b097f5 --- /dev/null +++ b/anneal/v2/vendor/futures-core/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/futures-core/LICENSE-MIT b/anneal/v2/vendor/futures-core/LICENSE-MIT new file mode 100644 index 0000000000..8ad082ec4f --- /dev/null +++ b/anneal/v2/vendor/futures-core/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/futures-core/README.md b/anneal/v2/vendor/futures-core/README.md new file mode 100644 index 0000000000..96e0e064bc --- /dev/null +++ b/anneal/v2/vendor/futures-core/README.md @@ -0,0 +1,23 @@ +# futures-core + +The core traits and types in for the `futures` library. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +futures-core = "0.3" +``` + +The current `futures-core` requires Rust 1.36 or later. + +## License + +Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or +[MIT license](LICENSE-MIT) at your option. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/futures-core/src/future.rs b/anneal/v2/vendor/futures-core/src/future.rs new file mode 100644 index 0000000000..30c0323a6b --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/future.rs @@ -0,0 +1,113 @@ +//! Futures. + +use core::ops::DerefMut; +use core::pin::Pin; +use core::task::{Context, Poll}; + +#[doc(no_inline)] +pub use core::future::Future; + +/// An owned dynamically typed [`Future`] for use in cases where you can't +/// statically type your result or need to add some indirection. +/// +/// This type is often created by the [`boxed`] method on [`FutureExt`]. See its documentation for more. +/// +/// [`boxed`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html#method.boxed +/// [`FutureExt`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html +#[cfg(feature = "alloc")] +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; + +/// `BoxFuture`, but without the `Send` requirement. +/// +/// This type is often created by the [`boxed_local`] method on [`FutureExt`]. See its documentation for more. +/// +/// [`boxed_local`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html#method.boxed_local +/// [`FutureExt`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html +#[cfg(feature = "alloc")] +pub type LocalBoxFuture<'a, T> = Pin + 'a>>; + +/// A future which tracks whether or not the underlying future +/// should no longer be polled. +/// +/// `is_terminated` will return `true` if a future should no longer be polled. +/// Usually, this state occurs after `poll` (or `try_poll`) returned +/// `Poll::Ready`. However, `is_terminated` may also return `true` if a future +/// has become inactive and can no longer make progress and should be ignored +/// or dropped rather than being `poll`ed again. +pub trait FusedFuture: Future { + /// Returns `true` if the underlying future should no longer be polled. + fn is_terminated(&self) -> bool; +} + +impl FusedFuture for &mut F { + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } +} + +impl

FusedFuture for Pin

+where + P: DerefMut + Unpin, + P::Target: FusedFuture, +{ + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } +} + +mod private_try_future { + use super::Future; + + pub trait Sealed {} + + impl Sealed for F where F: ?Sized + Future> {} +} + +/// A convenience for futures that return `Result` values that includes +/// a variety of adapters tailored to such futures. +pub trait TryFuture: Future + private_try_future::Sealed { + /// The type of successful values yielded by this future + type Ok; + + /// The type of failures yielded by this future + type Error; + + /// Poll this `TryFuture` as if it were a `Future`. + /// + /// This method is a stopgap for a compiler limitation that prevents us from + /// directly inheriting from the `Future` trait; in the future it won't be + /// needed. + fn try_poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; +} + +impl TryFuture for F +where + F: ?Sized + Future>, +{ + type Ok = T; + type Error = E; + + #[inline] + fn try_poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.poll(cx) + } +} + +#[cfg(feature = "alloc")] +mod if_alloc { + use super::*; + use alloc::boxed::Box; + + impl FusedFuture for Box { + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } + } + + #[cfg(feature = "std")] + impl FusedFuture for std::panic::AssertUnwindSafe { + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } + } +} diff --git a/anneal/v2/vendor/futures-core/src/lib.rs b/anneal/v2/vendor/futures-core/src/lib.rs new file mode 100644 index 0000000000..6ff6b974b1 --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/lib.rs @@ -0,0 +1,27 @@ +//! Core traits and types for asynchronous operations in Rust. + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms, single_use_lifetimes), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn(missing_docs, /* unsafe_op_in_unsafe_fn */)] // unsafe_op_in_unsafe_fn requires Rust 1.52 + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +pub mod future; +#[doc(no_inline)] +pub use self::future::{FusedFuture, Future, TryFuture}; + +pub mod stream; +#[doc(no_inline)] +pub use self::stream::{FusedStream, Stream, TryStream}; + +#[macro_use] +pub mod task; diff --git a/anneal/v2/vendor/futures-core/src/stream.rs b/anneal/v2/vendor/futures-core/src/stream.rs new file mode 100644 index 0000000000..dd07d5aa01 --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/stream.rs @@ -0,0 +1,245 @@ +//! Asynchronous streams. + +use core::ops::DerefMut; +use core::pin::Pin; +use core::task::{Context, Poll}; + +/// An owned dynamically typed [`Stream`] for use in cases where you can't +/// statically type your result or need to add some indirection. +/// +/// This type is often created by the [`boxed`] method on [`StreamExt`]. See its documentation for more. +/// +/// [`boxed`]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.boxed +/// [`StreamExt`]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html +#[cfg(feature = "alloc")] +pub type BoxStream<'a, T> = Pin + Send + 'a>>; + +/// `BoxStream`, but without the `Send` requirement. +/// +/// This type is often created by the [`boxed_local`] method on [`StreamExt`]. See its documentation for more. +/// +/// [`boxed_local`]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.boxed_local +/// [`StreamExt`]: https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html +#[cfg(feature = "alloc")] +pub type LocalBoxStream<'a, T> = Pin + 'a>>; + +/// A stream of values produced asynchronously. +/// +/// If `Future` is an asynchronous version of `T`, then `Stream` is an asynchronous version of `Iterator`. A stream +/// represents a sequence of value-producing events that occur asynchronously to +/// the caller. +/// +/// The trait is modeled after `Future`, but allows `poll_next` to be called +/// even after a value has been produced, yielding `None` once the stream has +/// been fully exhausted. +#[must_use = "streams do nothing unless polled"] +pub trait Stream { + /// Values yielded by the stream. + type Item; + + /// Attempt to pull out the next value of this stream, registering the + /// current task for wakeup if the value is not yet available, and returning + /// `None` if the stream is exhausted. + /// + /// # Return value + /// + /// There are several possible return values, each indicating a distinct + /// stream state: + /// + /// - `Poll::Pending` means that this stream's next value is not ready + /// yet. Implementations will ensure that the current task will be notified + /// when the next value may be ready. + /// + /// - `Poll::Ready(Some(val))` means that the stream has successfully + /// produced a value, `val`, and may produce further values on subsequent + /// `poll_next` calls. + /// + /// - `Poll::Ready(None)` means that the stream has terminated, and + /// `poll_next` should not be invoked again. + /// + /// # Panics + /// + /// Once a stream has finished (returned `Ready(None)` from `poll_next`), calling its + /// `poll_next` method again may panic, block forever, or cause other kinds of + /// problems; the `Stream` trait places no requirements on the effects of + /// such a call. However, as the `poll_next` method is not marked `unsafe`, + /// Rust's usual rules apply: calls must never cause undefined behavior + /// (memory corruption, incorrect use of `unsafe` functions, or the like), + /// regardless of the stream's state. + /// + /// If this is difficult to guard against then the [`fuse`] adapter can be used + /// to ensure that `poll_next` always returns `Ready(None)` in subsequent + /// calls. + /// + /// [`fuse`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.fuse + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + + /// Returns the bounds on the remaining length of the stream. + /// + /// Specifically, `size_hint()` returns a tuple where the first element + /// is the lower bound, and the second element is the upper bound. + /// + /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`. + /// A [`None`] here means that either there is no known upper bound, or the + /// upper bound is larger than [`usize`]. + /// + /// # Implementation notes + /// + /// It is not enforced that a stream implementation yields the declared + /// number of elements. A buggy stream may yield less than the lower bound + /// or more than the upper bound of elements. + /// + /// `size_hint()` is primarily intended to be used for optimizations such as + /// reserving space for the elements of the stream, but must not be + /// trusted to e.g., omit bounds checks in unsafe code. An incorrect + /// implementation of `size_hint()` should not lead to memory safety + /// violations. + /// + /// That said, the implementation should provide a correct estimation, + /// because otherwise it would be a violation of the trait's protocol. + /// + /// The default implementation returns `(0, `[`None`]`)` which is correct for any + /// stream. + #[inline] + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} + +impl Stream for &mut S { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + S::poll_next(Pin::new(&mut **self), cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +impl

Stream for Pin

+where + P: DerefMut + Unpin, + P::Target: Stream, +{ + type Item = ::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.get_mut().as_mut().poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +/// A stream which tracks whether or not the underlying stream +/// should no longer be polled. +/// +/// `is_terminated` will return `true` if a future should no longer be polled. +/// Usually, this state occurs after `poll_next` (or `try_poll_next`) returned +/// `Poll::Ready(None)`. However, `is_terminated` may also return `true` if a +/// stream has become inactive and can no longer make progress and should be +/// ignored or dropped rather than being polled again. +pub trait FusedStream: Stream { + /// Returns `true` if the stream should no longer be polled. + fn is_terminated(&self) -> bool; +} + +impl FusedStream for &mut F { + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } +} + +impl

FusedStream for Pin

+where + P: DerefMut + Unpin, + P::Target: FusedStream, +{ + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } +} + +mod private_try_stream { + use super::Stream; + + pub trait Sealed {} + + impl Sealed for S where S: ?Sized + Stream> {} +} + +/// A convenience for streams that return `Result` values that includes +/// a variety of adapters tailored to such futures. +pub trait TryStream: Stream + private_try_stream::Sealed { + /// The type of successful values yielded by this future + type Ok; + + /// The type of failures yielded by this future + type Error; + + /// Poll this `TryStream` as if it were a `Stream`. + /// + /// This method is a stopgap for a compiler limitation that prevents us from + /// directly inheriting from the `Stream` trait; in the future it won't be + /// needed. + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>>; +} + +impl TryStream for S +where + S: ?Sized + Stream>, +{ + type Ok = T; + type Error = E; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + self.poll_next(cx) + } +} + +#[cfg(feature = "alloc")] +mod if_alloc { + use super::*; + use alloc::boxed::Box; + + impl Stream for Box { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut **self).poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + } + + #[cfg(feature = "std")] + impl Stream for std::panic::AssertUnwindSafe { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + + impl FusedStream for Box { + fn is_terminated(&self) -> bool { + ::is_terminated(&**self) + } + } +} diff --git a/anneal/v2/vendor/futures-core/src/task/__internal/atomic_waker.rs b/anneal/v2/vendor/futures-core/src/task/__internal/atomic_waker.rs new file mode 100644 index 0000000000..e87943be0c --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/task/__internal/atomic_waker.rs @@ -0,0 +1,423 @@ +use core::cell::UnsafeCell; +use core::fmt; +use core::task::Waker; + +use atomic::AtomicUsize; +use atomic::Ordering::{AcqRel, Acquire, Release}; + +#[cfg(feature = "portable-atomic")] +use portable_atomic as atomic; + +#[cfg(not(feature = "portable-atomic"))] +use core::sync::atomic; + +/// A synchronization primitive for task wakeup. +/// +/// Sometimes the task interested in a given event will change over time. +/// An `AtomicWaker` can coordinate concurrent notifications with the consumer +/// potentially "updating" the underlying task to wake up. This is useful in +/// scenarios where a computation completes in another thread and wants to +/// notify the consumer, but the consumer is in the process of being migrated to +/// a new logical task. +/// +/// Consumers should call `register` before checking the result of a computation +/// and producers should call `wake` after producing the computation (this +/// differs from the usual `thread::park` pattern). It is also permitted for +/// `wake` to be called **before** `register`. This results in a no-op. +/// +/// A single `AtomicWaker` may be reused for any number of calls to `register` or +/// `wake`. +/// +/// # Memory ordering +/// +/// Calling `register` "acquires" all memory "released" by calls to `wake` +/// before the call to `register`. Later calls to `wake` will wake the +/// registered waker (on contention this wake might be triggered in `register`). +/// +/// For concurrent calls to `register` (should be avoided) the ordering is only +/// guaranteed for the winning call. +/// +/// # Examples +/// +/// Here is a simple example providing a `Flag` that can be signalled manually +/// when it is ready. +/// +/// ``` +/// use futures::future::Future; +/// use futures::task::{Context, Poll, AtomicWaker}; +/// use std::sync::Arc; +/// use std::sync::atomic::AtomicBool; +/// use std::sync::atomic::Ordering::Relaxed; +/// use std::pin::Pin; +/// +/// struct Inner { +/// waker: AtomicWaker, +/// set: AtomicBool, +/// } +/// +/// #[derive(Clone)] +/// struct Flag(Arc); +/// +/// impl Flag { +/// pub fn new() -> Self { +/// Self(Arc::new(Inner { +/// waker: AtomicWaker::new(), +/// set: AtomicBool::new(false), +/// })) +/// } +/// +/// pub fn signal(&self) { +/// self.0.set.store(true, Relaxed); +/// self.0.waker.wake(); +/// } +/// } +/// +/// impl Future for Flag { +/// type Output = (); +/// +/// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { +/// // quick check to avoid registration if already done. +/// if self.0.set.load(Relaxed) { +/// return Poll::Ready(()); +/// } +/// +/// self.0.waker.register(cx.waker()); +/// +/// // Need to check condition **after** `register` to avoid a race +/// // condition that would result in lost notifications. +/// if self.0.set.load(Relaxed) { +/// Poll::Ready(()) +/// } else { +/// Poll::Pending +/// } +/// } +/// } +/// ``` +pub struct AtomicWaker { + state: AtomicUsize, + waker: UnsafeCell>, +} + +// `AtomicWaker` is a multi-consumer, single-producer transfer cell. The cell +// stores a `Waker` value produced by calls to `register` and many threads can +// race to take the waker (to wake it) by calling `wake`. +// +// If a new `Waker` instance is produced by calling `register` before an +// existing one is consumed, then the existing one is overwritten. +// +// While `AtomicWaker` is single-producer, the implementation ensures memory +// safety. In the event of concurrent calls to `register`, there will be a +// single winner whose waker will get stored in the cell. The losers will not +// have their tasks woken. As such, callers should ensure to add synchronization +// to calls to `register`. +// +// The implementation uses a single `AtomicUsize` value to coordinate access to +// the `Waker` cell. There are two bits that are operated on independently. +// These are represented by `REGISTERING` and `WAKING`. +// +// The `REGISTERING` bit is set when a producer enters the critical section. The +// `WAKING` bit is set when a consumer enters the critical section. Neither bit +// being set is represented by `WAITING`. +// +// A thread obtains an exclusive lock on the waker cell by transitioning the +// state from `WAITING` to `REGISTERING` or `WAKING`, depending on the operation +// the thread wishes to perform. When this transition is made, it is guaranteed +// that no other thread will access the waker cell. +// +// # Registering +// +// On a call to `register`, an attempt to transition the state from WAITING to +// REGISTERING is made. On success, the caller obtains a lock on the waker cell. +// +// If the lock is obtained, then the thread sets the waker cell to the waker +// provided as an argument. Then it attempts to transition the state back from +// `REGISTERING` -> `WAITING`. +// +// If this transition is successful, then the registering process is complete +// and the next call to `wake` will observe the waker. +// +// If the transition fails, then there was a concurrent call to `wake` that was +// unable to access the waker cell (due to the registering thread holding the +// lock). To handle this, the registering thread removes the waker it just set +// from the cell and calls `wake` on it. This call to wake represents the +// attempt to wake by the other thread (that set the `WAKING` bit). The state is +// then transitioned from `REGISTERING | WAKING` back to `WAITING`. This +// transition must succeed because, at this point, the state cannot be +// transitioned by another thread. +// +// # Waking +// +// On a call to `wake`, an attempt to transition the state from `WAITING` to +// `WAKING` is made. On success, the caller obtains a lock on the waker cell. +// +// If the lock is obtained, then the thread takes ownership of the current value +// in the waker cell, and calls `wake` on it. The state is then transitioned +// back to `WAITING`. This transition must succeed as, at this point, the state +// cannot be transitioned by another thread. +// +// If the thread is unable to obtain the lock, the `WAKING` bit is still. This +// is because it has either been set by the current thread but the previous +// value included the `REGISTERING` bit **or** a concurrent thread is in the +// `WAKING` critical section. Either way, no action must be taken. +// +// If the current thread is the only concurrent call to `wake` and another +// thread is in the `register` critical section, when the other thread **exits** +// the `register` critical section, it will observe the `WAKING` bit and handle +// the wake itself. +// +// If another thread is in the `wake` critical section, then it will handle +// waking the task. +// +// # A potential race (is safely handled). +// +// Imagine the following situation: +// +// * Thread A obtains the `wake` lock and wakes a task. +// +// * Before thread A releases the `wake` lock, the woken task is scheduled. +// +// * Thread B attempts to wake the task. In theory this should result in the +// task being woken, but it cannot because thread A still holds the wake lock. +// +// This case is handled by requiring users of `AtomicWaker` to call `register` +// **before** attempting to observe the application state change that resulted +// in the task being awoken. The wakers also change the application state before +// calling wake. +// +// Because of this, the waker will do one of two things. +// +// 1) Observe the application state change that Thread B is woken for. In this +// case, it is OK for Thread B's wake to be lost. +// +// 2) Call register before attempting to observe the application state. Since +// Thread A still holds the `wake` lock, the call to `register` will result +// in the task waking itself and get scheduled again. + +/// Idle state +const WAITING: usize = 0; + +/// A new waker value is being registered with the `AtomicWaker` cell. +const REGISTERING: usize = 0b01; + +/// The waker currently registered with the `AtomicWaker` cell is being woken. +const WAKING: usize = 0b10; + +impl AtomicWaker { + /// Create an `AtomicWaker`. + pub const fn new() -> Self { + // Make sure that task is Sync + #[allow(dead_code)] + trait AssertSync: Sync {} + impl AssertSync for Waker {} + + Self { state: AtomicUsize::new(WAITING), waker: UnsafeCell::new(None) } + } + + /// Registers the waker to be notified on calls to `wake`. + /// + /// The new task will take place of any previous tasks that were registered + /// by previous calls to `register`. Any calls to `wake` that happen after + /// a call to `register` (as defined by the memory ordering rules), will + /// notify the `register` caller's task and deregister the waker from future + /// notifications. Because of this, callers should ensure `register` gets + /// invoked with a new `Waker` **each** time they require a wakeup. + /// + /// It is safe to call `register` with multiple other threads concurrently + /// calling `wake`. This will result in the `register` caller's current + /// task being notified once. + /// + /// This function is safe to call concurrently, but this is generally a bad + /// idea. Concurrent calls to `register` will attempt to register different + /// tasks to be notified. One of the callers will win and have its task set, + /// but there is no guarantee as to which caller will succeed. + /// + /// # Examples + /// + /// Here is how `register` is used when implementing a flag. + /// + /// ``` + /// use futures::future::Future; + /// use futures::task::{Context, Poll, AtomicWaker}; + /// use std::sync::atomic::AtomicBool; + /// use std::sync::atomic::Ordering::Relaxed; + /// use std::pin::Pin; + /// + /// struct Flag { + /// waker: AtomicWaker, + /// set: AtomicBool, + /// } + /// + /// impl Future for Flag { + /// type Output = (); + /// + /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + /// // Register **before** checking `set` to avoid a race condition + /// // that would result in lost notifications. + /// self.waker.register(cx.waker()); + /// + /// if self.set.load(Relaxed) { + /// Poll::Ready(()) + /// } else { + /// Poll::Pending + /// } + /// } + /// } + /// ``` + pub fn register(&self, waker: &Waker) { + match self + .state + .compare_exchange(WAITING, REGISTERING, Acquire, Acquire) + .unwrap_or_else(|x| x) + { + WAITING => { + unsafe { + // Locked acquired, update the waker cell + + // Avoid cloning the waker if the old waker will awaken the same task. + match &*self.waker.get() { + Some(old_waker) if old_waker.will_wake(waker) => (), + _ => *self.waker.get() = Some(waker.clone()), + } + + // Release the lock. If the state transitioned to include + // the `WAKING` bit, this means that at least one wake has + // been called concurrently. + // + // Start by assuming that the state is `REGISTERING` as this + // is what we just set it to. If this holds, we know that no + // other writes were performed in the meantime, so there is + // nothing to acquire, only release. In case of concurrent + // wakers, we need to acquire their releases, so success needs + // to do both. + let res = self.state.compare_exchange(REGISTERING, WAITING, AcqRel, Acquire); + + match res { + Ok(_) => { + // memory ordering: acquired self.state during CAS + // - if previous wakes went through it syncs with + // their final release (`fetch_and`) + // - if there was no previous wake the next wake + // will wake us, no sync needed. + } + Err(actual) => { + // This branch can only be reached if at least one + // concurrent thread called `wake`. In this + // case, `actual` **must** be `REGISTERING | + // `WAKING`. + debug_assert_eq!(actual, REGISTERING | WAKING); + + // Take the waker to wake once the atomic operation has + // completed. + let waker = (*self.waker.get()).take().unwrap(); + + // We need to return to WAITING state (clear our lock and + // concurrent WAKING flag). This needs to acquire all + // WAKING fetch_or releases and it needs to release our + // update to self.waker, so we need a `swap` operation. + self.state.swap(WAITING, AcqRel); + + // memory ordering: we acquired the state for all + // concurrent wakes, but future wakes might still + // need to wake us in case we can't make progress + // from the pending wakes. + // + // So we simply schedule to come back later (we could + // also simply leave the registration in place above). + waker.wake(); + } + } + } + } + WAKING => { + // Currently in the process of waking the task, i.e., + // `wake` is currently being called on the old task handle. + // + // memory ordering: we acquired the state for all + // concurrent wakes, but future wakes might still + // need to wake us in case we can't make progress + // from the pending wakes. + // + // So we simply schedule to come back later (we + // could also spin here trying to acquire the lock + // to register). + waker.wake_by_ref(); + } + state => { + // In this case, a concurrent thread is holding the + // "registering" lock. This probably indicates a bug in the + // caller's code as racing to call `register` doesn't make much + // sense. + // + // memory ordering: don't care. a concurrent register() is going + // to succeed and provide proper memory ordering. + // + // We just want to maintain memory safety. It is ok to drop the + // call to `register`. + debug_assert!(state == REGISTERING || state == REGISTERING | WAKING); + } + } + } + + /// Calls `wake` on the last `Waker` passed to `register`. + /// + /// If `register` has not been called yet, then this does nothing. + pub fn wake(&self) { + if let Some(waker) = self.take() { + waker.wake(); + } + } + + /// Returns the last `Waker` passed to `register`, so that the user can wake it. + /// + /// + /// Sometimes, just waking the AtomicWaker is not fine grained enough. This allows the user + /// to take the waker and then wake it separately, rather than performing both steps in one + /// atomic action. + /// + /// If a waker has not been registered, this returns `None`. + pub fn take(&self) -> Option { + // AcqRel ordering is used in order to acquire the value of the `task` + // cell as well as to establish a `release` ordering with whatever + // memory the `AtomicWaker` is associated with. + match self.state.fetch_or(WAKING, AcqRel) { + WAITING => { + // The waking lock has been acquired. + let waker = unsafe { (*self.waker.get()).take() }; + + // Release the lock + let old_state = self.state.swap(WAITING, Release); + debug_assert!(old_state == WAKING); + + waker + } + state => { + // There is a concurrent thread currently updating the + // associated task. + // + // Nothing more to do as the `WAKING` bit has been set. It + // doesn't matter if there are concurrent registering threads or + // not. + // + debug_assert!( + state == REGISTERING || state == REGISTERING | WAKING || state == WAKING + ); + None + } + } + } +} + +impl Default for AtomicWaker { + fn default() -> Self { + Self::new() + } +} + +impl fmt::Debug for AtomicWaker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "AtomicWaker") + } +} + +unsafe impl Send for AtomicWaker {} +unsafe impl Sync for AtomicWaker {} diff --git a/anneal/v2/vendor/futures-core/src/task/__internal/mod.rs b/anneal/v2/vendor/futures-core/src/task/__internal/mod.rs new file mode 100644 index 0000000000..c248742280 --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/task/__internal/mod.rs @@ -0,0 +1,7 @@ +#[cfg_attr(target_os = "none", cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")))] +mod atomic_waker; +#[cfg_attr( + target_os = "none", + cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")) +)] +pub use self::atomic_waker::AtomicWaker; diff --git a/anneal/v2/vendor/futures-core/src/task/mod.rs b/anneal/v2/vendor/futures-core/src/task/mod.rs new file mode 100644 index 0000000000..19e4eaecdd --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/task/mod.rs @@ -0,0 +1,10 @@ +//! Task notification. + +#[macro_use] +mod poll; + +#[doc(hidden)] +pub mod __internal; + +#[doc(no_inline)] +pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; diff --git a/anneal/v2/vendor/futures-core/src/task/poll.rs b/anneal/v2/vendor/futures-core/src/task/poll.rs new file mode 100644 index 0000000000..bde0f8a5fe --- /dev/null +++ b/anneal/v2/vendor/futures-core/src/task/poll.rs @@ -0,0 +1,15 @@ +/// Extracts the successful type of `Poll`. +/// +/// This macro bakes in propagation of `Pending` signals by returning early. +/// +/// **Note:** Since Rust 1.64, this macro is soft-deprecated in favor of +/// [`ready!`](core::task::ready) macro in the standard library. +#[macro_export] +macro_rules! ready { + ($e:expr $(,)?) => { + match $e { + $crate::task::Poll::Ready(t) => t, + $crate::task::Poll::Pending => return $crate::task::Poll::Pending, + } + }; +} diff --git a/anneal/v2/vendor/futures-task/.cargo-checksum.json b/anneal/v2/vendor/futures-task/.cargo-checksum.json new file mode 100644 index 0000000000..21469e56a9 --- /dev/null +++ b/anneal/v2/vendor/futures-task/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"084e9e7c49ccfd133f931dbea2551783ead77d307e9ae37ac290003028e51d98","Cargo.lock":"048bd956789e2e40f3a91f07a4218fddbe6cb2aba174121d50b6c42ae978a1cc","Cargo.toml":"32f63e3cf3ba8660b2890fc63c07b9872cb3e3c0d955b63d220fc274a819f380","Cargo.toml.orig":"08c075fcf84e4b6971739f1a29fab86d4233e09719effb3a34d4a6af84c9855c","LICENSE-APACHE":"275c491d6d1160553c32fd6127061d7f9606c3ea25abfad6ca3f6ed088785427","LICENSE-MIT":"6652c868f35dfe5e8ef636810a4e576b9d663f3a17fb0f5613ad73583e1b88fd","README.md":"7a458e69ff008c35cffbbbcd2a14ad3ba7ad75201ce74df2d8f8d0fdcf6c4a89","src/arc_wake.rs":"0e3f7d7883b75337b0b92ff55e477f0bf96f6eb08def7d953676a289fd9696ec","src/future_obj.rs":"be75a5b6f124cd25038c60961b5933062a06ccdce569e58e41c357802d3d1891","src/lib.rs":"b49478700ee4d64df460c225f1b4b3ce11ff5c24065602efe88ffb0f3ce4ca59","src/noop_waker.rs":"41246601dab77f69bf09257afc3321031a5a31a7eda51787029870eda9922356","src/spawn.rs":"cd0dafb52700e087a2793bb42d70da84e9e10181d5407ea74843d935f40cea02","src/waker.rs":"3fd071a6e951d873aa896b3ee7b377a70d340e738a51aef85f5bb1c46d3451a8","src/waker_ref.rs":"640264ad52ccd2ebbb650104eaab9a2d24b8d08749f8c76226bd22bd51006f2a"},"package":"037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-task/.cargo_vcs_info.json b/anneal/v2/vendor/futures-task/.cargo_vcs_info.json new file mode 100644 index 0000000000..6b09d8029a --- /dev/null +++ b/anneal/v2/vendor/futures-task/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d9bba94c239daa1175a5bb2958f37a5c72db3f6a" + }, + "path_in_vcs": "futures-task" +} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-task/Cargo.lock b/anneal/v2/vendor/futures-task/Cargo.lock new file mode 100644 index 0000000000..ec9bfb8424 --- /dev/null +++ b/anneal/v2/vendor/futures-task/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "futures-task" +version = "0.3.32" + diff --git a/anneal/v2/vendor/futures-task/Cargo.toml b/anneal/v2/vendor/futures-task/Cargo.toml new file mode 100644 index 0000000000..7cc868868a --- /dev/null +++ b/anneal/v2/vendor/futures-task/Cargo.toml @@ -0,0 +1,58 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.71" +name = "futures-task" +version = "0.3.32" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Tools for working with tasks. +""" +homepage = "https://rust-lang.github.io/futures-rs" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" + +[package.metadata.docs.rs] +all-features = true + +[features] +alloc = [] +cfg-target-has-atomic = [] +default = ["std"] +std = ["alloc"] +unstable = [] + +[lib] +name = "futures_task" +path = "src/lib.rs" + +[dependencies] + +[dev-dependencies] + +[lints.rust] +missing_debug_implementations = "warn" +rust_2018_idioms = "warn" +single_use_lifetimes = "warn" +unreachable_pub = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(futures_sanitizer)"] diff --git a/anneal/v2/vendor/futures-task/Cargo.toml.orig b/anneal/v2/vendor/futures-task/Cargo.toml.orig new file mode 100644 index 0000000000..80d963320e --- /dev/null +++ b/anneal/v2/vendor/futures-task/Cargo.toml.orig @@ -0,0 +1,33 @@ +[package] +name = "futures-task" +version = "0.3.32" +edition = "2018" +# NB: Sync with "Usage" section in README.md and util-msrv job in .github/workflows/ci.yml +rust-version = "1.71" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" +homepage = "https://rust-lang.github.io/futures-rs" +description = """ +Tools for working with tasks. +""" + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +# These features are no longer used. +# TODO: remove in the next major version. +unstable = [] +cfg-target-has-atomic = [] + +[dependencies] + +[dev-dependencies] +futures = { path = "../futures" } + +[package.metadata.docs.rs] +all-features = true + +[lints] +workspace = true diff --git a/anneal/v2/vendor/futures-task/LICENSE-APACHE b/anneal/v2/vendor/futures-task/LICENSE-APACHE new file mode 100644 index 0000000000..9eb0b097f5 --- /dev/null +++ b/anneal/v2/vendor/futures-task/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/futures-task/LICENSE-MIT b/anneal/v2/vendor/futures-task/LICENSE-MIT new file mode 100644 index 0000000000..8ad082ec4f --- /dev/null +++ b/anneal/v2/vendor/futures-task/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/futures-task/README.md b/anneal/v2/vendor/futures-task/README.md new file mode 100644 index 0000000000..64d582a22d --- /dev/null +++ b/anneal/v2/vendor/futures-task/README.md @@ -0,0 +1,23 @@ +# futures-task + +Tools for working with tasks. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +futures-task = "0.3" +``` + +The current `futures-task` requires Rust 1.71 or later. + +## License + +Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or +[MIT license](LICENSE-MIT) at your option. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/futures-task/src/arc_wake.rs b/anneal/v2/vendor/futures-task/src/arc_wake.rs new file mode 100644 index 0000000000..aa6de0fc43 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/arc_wake.rs @@ -0,0 +1,49 @@ +use alloc::sync::Arc; + +/// A way of waking up a specific task. +/// +/// By implementing this trait, types that are expected to be wrapped in an `Arc` +/// can be converted into [`Waker`] objects. +/// Those Wakers can be used to signal executors that a task it owns +/// is ready to be `poll`ed again. +/// +/// Currently, there are two ways to convert `ArcWake` into [`Waker`]: +/// +/// * [`waker`](super::waker()) converts `Arc` into [`Waker`]. +/// * [`waker_ref`](super::waker_ref()) converts `&Arc` into [`WakerRef`] that +/// provides access to a [`&Waker`][`Waker`]. +/// +/// [`Waker`]: std::task::Waker +/// [`WakerRef`]: super::WakerRef +// Note: Send + Sync required because `Arc` doesn't automatically imply +// those bounds, but `Waker` implements them. +pub trait ArcWake: Send + Sync { + /// Indicates that the associated task is ready to make progress and should + /// be `poll`ed. + /// + /// This function can be called from an arbitrary thread, including threads which + /// did not create the `ArcWake` based [`Waker`]. + /// + /// Executors generally maintain a queue of "ready" tasks; `wake` should place + /// the associated task onto this queue. + /// + /// [`Waker`]: std::task::Waker + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + + /// Indicates that the associated task is ready to make progress and should + /// be `poll`ed. + /// + /// This function can be called from an arbitrary thread, including threads which + /// did not create the `ArcWake` based [`Waker`]. + /// + /// Executors generally maintain a queue of "ready" tasks; `wake_by_ref` should place + /// the associated task onto this queue. + /// + /// This function is similar to [`wake`](ArcWake::wake), but must not consume the provided data + /// pointer. + /// + /// [`Waker`]: std::task::Waker + fn wake_by_ref(arc_self: &Arc); +} diff --git a/anneal/v2/vendor/futures-task/src/future_obj.rs b/anneal/v2/vendor/futures-task/src/future_obj.rs new file mode 100644 index 0000000000..a611382193 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/future_obj.rs @@ -0,0 +1,335 @@ +use core::{ + fmt, + future::Future, + marker::PhantomData, + mem, + pin::Pin, + task::{Context, Poll}, +}; + +/// A custom trait object for polling futures, roughly akin to +/// `Box + 'a>`. +/// +/// This custom trait object was introduced as currently it is not possible to +/// take `dyn Trait` by value and `Box` is not available in no_std +/// contexts. +pub struct LocalFutureObj<'a, T> { + future: *mut (dyn Future + 'static), + drop_fn: unsafe fn(*mut (dyn Future + 'static)), + _marker: PhantomData<&'a ()>, +} + +// As LocalFutureObj only holds pointers, even if we move it, the pointed to values won't move, +// so this is safe as long as we don't provide any way for a user to directly access the pointers +// and move their values. +impl Unpin for LocalFutureObj<'_, T> {} + +#[allow(single_use_lifetimes)] +#[allow(clippy::transmute_ptr_to_ptr)] +unsafe fn remove_future_lifetime<'a, T>( + ptr: *mut (dyn Future + 'a), +) -> *mut (dyn Future + 'static) { + unsafe { mem::transmute(ptr) } +} + +#[allow(single_use_lifetimes)] +unsafe fn remove_drop_lifetime<'a, T>( + ptr: unsafe fn(*mut (dyn Future + 'a)), +) -> unsafe fn(*mut (dyn Future + 'static)) { + unsafe { mem::transmute(ptr) } +} + +impl<'a, T> LocalFutureObj<'a, T> { + /// Create a `LocalFutureObj` from a custom trait object representation. + #[inline] + pub fn new + 'a>(f: F) -> Self { + Self { + future: unsafe { remove_future_lifetime(f.into_raw()) }, + drop_fn: unsafe { remove_drop_lifetime(F::drop) }, + _marker: PhantomData, + } + } + + /// Converts the `LocalFutureObj` into a `FutureObj`. + /// + /// # Safety + /// + /// To make this operation safe one has to ensure that the `UnsafeFutureObj` + /// instance from which this `LocalFutureObj` was created actually + /// implements `Send`. + #[inline] + pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> { + FutureObj(self) + } +} + +impl fmt::Debug for LocalFutureObj<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("LocalFutureObj").finish() + } +} + +impl<'a, T> From> for LocalFutureObj<'a, T> { + #[inline] + fn from(f: FutureObj<'a, T>) -> Self { + f.0 + } +} + +impl Future for LocalFutureObj<'_, T> { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unsafe { Pin::new_unchecked(&mut *self.future).poll(cx) } + } +} + +impl Drop for LocalFutureObj<'_, T> { + fn drop(&mut self) { + unsafe { (self.drop_fn)(self.future) } + } +} + +/// A custom trait object for polling futures, roughly akin to +/// `Box + Send + 'a>`. +/// +/// This custom trait object was introduced as currently it is not possible to +/// take `dyn Trait` by value and `Box` is not available in no_std +/// contexts. +/// +/// You should generally not need to use this type outside of `no_std` or when +/// implementing `Spawn`, consider using `BoxFuture` instead. +pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); + +impl Unpin for FutureObj<'_, T> {} +unsafe impl Send for FutureObj<'_, T> {} + +impl<'a, T> FutureObj<'a, T> { + /// Create a `FutureObj` from a custom trait object representation. + #[inline] + pub fn new + Send>(f: F) -> Self { + Self(LocalFutureObj::new(f)) + } +} + +impl fmt::Debug for FutureObj<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FutureObj").finish() + } +} + +impl Future for FutureObj<'_, T> { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.0).poll(cx) + } +} + +/// A custom implementation of a future trait object for `FutureObj`, providing +/// a vtable with drop support. +/// +/// This custom representation is typically used only in `no_std` contexts, +/// where the default `Box`-based implementation is not available. +/// +/// # Safety +/// +/// See the safety notes on individual methods for what guarantees an +/// implementor must provide. +pub unsafe trait UnsafeFutureObj<'a, T>: 'a { + /// Convert an owned instance into a (conceptually owned) fat pointer. + /// + /// # Safety + /// + /// ## Implementor + /// + /// The trait implementor must guarantee that it is safe to convert the + /// provided `*mut (dyn Future + 'a)` into a `Pin<&mut (dyn + /// Future + 'a)>` and call methods on it, non-reentrantly, + /// until `UnsafeFutureObj::drop` is called with it. + #[allow(clippy::unnecessary_safety_doc)] + fn into_raw(self) -> *mut (dyn Future + 'a); + + /// Drops the future represented by the given fat pointer. + /// + /// # Safety + /// + /// ## Implementor + /// + /// The trait implementor must guarantee that it is safe to call this + /// function once per `into_raw` invocation. + /// + /// ## Caller + /// + /// The caller must ensure: + /// + /// * the pointer passed was obtained from an `into_raw` invocation from + /// this same trait object + /// * the pointer is not currently in use as a `Pin<&mut (dyn Future + 'a)>` + /// * the pointer must not be used again after this function is called + unsafe fn drop(ptr: *mut (dyn Future + 'a)); +} + +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F +where + F: Future + Unpin + 'a, +{ + fn into_raw(self) -> *mut (dyn Future + 'a) { + self as *mut dyn Future + } + + unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} +} + +unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future + Unpin + 'a) { + fn into_raw(self) -> *mut (dyn Future + 'a) { + self as *mut dyn Future + } + + unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} +} + +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F> +where + F: Future + 'a, +{ + fn into_raw(self) -> *mut (dyn Future + 'a) { + unsafe { self.get_unchecked_mut() as *mut dyn Future } + } + + unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} +} + +unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future + 'a)> { + fn into_raw(self) -> *mut (dyn Future + 'a) { + unsafe { self.get_unchecked_mut() as *mut dyn Future } + } + + unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} +} + +#[cfg(feature = "alloc")] +mod if_alloc { + use super::*; + use alloc::boxed::Box; + + unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box + where + F: Future + 'a, + { + fn into_raw(self) -> *mut (dyn Future + 'a) { + Box::into_raw(self) + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(unsafe { Box::from_raw(ptr.cast::()) }) + } + } + + unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box + 'a> { + fn into_raw(self) -> *mut (dyn Future + 'a) { + Box::into_raw(self) + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(unsafe { Box::from_raw(ptr) }) + } + } + + unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box + Send + 'a> { + fn into_raw(self) -> *mut (dyn Future + 'a) { + Box::into_raw(self) + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(unsafe { Box::from_raw(ptr) }) + } + } + + unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin> + where + F: Future + 'a, + { + fn into_raw(self) -> *mut (dyn Future + 'a) { + let mut this = mem::ManuallyDrop::new(self); + unsafe { this.as_mut().get_unchecked_mut() as *mut _ } + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(Pin::from(unsafe { Box::from_raw(ptr) })) + } + } + + unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin + 'a>> { + fn into_raw(self) -> *mut (dyn Future + 'a) { + let mut this = mem::ManuallyDrop::new(self); + unsafe { this.as_mut().get_unchecked_mut() as *mut _ } + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(Pin::from(unsafe { Box::from_raw(ptr) })) + } + } + + unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin + Send + 'a>> { + fn into_raw(self) -> *mut (dyn Future + 'a) { + let mut this = mem::ManuallyDrop::new(self); + unsafe { this.as_mut().get_unchecked_mut() as *mut _ } + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(Pin::from(unsafe { Box::from_raw(ptr) })) + } + } + + impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { + fn from(boxed: Box) -> Self { + Self::new(boxed) + } + } + + impl<'a> From + Send + 'a>> for FutureObj<'a, ()> { + fn from(boxed: Box + Send + 'a>) -> Self { + Self::new(boxed) + } + } + + impl<'a, F: Future + Send + 'a> From>> for FutureObj<'a, ()> { + fn from(boxed: Pin>) -> Self { + Self::new(boxed) + } + } + + impl<'a> From + Send + 'a>>> for FutureObj<'a, ()> { + fn from(boxed: Pin + Send + 'a>>) -> Self { + Self::new(boxed) + } + } + + impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { + fn from(boxed: Box) -> Self { + Self::new(boxed) + } + } + + impl<'a> From + 'a>> for LocalFutureObj<'a, ()> { + fn from(boxed: Box + 'a>) -> Self { + Self::new(boxed) + } + } + + impl<'a, F: Future + 'a> From>> for LocalFutureObj<'a, ()> { + fn from(boxed: Pin>) -> Self { + Self::new(boxed) + } + } + + impl<'a> From + 'a>>> for LocalFutureObj<'a, ()> { + fn from(boxed: Pin + 'a>>) -> Self { + Self::new(boxed) + } + } +} diff --git a/anneal/v2/vendor/futures-task/src/lib.rs b/anneal/v2/vendor/futures-task/src/lib.rs new file mode 100644 index 0000000000..c119b6b1e4 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/lib.rs @@ -0,0 +1,50 @@ +//! Tools for working with tasks. + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms, single_use_lifetimes), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn(missing_docs, unsafe_op_in_unsafe_fn)] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +mod spawn; +pub use crate::spawn::{LocalSpawn, Spawn, SpawnError}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod arc_wake; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use crate::arc_wake::ArcWake; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod waker; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use crate::waker::waker; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod waker_ref; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use crate::waker_ref::{waker_ref, WakerRef}; + +mod future_obj; +pub use crate::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; + +mod noop_waker; +pub use crate::noop_waker::noop_waker; +pub use crate::noop_waker::noop_waker_ref; + +#[doc(no_inline)] +pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; diff --git a/anneal/v2/vendor/futures-task/src/noop_waker.rs b/anneal/v2/vendor/futures-task/src/noop_waker.rs new file mode 100644 index 0000000000..f76a8a2e95 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/noop_waker.rs @@ -0,0 +1,63 @@ +//! Utilities for creating zero-cost wakers that don't do anything. + +use core::ptr::null; +use core::task::{RawWaker, RawWakerVTable, Waker}; + +unsafe fn noop_clone(_data: *const ()) -> RawWaker { + noop_raw_waker() +} + +unsafe fn noop(_data: *const ()) {} + +const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + +const fn noop_raw_waker() -> RawWaker { + RawWaker::new(null(), &NOOP_WAKER_VTABLE) +} + +/// Create a new [`Waker`] which does +/// nothing when `wake()` is called on it. +/// +/// # Examples +/// +/// ``` +/// use futures::task::noop_waker; +/// let waker = noop_waker(); +/// waker.wake(); +/// ``` +#[inline] +pub fn noop_waker() -> Waker { + // FIXME: Since 1.46.0 we can use transmute in consts, allowing this function to be const. + unsafe { Waker::from_raw(noop_raw_waker()) } +} + +/// Get a static reference to a [`Waker`] which +/// does nothing when `wake()` is called on it. +/// +/// # Examples +/// +/// ``` +/// use futures::task::noop_waker_ref; +/// let waker = noop_waker_ref(); +/// waker.wake_by_ref(); +/// ``` +#[inline] +pub fn noop_waker_ref() -> &'static Waker { + struct SyncRawWaker(RawWaker); + unsafe impl Sync for SyncRawWaker {} + + static NOOP_WAKER_INSTANCE: SyncRawWaker = SyncRawWaker(noop_raw_waker()); + + // SAFETY: `Waker` is #[repr(transparent)] over its `RawWaker`. + unsafe { &*(&NOOP_WAKER_INSTANCE.0 as *const RawWaker as *const Waker) } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "std")] + fn issue_2091_cross_thread_segfault() { + let waker = std::thread::spawn(super::noop_waker_ref).join().unwrap(); + waker.wake_by_ref(); + } +} diff --git a/anneal/v2/vendor/futures-task/src/spawn.rs b/anneal/v2/vendor/futures-task/src/spawn.rs new file mode 100644 index 0000000000..4a9a45a446 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/spawn.rs @@ -0,0 +1,192 @@ +use crate::{FutureObj, LocalFutureObj}; +use core::fmt; + +/// The `Spawn` trait allows for pushing futures onto an executor that will +/// run them to completion. +pub trait Spawn { + /// Spawns a future that will be run to completion. + /// + /// # Errors + /// + /// The executor may be unable to spawn tasks. Spawn errors should + /// represent relatively rare scenarios, such as the executor + /// having been shut down so that it is no longer able to accept + /// tasks. + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError>; + + /// Determines whether the executor is able to spawn new tasks. + /// + /// This method will return `Ok` when the executor is *likely* + /// (but not guaranteed) to accept a subsequent spawn attempt. + /// Likewise, an `Err` return means that `spawn` is likely, but + /// not guaranteed, to yield an error. + #[inline] + fn status(&self) -> Result<(), SpawnError> { + Ok(()) + } +} + +/// The `LocalSpawn` is similar to [`Spawn`], but allows spawning futures +/// that don't implement `Send`. +pub trait LocalSpawn { + /// Spawns a future that will be run to completion. + /// + /// # Errors + /// + /// The executor may be unable to spawn tasks. Spawn errors should + /// represent relatively rare scenarios, such as the executor + /// having been shut down so that it is no longer able to accept + /// tasks. + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError>; + + /// Determines whether the executor is able to spawn new tasks. + /// + /// This method will return `Ok` when the executor is *likely* + /// (but not guaranteed) to accept a subsequent spawn attempt. + /// Likewise, an `Err` return means that `spawn` is likely, but + /// not guaranteed, to yield an error. + #[inline] + fn status_local(&self) -> Result<(), SpawnError> { + Ok(()) + } +} + +/// An error that occurred during spawning. +pub struct SpawnError { + _priv: (), +} + +impl fmt::Debug for SpawnError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SpawnError").field(&"shutdown").finish() + } +} + +impl fmt::Display for SpawnError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Executor is shutdown") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SpawnError {} + +impl SpawnError { + /// Spawning failed because the executor has been shut down. + pub fn shutdown() -> Self { + Self { _priv: () } + } + + /// Check whether spawning failed to the executor being shut down. + pub fn is_shutdown(&self) -> bool { + true + } +} + +impl Spawn for &Sp { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_obj(self, future) + } + + fn status(&self) -> Result<(), SpawnError> { + Sp::status(self) + } +} + +impl Spawn for &mut Sp { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_obj(self, future) + } + + fn status(&self) -> Result<(), SpawnError> { + Sp::status(self) + } +} + +impl LocalSpawn for &Sp { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_local_obj(self, future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + Sp::status_local(self) + } +} + +impl LocalSpawn for &mut Sp { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + Sp::spawn_local_obj(self, future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + Sp::status_local(self) + } +} + +#[cfg(feature = "alloc")] +mod if_alloc { + use super::*; + use alloc::{boxed::Box, rc::Rc}; + + impl Spawn for Box { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + impl LocalSpawn for Box { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } + + impl Spawn for Rc { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + impl LocalSpawn for Rc { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } + + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + impl Spawn for alloc::sync::Arc { + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_obj(future) + } + + fn status(&self) -> Result<(), SpawnError> { + (**self).status() + } + } + + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + impl LocalSpawn for alloc::sync::Arc { + fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + (**self).spawn_local_obj(future) + } + + fn status_local(&self) -> Result<(), SpawnError> { + (**self).status_local() + } + } +} diff --git a/anneal/v2/vendor/futures-task/src/waker.rs b/anneal/v2/vendor/futures-task/src/waker.rs new file mode 100644 index 0000000000..ce90aa83d9 --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/waker.rs @@ -0,0 +1,60 @@ +use super::arc_wake::ArcWake; +use alloc::sync::Arc; +use core::mem; +use core::task::{RawWaker, RawWakerVTable, Waker}; + +pub(super) fn waker_vtable() -> &'static RawWakerVTable { + &RawWakerVTable::new( + clone_arc_raw::, + wake_arc_raw::, + wake_by_ref_arc_raw::, + drop_arc_raw::, + ) +} + +/// Creates a [`Waker`] from an `Arc`. +/// +/// The returned [`Waker`] will call +/// [`ArcWake.wake()`](ArcWake::wake) if awoken. +pub fn waker(wake: Arc) -> Waker +where + W: ArcWake + 'static, +{ + let ptr = Arc::into_raw(wake).cast::<()>(); + + unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::())) } +} + +// FIXME: panics on Arc::clone / refcount changes could wreak havoc on the +// code here. We should guard against this by aborting. + +#[allow(clippy::redundant_clone)] // The clone here isn't actually redundant. +unsafe fn increase_refcount(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); +} + +// used by `waker_ref` +#[inline(always)] +unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { + unsafe { increase_refcount::(data) } + RawWaker::new(data, waker_vtable::()) +} + +unsafe fn wake_arc_raw(data: *const ()) { + let arc: Arc = unsafe { Arc::from_raw(data.cast::()) }; + ArcWake::wake(arc); +} + +// used by `waker_ref` +unsafe fn wake_by_ref_arc_raw(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); + ArcWake::wake_by_ref(&arc); +} + +unsafe fn drop_arc_raw(data: *const ()) { + drop(unsafe { Arc::::from_raw(data.cast::()) }) +} diff --git a/anneal/v2/vendor/futures-task/src/waker_ref.rs b/anneal/v2/vendor/futures-task/src/waker_ref.rs new file mode 100644 index 0000000000..5957b4d46a --- /dev/null +++ b/anneal/v2/vendor/futures-task/src/waker_ref.rs @@ -0,0 +1,66 @@ +use super::arc_wake::ArcWake; +use super::waker::waker_vtable; +use alloc::sync::Arc; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ops::Deref; +use core::task::{RawWaker, Waker}; + +/// A [`Waker`] that is only valid for a given lifetime. +/// +/// Note: this type implements [`Deref`](std::ops::Deref), +/// so it can be used to get a `&Waker`. +#[derive(Debug)] +pub struct WakerRef<'a> { + waker: ManuallyDrop, + _marker: PhantomData<&'a ()>, +} + +impl<'a> WakerRef<'a> { + /// Create a new [`WakerRef`] from a [`Waker`] reference. + #[inline] + pub fn new(waker: &'a Waker) -> Self { + // copy the underlying (raw) waker without calling a clone, + // as we won't call Waker::drop either. + let waker = ManuallyDrop::new(unsafe { core::ptr::read(waker) }); + Self { waker, _marker: PhantomData } + } + + /// Create a new [`WakerRef`] from a [`Waker`] that must not be dropped. + /// + /// Note: this if for rare cases where the caller created a [`Waker`] in + /// an unsafe way (that will be valid only for a lifetime to be determined + /// by the caller), and the [`Waker`] doesn't need to or must not be + /// destroyed. + #[inline] + pub fn new_unowned(waker: ManuallyDrop) -> Self { + Self { waker, _marker: PhantomData } + } +} + +impl Deref for WakerRef<'_> { + type Target = Waker; + + #[inline] + fn deref(&self) -> &Waker { + &self.waker + } +} + +/// Creates a reference to a [`Waker`] from a reference to `Arc`. +/// +/// The resulting [`Waker`] will call +/// [`ArcWake.wake()`](ArcWake::wake) if awoken. +#[inline] +pub fn waker_ref(wake: &Arc) -> WakerRef<'_> +where + W: ArcWake + 'static, +{ + // simply copy the pointer instead of using Arc::into_raw, + // as we don't actually keep a refcount by using ManuallyDrop.< + let ptr = Arc::as_ptr(wake).cast::<()>(); + + let waker = + ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::())) }); + WakerRef::new_unowned(waker) +} diff --git a/anneal/v2/vendor/futures-util/.cargo-checksum.json b/anneal/v2/vendor/futures-util/.cargo-checksum.json new file mode 100644 index 0000000000..81dbe9d217 --- /dev/null +++ b/anneal/v2/vendor/futures-util/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"c29e1ba833587f3df71f8ed152e980cf40e0d3cb2090fac3831db7a1f798f0de","Cargo.lock":"08c3748ebe6ae33c0f1514a1fb5dea68ce9cb8a612bc0cbb40f5bedb3f56fae3","Cargo.toml":"154c37245e36982072655c79b83a9ba932a263824228ef6ddbd15cf1e4f47153","Cargo.toml.orig":"b60b84c134b0bc25ad452167db4ae051a02c70eb88f9b3802a44147ef3b605f2","LICENSE-APACHE":"275c491d6d1160553c32fd6127061d7f9606c3ea25abfad6ca3f6ed088785427","LICENSE-MIT":"6652c868f35dfe5e8ef636810a4e576b9d663f3a17fb0f5613ad73583e1b88fd","README.md":"00510d047b36feb45db9034bf5f07a049a99b51d6b8c40d028cb35977baeb723","benches/bilock.rs":"6f59b71f9b9ca5751018a985eff0ea8d63d4cb6d18a17e672e17bc786b972c20","benches/flatten_unordered.rs":"79330465a5d8f2d6e450861e7ca2ed8ae7fe78a5fb221b6ab7121227810c1bcf","benches/futures_unordered.rs":"5eb8280be8d8fb7bd5fb103ce20db10f618f47e180a402105e0d5e9f8c9fe35a","benches/select.rs":"ca0a79bc3434f0fc025e0b0e37941ba1d592b40f36ce6544cdfede9f23e70581","src/abortable.rs":"d58fd321880308cb81258bdfe8519e6c4d25301ad6fbb748cf84c0b4e5bd567c","src/async_await/join_mod.rs":"8f83c0001df867f5eb47a4174bf4a0c0b548f8ff3be3b532e0c759ad981b87da","src/async_await/mod.rs":"9a81d2eb3c89a31e1241c50438ff92d08d5c1fa879f0f8d52bfbcc261aa88272","src/async_await/pending.rs":"7971ec1d5d89ad80390e2a0c51e396257b2e78f1436cce79ea2b55ac2f13b328","src/async_await/poll.rs":"440c19a89fd42b12da09ff48a69523b5a8a5baea0bcd2f860589a0ab996ed781","src/async_await/random.rs":"30d4a46068c539a58f475b971a9114b7b1ac08d22df5331b2f31d42ecbef7b90","src/async_await/select_mod.rs":"5c87005c830f820da8e45bf9bec86fef2f13791e8c6ff3c69aa93576ddd0d40a","src/async_await/stream_select_mod.rs":"bb4c585281a00de64e36ea7a3c2f8d7ce5c21d296698f85ec817f04c742fd251","src/compat/compat01as03.rs":"7c9203250eef5a79c1dd582e67c1a09255b5a4884d9991cc871f76962c9ffa54","src/compat/compat03as01.rs":"5cb89dd890baf02018780c7ca753c46e6c24fba967f8476e4c173f19b185073b","src/compat/executor.rs":"3e40b4ccd905a99eab42c47fefc5502b530eef869158ce9ceaa28f8f1638436f","src/compat/mod.rs":"6cf3412f6a3f9ee8406118ea75de65468a83febc6ba61bdbad69261f0cfea02e","src/fns.rs":"58d43b04a570263344622a91e84c7c8838e77f3e2a562a19d78964e91b075d5a","src/future/abortable.rs":"373ce61c0c7c31718ff572113503bb88f55e3b49ed5d028a3dfafd69070f44c1","src/future/always_ready.rs":"c8f1ac9bb3ce49200ccc9c26454b6c84526781dc523ded4e16f76055d85d900a","src/future/either.rs":"8505e7cbbe75ccb9dbde371fd0ba181015bf5ab3869d48192f00d85ed3284cd1","src/future/future/catch_unwind.rs":"f43098955f6e1f3de254c24969810d844211c52d9ae0e1cebd8137567c78e5b5","src/future/future/flatten.rs":"5bf9846cef8dec5dcc38b992653e11146bc149a0d3efc09b1f8268bd29de0b2b","src/future/future/fuse.rs":"789bec97248a529e0b4994a644ad8e19c5593a6cb20ac8608976e87881ed50b8","src/future/future/map.rs":"2ad91b79d7aac197b16beb9e97d6eb1b9b75fce558d1ff1f305421f894834042","src/future/future/mod.rs":"93b6177d1b8f01876f5ec3960ca2ae4c50fbf9a29c467f23d7cf7f672e33e9db","src/future/future/remote_handle.rs":"9f2230e7fafa3954960c2f4c0bfd3207b54aa2c19357af98edfd53b4f878f90c","src/future/future/shared.rs":"bb281d9e3868a3e1f02dd61a60c357721fb804a01543606af625000c789fd8d8","src/future/join.rs":"38b55fc7cdbbdaaa525e51f8ce09783dbbcb65eabfd7de9f46610593e0bbef17","src/future/join_all.rs":"4893629a9e5342f92fe58165dbb2ec80107c2ae4a0dbf97c9bba6847dbab0743","src/future/lazy.rs":"d161fc4108a97348c1becbbd5ba8fccb7225dcf1d81c097666f5c8b40718251d","src/future/maybe_done.rs":"a17c82a822688c3e82c77a364e0620ff61cd287904e02387d0cd61a8471377da","src/future/mod.rs":"7398daef9885eab951906fa3658bbf4498654850cb0e5e32afe83486c9633465","src/future/option.rs":"73daca814800b91b707753dcfe074265372b0077fae2504ea6efddc713453579","src/future/pending.rs":"3967984d2061e6b201c407f28ba8392a21fc9ef7c0b9201e2e244110af0782c5","src/future/poll_fn.rs":"8e54bf57d60e01d496ae31df35e0b96868f4bda504c024a14f51ab723d67885f","src/future/poll_immediate.rs":"4bcddade702aabdf434b258a4442fcbff31835c76e881d807f4c6114529727e9","src/future/ready.rs":"c9860ccd8ac529f44f66dee73ca9b9d7f1b1b3e5e9e4dc70c59640c752553d58","src/future/select.rs":"9a5813e137ca56a4d0cbb91233e1cec534730a3450b60502b08b34cadd278dba","src/future/select_all.rs":"5b304210c34cc2bd84f7b1819baa30a68eea2ee578b10b243f5dd884ee9a4791","src/future/select_ok.rs":"dc35027db70c0111399c6ab6f7c977e6e7362f069a3891e4a62006c52643528e","src/future/try_future/into_future.rs":"d966bde7b06a88443f0efd877e95f91541778c4e713f3f4b66e00ca5d3f352b6","src/future/try_future/mod.rs":"991edb3b52903ceb3bcb6599d04d898509023cd038c5974f4872eaafa9748f08","src/future/try_future/try_flatten.rs":"16c02e1780bd312b8b386e41c1d9dd4bcc4e8ef10f26007364f857b3adcc6e99","src/future/try_future/try_flatten_err.rs":"130f3fc3fd95a19f4e4a50e69301106fab02f77d0faf3aac9c473a92b826c2ca","src/future/try_join.rs":"1836931f8ba32da41c6810e6acc0ea2fee75b74b3153e760c4542cb12b220540","src/future/try_join_all.rs":"5df69dcae742816b9ba68a0152a3a39a1154fccf22af36683158ae7abb5edc11","src/future/try_maybe_done.rs":"69ae2deefd80652f5d68e7cfd5fbf1202e428e102cf7ced486534fa1cc7dde17","src/future/try_select.rs":"5d6187ace76b5f26e60c713a1fe9fcb9cbb0d161c5881c532ce9472a230b595d","src/io/allow_std.rs":"ebba19bb35737ed46b2738fccf54c65487b183dfb902921711e318a01d7697da","src/io/buf_reader.rs":"a7f7abb5d3834c097280f1a7b16f14c63fecfa4056ada3b729175b3128732c8c","src/io/buf_writer.rs":"3cbfc628f025ae8a41c57d258610e653aa046b803ea0031e551602168e6a7675","src/io/chain.rs":"12f508fc39c3234a71a0f886505245c5d659aed09c7d874b1bd8ca0a0d456cf3","src/io/close.rs":"9832210a870637198fa58642cdf2779afab71f2e31a9953e663fa6854bd73ac7","src/io/copy.rs":"cb2466dcd7ea8bb1f07d00c03e66ed55abf71fe4be6937adc9f533ef9d99fb2d","src/io/copy_buf.rs":"e9a5f6aac8375e298bddb332f23d8b626d056ce452b58f772a05df7e2cd326cf","src/io/copy_buf_abortable.rs":"ced73b6420e892f220965315ed44ec774de4b44082ea53d0c9c64dbed72feed6","src/io/cursor.rs":"7068a9233a8ec0cd685e4f784bda21ea0e76dba74d0de1d36d1fa9a48051b634","src/io/empty.rs":"6ae40b4bc8fc41572abad2d013285d78d8df445868d41fac77bde508ec9bc1a5","src/io/fill_buf.rs":"a3623e037db59efab227a769698098597f1b531a75b6c045e75f068c0137c738","src/io/flush.rs":"0c9b588dfd9da039dc123ba9448ac31ca21ee3da0a164a21f6c2c182183d43e2","src/io/into_sink.rs":"ab5bdb12bff62672175b69b8c9f5a4bbbea716b9cf89169ed6a723ab43da9df8","src/io/line_writer.rs":"b6174d334db1808f924b5617a80630f8dfcf9d569ee69e26f36c1913e7f63fc9","src/io/lines.rs":"32efc076c95603571dd0d9587acb5e92abd00d9d92f699f9ee468b4bf264eeb7","src/io/mod.rs":"dcceaea6783fc2591d27b1d15e826c5b3dc83858f4195621d7c70be1486e0a41","src/io/read.rs":"4ea675a83cec98a22c9c4731ff980209f0cf67f63c71871cd1deed53c1266345","src/io/read_exact.rs":"ddebd58db9f6766efa3f50543fb51b138538533921e1ee1da4621fff9c64efe2","src/io/read_line.rs":"f1978d109cbcdd9aaa8ba4c762671b7a96ab14df668d3a46e2bc3fd45c93b596","src/io/read_to_end.rs":"c74689011c1a95b991a89ff25cfbb5ec487468515119bda7bdcf5d048d01ce7f","src/io/read_to_string.rs":"c026184f29c2655a586af8b9d25de77a7a81dbce9950560bd7fbd21555816586","src/io/read_until.rs":"bc052a36cb760bfdbc3abf97f66eca79eac7bd47621ed65d733fa4f7af4cc0c9","src/io/read_vectored.rs":"bd7f442c92f2cb320075d0983b0d08d51c23078898d72e6c2857cf6c7ad4cec7","src/io/repeat.rs":"53bc472e4bd7d286bf90765ce574f13b7aabc871c4f04f712da7cea160491390","src/io/seek.rs":"9863e9fb6495eb6e1f8c45c283c8a6993b9bdb1462f75a3e525e135c6840dec7","src/io/sink.rs":"30a503631d196e5da92c386d0afc1af9656a5f7682456cfa2489a2c30a05cac5","src/io/split.rs":"b9685e9ae07c45e4fb3a414a796418ddfbeee1f9ffa34671d5694ca3703a46ad","src/io/take.rs":"c53fec5b5e8c3742b7e60e6ebfa625cf2e566fbea193fb1eee2f0a8e561d63d5","src/io/window.rs":"ec6a9d20a7b252a5b272a74afa32e2279d372b806840ab985eae17bc06a25d27","src/io/write.rs":"60670eb00f999f2e2c43b099759a7fb030325b323744d88c9d20f75926ec30df","src/io/write_all.rs":"8fcd4ff233650b5abd20f7b987000cac095d8de23445572de588dccf710623c6","src/io/write_all_vectored.rs":"02fd19815a7d1b9ad61d14169743f6b0b4efe2ac2b127a03e6b24a039f498863","src/io/write_vectored.rs":"bc98ff4a709cb75cd9ffedefa8ef251089a49906b98e142d76447ddf4ac098bb","src/lib.rs":"cc643a120ebd00c779c7a0a7dfc14a9bec709a4b17d5e0bd72ccf540c0ec71bc","src/lock/bilock.rs":"3808d76ea97c01b76e42032c209166f974b4f0cc7d252539bc5755a3099d630e","src/lock/mod.rs":"17505464b0d63d00ccbfc0e512b4a0edb4c6d8fef98c6ac46d0dd43c995a0673","src/lock/mutex.rs":"9ec6ca7274dbc53b864152e096ecc41709a9875d0612fc3a1b157ed6faaa004b","src/macros.rs":"decd92ce8b97d450e11d009352cd2d49ef07689aaa91e4dd2e958ddf40253d32","src/never.rs":"2066481ab04921269cfa768cb8b778a035ab6aa49ec404d9ac0aeb07a4bf6094","src/sink/buffer.rs":"33a7380f8232225a8e9ac5ee138fd095979efa3a64f9fecf5fcaf2e78fcbc355","src/sink/close.rs":"f2f31c884f048163abebd4f5a877b7b4306f7d02beae428325636fd00ed42ca9","src/sink/drain.rs":"60262bf3ef48c09b4d52e52953f9437d536e20f63690b73e975388751405d239","src/sink/err_into.rs":"ced2998b2b0b792d80f7543523c9e07e8f5d20a4336cae93084b995e46671b15","src/sink/fanout.rs":"66dcde056e0bbee4e0074d331838ed2743dc872ea1597f05d61970523dc34926","src/sink/feed.rs":"64b9d296d37aedde37e1421c459ebcd9a7e8814db905996996167850124f3b3f","src/sink/flush.rs":"fbba344f428ca7636541ba013f7db2ece480b404a9e0b421c5537552d61e2492","src/sink/map_err.rs":"0f68f444ef13fe7115164be855c3b7b1d269e1119e69fcdad1706988255641f1","src/sink/mod.rs":"37cf379170f3099992eb59f3181be4c4e4a5c2d3581dbe424d22ab360840d321","src/sink/send.rs":"56aaba9aa4a562e0af39473a5779206d91b0acb1fced4fc06cd8b959d1897524","src/sink/send_all.rs":"a8e4956604fe73e321b0a3896c2018bc5c27149f2862f8406112db140b3aa2dd","src/sink/unfold.rs":"74996cece1979ab72b8b79bb531cbb6c8f45ff24b952654ec523b4a29176716f","src/sink/with.rs":"d93889f5043fcd9909954f1dbfb11c33320006d9c00d226ebdb3853db80f402f","src/sink/with_flat_map.rs":"5e0f527b33ee8f1cc6a6a46d45b6d74dad5c735d88b2cb24e1cb34fdc6ef501b","src/stream/abortable.rs":"935d79aa44d793f4abe87ca27a9e4a20891500488cf942693cd2756d65b3aab2","src/stream/empty.rs":"5000c856186408a17f68bbef432d4a1a3edb7fb5a07ed8699342fef04b10a181","src/stream/futures_ordered.rs":"eadd4934fb4f3fbcb540dba1641b9e66278afa43baee406a96cb08bf29de9282","src/stream/futures_unordered/abort.rs":"bdfece9f91accafd5122be36d628c37c5b219ac0eecec181267840fbb1e95a45","src/stream/futures_unordered/iter.rs":"01f8aaa2ac7ea493bf727a945424cc6ae695c9a0c289ac57cbb26697abb05827","src/stream/futures_unordered/mod.rs":"2a7633ca39d21819565c921154a7b499abae5807924d02b6d5556a28e5a7483c","src/stream/futures_unordered/ready_to_run_queue.rs":"92102869386656494fa54f1a0d23a9291598dc8e62aaa17e6ada9b56ec94135b","src/stream/futures_unordered/task.rs":"617aad21eaafd9747cfda4796cc9184b2c60d20de94d7ea6baf3d858a52afe54","src/stream/iter.rs":"80cc232b90c0fc2e7c4ee2c1f40c61290756cc5325bf40427ea97b955c6ef41b","src/stream/mod.rs":"9a0f4428681bf447c3b34eab0de58322ca0f0ab8cf9e0daf0e761d3fc9346e5e","src/stream/once.rs":"d7b70adabad1f10af711ac3dcef33fd4c287e9852fdb678406e7ff350ba8fd47","src/stream/pending.rs":"84aaa15c8bbb17a250da5b1b5f0c7f6717410915d63340a3fcbf098bebe19d6f","src/stream/poll_fn.rs":"35952ea514b8aade14a3934d7777006475f50bbf0c5b50141710e31637f980be","src/stream/poll_immediate.rs":"e7a53ff8275ebe89dab8f9b984cce2ee0fde0a828e540b77c5500ca017d5bb98","src/stream/repeat.rs":"88a86074b7a817940b019ebbd397e104bd1849f4aa4e0aa08369af64ccc290b9","src/stream/repeat_with.rs":"823c9a7d3660c6f4fa4b48b331ecd03e38ea560d4b3f741ebb7890199d703411","src/stream/select.rs":"28eb422c0eca9fd02778a6003004471b3489db09746a70e617a506303ea8b81d","src/stream/select_all.rs":"19ef94abcf63fa9e46a73b6ab783642d2d069a015c7fa57fea36eeac7b6f2a20","src/stream/select_with_strategy.rs":"ef419a47980bd984600110afe20b8b1f581ae30210591326a11dc05e454df7b9","src/stream/stream/all.rs":"267a2cc251775fa0c60c6e41ae1e4a9611fc493be0fd1c3494ca75f24d60de51","src/stream/stream/any.rs":"a3eb3eecce02142b8eb95d0b8a62178f177c8152d63f52da5effbe3a4be45580","src/stream/stream/buffer_unordered.rs":"b0f7a1c72cee178e7bfd8990e6e426c1258eeba6d952b82c6be8e4cac0a054ea","src/stream/stream/buffered.rs":"e37d08d6a18090ba37079937575920cc8c7569f4183dba710d3f4b94c11da01b","src/stream/stream/catch_unwind.rs":"b9515b4013d28a99bbd84b2fa6ff4a050f74a10ff4ff0c33d717ea3461b6cb30","src/stream/stream/chain.rs":"809b6b5c8372f65341dc9810d39f60ae3bcf74a78f133b4ab8d289fb5f2a7cbb","src/stream/stream/chunks.rs":"9f872b473de14d2251584050f04d56eada9c3b1d8dc3e746bdd57c1f757bfc6f","src/stream/stream/collect.rs":"6e4d2d580189f7d3b6b294b6b17437e8e2570502f08c11786a71caac207f0309","src/stream/stream/concat.rs":"171ea941b45c0295ed978c3f318a449ea295e33cb4ea82c764f4e9e7c48ad5de","src/stream/stream/count.rs":"ff218aea3d2d2456c8163926ea0c357b2752e92578e5fd4bec6b789fe1246556","src/stream/stream/cycle.rs":"f8cc22b5a24e8726a5bfb71bf06c00dd974496982f89f6964952ab94e2d9f25a","src/stream/stream/enumerate.rs":"fc7565d21d39565790859eeac9ae8dd74123a9d15b88258d3abe894f1876cc39","src/stream/stream/filter.rs":"5d871f416d41baff3733121f564229fe31bdf7dfaaeb78ab940fafba6ab4b7c6","src/stream/stream/filter_map.rs":"179045a5ab1295e77ab5cfea1964be69dc50984ef8ac9ee04034adf0a043514f","src/stream/stream/flatten.rs":"69493fc106a1447abe109fd54375bb30363f7bc419463a8f835e4c80d97f2186","src/stream/stream/flatten_unordered.rs":"482c3dfa9034a665fbded6079c2ae280e4e42dd8221aca0f235541a9d715ce22","src/stream/stream/fold.rs":"75d61d4321db1bcbbdd1a0102d9ad60206275777167c008fc8953e50cd978a09","src/stream/stream/for_each.rs":"07bca889821bad18ff083e54abe679fbeb8cd19c086581c2f2722cba6b42263f","src/stream/stream/for_each_concurrent.rs":"4e1e7eb3d4ccfae0e8000651b75834e2960a7f9c62ab92dba35a0bdbbf5bbb21","src/stream/stream/forward.rs":"cd024ba1a3d5098d3ff2d5178a12e068916cc4307284b00c18dbc54b554a5560","src/stream/stream/fuse.rs":"061c5385f12f80c7906cb15ddb8f455ced6ce21d1de9a97de9db2616407c0cac","src/stream/stream/into_future.rs":"b46ad45cc03ddd778a9ffaa0d603c8ee0b411f49333100160959942cde9588bd","src/stream/stream/map.rs":"b91bdd5b33821a50c9b5034261a14f89ff1a9d541ab99b9d9a6921b12a5d434e","src/stream/stream/mod.rs":"c940b9c8793d23e4a971504bfccdb38c12f90ffa2e56003f43ed9c7216ab70e2","src/stream/stream/next.rs":"7b4d5a22b5e00aa191ea82346bb1f392121cc68692864a8230e462d59e622928","src/stream/stream/peek.rs":"eddcef75db10335b30b9eaac39e366e9637f2f757bcf1cd59858528e4fff80b7","src/stream/stream/ready_chunks.rs":"7e17c49ff29c106c13a2ec13fb05f32ff048e482b47a157d3965bd03c38c01c2","src/stream/stream/scan.rs":"54489c8efef60dbf3c35ee803afee5c5ea7c364fb9b68939a04956e46febb856","src/stream/stream/select_next_some.rs":"0094eccc96cfe78d9b6d0a9bdb82cada8fb7929770a3ac00ffcb5441d7dc4f51","src/stream/stream/skip.rs":"61f7ec7fe25663d2c87cffaad19ed27eda032842edb8af731b521025b244f120","src/stream/stream/skip_while.rs":"6f114a3fa538bd479e4fa24d8aa0e0e0454613643a97c44242c5683ae7293b82","src/stream/stream/split.rs":"1f575a11cb0c286b06c2730c328c256a01b9b067609ed2ffd590f2b615c394b9","src/stream/stream/take.rs":"57d381b482c3d584c4c26b0e15941bc2ea58e3f39a2e5c74391a2ee7b825cc8c","src/stream/stream/take_until.rs":"0f1fa7d158192a5dee32392dfdd062c15dab6d246b0ca267e91aae490d7d7fdb","src/stream/stream/take_while.rs":"2f57a6e5b903c045da642e9a40eb19dabbc612a80a6ce8098df1a1973555f108","src/stream/stream/then.rs":"c995c6b0d9151927b26b10fba70e135dfc41224b969d1367dc8c11697218c1e9","src/stream/stream/unzip.rs":"e7beedc2192604e0091ac3d0265b487127a37c780198838f6419c21ef1b38df0","src/stream/stream/zip.rs":"3890b40daea00341fac6ac977de0b534d1ec7cdaabece44af5df2ca56026fe62","src/stream/try_stream/and_then.rs":"6f92b333955f5ec30fddf8e087e3f60ebf53a054769fc72c80bbccdf13a9431e","src/stream/try_stream/into_async_read.rs":"5b200c76ccb95460d94286ca8e63f5454940eb62b5f15aae998da48aa06fbffd","src/stream/try_stream/into_stream.rs":"4fee94e89956a42871fc4a0cdba7ae1b7d4265e884528799cd227c9dd851acce","src/stream/try_stream/mod.rs":"9f9ced9f2d64461744c91d70577ce400e563c459d6ce3d5bb8cc7d6d6c688016","src/stream/try_stream/or_else.rs":"473ca77e0e81a1a0834d2d882076b8823a5a3027b2d7d78f887be2d5edfd0de3","src/stream/try_stream/try_all.rs":"58a4c9abe3b2d6ad2debcfc09701bb828732c9d7edf2a42f12a74beff5ae2db0","src/stream/try_stream/try_any.rs":"822f21af5cb27b1269046af076415216fdfc9e0b9fd877cb6e7d65c69d659471","src/stream/try_stream/try_buffer_unordered.rs":"64e698ea6aefbe7e32d48e737553b20b9cde5c258963bb20486b48b7d6899660","src/stream/try_stream/try_buffered.rs":"38f60d7290f44471a02084c6b394b754c224a84ee8d2ba01c08568168b48a21f","src/stream/try_stream/try_chunks.rs":"69c4d85a256250d73c6372d8047e6055da7eac918cb5d7ef4f3697898f4dcb4c","src/stream/try_stream/try_collect.rs":"979920e3034dad6c75961e3f6b4c0234691db7063eca1a05562cc5d41f2943c1","src/stream/try_stream/try_concat.rs":"f2330ebeeab30273e9ac0e8600bfe2f405ce671f6386e688b3afb1d2fdd7c2c6","src/stream/try_stream/try_filter.rs":"1344e9aea05e2d0078f30caff176a99e1ccb8fcdf0a287817abc82fbaf09c48b","src/stream/try_stream/try_filter_map.rs":"285e7ea875a3ea3e16942c1b1acae5a1cb26b9bac476dce3903547cb99306602","src/stream/try_stream/try_flatten.rs":"e05614d86a27ab8386476eea35fd424c07e5f7f99cf0401d63a6655eb7ca1247","src/stream/try_stream/try_flatten_unordered.rs":"1cc4c4a5ea0a8db3010958f34fb1886dcfbd2e1584082d2004030eb70b13cd6c","src/stream/try_stream/try_fold.rs":"b96aa2fe1a16f625d5045028a86ff8684dcf5198ef8c7c072f52f39aeaa8b619","src/stream/try_stream/try_for_each.rs":"3f3901d618333b740d470eb02fcbb645df92483493872298bb7bd0382646028a","src/stream/try_stream/try_for_each_concurrent.rs":"db1ca85cc658a754076546edf9891c2427f41a3f12fb19cd63cdb4d794a28758","src/stream/try_stream/try_next.rs":"6e29473153db1435906e79f7eaa13ce9da842d4528ba9eb1c0034665feacc565","src/stream/try_stream/try_ready_chunks.rs":"e8a658f5e48bb5c12b59998adbc5534f7eb830d0a60b53c0a3acd945752166fd","src/stream/try_stream/try_skip_while.rs":"7c2fa31fe8b0b4e59c5d7f2972c8d9f83e8f01a687b08f5cd631f92a14b402f1","src/stream/try_stream/try_take_while.rs":"2783664637aff0442f0c9204d35600139c941332310f70495cbc4dc345cae99d","src/stream/try_stream/try_unfold.rs":"aaf0f4857a4ec8233ac842ae509f29e5a210827a0bb40cfc0dc3e858f153d2b4","src/stream/unfold.rs":"201428f3dfcd10c556367d9aa87c4ae20fc9db6396380674b3b8c43b5d2a307e","src/task/mod.rs":"781f6d7d2484d6bd88ef9533d5c4729eeb8d4ee9bb8b9f4bad7049a78e190c32","src/task/spawn.rs":"8ff3a3652d8d2cb45717324b6ead9c3f111629e7eb0c0b33d3639a0e7c5bbf3e","src/unfold_state.rs":"3e2ffb91c3db8d938af7365da4b91dc6ef6eb21c5a26bfbb4a4a882e4d2c28bc"},"package":"389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-util/.cargo_vcs_info.json b/anneal/v2/vendor/futures-util/.cargo_vcs_info.json new file mode 100644 index 0000000000..6a7bd96dfd --- /dev/null +++ b/anneal/v2/vendor/futures-util/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d9bba94c239daa1175a5bb2958f37a5c72db3f6a" + }, + "path_in_vcs": "futures-util" +} \ No newline at end of file diff --git a/anneal/v2/vendor/futures-util/Cargo.lock b/anneal/v2/vendor/futures-util/Cargo.lock new file mode 100644 index 0000000000..e13207af84 --- /dev/null +++ b/anneal/v2/vendor/futures-util/Cargo.lock @@ -0,0 +1,693 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "portable-atomic 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.32" +dependencies = [ + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-ident 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum autocfg 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +"checksum bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +"checksum byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum crossbeam-deque 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" +"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +"checksum crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" +"checksum futures-channel 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +"checksum futures-core 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +"checksum futures-io 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +"checksum futures-macro 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +"checksum futures-sink 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +"checksum futures-task 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +"checksum hermit-abi 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +"checksum libc 0.2.175 (registry+https://github.com/rust-lang/crates.io-index)" = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +"checksum lock_api 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +"checksum log 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +"checksum memchr 2.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +"checksum memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +"checksum mio 0.6.23 (registry+https://github.com/rust-lang/crates.io-index)" = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +"checksum mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +"checksum miow 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +"checksum net2 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +"checksum num_cpus 1.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" +"checksum pin-project-lite 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +"checksum portable-atomic 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +"checksum proc-macro2 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +"checksum quote 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +"checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scopeguard 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum slab 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +"checksum smallvec 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +"checksum spin 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +"checksum syn 2.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +"checksum tokio-uds 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +"checksum unicode-ident 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/anneal/v2/vendor/futures-util/Cargo.toml b/anneal/v2/vendor/futures-util/Cargo.toml new file mode 100644 index 0000000000..e4ad37caa9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/Cargo.toml @@ -0,0 +1,181 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.71" +name = "futures-util" +version = "0.3.32" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Common utilities and extension traits for the futures-rs library. +""" +homepage = "https://rust-lang.github.io/futures-rs" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +alloc = [ + "futures-core/alloc", + "futures-task/alloc", + "slab", +] +async-await = [] +async-await-macro = [ + "async-await", + "futures-macro", +] +bilock = [] +cfg-target-has-atomic = [] +channel = [ + "std", + "futures-channel", +] +compat = [ + "std", + "futures_01", + "libc", +] +default = [ + "std", + "async-await", + "async-await-macro", +] +io = [ + "std", + "futures-io", + "memchr", +] +io-compat = [ + "io", + "compat", + "tokio-io", + "libc", +] +portable-atomic = ["futures-core/portable-atomic"] +sink = ["futures-sink"] +std = [ + "alloc", + "futures-core/std", + "futures-task/std", + "slab/std", +] +unstable = [ + "futures-core/unstable", + "futures-task/unstable", +] +write-all-vectored = ["io"] + +[lib] +name = "futures_util" +path = "src/lib.rs" + +[[bench]] +name = "bilock" +path = "benches/bilock.rs" + +[[bench]] +name = "flatten_unordered" +path = "benches/flatten_unordered.rs" + +[[bench]] +name = "futures_unordered" +path = "benches/futures_unordered.rs" + +[[bench]] +name = "select" +path = "benches/select.rs" + +[dependencies.futures-channel] +version = "0.3.32" +features = ["std"] +optional = true +default-features = false + +[dependencies.futures-core] +version = "0.3.32" +default-features = false + +[dependencies.futures-io] +version = "0.3.32" +features = ["std"] +optional = true +default-features = false + +[dependencies.futures-macro] +version = "=0.3.32" +optional = true +default-features = false + +[dependencies.futures-sink] +version = "0.3.32" +optional = true +default-features = false + +[dependencies.futures-task] +version = "0.3.32" +default-features = false + +[dependencies.futures_01] +version = "0.1.25" +optional = true +package = "futures" + +[dependencies.libc] +version = "0.2.26" +optional = true + +[dependencies.memchr] +version = "2.2" +optional = true + +[dependencies.pin-project-lite] +version = "0.2.6" + +[dependencies.slab] +version = "0.4.7" +optional = true +default-features = false + +[dependencies.spin] +version = "0.10.0" +optional = true + +[dependencies.tokio-io] +version = "0.1.9" +optional = true + +[dev-dependencies.tokio] +version = "0.1.11" + +[lints.rust] +missing_debug_implementations = "warn" +rust_2018_idioms = "warn" +single_use_lifetimes = "warn" +unreachable_pub = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(futures_sanitizer)"] diff --git a/anneal/v2/vendor/futures-util/Cargo.toml.orig b/anneal/v2/vendor/futures-util/Cargo.toml.orig new file mode 100644 index 0000000000..7915dfa120 --- /dev/null +++ b/anneal/v2/vendor/futures-util/Cargo.toml.orig @@ -0,0 +1,65 @@ +[package] +name = "futures-util" +version = "0.3.32" +edition = "2018" +# NB: Sync with "Usage" section in README.md and util-msrv job in .github/workflows/ci.yml +rust-version = "1.71" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/futures-rs" +homepage = "https://rust-lang.github.io/futures-rs" +description = """ +Common utilities and extension traits for the futures-rs library. +""" + +[features] +default = ["std", "async-await", "async-await-macro"] +std = ["alloc", "futures-core/std", "futures-task/std", "slab/std"] +alloc = ["futures-core/alloc", "futures-task/alloc", "slab"] +async-await = [] +async-await-macro = ["async-await", "futures-macro"] +compat = ["std", "futures_01", "libc"] +io-compat = ["io", "compat", "tokio-io", "libc"] +sink = ["futures-sink"] +io = ["std", "futures-io", "memchr"] +channel = ["std", "futures-channel"] +portable-atomic = ["futures-core/portable-atomic"] + +# Unstable features +# These features are outside of the normal semver guarantees and require the +# `unstable` feature as an explicit opt-in to unstable API. +unstable = ["futures-core/unstable", "futures-task/unstable"] +bilock = [] +write-all-vectored = ["io"] + +# These features are no longer used. +# TODO: remove in the next major version. +cfg-target-has-atomic = [] + +[dependencies] +futures-core = { path = "../futures-core", version = "0.3.32", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.32", default-features = false } +futures-channel = { path = "../futures-channel", version = "0.3.32", default-features = false, features = ["std"], optional = true } +futures-io = { path = "../futures-io", version = "0.3.32", default-features = false, features = ["std"], optional = true } +futures-sink = { path = "../futures-sink", version = "0.3.32", default-features = false, optional = true } +futures-macro = { path = "../futures-macro", version = "=0.3.32", default-features = false, optional = true } +slab = { version = "0.4.7", default-features = false, optional = true } +memchr = { version = "2.2", optional = true } +futures_01 = { version = "0.1.25", optional = true, package = "futures" } +tokio-io = { version = "0.1.9", optional = true } +pin-project-lite = "0.2.6" +spin = { version = "0.10.0", optional = true } + +# INDIRECT DEPENDENCYS BUT ONLY FOR SPECIFIC MINIMAL VERSIONS +libc = { version = "0.2.26", optional = true } + +[dev-dependencies] +futures = { path = "../futures", features = ["async-await", "thread-pool"] } +futures-test = { path = "../futures-test" } +tokio = "0.1.11" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true diff --git a/anneal/v2/vendor/futures-util/LICENSE-APACHE b/anneal/v2/vendor/futures-util/LICENSE-APACHE new file mode 100644 index 0000000000..9eb0b097f5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/futures-util/LICENSE-MIT b/anneal/v2/vendor/futures-util/LICENSE-MIT new file mode 100644 index 0000000000..8ad082ec4f --- /dev/null +++ b/anneal/v2/vendor/futures-util/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/futures-util/README.md b/anneal/v2/vendor/futures-util/README.md new file mode 100644 index 0000000000..91d98c8f89 --- /dev/null +++ b/anneal/v2/vendor/futures-util/README.md @@ -0,0 +1,23 @@ +# futures-util + +Common utilities and extension traits for the futures-rs library. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +futures-util = "0.3" +``` + +The current `futures-util` requires Rust 1.71 or later. + +## License + +Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or +[MIT license](LICENSE-MIT) at your option. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/futures-util/benches/bilock.rs b/anneal/v2/vendor/futures-util/benches/bilock.rs new file mode 100644 index 0000000000..013f3351e4 --- /dev/null +++ b/anneal/v2/vendor/futures-util/benches/bilock.rs @@ -0,0 +1,68 @@ +#![feature(test)] +#![cfg(feature = "bilock")] + +extern crate test; + +use futures::task::Poll; +use futures_test::task::noop_context; +use futures_util::lock::BiLock; + +use crate::test::Bencher; + +#[bench] +fn contended(b: &mut Bencher) { + let mut context = noop_context(); + + b.iter(|| { + let (x, y) = BiLock::new(1); + + for _ in 0..1000 { + let x_guard = match x.poll_lock(&mut context) { + Poll::Ready(guard) => guard, + _ => panic!(), + }; + + // Try poll second lock while first lock still holds the lock + match y.poll_lock(&mut context) { + Poll::Pending => (), + _ => panic!(), + }; + + drop(x_guard); + + let y_guard = match y.poll_lock(&mut context) { + Poll::Ready(guard) => guard, + _ => panic!(), + }; + + drop(y_guard); + } + (x, y) + }); +} + +#[bench] +fn lock_unlock(b: &mut Bencher) { + let mut context = noop_context(); + + b.iter(|| { + let (x, y) = BiLock::new(1); + + for _ in 0..1000 { + let x_guard = match x.poll_lock(&mut context) { + Poll::Ready(guard) => guard, + _ => panic!(), + }; + + drop(x_guard); + + let y_guard = match y.poll_lock(&mut context) { + Poll::Ready(guard) => guard, + _ => panic!(), + }; + + drop(y_guard); + } + (x, y) + }) +} diff --git a/anneal/v2/vendor/futures-util/benches/flatten_unordered.rs b/anneal/v2/vendor/futures-util/benches/flatten_unordered.rs new file mode 100644 index 0000000000..517b2816c3 --- /dev/null +++ b/anneal/v2/vendor/futures-util/benches/flatten_unordered.rs @@ -0,0 +1,58 @@ +#![feature(test)] + +extern crate test; +use crate::test::Bencher; + +use futures::channel::oneshot; +use futures::executor::block_on; +use futures::future; +use futures::stream::{self, StreamExt}; +use futures::task::Poll; +use futures_util::FutureExt; +use std::collections::VecDeque; +use std::thread; + +#[bench] +fn oneshot_streams(b: &mut Bencher) { + const STREAM_COUNT: usize = 10_000; + const STREAM_ITEM_COUNT: usize = 1; + + b.iter(|| { + let mut txs = VecDeque::with_capacity(STREAM_COUNT); + let mut rxs = Vec::new(); + + for _ in 0..STREAM_COUNT { + let (tx, rx) = oneshot::channel(); + txs.push_back(tx); + rxs.push(rx); + } + + thread::spawn(move || { + let mut last = 1; + while let Some(tx) = txs.pop_front() { + let _ = tx.send(stream::iter(last..last + STREAM_ITEM_COUNT)); + last += STREAM_ITEM_COUNT; + } + }); + + let mut flatten = stream::iter(rxs) + .map(|recv| recv.into_stream().map(|val| val.unwrap()).flatten()) + .flatten_unordered(None); + + block_on(future::poll_fn(move |cx| { + let mut count = 0; + loop { + match flatten.poll_next_unpin(cx) { + Poll::Ready(None) => break, + Poll::Ready(Some(_)) => { + count += 1; + } + _ => {} + } + } + assert_eq!(count, STREAM_COUNT * STREAM_ITEM_COUNT); + + Poll::Ready(()) + })) + }); +} diff --git a/anneal/v2/vendor/futures-util/benches/futures_unordered.rs b/anneal/v2/vendor/futures-util/benches/futures_unordered.rs new file mode 100644 index 0000000000..d5fe7a59de --- /dev/null +++ b/anneal/v2/vendor/futures-util/benches/futures_unordered.rs @@ -0,0 +1,43 @@ +#![feature(test)] + +extern crate test; +use crate::test::Bencher; + +use futures::channel::oneshot; +use futures::executor::block_on; +use futures::future; +use futures::stream::{FuturesUnordered, StreamExt}; +use futures::task::Poll; +use std::collections::VecDeque; +use std::thread; + +#[bench] +fn oneshots(b: &mut Bencher) { + const NUM: usize = 10_000; + + b.iter(|| { + let mut txs = VecDeque::with_capacity(NUM); + let mut rxs = FuturesUnordered::new(); + + for _ in 0..NUM { + let (tx, rx) = oneshot::channel(); + txs.push_back(tx); + rxs.push(rx); + } + + thread::spawn(move || { + while let Some(tx) = txs.pop_front() { + let _ = tx.send("hello"); + } + }); + + block_on(future::poll_fn(move |cx| { + loop { + if let Poll::Ready(None) = rxs.poll_next_unpin(cx) { + break; + } + } + Poll::Ready(()) + })) + }); +} diff --git a/anneal/v2/vendor/futures-util/benches/select.rs b/anneal/v2/vendor/futures-util/benches/select.rs new file mode 100644 index 0000000000..5410a95299 --- /dev/null +++ b/anneal/v2/vendor/futures-util/benches/select.rs @@ -0,0 +1,35 @@ +#![feature(test)] + +extern crate test; +use crate::test::Bencher; + +use futures::executor::block_on; +use futures::stream::{repeat, select, StreamExt}; + +#[bench] +fn select_streams(b: &mut Bencher) { + const STREAM_COUNT: usize = 10_000; + + b.iter(|| { + let stream1 = repeat(1).take(STREAM_COUNT); + let stream2 = repeat(2).take(STREAM_COUNT); + let stream3 = repeat(3).take(STREAM_COUNT); + let stream4 = repeat(4).take(STREAM_COUNT); + let stream5 = repeat(5).take(STREAM_COUNT); + let stream6 = repeat(6).take(STREAM_COUNT); + let stream7 = repeat(7).take(STREAM_COUNT); + let count = block_on(async { + let count = select( + stream1, + select( + stream2, + select(stream3, select(stream4, select(stream5, select(stream6, stream7)))), + ), + ) + .count() + .await; + count + }); + assert_eq!(count, STREAM_COUNT * 7); + }); +} diff --git a/anneal/v2/vendor/futures-util/src/abortable.rs b/anneal/v2/vendor/futures-util/src/abortable.rs new file mode 100644 index 0000000000..e1e79e371d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/abortable.rs @@ -0,0 +1,209 @@ +use crate::task::AtomicWaker; +use alloc::sync::Arc; +use core::fmt; +use core::pin::Pin; +use core::sync::atomic::{AtomicBool, Ordering}; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_core::Stream; +use pin_project_lite::pin_project; + +pin_project! { + /// A future/stream which can be remotely short-circuited using an `AbortHandle`. + #[derive(Debug, Clone)] + #[must_use = "futures/streams do nothing unless you poll them"] + pub struct Abortable { + #[pin] + task: T, + inner: Arc, + } +} + +impl Abortable { + /// Creates a new `Abortable` future/stream using an existing `AbortRegistration`. + /// `AbortRegistration`s can be acquired through `AbortHandle::new`. + /// + /// When `abort` is called on the handle tied to `reg` or if `abort` has + /// already been called, the future/stream will complete immediately without making + /// any further progress. + /// + /// # Examples: + /// + /// Usage with futures: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::{Abortable, AbortHandle, Aborted}; + /// + /// let (abort_handle, abort_registration) = AbortHandle::new_pair(); + /// let future = Abortable::new(async { 2 }, abort_registration); + /// abort_handle.abort(); + /// assert_eq!(future.await, Err(Aborted)); + /// # }); + /// ``` + /// + /// Usage with streams: + /// + /// ``` + /// # futures::executor::block_on(async { + /// # use futures::future::{Abortable, AbortHandle}; + /// # use futures::stream::{self, StreamExt}; + /// + /// let (abort_handle, abort_registration) = AbortHandle::new_pair(); + /// let mut stream = Abortable::new(stream::iter(vec![1, 2, 3]), abort_registration); + /// abort_handle.abort(); + /// assert_eq!(stream.next().await, None); + /// # }); + /// ``` + pub fn new(task: T, reg: AbortRegistration) -> Self { + Self { task, inner: reg.inner } + } + + /// Checks whether the task has been aborted. Note that all this + /// method indicates is whether [`AbortHandle::abort`] was *called*. + /// This means that it will return `true` even if: + /// * `abort` was called after the task had completed. + /// * `abort` was called while the task was being polled - the task may still be running and + /// will not be stopped until `poll` returns. + pub fn is_aborted(&self) -> bool { + self.inner.aborted.load(Ordering::Relaxed) + } +} + +/// A registration handle for an `Abortable` task. +/// Values of this type can be acquired from `AbortHandle::new` and are used +/// in calls to `Abortable::new`. +#[derive(Debug)] +pub struct AbortRegistration { + pub(crate) inner: Arc, +} + +impl AbortRegistration { + /// Create an [`AbortHandle`] from the given [`AbortRegistration`]. + /// + /// The created [`AbortHandle`] is functionally the same as any other + /// [`AbortHandle`]s that are associated with the same [`AbortRegistration`], + /// such as the one created by [`AbortHandle::new_pair`]. + pub fn handle(&self) -> AbortHandle { + AbortHandle { inner: self.inner.clone() } + } +} + +/// A handle to an `Abortable` task. +#[derive(Debug, Clone)] +pub struct AbortHandle { + inner: Arc, +} + +impl AbortHandle { + /// Creates an (`AbortHandle`, `AbortRegistration`) pair which can be used + /// to abort a running future or stream. + /// + /// This function is usually paired with a call to [`Abortable::new`]. + pub fn new_pair() -> (Self, AbortRegistration) { + let inner = + Arc::new(AbortInner { waker: AtomicWaker::new(), aborted: AtomicBool::new(false) }); + + (Self { inner: inner.clone() }, AbortRegistration { inner }) + } +} + +// Inner type storing the waker to awaken and a bool indicating that it +// should be aborted. +#[derive(Debug)] +pub(crate) struct AbortInner { + pub(crate) waker: AtomicWaker, + pub(crate) aborted: AtomicBool, +} + +/// Indicator that the `Abortable` task was aborted. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct Aborted; + +impl fmt::Display for Aborted { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "`Abortable` future has been aborted") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Aborted {} + +impl Abortable { + fn try_poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + poll: impl Fn(Pin<&mut T>, &mut Context<'_>) -> Poll, + ) -> Poll> { + // Check if the task has been aborted + if self.is_aborted() { + return Poll::Ready(Err(Aborted)); + } + + // attempt to complete the task + if let Poll::Ready(x) = poll(self.as_mut().project().task, cx) { + return Poll::Ready(Ok(x)); + } + + // Register to receive a wakeup if the task is aborted in the future + self.inner.waker.register(cx.waker()); + + // Check to see if the task was aborted between the first check and + // registration. + // Checking with `is_aborted` which uses `Relaxed` is sufficient because + // `register` introduces an `AcqRel` barrier. + if self.is_aborted() { + return Poll::Ready(Err(Aborted)); + } + + Poll::Pending + } +} + +impl Future for Abortable +where + Fut: Future, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.try_poll(cx, |fut, cx| fut.poll(cx)) + } +} + +impl Stream for Abortable +where + St: Stream, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.try_poll(cx, |stream, cx| stream.poll_next(cx)).map(Result::ok).map(Option::flatten) + } +} + +impl AbortHandle { + /// Abort the `Abortable` stream/future associated with this handle. + /// + /// Notifies the Abortable task associated with this handle that it + /// should abort. Note that if the task is currently being polled on + /// another thread, it will not immediately stop running. Instead, it will + /// continue to run until its poll method returns. + pub fn abort(&self) { + self.inner.aborted.store(true, Ordering::Relaxed); + self.inner.waker.wake(); + } + + /// Checks whether [`AbortHandle::abort`] was *called* on any associated + /// [`AbortHandle`]s, which includes all the [`AbortHandle`]s linked with + /// the same [`AbortRegistration`]. This means that it will return `true` + /// even if: + /// * `abort` was called after the task had completed. + /// * `abort` was called while the task was being polled - the task may still be running and + /// will not be stopped until `poll` returns. + /// + /// This operation has a Relaxed ordering. + pub fn is_aborted(&self) -> bool { + self.inner.aborted.load(Ordering::Relaxed) + } +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/join_mod.rs b/anneal/v2/vendor/futures-util/src/async_await/join_mod.rs new file mode 100644 index 0000000000..28f3b232e7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/join_mod.rs @@ -0,0 +1,110 @@ +//! The `join` macro. + +macro_rules! document_join_macro { + ($join:item $try_join:item) => { + /// Polls multiple futures simultaneously, returning a tuple + /// of all results once complete. + /// + /// While `join!(a, b)` is similar to `(a.await, b.await)`, + /// `join!` polls both futures concurrently and therefore is more efficient. + /// + /// This macro is only usable inside of async functions, closures, and blocks. + /// It is also gated behind the `async-await` feature of this library, which is + /// activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::join; + /// + /// let a = async { 1 }; + /// let b = async { 2 }; + /// assert_eq!(join!(a, b), (1, 2)); + /// + /// // `join!` is variadic, so you can pass any number of futures + /// let c = async { 3 }; + /// let d = async { 4 }; + /// let e = async { 5 }; + /// assert_eq!(join!(c, d, e), (3, 4, 5)); + /// # }); + /// ``` + $join + + /// Polls multiple futures simultaneously, resolving to a [`Result`] containing + /// either a tuple of the successful outputs or an error. + /// + /// `try_join!` is similar to [`join!`], but completes immediately if any of + /// the futures return an error. + /// + /// This macro is only usable inside of async functions, closures, and blocks. + /// It is also gated behind the `async-await` feature of this library, which is + /// activated by default. + /// + /// # Examples + /// + /// When used on multiple futures that return `Ok`, `try_join!` will return + /// `Ok` of a tuple of the values: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::try_join; + /// + /// let a = async { Ok::(1) }; + /// let b = async { Ok::(2) }; + /// assert_eq!(try_join!(a, b), Ok((1, 2))); + /// + /// // `try_join!` is variadic, so you can pass any number of futures + /// let c = async { Ok::(3) }; + /// let d = async { Ok::(4) }; + /// let e = async { Ok::(5) }; + /// assert_eq!(try_join!(c, d, e), Ok((3, 4, 5))); + /// # }); + /// ``` + /// + /// If one of the futures resolves to an error, `try_join!` will return + /// that error: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::try_join; + /// + /// let a = async { Ok::(1) }; + /// let b = async { Err::(2) }; + /// + /// assert_eq!(try_join!(a, b), Err(2)); + /// # }); + /// ``` + $try_join + } +} + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub use futures_macro::join_internal; + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub use futures_macro::try_join_internal; + +document_join_macro! { + #[macro_export] + macro_rules! join { + ($($tokens:tt)*) => {{ + use $crate::__private as __futures_crate; + $crate::join_internal! { + $( $tokens )* + } + }} + } + + #[macro_export] + macro_rules! try_join { + ($($tokens:tt)*) => {{ + use $crate::__private as __futures_crate; + $crate::try_join_internal! { + $( $tokens )* + } + }} + } +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/mod.rs b/anneal/v2/vendor/futures-util/src/async_await/mod.rs new file mode 100644 index 0000000000..7e3f12c99f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/mod.rs @@ -0,0 +1,60 @@ +//! Await +//! +//! This module contains a number of functions and combinators for working +//! with `async`/`await` code. + +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::{FusedStream, Stream}; + +#[macro_use] +mod poll; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +pub use self::poll::*; + +#[macro_use] +mod pending; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +pub use self::pending::*; + +// Primary export is a macro +#[cfg(feature = "async-await-macro")] +mod join_mod; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +#[cfg(feature = "async-await-macro")] +pub use self::join_mod::*; + +// Primary export is a macro +#[cfg(feature = "async-await-macro")] +mod select_mod; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +#[cfg(feature = "async-await-macro")] +pub use self::select_mod::*; + +// Primary export is a macro +#[cfg(feature = "std")] +#[cfg(feature = "async-await-macro")] +mod stream_select_mod; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +#[cfg(feature = "std")] +#[cfg(feature = "async-await-macro")] +pub use self::stream_select_mod::*; + +#[cfg(feature = "std")] +#[cfg(feature = "async-await-macro")] +mod random; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762 +#[cfg(feature = "std")] +#[cfg(feature = "async-await-macro")] +pub use self::random::*; + +#[doc(hidden)] +#[inline(always)] +pub fn assert_unpin(_: &T) {} + +#[doc(hidden)] +#[inline(always)] +pub fn assert_fused_future(_: &T) {} + +#[doc(hidden)] +#[inline(always)] +pub fn assert_fused_stream(_: &T) {} diff --git a/anneal/v2/vendor/futures-util/src/async_await/pending.rs b/anneal/v2/vendor/futures-util/src/async_await/pending.rs new file mode 100644 index 0000000000..5d7a431811 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/pending.rs @@ -0,0 +1,43 @@ +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; + +/// A macro which yields to the event loop once. +/// +/// This is equivalent to returning [`Poll::Pending`](futures_core::task::Poll) +/// from a [`Future::poll`](futures_core::future::Future::poll) implementation. +/// Similarly, when using this macro, it must be ensured that [`wake`](std::task::Waker::wake) +/// is called somewhere when further progress can be made. +/// +/// This macro is only usable inside of async functions, closures, and blocks. +/// It is also gated behind the `async-await` feature of this library, which is +/// activated by default. +#[macro_export] +macro_rules! pending { + () => { + $crate::__private::async_await::pending_once().await + }; +} + +#[doc(hidden)] +pub fn pending_once() -> PendingOnce { + PendingOnce { is_ready: false } +} + +#[allow(missing_debug_implementations)] +#[doc(hidden)] +pub struct PendingOnce { + is_ready: bool, +} + +impl Future for PendingOnce { + type Output = (); + fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + if self.is_ready { + Poll::Ready(()) + } else { + self.is_ready = true; + Poll::Pending + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/poll.rs b/anneal/v2/vendor/futures-util/src/async_await/poll.rs new file mode 100644 index 0000000000..b62f45a943 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/poll.rs @@ -0,0 +1,39 @@ +use crate::future::FutureExt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; + +/// A macro which returns the result of polling a future once within the +/// current `async` context. +/// +/// This macro is only usable inside of `async` functions, closures, and blocks. +/// It is also gated behind the `async-await` feature of this library, which is +/// activated by default. +/// +/// If you need the result of polling a [`Stream`](crate::stream::Stream), +/// you can use this macro with the [`next`](crate::stream::StreamExt::next) method: +/// `poll!(stream.next())`. +#[macro_export] +macro_rules! poll { + ($x:expr $(,)?) => { + $crate::__private::async_await::poll($x).await + }; +} + +#[doc(hidden)] +pub fn poll(future: F) -> PollOnce { + PollOnce { future } +} + +#[allow(missing_debug_implementations)] +#[doc(hidden)] +pub struct PollOnce { + future: F, +} + +impl Future for PollOnce { + type Output = Poll; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.future.poll_unpin(cx)) + } +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/random.rs b/anneal/v2/vendor/futures-util/src/async_await/random.rs new file mode 100644 index 0000000000..2ac2f78a87 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/random.rs @@ -0,0 +1,54 @@ +use std::{ + cell::Cell, + collections::hash_map::DefaultHasher, + hash::Hasher, + num::Wrapping, + sync::atomic::{AtomicUsize, Ordering}, +}; + +// Based on [Fisher–Yates shuffle]. +// +// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle +#[doc(hidden)] +pub fn shuffle(slice: &mut [T]) { + for i in (1..slice.len()).rev() { + slice.swap(i, gen_index(i + 1)); + } +} + +/// Return a value from `0..n`. +fn gen_index(n: usize) -> usize { + (random() % n as u64) as usize +} + +/// Pseudorandom number generator based on [xorshift*]. +/// +/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift* +fn random() -> u64 { + std::thread_local! { + static RNG: Cell> = Cell::new(Wrapping(prng_seed())); + } + + fn prng_seed() -> u64 { + static COUNTER: AtomicUsize = AtomicUsize::new(0); + + // Any non-zero seed will do + let mut seed = 0; + while seed == 0 { + let mut hasher = DefaultHasher::new(); + hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed)); + seed = hasher.finish(); + } + seed + } + + RNG.with(|rng| { + let mut x = rng.get(); + debug_assert_ne!(x.0, 0); + x ^= x >> 12; + x ^= x << 25; + x ^= x >> 27; + rng.set(x); + x.0.wrapping_mul(0x2545_f491_4f6c_dd1d) + }) +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/select_mod.rs b/anneal/v2/vendor/futures-util/src/async_await/select_mod.rs new file mode 100644 index 0000000000..a554a696e6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/select_mod.rs @@ -0,0 +1,340 @@ +//! The `select` macro. + +macro_rules! document_select_macro { + // This branch is required for `futures 0.3.1`, from before select_biased was introduced + ($select:item) => { + #[allow(clippy::too_long_first_doc_paragraph)] + /// Polls multiple futures and streams simultaneously, executing the branch + /// for the future that finishes first. If multiple futures are ready, + /// one will be pseudo-randomly selected at runtime. Futures directly + /// passed to `select!` must be `Unpin` and implement `FusedFuture`. + /// + /// If an expression which yields a `Future` is passed to `select!` + /// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin` + /// requirement is relaxed, since the macro will pin the resulting `Future` + /// on the stack. However the `Future` returned by the expression must + /// still implement `FusedFuture`. + /// + /// Futures and streams which are not already fused can be fused using the + /// `.fuse()` method. Note, though, that fusing a future or stream directly + /// in the call to `select!` will not be enough to prevent it from being + /// polled after completion if the `select!` call is in a loop, so when + /// `select!`ing in a loop, users should take care to `fuse()` outside of + /// the loop. + /// + /// `select!` can be used as an expression and will return the return + /// value of the selected branch. For this reason the return type of every + /// branch in a `select!` must be the same. + /// + /// This macro is only usable inside of async functions, closures, and blocks. + /// It is also gated behind the `async-await` feature of this library, which is + /// activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::select; + /// let mut a = future::ready(4); + /// let mut b = future::pending::<()>(); + /// + /// let res = select! { + /// a_res = a => a_res + 1, + /// _ = b => 0, + /// }; + /// assert_eq!(res, 5); + /// # }); + /// ``` + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// use futures::select; + /// let mut st = stream::iter(vec![2]).fuse(); + /// let mut fut = future::pending::<()>(); + /// + /// select! { + /// x = st.next() => assert_eq!(Some(2), x), + /// _ = fut => panic!(), + /// } + /// # }); + /// ``` + /// + /// As described earlier, `select` can directly select on expressions + /// which return `Future`s - even if those do not implement `Unpin`: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::select; + /// + /// // Calling the following async fn returns a Future which does not + /// // implement Unpin + /// async fn async_identity_fn(arg: usize) -> usize { + /// arg + /// } + /// + /// let res = select! { + /// a_res = async_identity_fn(62).fuse() => a_res + 1, + /// b_res = async_identity_fn(13).fuse() => b_res, + /// }; + /// assert!(res == 63 || res == 13); + /// # }); + /// ``` + /// + /// If a similar async function is called outside of `select` to produce + /// a `Future`, the `Future` must be pinned in order to be able to pass + /// it to `select`. This can be achieved via `Box::pin` for pinning a + /// `Future` on the heap or the `pin!` macro for pinning a `Future` + /// on the stack. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::future::FutureExt; + /// use futures::select; + /// + /// // Calling the following async fn returns a Future which does not + /// // implement Unpin + /// async fn async_identity_fn(arg: usize) -> usize { + /// arg + /// } + /// + /// let fut_1 = async_identity_fn(1).fuse(); + /// let fut_2 = async_identity_fn(2).fuse(); + /// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap + /// let mut fut_2 = pin!(fut_2); // Pins the Future on the stack + /// + /// let res = select! { + /// a_res = fut_1 => a_res, + /// b_res = fut_2 => b_res, + /// }; + /// assert!(res == 1 || res == 2); + /// # }); + /// ``` + /// + /// `select` also accepts a `complete` branch and a `default` branch. + /// `complete` will run if all futures and streams have already been + /// exhausted. `default` will run if no futures or streams are + /// immediately ready. `complete` takes priority over `default` in + /// the case where all futures have completed. + /// A motivating use-case for passing `Future`s by name as well as for + /// `complete` blocks is to call `select!` in a loop, which is + /// demonstrated in the following example: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::select; + /// let mut a_fut = future::ready(4); + /// let mut b_fut = future::ready(6); + /// let mut total = 0; + /// + /// loop { + /// select! { + /// a = a_fut => total += a, + /// b = b_fut => total += b, + /// complete => break, + /// default => panic!(), // never runs (futures run first, then complete) + /// } + /// } + /// assert_eq!(total, 10); + /// # }); + /// ``` + /// + /// Note that the futures that have been matched over can still be mutated + /// from inside the `select!` block's branches. This can be used to implement + /// more complex behavior such as timer resets or writing into the head of + /// a stream. + $select + }; + + ($select:item $select_biased:item) => { + document_select_macro!($select); + + #[allow(clippy::too_long_first_doc_paragraph)] + /// Polls multiple futures and streams simultaneously, executing the branch + /// for the future that finishes first. Unlike [`select!`], if multiple futures are ready, + /// one will be selected in order of declaration. Futures directly + /// passed to `select_biased!` must be `Unpin` and implement `FusedFuture`. + /// + /// If an expression which yields a `Future` is passed to `select_biased!` + /// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin` + /// requirement is relaxed, since the macro will pin the resulting `Future` + /// on the stack. However the `Future` returned by the expression must + /// still implement `FusedFuture`. + /// + /// Futures and streams which are not already fused can be fused using the + /// `.fuse()` method. Note, though, that fusing a future or stream directly + /// in the call to `select_biased!` will not be enough to prevent it from being + /// polled after completion if the `select_biased!` call is in a loop, so when + /// `select_biased!`ing in a loop, users should take care to `fuse()` outside of + /// the loop. + /// + /// `select_biased!` can be used as an expression and will return the return + /// value of the selected branch. For this reason the return type of every + /// branch in a `select_biased!` must be the same. + /// + /// This macro is only usable inside of async functions, closures, and blocks. + /// It is also gated behind the `async-await` feature of this library, which is + /// activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::select_biased; + /// let mut a = future::ready(4); + /// let mut b = future::pending::<()>(); + /// + /// let res = select_biased! { + /// a_res = a => a_res + 1, + /// _ = b => 0, + /// }; + /// assert_eq!(res, 5); + /// # }); + /// ``` + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// use futures::select_biased; + /// let mut st = stream::iter(vec![2]).fuse(); + /// let mut fut = future::pending::<()>(); + /// + /// select_biased! { + /// x = st.next() => assert_eq!(Some(2), x), + /// _ = fut => panic!(), + /// } + /// # }); + /// ``` + /// + /// As described earlier, `select_biased` can directly select on expressions + /// which return `Future`s - even if those do not implement `Unpin`: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::select_biased; + /// + /// // Calling the following async fn returns a Future which does not + /// // implement Unpin + /// async fn async_identity_fn(arg: usize) -> usize { + /// arg + /// } + /// + /// let res = select_biased! { + /// a_res = async_identity_fn(62).fuse() => a_res + 1, + /// b_res = async_identity_fn(13).fuse() => b_res, + /// }; + /// assert_eq!(res, 63); + /// # }); + /// ``` + /// + /// If a similar async function is called outside of `select_biased` to produce + /// a `Future`, the `Future` must be pinned in order to be able to pass + /// it to `select_biased`. This can be achieved via `Box::pin` for pinning a + /// `Future` on the heap or the `pin!` macro for pinning a `Future` + /// on the stack. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::future::FutureExt; + /// use futures::select_biased; + /// + /// // Calling the following async fn returns a Future which does not + /// // implement Unpin + /// async fn async_identity_fn(arg: usize) -> usize { + /// arg + /// } + /// + /// let fut_1 = async_identity_fn(1).fuse(); + /// let fut_2 = async_identity_fn(2).fuse(); + /// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap + /// let mut fut_2 = pin!(fut_2); // Pins the Future on the stack + /// + /// let res = select_biased! { + /// a_res = fut_1 => a_res, + /// b_res = fut_2 => b_res, + /// }; + /// assert!(res == 1 || res == 2); + /// # }); + /// ``` + /// + /// `select_biased` also accepts a `complete` branch and a `default` branch. + /// `complete` will run if all futures and streams have already been + /// exhausted. `default` will run if no futures or streams are + /// immediately ready. `complete` takes priority over `default` in + /// the case where all futures have completed. + /// A motivating use-case for passing `Future`s by name as well as for + /// `complete` blocks is to call `select_biased!` in a loop, which is + /// demonstrated in the following example: + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::select_biased; + /// let mut a_fut = future::ready(4); + /// let mut b_fut = future::ready(6); + /// let mut total = 0; + /// + /// loop { + /// select_biased! { + /// a = a_fut => total += a, + /// b = b_fut => total += b, + /// complete => break, + /// default => panic!(), // never runs (futures run first, then complete) + /// } + /// } + /// assert_eq!(total, 10); + /// # }); + /// ``` + /// + /// Note that the futures that have been matched over can still be mutated + /// from inside the `select_biased!` block's branches. This can be used to implement + /// more complex behavior such as timer resets or writing into the head of + /// a stream. + /// + /// [`select!`]: macro.select.html + $select_biased + }; +} + +#[cfg(feature = "std")] +#[allow(unreachable_pub)] +#[doc(hidden)] +pub use futures_macro::select_internal; + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub use futures_macro::select_biased_internal; + +document_select_macro! { + #[cfg(feature = "std")] + #[macro_export] + macro_rules! select { + ($($tokens:tt)*) => {{ + use $crate::__private as __futures_crate; + $crate::select_internal! { + $( $tokens )* + } + }} + } + + #[macro_export] + macro_rules! select_biased { + ($($tokens:tt)*) => {{ + use $crate::__private as __futures_crate; + $crate::select_biased_internal! { + $( $tokens )* + } + }} + } +} diff --git a/anneal/v2/vendor/futures-util/src/async_await/stream_select_mod.rs b/anneal/v2/vendor/futures-util/src/async_await/stream_select_mod.rs new file mode 100644 index 0000000000..c3e4f0052c --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/async_await/stream_select_mod.rs @@ -0,0 +1,39 @@ +//! The `stream_select` macro. + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub use futures_macro::stream_select_internal; + +#[allow(clippy::too_long_first_doc_paragraph)] +/// Combines several streams, all producing the same `Item` type, into one stream. +/// This is similar to `select_all` but does not require the streams to all be the same type. +/// It also keeps the streams inline, and does not require `Box`s to be allocated. +/// Streams passed to this macro must be `Unpin`. +/// +/// If multiple streams are ready, one will be pseudo randomly selected at runtime. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::{stream, StreamExt, stream_select}; +/// let endless_ints = |i| stream::iter(vec![i].into_iter().cycle()).fuse(); +/// +/// let mut endless_numbers = stream_select!(endless_ints(1i32), endless_ints(2), endless_ints(3)); +/// match endless_numbers.next().await { +/// Some(1) => println!("Got a 1"), +/// Some(2) => println!("Got a 2"), +/// Some(3) => println!("Got a 3"), +/// _ => unreachable!(), +/// } +/// # }); +/// ``` +#[macro_export] +macro_rules! stream_select { + ($($tokens:tt)*) => {{ + use $crate::__private as __futures_crate; + $crate::stream_select_internal! { + $( $tokens )* + } + }} +} diff --git a/anneal/v2/vendor/futures-util/src/compat/compat01as03.rs b/anneal/v2/vendor/futures-util/src/compat/compat01as03.rs new file mode 100644 index 0000000000..0de2d53301 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/compat/compat01as03.rs @@ -0,0 +1,455 @@ +use futures_01::executor::{ + spawn as spawn01, Notify as Notify01, NotifyHandle as NotifyHandle01, Spawn as Spawn01, + UnsafeNotify as UnsafeNotify01, +}; +use futures_01::{Async as Async01, Future as Future01, Stream as Stream01}; +#[cfg(feature = "sink")] +use futures_01::{AsyncSink as AsyncSink01, Sink as Sink01}; +use futures_core::{future::Future as Future03, stream::Stream as Stream03, task as task03}; +#[cfg(feature = "sink")] +use futures_sink::Sink as Sink03; +use std::boxed::Box; +use std::pin::Pin; +use std::task::Context; + +#[cfg(feature = "io-compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use io::{AsyncRead01CompatExt, AsyncWrite01CompatExt}; + +/// Converts a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite +/// object to a futures 0.3-compatible version, +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Compat01As03 { + pub(crate) inner: Spawn01, +} + +impl Unpin for Compat01As03 {} + +impl Compat01As03 { + /// Wraps a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite + /// object in a futures 0.3-compatible wrapper. + pub fn new(object: T) -> Self { + Self { inner: spawn01(object) } + } + + fn in_notify(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut T) -> R) -> R { + let notify = &WakerToHandle(cx.waker()); + self.inner.poll_fn_notify(notify, 0, f) + } + + /// Get a reference to 0.1 Future, Stream, AsyncRead, or AsyncWrite object contained within. + pub fn get_ref(&self) -> &T { + self.inner.get_ref() + } + + /// Get a mutable reference to 0.1 Future, Stream, AsyncRead or AsyncWrite object contained + /// within. + pub fn get_mut(&mut self) -> &mut T { + self.inner.get_mut() + } + + /// Consume this wrapper to return the underlying 0.1 Future, Stream, AsyncRead, or + /// AsyncWrite object. + pub fn into_inner(self) -> T { + self.inner.into_inner() + } +} + +/// Extension trait for futures 0.1 [`Future`](futures_01::future::Future) +pub trait Future01CompatExt: Future01 { + /// Converts a futures 0.1 + /// [`Future`](futures_01::future::Future) + /// into a futures 0.3 + /// [`Future>`](futures_core::future::Future). + /// + /// ``` + /// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514 + /// # futures::executor::block_on(async { + /// # // TODO: These should be all using `futures::compat`, but that runs up against Cargo + /// # // feature issues + /// use futures_util::compat::Future01CompatExt; + /// + /// let future = futures_01::future::ok::(1); + /// assert_eq!(future.compat().await, Ok(1)); + /// # }); + /// ``` + fn compat(self) -> Compat01As03 + where + Self: Sized, + { + Compat01As03::new(self) + } +} +impl Future01CompatExt for Fut {} + +/// Extension trait for futures 0.1 [`Stream`](futures_01::stream::Stream) +pub trait Stream01CompatExt: Stream01 { + /// Converts a futures 0.1 + /// [`Stream`](futures_01::stream::Stream) + /// into a futures 0.3 + /// [`Stream>`](futures_core::stream::Stream). + /// + /// ``` + /// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514 + /// # futures::executor::block_on(async { + /// use futures::stream::StreamExt; + /// use futures_util::compat::Stream01CompatExt; + /// + /// let stream = futures_01::stream::once::(Ok(1)); + /// let mut stream = stream.compat(); + /// assert_eq!(stream.next().await, Some(Ok(1))); + /// assert_eq!(stream.next().await, None); + /// # }); + /// ``` + fn compat(self) -> Compat01As03 + where + Self: Sized, + { + Compat01As03::new(self) + } +} +impl Stream01CompatExt for St {} + +/// Extension trait for futures 0.1 [`Sink`](futures_01::sink::Sink) +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub trait Sink01CompatExt: Sink01 { + /// Converts a futures 0.1 + /// [`Sink`](futures_01::sink::Sink) + /// into a futures 0.3 + /// [`Sink`](futures_sink::Sink). + /// + /// ``` + /// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514 + /// # futures::executor::block_on(async { + /// use futures::{sink::SinkExt, stream::StreamExt}; + /// use futures_util::compat::{Stream01CompatExt, Sink01CompatExt}; + /// + /// let (tx, rx) = futures_01::unsync::mpsc::channel(1); + /// let (mut tx, mut rx) = (tx.sink_compat(), rx.compat()); + /// + /// tx.send(1).await.unwrap(); + /// drop(tx); + /// assert_eq!(rx.next().await, Some(Ok(1))); + /// assert_eq!(rx.next().await, None); + /// # }); + /// ``` + fn sink_compat(self) -> Compat01As03Sink + where + Self: Sized, + { + Compat01As03Sink::new(self) + } +} +#[cfg(feature = "sink")] +impl Sink01CompatExt for Si {} + +fn poll_01_to_03(x: Result, E>) -> task03::Poll> { + match x? { + Async01::Ready(t) => task03::Poll::Ready(Ok(t)), + Async01::NotReady => task03::Poll::Pending, + } +} + +impl Future03 for Compat01As03 { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> task03::Poll { + poll_01_to_03(self.in_notify(cx, Future01::poll)) + } +} + +impl Stream03 for Compat01As03 { + type Item = Result; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + match self.in_notify(cx, Stream01::poll)? { + Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))), + Async01::Ready(None) => task03::Poll::Ready(None), + Async01::NotReady => task03::Poll::Pending, + } + } +} + +/// Converts a futures 0.1 Sink object to a futures 0.3-compatible version +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +#[derive(Debug)] +#[must_use = "sinks do nothing unless polled"] +pub struct Compat01As03Sink { + pub(crate) inner: Spawn01, + pub(crate) buffer: Option, + pub(crate) close_started: bool, +} + +#[cfg(feature = "sink")] +impl Unpin for Compat01As03Sink {} + +#[cfg(feature = "sink")] +impl Compat01As03Sink { + /// Wraps a futures 0.1 Sink object in a futures 0.3-compatible wrapper. + pub fn new(inner: S) -> Self { + Self { inner: spawn01(inner), buffer: None, close_started: false } + } + + fn in_notify(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut S) -> R) -> R { + let notify = &WakerToHandle(cx.waker()); + self.inner.poll_fn_notify(notify, 0, f) + } + + /// Get a reference to 0.1 Sink object contained within. + pub fn get_ref(&self) -> &S { + self.inner.get_ref() + } + + /// Get a mutable reference to 0.1 Sink contained within. + pub fn get_mut(&mut self) -> &mut S { + self.inner.get_mut() + } + + /// Consume this wrapper to return the underlying 0.1 Sink. + pub fn into_inner(self) -> S { + self.inner.into_inner() + } +} + +#[cfg(feature = "sink")] +impl Stream03 for Compat01As03Sink +where + S: Stream01, +{ + type Item = Result; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + match self.in_notify(cx, Stream01::poll)? { + Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))), + Async01::Ready(None) => task03::Poll::Ready(None), + Async01::NotReady => task03::Poll::Pending, + } + } +} + +#[cfg(feature = "sink")] +impl Sink03 for Compat01As03Sink +where + S: Sink01, +{ + type Error = S::SinkError; + + fn start_send(mut self: Pin<&mut Self>, item: SinkItem) -> Result<(), Self::Error> { + debug_assert!(self.buffer.is_none()); + self.buffer = Some(item); + Ok(()) + } + + fn poll_ready( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + match self.buffer.take() { + Some(item) => match self.in_notify(cx, |f| f.start_send(item))? { + AsyncSink01::Ready => task03::Poll::Ready(Ok(())), + AsyncSink01::NotReady(i) => { + self.buffer = Some(i); + task03::Poll::Pending + } + }, + None => task03::Poll::Ready(Ok(())), + } + } + + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + let item = self.buffer.take(); + match self.in_notify(cx, |f| match item { + Some(i) => match f.start_send(i)? { + AsyncSink01::Ready => f.poll_complete().map(|i| (i, None)), + AsyncSink01::NotReady(t) => Ok((Async01::NotReady, Some(t))), + }, + None => f.poll_complete().map(|i| (i, None)), + })? { + (Async01::Ready(_), _) => task03::Poll::Ready(Ok(())), + (Async01::NotReady, item) => { + self.buffer = item; + task03::Poll::Pending + } + } + } + + fn poll_close( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + let item = self.buffer.take(); + let close_started = self.close_started; + + let result = self.in_notify(cx, |f| { + if !close_started { + if let Some(item) = item { + if let AsyncSink01::NotReady(item) = f.start_send(item)? { + return Ok((Async01::NotReady, Some(item), false)); + } + } + + if let Async01::NotReady = f.poll_complete()? { + return Ok((Async01::NotReady, None, false)); + } + } + + Ok((::close(f)?, None, true)) + }); + + match result? { + (Async01::Ready(_), _, _) => task03::Poll::Ready(Ok(())), + (Async01::NotReady, item, close_started) => { + self.buffer = item; + self.close_started = close_started; + task03::Poll::Pending + } + } + } +} + +struct NotifyWaker(task03::Waker); + +#[allow(missing_debug_implementations)] // false positive: this is private type +#[derive(Clone)] +struct WakerToHandle<'a>(&'a task03::Waker); + +impl From> for NotifyHandle01 { + fn from(handle: WakerToHandle<'_>) -> Self { + let ptr = Box::new(NotifyWaker(handle.0.clone())); + + unsafe { Self::new(Box::into_raw(ptr)) } + } +} + +impl Notify01 for NotifyWaker { + fn notify(&self, _: usize) { + self.0.wake_by_ref(); + } +} + +unsafe impl UnsafeNotify01 for NotifyWaker { + unsafe fn clone_raw(&self) -> NotifyHandle01 { + WakerToHandle(&self.0).into() + } + + unsafe fn drop_raw(&self) { + let ptr: *const dyn UnsafeNotify01 = self; + drop(unsafe { Box::from_raw(ptr as *mut dyn UnsafeNotify01) }); + } +} + +#[cfg(feature = "io-compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] +mod io { + use super::*; + use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03}; + use std::io::Error; + use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01}; + + /// Extension trait for tokio-io [`AsyncRead`](tokio_io::AsyncRead) + #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] + pub trait AsyncRead01CompatExt: AsyncRead01 { + /// Converts a tokio-io [`AsyncRead`](tokio_io::AsyncRead) into a futures-io 0.3 + /// [`AsyncRead`](futures_io::AsyncRead). + /// + /// ``` + /// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514 + /// # futures::executor::block_on(async { + /// use futures::io::AsyncReadExt; + /// use futures_util::compat::AsyncRead01CompatExt; + /// + /// let input = b"Hello World!"; + /// let reader /* : impl tokio_io::AsyncRead */ = std::io::Cursor::new(input); + /// let mut reader /* : impl futures::io::AsyncRead + Unpin */ = reader.compat(); + /// + /// let mut output = Vec::with_capacity(12); + /// reader.read_to_end(&mut output).await.unwrap(); + /// assert_eq!(output, input); + /// # }); + /// ``` + fn compat(self) -> Compat01As03 + where + Self: Sized, + { + Compat01As03::new(self) + } + } + impl AsyncRead01CompatExt for R {} + + /// Extension trait for tokio-io [`AsyncWrite`](tokio_io::AsyncWrite) + #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] + pub trait AsyncWrite01CompatExt: AsyncWrite01 { + /// Converts a tokio-io [`AsyncWrite`](tokio_io::AsyncWrite) into a futures-io 0.3 + /// [`AsyncWrite`](futures_io::AsyncWrite). + /// + /// ``` + /// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514 + /// # futures::executor::block_on(async { + /// use futures::io::AsyncWriteExt; + /// use futures_util::compat::AsyncWrite01CompatExt; + /// + /// let input = b"Hello World!"; + /// let mut cursor = std::io::Cursor::new(Vec::with_capacity(12)); + /// + /// let mut writer = (&mut cursor).compat(); + /// writer.write_all(input).await.unwrap(); + /// + /// assert_eq!(cursor.into_inner(), input); + /// # }); + /// ``` + fn compat(self) -> Compat01As03 + where + Self: Sized, + { + Compat01As03::new(self) + } + } + impl AsyncWrite01CompatExt for W {} + + impl AsyncRead03 for Compat01As03 { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> task03::Poll> { + poll_01_to_03(self.in_notify(cx, |x| x.poll_read(buf))) + } + } + + impl AsyncWrite03 for Compat01As03 { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> task03::Poll> { + poll_01_to_03(self.in_notify(cx, |x| x.poll_write(buf))) + } + + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + poll_01_to_03(self.in_notify(cx, AsyncWrite01::poll_flush)) + } + + fn poll_close( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> task03::Poll> { + poll_01_to_03(self.in_notify(cx, AsyncWrite01::shutdown)) + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/compat/compat03as01.rs b/anneal/v2/vendor/futures-util/src/compat/compat03as01.rs new file mode 100644 index 0000000000..3c5bb77b49 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/compat/compat03as01.rs @@ -0,0 +1,268 @@ +use crate::task::{self as task03, ArcWake as ArcWake03, WakerRef}; +use futures_01::{ + task as task01, Async as Async01, Future as Future01, Poll as Poll01, Stream as Stream01, +}; +#[cfg(feature = "sink")] +use futures_01::{AsyncSink as AsyncSink01, Sink as Sink01, StartSend as StartSend01}; +use futures_core::{ + future::TryFuture as TryFuture03, + stream::TryStream as TryStream03, + task::{RawWaker, RawWakerVTable}, +}; +#[cfg(feature = "sink")] +use futures_sink::Sink as Sink03; +#[cfg(feature = "sink")] +use std::marker::PhantomData; +use std::{mem, pin::Pin, sync::Arc, task::Context}; + +#[allow(clippy::too_long_first_doc_paragraph)] // clippy bug, see https://github.com/rust-lang/rust-clippy/issues/13315 +/// Converts a futures 0.3 [`TryFuture`](futures_core::future::TryFuture) or +/// [`TryStream`](futures_core::stream::TryStream) into a futures 0.1 +/// [`Future`](futures_01::future::Future) or +/// [`Stream`](futures_01::stream::Stream). +#[derive(Debug, Clone, Copy)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Compat { + pub(crate) inner: T, +} + +/// Converts a futures 0.3 [`Sink`](futures_sink::Sink) into a futures 0.1 +/// [`Sink`](futures_01::sink::Sink). +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +#[derive(Debug)] +#[must_use = "sinks do nothing unless polled"] +pub struct CompatSink { + inner: T, + _phantom: PhantomData, +} + +impl Compat { + /// Creates a new [`Compat`]. + /// + /// For types which implement appropriate futures `0.3` + /// traits, the result will be a type which implements + /// the corresponding futures 0.1 type. + pub fn new(inner: T) -> Self { + Self { inner } + } + + /// Get a reference to 0.3 Future, Stream, AsyncRead, or AsyncWrite object + /// contained within. + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Get a mutable reference to 0.3 Future, Stream, AsyncRead, or AsyncWrite object + /// contained within. + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Returns the inner item. + pub fn into_inner(self) -> T { + self.inner + } +} + +#[cfg(feature = "sink")] +impl CompatSink { + /// Creates a new [`CompatSink`]. + pub fn new(inner: T) -> Self { + Self { inner, _phantom: PhantomData } + } + + /// Get a reference to 0.3 Sink contained within. + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Get a mutable reference to 0.3 Sink contained within. + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Returns the inner item. + pub fn into_inner(self) -> T { + self.inner + } +} + +fn poll_03_to_01(x: task03::Poll>) -> Result, E> { + match x? { + task03::Poll::Ready(t) => Ok(Async01::Ready(t)), + task03::Poll::Pending => Ok(Async01::NotReady), + } +} + +impl Future01 for Compat +where + Fut: TryFuture03 + Unpin, +{ + type Item = Fut::Ok; + type Error = Fut::Error; + + fn poll(&mut self) -> Poll01 { + with_context(self, |inner, cx| poll_03_to_01(inner.try_poll(cx))) + } +} + +impl Stream01 for Compat +where + St: TryStream03 + Unpin, +{ + type Item = St::Ok; + type Error = St::Error; + + fn poll(&mut self) -> Poll01, Self::Error> { + with_context(self, |inner, cx| match inner.try_poll_next(cx)? { + task03::Poll::Ready(None) => Ok(Async01::Ready(None)), + task03::Poll::Ready(Some(t)) => Ok(Async01::Ready(Some(t))), + task03::Poll::Pending => Ok(Async01::NotReady), + }) + } +} + +#[cfg(feature = "sink")] +impl Sink01 for CompatSink +where + T: Sink03 + Unpin, +{ + type SinkItem = Item; + type SinkError = T::Error; + + fn start_send(&mut self, item: Self::SinkItem) -> StartSend01 { + with_sink_context(self, |mut inner, cx| match inner.as_mut().poll_ready(cx)? { + task03::Poll::Ready(()) => inner.start_send(item).map(|()| AsyncSink01::Ready), + task03::Poll::Pending => Ok(AsyncSink01::NotReady(item)), + }) + } + + fn poll_complete(&mut self) -> Poll01<(), Self::SinkError> { + with_sink_context(self, |inner, cx| poll_03_to_01(inner.poll_flush(cx))) + } + + fn close(&mut self) -> Poll01<(), Self::SinkError> { + with_sink_context(self, |inner, cx| poll_03_to_01(inner.poll_close(cx))) + } +} + +#[derive(Clone)] +struct Current(task01::Task); + +impl Current { + fn new() -> Self { + Self(task01::current()) + } + + fn as_waker(&self) -> WakerRef<'_> { + unsafe fn ptr_to_current<'a>(ptr: *const ()) -> &'a Current { + unsafe { &*(ptr as *const Current) } + } + fn current_to_ptr(current: &Current) -> *const () { + current as *const Current as *const () + } + + unsafe fn clone(ptr: *const ()) -> RawWaker { + // Lazily create the `Arc` only when the waker is actually cloned. + // FIXME: remove `transmute` when a `Waker` -> `RawWaker` conversion + // function is landed in `core`. + unsafe { + mem::transmute::(task03::waker(Arc::new( + ptr_to_current(ptr).clone(), + ))) + } + } + unsafe fn drop(_: *const ()) {} + unsafe fn wake(ptr: *const ()) { + unsafe { ptr_to_current(ptr).0.notify() } + } + + let ptr = current_to_ptr(self); + let vtable = &RawWakerVTable::new(clone, wake, wake, drop); + WakerRef::new_unowned(std::mem::ManuallyDrop::new(unsafe { + task03::Waker::from_raw(RawWaker::new(ptr, vtable)) + })) + } +} + +impl ArcWake03 for Current { + fn wake_by_ref(arc_self: &Arc) { + arc_self.0.notify(); + } +} + +fn with_context(compat: &mut Compat, f: F) -> R +where + T: Unpin, + F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> R, +{ + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + f(Pin::new(&mut compat.inner), &mut cx) +} + +#[cfg(feature = "sink")] +fn with_sink_context(compat: &mut CompatSink, f: F) -> R +where + T: Unpin, + F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> R, +{ + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + f(Pin::new(&mut compat.inner), &mut cx) +} + +#[cfg(feature = "io-compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] +mod io { + use super::*; + use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03}; + use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01}; + + fn poll_03_to_io(x: task03::Poll>) -> Result { + match x { + task03::Poll::Ready(Ok(t)) => Ok(t), + task03::Poll::Pending => Err(std::io::ErrorKind::WouldBlock.into()), + task03::Poll::Ready(Err(e)) => Err(e), + } + } + + impl std::io::Read for Compat { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + poll_03_to_io(Pin::new(&mut self.inner).poll_read(&mut cx, buf)) + } + } + + impl AsyncRead01 for Compat {} + + impl std::io::Write for Compat { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + poll_03_to_io(Pin::new(&mut self.inner).poll_write(&mut cx, buf)) + } + + fn flush(&mut self) -> std::io::Result<()> { + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + poll_03_to_io(Pin::new(&mut self.inner).poll_flush(&mut cx)) + } + } + + impl AsyncWrite01 for Compat { + fn shutdown(&mut self) -> std::io::Result> { + let current = Current::new(); + let waker = current.as_waker(); + let mut cx = Context::from_waker(&waker); + poll_03_to_01(Pin::new(&mut self.inner).poll_close(&mut cx)) + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/compat/executor.rs b/anneal/v2/vendor/futures-util/src/compat/executor.rs new file mode 100644 index 0000000000..ea0c67a0ae --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/compat/executor.rs @@ -0,0 +1,86 @@ +use super::{Compat, Future01CompatExt}; +use crate::{ + future::{FutureExt, TryFutureExt, UnitError}, + task::SpawnExt, +}; +use futures_01::future::{ExecuteError as ExecuteError01, Executor as Executor01}; +use futures_01::Future as Future01; +use futures_task::{FutureObj, Spawn as Spawn03, SpawnError as SpawnError03}; + +/// A future that can run on a futures 0.1 +/// [`Executor`](futures_01::future::Executor). +pub type Executor01Future = Compat>>; + +/// Extension trait for futures 0.1 [`Executor`](futures_01::future::Executor). +pub trait Executor01CompatExt: Executor01 + Clone + Send + 'static { + /// Converts a futures 0.1 [`Executor`](futures_01::future::Executor) into a + /// futures 0.3 [`Spawn`](futures_task::Spawn). + /// + /// ``` + /// # if cfg!(miri) { return; } // Miri does not support epoll + /// use futures::task::SpawnExt; + /// use futures::future::{FutureExt, TryFutureExt}; + /// use futures_util::compat::Executor01CompatExt; + /// use tokio::executor::DefaultExecutor; + /// + /// # let (tx, rx) = futures::channel::oneshot::channel(); + /// + /// let spawner = DefaultExecutor::current().compat(); + /// let future03 = async move { + /// println!("Running on the pool"); + /// spawner.spawn(async { + /// println!("Spawned!"); + /// # tx.send(42).unwrap(); + /// }).unwrap(); + /// }; + /// + /// let future01 = future03.unit_error().boxed().compat(); + /// + /// tokio::run(future01); + /// # futures::executor::block_on(rx).unwrap(); + /// ``` + fn compat(self) -> Executor01As03 + where + Self: Sized; +} + +impl Executor01CompatExt for Ex +where + Ex: Executor01 + Clone + Send + 'static, +{ + fn compat(self) -> Executor01As03 { + Executor01As03 { executor01: self } + } +} + +/// Converts a futures 0.1 [`Executor`](futures_01::future::Executor) into a +/// futures 0.3 [`Spawn`](futures_task::Spawn). +#[derive(Debug, Clone)] +pub struct Executor01As03 { + executor01: Ex, +} + +impl Spawn03 for Executor01As03 +where + Ex: Executor01 + Clone + Send + 'static, +{ + fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError03> { + let future = future.unit_error().compat(); + + self.executor01.execute(future).map_err(|_| SpawnError03::shutdown()) + } +} + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl Executor01 for Compat +where + for<'a> &'a Sp: Spawn03, + Fut: Future01 + Send + 'static, +{ + fn execute(&self, future: Fut) -> Result<(), ExecuteError01> { + (&self.inner) + .spawn(future.compat().map(|_| ())) + .expect("unable to spawn future from Compat executor"); + Ok(()) + } +} diff --git a/anneal/v2/vendor/futures-util/src/compat/mod.rs b/anneal/v2/vendor/futures-util/src/compat/mod.rs new file mode 100644 index 0000000000..4812803eb6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/compat/mod.rs @@ -0,0 +1,22 @@ +//! Interop between `futures` 0.1 and 0.3. +//! +//! This module is only available when the `compat` feature of this +//! library is activated. + +mod executor; +pub use self::executor::{Executor01As03, Executor01CompatExt, Executor01Future}; + +mod compat01as03; +#[cfg(feature = "io-compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] +pub use self::compat01as03::{AsyncRead01CompatExt, AsyncWrite01CompatExt}; +pub use self::compat01as03::{Compat01As03, Future01CompatExt, Stream01CompatExt}; +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::compat01as03::{Compat01As03Sink, Sink01CompatExt}; + +mod compat03as01; +pub use self::compat03as01::Compat; +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::compat03as01::CompatSink; diff --git a/anneal/v2/vendor/futures-util/src/fns.rs b/anneal/v2/vendor/futures-util/src/fns.rs new file mode 100644 index 0000000000..fc3096a5da --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/fns.rs @@ -0,0 +1,372 @@ +use core::fmt::{self, Debug}; +use core::marker::PhantomData; + +pub trait FnOnce1 { + type Output; + fn call_once(self, arg: A) -> Self::Output; +} + +impl FnOnce1 for T +where + T: FnOnce(A) -> R, +{ + type Output = R; + fn call_once(self, arg: A) -> R { + self(arg) + } +} + +pub trait FnMut1: FnOnce1 { + fn call_mut(&mut self, arg: A) -> Self::Output; +} + +impl FnMut1 for T +where + T: FnMut(A) -> R, +{ + fn call_mut(&mut self, arg: A) -> R { + self(arg) + } +} + +// Not used, but present for completeness +#[allow(dead_code, unreachable_pub)] +pub trait Fn1: FnMut1 { + fn call(&self, arg: A) -> Self::Output; +} + +impl Fn1 for T +where + T: Fn(A) -> R, +{ + fn call(&self, arg: A) -> R { + self(arg) + } +} + +macro_rules! trivial_fn_impls { + ($name:ident <$($arg:ident),*> $t:ty = $debug:literal) => { + impl<$($arg),*> Copy for $t {} + impl<$($arg),*> Clone for $t { + fn clone(&self) -> Self { *self } + } + impl<$($arg),*> Debug for $t { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str($debug) + } + } + impl<$($arg,)* A> FnMut1 for $t where Self: FnOnce1 { + fn call_mut(&mut self, arg: A) -> Self::Output { + self.call_once(arg) + } + } + impl<$($arg,)* A> Fn1 for $t where Self: FnOnce1 { + fn call(&self, arg: A) -> Self::Output { + self.call_once(arg) + } + } + pub(crate) fn $name<$($arg),*>() -> $t { + Default::default() + } + } +} + +pub struct OkFn(PhantomData); + +impl Default for OkFn { + fn default() -> Self { + Self(PhantomData) + } +} + +impl FnOnce1 for OkFn { + type Output = Result; + fn call_once(self, arg: A) -> Self::Output { + Ok(arg) + } +} + +trivial_fn_impls!(ok_fn OkFn = "Ok"); + +#[derive(Debug, Copy, Clone, Default)] +pub struct ChainFn(F, G); + +impl FnOnce1 for ChainFn +where + F: FnOnce1, + G: FnOnce1, +{ + type Output = G::Output; + fn call_once(self, arg: A) -> Self::Output { + self.1.call_once(self.0.call_once(arg)) + } +} +impl FnMut1 for ChainFn +where + F: FnMut1, + G: FnMut1, +{ + fn call_mut(&mut self, arg: A) -> Self::Output { + self.1.call_mut(self.0.call_mut(arg)) + } +} +impl Fn1 for ChainFn +where + F: Fn1, + G: Fn1, +{ + fn call(&self, arg: A) -> Self::Output { + self.1.call(self.0.call(arg)) + } +} +pub(crate) fn chain_fn(f: F, g: G) -> ChainFn { + ChainFn(f, g) +} + +#[derive(Default)] +pub struct MergeResultFn; + +impl FnOnce1> for MergeResultFn { + type Output = T; + fn call_once(self, arg: Result) -> Self::Output { + match arg { + Ok(x) => x, + Err(x) => x, + } + } +} +trivial_fn_impls!(merge_result_fn <> MergeResultFn = "merge_result"); + +#[derive(Debug, Copy, Clone, Default)] +pub struct InspectFn(F); + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl FnOnce1 for InspectFn +where + F: for<'a> FnOnce1<&'a A, Output = ()>, +{ + type Output = A; + fn call_once(self, arg: A) -> Self::Output { + self.0.call_once(&arg); + arg + } +} +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl FnMut1 for InspectFn +where + F: for<'a> FnMut1<&'a A, Output = ()>, +{ + fn call_mut(&mut self, arg: A) -> Self::Output { + self.0.call_mut(&arg); + arg + } +} +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl Fn1 for InspectFn +where + F: for<'a> Fn1<&'a A, Output = ()>, +{ + fn call(&self, arg: A) -> Self::Output { + self.0.call(&arg); + arg + } +} +pub(crate) fn inspect_fn(f: F) -> InspectFn { + InspectFn(f) +} + +#[derive(Debug, Copy, Clone, Default)] +pub struct MapOkFn(F); + +impl FnOnce1> for MapOkFn +where + F: FnOnce1, +{ + type Output = Result; + fn call_once(self, arg: Result) -> Self::Output { + arg.map(|x| self.0.call_once(x)) + } +} +impl FnMut1> for MapOkFn +where + F: FnMut1, +{ + fn call_mut(&mut self, arg: Result) -> Self::Output { + arg.map(|x| self.0.call_mut(x)) + } +} +impl Fn1> for MapOkFn +where + F: Fn1, +{ + fn call(&self, arg: Result) -> Self::Output { + arg.map(|x| self.0.call(x)) + } +} +pub(crate) fn map_ok_fn(f: F) -> MapOkFn { + MapOkFn(f) +} + +#[derive(Debug, Copy, Clone, Default)] +pub struct MapErrFn(F); + +impl FnOnce1> for MapErrFn +where + F: FnOnce1, +{ + type Output = Result; + fn call_once(self, arg: Result) -> Self::Output { + arg.map_err(|x| self.0.call_once(x)) + } +} +impl FnMut1> for MapErrFn +where + F: FnMut1, +{ + fn call_mut(&mut self, arg: Result) -> Self::Output { + arg.map_err(|x| self.0.call_mut(x)) + } +} +impl Fn1> for MapErrFn +where + F: Fn1, +{ + fn call(&self, arg: Result) -> Self::Output { + arg.map_err(|x| self.0.call(x)) + } +} +pub(crate) fn map_err_fn(f: F) -> MapErrFn { + MapErrFn(f) +} + +#[derive(Debug, Copy, Clone)] +pub struct InspectOkFn(F); + +impl<'a, F, T, E> FnOnce1<&'a Result> for InspectOkFn +where + F: FnOnce1<&'a T, Output = ()>, +{ + type Output = (); + fn call_once(self, arg: &'a Result) -> Self::Output { + if let Ok(x) = arg { + self.0.call_once(x) + } + } +} +impl<'a, F, T, E> FnMut1<&'a Result> for InspectOkFn +where + F: FnMut1<&'a T, Output = ()>, +{ + fn call_mut(&mut self, arg: &'a Result) -> Self::Output { + if let Ok(x) = arg { + self.0.call_mut(x) + } + } +} +impl<'a, F, T, E> Fn1<&'a Result> for InspectOkFn +where + F: Fn1<&'a T, Output = ()>, +{ + fn call(&self, arg: &'a Result) -> Self::Output { + if let Ok(x) = arg { + self.0.call(x) + } + } +} +pub(crate) fn inspect_ok_fn(f: F) -> InspectOkFn { + InspectOkFn(f) +} + +#[derive(Debug, Copy, Clone)] +pub struct InspectErrFn(F); + +impl<'a, F, T, E> FnOnce1<&'a Result> for InspectErrFn +where + F: FnOnce1<&'a E, Output = ()>, +{ + type Output = (); + fn call_once(self, arg: &'a Result) -> Self::Output { + if let Err(x) = arg { + self.0.call_once(x) + } + } +} +impl<'a, F, T, E> FnMut1<&'a Result> for InspectErrFn +where + F: FnMut1<&'a E, Output = ()>, +{ + fn call_mut(&mut self, arg: &'a Result) -> Self::Output { + if let Err(x) = arg { + self.0.call_mut(x) + } + } +} +impl<'a, F, T, E> Fn1<&'a Result> for InspectErrFn +where + F: Fn1<&'a E, Output = ()>, +{ + fn call(&self, arg: &'a Result) -> Self::Output { + if let Err(x) = arg { + self.0.call(x) + } + } +} +pub(crate) fn inspect_err_fn(f: F) -> InspectErrFn { + InspectErrFn(f) +} + +pub(crate) type MapOkOrElseFn = ChainFn, ChainFn, MergeResultFn>>; +pub(crate) fn map_ok_or_else_fn(f: F, g: G) -> MapOkOrElseFn { + chain_fn(map_ok_fn(f), chain_fn(map_err_fn(g), merge_result_fn())) +} + +#[derive(Debug, Copy, Clone, Default)] +pub struct UnwrapOrElseFn(F); + +impl FnOnce1> for UnwrapOrElseFn +where + F: FnOnce1, +{ + type Output = T; + fn call_once(self, arg: Result) -> Self::Output { + arg.unwrap_or_else(|x| self.0.call_once(x)) + } +} +impl FnMut1> for UnwrapOrElseFn +where + F: FnMut1, +{ + fn call_mut(&mut self, arg: Result) -> Self::Output { + arg.unwrap_or_else(|x| self.0.call_mut(x)) + } +} +impl Fn1> for UnwrapOrElseFn +where + F: Fn1, +{ + fn call(&self, arg: Result) -> Self::Output { + arg.unwrap_or_else(|x| self.0.call(x)) + } +} +pub(crate) fn unwrap_or_else_fn(f: F) -> UnwrapOrElseFn { + UnwrapOrElseFn(f) +} + +pub struct IntoFn(PhantomData T>); + +impl Default for IntoFn { + fn default() -> Self { + Self(PhantomData) + } +} +impl FnOnce1 for IntoFn +where + A: Into, +{ + type Output = T; + fn call_once(self, arg: A) -> Self::Output { + arg.into() + } +} + +trivial_fn_impls!(into_fn IntoFn = "Into::into"); diff --git a/anneal/v2/vendor/futures-util/src/future/abortable.rs b/anneal/v2/vendor/futures-util/src/future/abortable.rs new file mode 100644 index 0000000000..d017ab7340 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/abortable.rs @@ -0,0 +1,19 @@ +use super::assert_future; +use crate::future::{AbortHandle, Abortable, Aborted}; +use futures_core::future::Future; + +/// Creates a new `Abortable` future and an `AbortHandle` which can be used to stop it. +/// +/// This function is a convenient (but less flexible) alternative to calling +/// `AbortHandle::new` and `Abortable::new` manually. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +pub fn abortable(future: Fut) -> (Abortable, AbortHandle) +where + Fut: Future, +{ + let (handle, reg) = AbortHandle::new_pair(); + let abortable = assert_future::, _>(Abortable::new(future, reg)); + (abortable, handle) +} diff --git a/anneal/v2/vendor/futures-util/src/future/always_ready.rs b/anneal/v2/vendor/futures-util/src/future/always_ready.rs new file mode 100644 index 0000000000..422268857a --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/always_ready.rs @@ -0,0 +1,62 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`always_ready`](always_ready()) function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct AlwaysReady T>(F); + +impl T> core::fmt::Debug for AlwaysReady { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("AlwaysReady").finish() + } +} + +impl T + Clone> Clone for AlwaysReady { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl T + Copy> Copy for AlwaysReady {} + +impl T> Unpin for AlwaysReady {} + +impl T> FusedFuture for AlwaysReady { + fn is_terminated(&self) -> bool { + false + } +} + +impl T> Future for AlwaysReady { + type Output = T; + + #[inline] + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0()) + } +} + +/// Creates a future that is always immediately ready with a value. +/// +/// This is particularly useful in avoiding a heap allocation when an API needs `Box>`, +/// as [`AlwaysReady`] does not have to store a boolean for `is_finished`. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use std::mem::size_of_val; +/// +/// use futures::future; +/// +/// let a = future::always_ready(|| 1); +/// assert_eq!(size_of_val(&a), 0); +/// assert_eq!(a.await, 1); +/// assert_eq!(a.await, 1); +/// # }); +/// ``` +pub fn always_ready T>(prod: F) -> AlwaysReady { + assert_future::(AlwaysReady(prod)) +} diff --git a/anneal/v2/vendor/futures-util/src/future/either.rs b/anneal/v2/vendor/futures-util/src/future/either.rs new file mode 100644 index 0000000000..018e51e72f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/either.rs @@ -0,0 +1,314 @@ +use core::pin::Pin; +use core::task::{Context, Poll}; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::{FusedStream, Stream}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +/// Combines two different futures, streams, or sinks having the same associated types into a single type. +/// +/// This is useful when conditionally choosing between two distinct future types: +/// +/// ```rust +/// use futures::future::Either; +/// +/// # futures::executor::block_on(async { +/// let cond = true; +/// +/// let fut = if cond { +/// Either::Left(async move { 12 }) +/// } else { +/// Either::Right(async move { 44 }) +/// }; +/// +/// assert_eq!(fut.await, 12); +/// # }) +/// ``` +#[derive(Debug, Clone)] +pub enum Either { + /// First branch of the type + Left(/* #[pin] */ A), + /// Second branch of the type + Right(/* #[pin] */ B), +} + +impl Either { + /// Convert `Pin<&Either>` to `Either, Pin<&B>>`, + /// pinned projections of the inner variants. + pub fn as_pin_ref(self: Pin<&Self>) -> Either, Pin<&B>> { + // SAFETY: We can use `new_unchecked` because the `inner` parts are + // guaranteed to be pinned, as they come from `self` which is pinned. + unsafe { + match self.get_ref() { + Self::Left(inner) => Either::Left(Pin::new_unchecked(inner)), + Self::Right(inner) => Either::Right(Pin::new_unchecked(inner)), + } + } + } + + /// Convert `Pin<&mut Either>` to `Either, Pin<&mut B>>`, + /// pinned projections of the inner variants. + pub fn as_pin_mut(self: Pin<&mut Self>) -> Either, Pin<&mut B>> { + // SAFETY: `get_unchecked_mut` is fine because we don't move anything. + // We can use `new_unchecked` because the `inner` parts are guaranteed + // to be pinned, as they come from `self` which is pinned, and we never + // offer an unpinned `&mut A` or `&mut B` through `Pin<&mut Self>`. We + // also don't have an implementation of `Drop`, nor manual `Unpin`. + unsafe { + match self.get_unchecked_mut() { + Self::Left(inner) => Either::Left(Pin::new_unchecked(inner)), + Self::Right(inner) => Either::Right(Pin::new_unchecked(inner)), + } + } + } +} + +impl Either<(T, A), (T, B)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the first element of the pairs. + pub fn factor_first(self) -> (T, Either) { + match self { + Self::Left((x, a)) => (x, Either::Left(a)), + Self::Right((x, b)) => (x, Either::Right(b)), + } + } +} + +impl Either<(A, T), (B, T)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the second element of the pairs. + pub fn factor_second(self) -> (Either, T) { + match self { + Self::Left((a, x)) => (Either::Left(a), x), + Self::Right((b, x)) => (Either::Right(b), x), + } + } +} + +impl Either { + /// Extract the value of an either over two equivalent types. + pub fn into_inner(self) -> T { + match self { + Self::Left(x) | Self::Right(x) => x, + } + } +} + +impl Future for Either +where + A: Future, + B: Future, +{ + type Output = A::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_pin_mut() { + Either::Left(x) => x.poll(cx), + Either::Right(x) => x.poll(cx), + } + } +} + +impl FusedFuture for Either +where + A: FusedFuture, + B: FusedFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Left(x) => x.is_terminated(), + Self::Right(x) => x.is_terminated(), + } + } +} + +impl Stream for Either +where + A: Stream, + B: Stream, +{ + type Item = A::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_next(cx), + Either::Right(x) => x.poll_next(cx), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + Self::Left(x) => x.size_hint(), + Self::Right(x) => x.size_hint(), + } + } +} + +impl FusedStream for Either +where + A: FusedStream, + B: FusedStream, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Left(x) => x.is_terminated(), + Self::Right(x) => x.is_terminated(), + } + } +} + +#[cfg(feature = "sink")] +impl Sink for Either +where + A: Sink, + B: Sink, +{ + type Error = A::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_ready(cx), + Either::Right(x) => x.poll_ready(cx), + } + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.as_pin_mut() { + Either::Left(x) => x.start_send(item), + Either::Right(x) => x.start_send(item), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_flush(cx), + Either::Right(x) => x.poll_flush(cx), + } + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_close(cx), + Either::Right(x) => x.poll_close(cx), + } + } +} + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +mod if_std { + use super::*; + + use futures_io::{ + AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, Result, SeekFrom, + }; + + impl AsyncRead for Either + where + A: AsyncRead, + B: AsyncRead, + { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_read(cx, buf), + Either::Right(x) => x.poll_read(cx, buf), + } + } + + fn poll_read_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_read_vectored(cx, bufs), + Either::Right(x) => x.poll_read_vectored(cx, bufs), + } + } + } + + impl AsyncWrite for Either + where + A: AsyncWrite, + B: AsyncWrite, + { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_write(cx, buf), + Either::Right(x) => x.poll_write(cx, buf), + } + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_write_vectored(cx, bufs), + Either::Right(x) => x.poll_write_vectored(cx, bufs), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_flush(cx), + Either::Right(x) => x.poll_flush(cx), + } + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_close(cx), + Either::Right(x) => x.poll_close(cx), + } + } + } + + impl AsyncSeek for Either + where + A: AsyncSeek, + B: AsyncSeek, + { + fn poll_seek( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_seek(cx, pos), + Either::Right(x) => x.poll_seek(cx, pos), + } + } + } + + impl AsyncBufRead for Either + where + A: AsyncBufRead, + B: AsyncBufRead, + { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_fill_buf(cx), + Either::Right(x) => x.poll_fill_buf(cx), + } + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + match self.as_pin_mut() { + Either::Left(x) => x.consume(amt), + Either::Right(x) => x.consume(amt), + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/catch_unwind.rs b/anneal/v2/vendor/futures-util/src/future/future/catch_unwind.rs new file mode 100644 index 0000000000..ed49e314d2 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/catch_unwind.rs @@ -0,0 +1,39 @@ +use core::any::Any; +use core::pin::Pin; +use std::boxed::Box; +use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; + +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`catch_unwind`](super::FutureExt::catch_unwind) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct CatchUnwind { + #[pin] + future: Fut, + } +} + +impl CatchUnwind +where + Fut: Future + UnwindSafe, +{ + pub(super) fn new(future: Fut) -> Self { + Self { future } + } +} + +impl Future for CatchUnwind +where + Fut: Future + UnwindSafe, +{ + type Output = Result>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let f = self.project().future; + catch_unwind(AssertUnwindSafe(|| f.poll(cx)))?.map(Ok) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/flatten.rs b/anneal/v2/vendor/futures-util/src/future/future/flatten.rs new file mode 100644 index 0000000000..bd767af344 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/flatten.rs @@ -0,0 +1,153 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + #[project = FlattenProj] + #[derive(Debug)] + pub enum Flatten { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl Flatten { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for Flatten +where + Fut: Future, + Fut::Output: Future, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for Flatten +where + Fut: Future, + Fut::Output: Future, +{ + type Output = ::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + let output = ready!(f.poll(cx)); + self.set(Self::Empty); + break output; + } + FlattenProj::Empty => panic!("Flatten polled after completion"), + } + }) + } +} + +impl FusedStream for Flatten +where + Fut: Future, + Fut::Output: Stream, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Stream for Flatten +where + Fut: Future, + Fut::Output: Stream, +{ + type Item = ::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + let output = ready!(f.poll_next(cx)); + if output.is_none() { + self.set(Self::Empty); + } + break output; + } + FlattenProj::Empty => break None, + } + }) + } +} + +#[cfg(feature = "sink")] +impl Sink for Flatten +where + Fut: Future, + Fut::Output: Sink, +{ + type Error = >::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + break ready!(f.poll_ready(cx)); + } + FlattenProj::Empty => panic!("poll_ready called after eof"), + } + }) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.project() { + FlattenProj::First { .. } => panic!("poll_ready not called first"), + FlattenProj::Second { f } => f.start_send(item), + FlattenProj::Empty => panic!("start_send called after eof"), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project() { + FlattenProj::First { .. } => Poll::Ready(Ok(())), + FlattenProj::Second { f } => f.poll_flush(cx), + FlattenProj::Empty => panic!("poll_flush called after eof"), + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let res = match self.as_mut().project() { + FlattenProj::Second { f } => f.poll_close(cx), + _ => Poll::Ready(Ok(())), + }; + if res.is_ready() { + self.set(Self::Empty); + } + res + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/fuse.rs b/anneal/v2/vendor/futures-util/src/future/future/fuse.rs new file mode 100644 index 0000000000..100e910776 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/fuse.rs @@ -0,0 +1,92 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`fuse`](super::FutureExt::fuse) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Fuse { + #[pin] + inner: Option, + } +} + +impl Fuse { + pub(super) fn new(f: Fut) -> Self { + Self { inner: Some(f) } + } +} + +impl Fuse { + /// Creates a new `Fuse`-wrapped future which is already terminated. + /// + /// This can be useful in combination with looping and the `select!` + /// macro, which bypasses terminated futures. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::channel::mpsc; + /// use futures::future::{Fuse, FusedFuture, FutureExt}; + /// use futures::select; + /// use futures::stream::StreamExt; + /// + /// let (sender, mut stream) = mpsc::unbounded(); + /// + /// // Send a few messages into the stream + /// sender.unbounded_send(()).unwrap(); + /// sender.unbounded_send(()).unwrap(); + /// drop(sender); + /// + /// // Use `Fuse::terminated()` to create an already-terminated future + /// // which may be instantiated later. + /// let foo_printer = Fuse::terminated(); + /// let mut foo_printer = pin!(foo_printer); + /// + /// loop { + /// select! { + /// _ = foo_printer => {}, + /// () = stream.select_next_some() => { + /// if !foo_printer.is_terminated() { + /// println!("Foo is already being printed!"); + /// } else { + /// foo_printer.set(async { + /// // do some other async operations + /// println!("Printing foo from `foo_printer` future"); + /// }.fuse()); + /// } + /// }, + /// complete => break, // `foo_printer` is terminated and the stream is done + /// } + /// } + /// # }); + /// ``` + pub fn terminated() -> Self { + Self { inner: None } + } +} + +impl FusedFuture for Fuse { + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl Future for Fuse { + type Output = Fut::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_mut().project().inner.as_pin_mut() { + Some(fut) => fut.poll(cx).map(|output| { + self.project().inner.set(None); + output + }), + None => Poll::Pending, + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/map.rs b/anneal/v2/vendor/futures-util/src/future/future/map.rs new file mode 100644 index 0000000000..6991a35022 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/map.rs @@ -0,0 +1,66 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +use crate::fns::FnOnce1; + +pin_project! { + /// Internal Map future + #[project = MapProj] + #[project_replace = MapProjReplace] + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub enum Map { + Incomplete { + #[pin] + future: Fut, + f: F, + }, + Complete, + } +} + +impl Map { + /// Creates a new Map. + pub(crate) fn new(future: Fut, f: F) -> Self { + Self::Incomplete { future, f } + } +} + +impl FusedFuture for Map +where + Fut: Future, + F: FnOnce1, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Incomplete { .. } => false, + Self::Complete => true, + } + } +} + +impl Future for Map +where + Fut: Future, + F: FnOnce1, +{ + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_mut().project() { + MapProj::Incomplete { future, .. } => { + let output = ready!(future.poll(cx)); + match self.project_replace(Self::Complete) { + MapProjReplace::Incomplete { f, .. } => Poll::Ready(f.call_once(output)), + MapProjReplace::Complete => unreachable!(), + } + } + MapProj::Complete => { + panic!("Map must not be polled after it returned `Poll::Ready`") + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/mod.rs b/anneal/v2/vendor/futures-util/src/future/future/mod.rs new file mode 100644 index 0000000000..a3237b1a1c --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/mod.rs @@ -0,0 +1,603 @@ +//! Futures +//! +//! This module contains a number of functions for working with `Future`s, +//! including the `FutureExt` trait which adds methods to `Future` types. + +use crate::fns::{inspect_fn, into_fn, ok_fn, InspectFn, IntoFn, OkFn}; +use crate::future::{assert_future, Either}; +use crate::never::Never; +use crate::stream::assert_stream; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +use core::pin::pin; +use core::pin::Pin; +#[cfg(feature = "alloc")] +use futures_core::future::{BoxFuture, LocalBoxFuture}; +use futures_core::{ + future::Future, + stream::Stream, + task::{Context, Poll}, +}; + +// Combinators + +mod flatten; +mod fuse; +mod map; + +delegate_all!( + /// Future for the [`flatten`](super::FutureExt::flatten) method. + Flatten( + flatten::Flatten::Output> + ): Debug + Future + FusedFuture + New[|x: F| flatten::Flatten::new(x)] + where F: Future +); + +delegate_all!( + /// Stream for the [`flatten_stream`](FutureExt::flatten_stream) method. + FlattenStream( + flatten::Flatten::Output> + ): Debug + Sink + Stream + FusedStream + New[|x: F| flatten::Flatten::new(x)] + where F: Future +); + +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use fuse::Fuse; + +delegate_all!( + /// Future for the [`map`](super::FutureExt::map) method. + Map( + map::Map + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| map::Map::new(x, f)] +); + +delegate_all!( + /// Stream for the [`into_stream`](FutureExt::into_stream) method. + IntoStream( + crate::stream::Once + ): Debug + Stream + FusedStream + New[|x: F| crate::stream::Once::new(x)] +); + +delegate_all!( + /// Future for the [`map_into`](FutureExt::map_into) combinator. + MapInto( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`then`](FutureExt::then) method. + Then( + flatten::Flatten, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, y: F| flatten::Flatten::new(Map::new(x, y))] +); + +delegate_all!( + /// Future for the [`inspect`](FutureExt::inspect) method. + Inspect( + map::Map> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| map::Map::new(x, inspect_fn(f))] +); + +delegate_all!( + /// Future for the [`never_error`](super::FutureExt::never_error) combinator. + NeverError( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, ok_fn())] +); + +delegate_all!( + /// Future for the [`unit_error`](super::FutureExt::unit_error) combinator. + UnitError( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, ok_fn())] +); + +#[cfg(feature = "std")] +mod catch_unwind; +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::catch_unwind::CatchUnwind; + +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +mod remote_handle; +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::remote_handle::{Remote, RemoteHandle}; + +#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))] +mod shared; +#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))] +pub use self::shared::{Shared, WeakShared}; + +impl FutureExt for T where T: Future {} + +/// An extension trait for `Future`s that provides a variety of convenient +/// adapters. +pub trait FutureExt: Future { + /// Map this future's output to a different type, returning a new future of + /// the resulting type. + /// + /// This function is similar to the `Option::map` or `Iterator::map` where + /// it will change the type of the underlying future. This is useful to + /// chain along a computation once a future has been resolved. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it, similar to the existing `map` methods in the + /// standard library. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 1 }; + /// let new_future = future.map(|x| x + 3); + /// assert_eq!(new_future.await, 4); + /// # }); + /// ``` + fn map(self, f: F) -> Map + where + F: FnOnce(Self::Output) -> U, + Self: Sized, + { + assert_future::(Map::new(self, f)) + } + + /// Map this future's output to a different type, returning a new future of + /// the resulting type. + /// + /// This function is equivalent to calling `map(Into::into)` but allows naming + /// the return type. + fn map_into(self) -> MapInto + where + Self::Output: Into, + Self: Sized, + { + assert_future::(MapInto::new(self)) + } + + /// Chain on a computation for when a future finished, passing the result of + /// the future to the provided closure `f`. + /// + /// The returned value of the closure must implement the `Future` trait + /// and can represent some more work to be done before the composed future + /// is finished. + /// + /// The closure `f` is only run *after* successful completion of the `self` + /// future. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future_of_1 = async { 1 }; + /// let future_of_4 = future_of_1.then(|x| async move { x + 3 }); + /// assert_eq!(future_of_4.await, 4); + /// # }); + /// ``` + fn then(self, f: F) -> Then + where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::(Then::new(self, f)) + } + + /// Wrap this future in an `Either` future, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let x = 6; + /// let future = if x < 10 { + /// async { true }.left_future() + /// } else { + /// async { false }.right_future() + /// }; + /// + /// assert_eq!(future.await, true); + /// # }); + /// ``` + fn left_future(self) -> Either + where + B: Future, + Self: Sized, + { + assert_future::(Either::Left(self)) + } + + /// Wrap this future in an `Either` future, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let x = 6; + /// let future = if x > 10 { + /// async { true }.left_future() + /// } else { + /// async { false }.right_future() + /// }; + /// + /// assert_eq!(future.await, false); + /// # }); + /// ``` + fn right_future(self) -> Either + where + A: Future, + Self: Sized, + { + assert_future::(Either::Right(self)) + } + + /// Convert this future into a single element stream. + /// + /// The returned stream contains single success if this future resolves to + /// success or single error if this future resolves into error. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::stream::StreamExt; + /// + /// let future = async { 17 }; + /// let stream = future.into_stream(); + /// let collected: Vec<_> = stream.collect().await; + /// assert_eq!(collected, vec![17]); + /// # }); + /// ``` + fn into_stream(self) -> IntoStream + where + Self: Sized, + { + assert_stream::(IntoStream::new(self)) + } + + /// Flatten the execution of this future when the output of this + /// future is itself another future. + /// + /// This can be useful when combining futures together to flatten the + /// computation out the final result. + /// + /// This method is roughly equivalent to `self.then(|x| x)`. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let nested_future = async { async { 1 } }; + /// let future = nested_future.flatten(); + /// assert_eq!(future.await, 1); + /// # }); + /// ``` + fn flatten(self) -> Flatten + where + Self::Output: Future, + Self: Sized, + { + let f = Flatten::new(self); + assert_future::<<::Output as Future>::Output, _>(f) + } + + /// Flatten the execution of this future when the successful result of this + /// future is a stream. + /// + /// This can be useful when stream initialization is deferred, and it is + /// convenient to work with that stream as if stream was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream_items = vec![17, 18, 19]; + /// let future_of_a_stream = async { stream::iter(stream_items) }; + /// + /// let stream = future_of_a_stream.flatten_stream(); + /// let list: Vec<_> = stream.collect().await; + /// assert_eq!(list, vec![17, 18, 19]); + /// # }); + /// ``` + fn flatten_stream(self) -> FlattenStream + where + Self::Output: Stream, + Self: Sized, + { + assert_stream::<::Item, _>(FlattenStream::new(self)) + } + + /// Fuse a future such that `poll` will never again be called once it has + /// completed. This method can be used to turn any `Future` into a + /// `FusedFuture`. + /// + /// Normally, once a future has returned `Poll::Ready` from `poll`, + /// any further calls could exhibit bad behavior such as blocking + /// forever, panicking, never returning, etc. If it is known that `poll` + /// may be called too often then this method can be used to ensure that it + /// has defined semantics. + /// + /// If a `fuse`d future is `poll`ed after having returned `Poll::Ready` + /// previously, it will return `Poll::Pending`, from `poll` again (and will + /// continue to do so for all future calls to `poll`). + /// + /// This combinator will drop the underlying future as soon as it has been + /// completed to ensure resources are reclaimed as soon as possible. + fn fuse(self) -> Fuse + where + Self: Sized, + { + let f = Fuse::new(self); + assert_future::(f) + } + + /// Do something with the output of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 1 }; + /// let new_future = future.inspect(|&x| println!("about to resolve: {}", x)); + /// assert_eq!(new_future.await, 1); + /// # }); + /// ``` + fn inspect(self, f: F) -> Inspect + where + F: FnOnce(&Self::Output), + Self: Sized, + { + assert_future::(Inspect::new(self, f)) + } + + /// Catches unwinding panics while polling the future. + /// + /// In general, panics within a future can propagate all the way out to the + /// task level. This combinator makes it possible to halt unwinding within + /// the future itself. It's most commonly used within task executors. It's + /// not recommended to use this for error handling. + /// + /// Note that this method requires the `UnwindSafe` bound from the standard + /// library. This isn't always applied automatically, and the standard + /// library provides an `AssertUnwindSafe` wrapper type to apply it + /// after-the fact. To assist using this method, the `Future` trait is also + /// implemented for `AssertUnwindSafe` where `F` implements `Future`. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::{self, FutureExt, Ready}; + /// + /// let future = future::ready(2); + /// assert!(future.catch_unwind().await.is_ok()); + /// + /// let future = future::lazy(|_| -> Ready { + /// unimplemented!() + /// }); + /// assert!(future.catch_unwind().await.is_err()); + /// # }); + /// ``` + #[cfg(feature = "std")] + fn catch_unwind(self) -> CatchUnwind + where + Self: Sized + ::std::panic::UnwindSafe, + { + assert_future::>, _>(CatchUnwind::new( + self, + )) + } + + /// Create a cloneable handle to this future where all handles will resolve + /// to the same result. + /// + /// The `shared` combinator method provides a method to convert any future + /// into a cloneable future. It enables a future to be polled by multiple + /// threads. + /// + /// This method is only available when the `std` or 'spin' feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 6 }; + /// let shared1 = future.shared(); + /// let shared2 = shared1.clone(); + /// + /// assert_eq!(6, shared1.await); + /// assert_eq!(6, shared2.await); + /// # }); + /// ``` + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::executor::block_on; + /// use std::thread; + /// + /// let future = async { 6 }; + /// let shared1 = future.shared(); + /// let shared2 = shared1.clone(); + /// let join_handle = thread::spawn(move || { + /// assert_eq!(6, block_on(shared2)); + /// }); + /// assert_eq!(6, shared1.await); + /// join_handle.join().unwrap(); + /// # }); + /// ``` + #[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))] + fn shared(self) -> Shared + where + Self: Sized, + Self::Output: Clone, + { + assert_future::(Shared::new(self)) + } + + /// Turn this future into a future that yields `()` on completion and sends + /// its output to another future on a separate task. + /// + /// This can be used with spawning executors to easily retrieve the result + /// of a future executing on a separate task or thread. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn remote_handle(self) -> (Remote, RemoteHandle) + where + Self: Sized, + { + let (wrapped, handle) = remote_handle::remote_handle(self); + (assert_future::<(), _>(wrapped), handle) + } + + /// Wrap the future in a Box, pinning it. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + assert_future::(Box::pin(self)) + } + + /// Wrap the future in a Box, pinning it. + /// + /// Similar to `boxed`, but without the `Send` requirement. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed_local<'a>(self) -> LocalBoxFuture<'a, Self::Output> + where + Self: Sized + 'a, + { + assert_future::(Box::pin(self)) + } + + /// Turns a [`Future`](Future) into a + /// [`TryFuture](futures_core::future::TryFuture). + fn unit_error(self) -> UnitError + where + Self: Sized, + { + assert_future::, _>(UnitError::new(self)) + } + + /// Turns a [`Future`](Future) into a + /// [`TryFuture](futures_core::future::TryFuture). + fn never_error(self) -> NeverError + where + Self: Sized, + { + assert_future::, _>(NeverError::new(self)) + } + + /// A convenience for calling `Future::poll` on `Unpin` future types. + fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll + where + Self: Unpin, + { + Pin::new(self).poll(cx) + } + + /// Evaluates and consumes the future, returning the resulting output if + /// the future is ready after the first call to `Future::poll`. + /// + /// If `poll` instead returns `Poll::Pending`, `None` is returned. + /// + /// This method is useful in cases where immediacy is more important than + /// waiting for a result. It is also convenient for quickly obtaining + /// the value of a future that is known to always resolve immediately. + /// + /// # Examples + /// + /// ``` + /// # use futures::prelude::*; + /// use futures::{future::ready, future::pending}; + /// let future_ready = ready("foobar"); + /// let future_pending = pending::<&'static str>(); + /// + /// assert_eq!(future_ready.now_or_never(), Some("foobar")); + /// assert_eq!(future_pending.now_or_never(), None); + /// ``` + /// + /// In cases where it is absolutely known that a future should always + /// resolve immediately and never return `Poll::Pending`, this method can + /// be combined with `expect()`: + /// + /// ``` + /// # use futures::{prelude::*, future::ready}; + /// let future_ready = ready("foobar"); + /// + /// assert_eq!(future_ready.now_or_never().expect("Future not ready"), "foobar"); + /// ``` + fn now_or_never(self) -> Option + where + Self: Sized, + { + let noop_waker = crate::task::noop_waker(); + let mut cx = Context::from_waker(&noop_waker); + + let this = pin!(self); + match this.poll(&mut cx) { + Poll::Ready(x) => Some(x), + _ => None, + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/remote_handle.rs b/anneal/v2/vendor/futures-util/src/future/future/remote_handle.rs new file mode 100644 index 0000000000..4aacd2d6be --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/remote_handle.rs @@ -0,0 +1,127 @@ +use { + crate::future::{CatchUnwind, FutureExt}, + futures_channel::oneshot::{self, Receiver, Sender}, + futures_core::{ + future::Future, + ready, + task::{Context, Poll}, + }, + pin_project_lite::pin_project, + std::{ + any::Any, + boxed::Box, + fmt, + panic::{self, AssertUnwindSafe}, + pin::Pin, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, + }, +}; + +/// The handle to a remote future returned by +/// [`remote_handle`](crate::future::FutureExt::remote_handle). When you drop this, +/// the remote future will be woken up to be dropped by the executor. +/// +/// ## Unwind safety +/// +/// When the remote future panics, [Remote] will catch the unwind and transfer it to +/// the thread where `RemoteHandle` is being awaited. This is good for the common +/// case where [Remote] is spawned on a threadpool. It is unlikely that other code +/// in the executor working thread shares mutable data with the spawned future and we +/// preserve the executor from losing its working threads. +/// +/// If you run the future locally and send the handle of to be awaited elsewhere, you +/// must be careful with regard to unwind safety because the thread in which the future +/// is polled will keep running after the panic and the thread running the [RemoteHandle] +/// will unwind. +#[must_use = "dropping a remote handle cancels the underlying future"] +#[derive(Debug)] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +pub struct RemoteHandle { + rx: Receiver>, + keep_running: Arc, +} + +impl RemoteHandle { + /// Drops this handle *without* canceling the underlying future. + /// + /// This method can be used if you want to drop the handle, but let the + /// execution continue. + pub fn forget(self) { + self.keep_running.store(true, Ordering::SeqCst); + } +} + +impl Future for RemoteHandle { + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match ready!(self.rx.poll_unpin(cx)) { + Ok(Ok(output)) => Poll::Ready(output), + // the remote future panicked. + Ok(Err(e)) => panic::resume_unwind(e), + // The oneshot sender was dropped. + Err(e) => panic::resume_unwind(Box::new(e)), + } + } +} + +type SendMsg = Result<::Output, Box>; + +pin_project! { + /// A future which sends its output to the corresponding `RemoteHandle`. + /// Created by [`remote_handle`](crate::future::FutureExt::remote_handle). + #[must_use = "futures do nothing unless you `.await` or poll them"] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + pub struct Remote { + tx: Option>>, + keep_running: Arc, + #[pin] + future: CatchUnwind>, + } +} + +impl fmt::Debug for Remote { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Remote").field(&self.future).finish() + } +} + +impl Future for Remote { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + + if this.tx.as_mut().unwrap().poll_canceled(cx).is_ready() + && !this.keep_running.load(Ordering::SeqCst) + { + // Cancelled, bail out + return Poll::Ready(()); + } + + let output = ready!(this.future.poll(cx)); + + // if the receiving end has gone away then that's ok, we just ignore the + // send error here. + drop(this.tx.take().unwrap().send(output)); + Poll::Ready(()) + } +} + +pub(super) fn remote_handle(future: Fut) -> (Remote, RemoteHandle) { + let (tx, rx) = oneshot::channel(); + let keep_running = Arc::new(AtomicBool::new(false)); + + // Unwind Safety: See the docs for RemoteHandle. + let wrapped = Remote { + future: AssertUnwindSafe(future).catch_unwind(), + tx: Some(tx), + keep_running: keep_running.clone(), + }; + + (wrapped, RemoteHandle { rx, keep_running }) +} diff --git a/anneal/v2/vendor/futures-util/src/future/future/shared.rs b/anneal/v2/vendor/futures-util/src/future/future/shared.rs new file mode 100644 index 0000000000..ed8fceab3e --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/future/shared.rs @@ -0,0 +1,430 @@ +use crate::task::{waker_ref, ArcWake}; +use alloc::sync::{Arc, Weak}; +use core::cell::UnsafeCell; +use core::fmt; +use core::hash::Hasher; +use core::pin::Pin; +use core::ptr; +use core::sync::atomic::AtomicUsize; +use core::sync::atomic::Ordering::{Acquire, SeqCst}; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll, Waker}; +use slab::Slab; + +#[cfg(feature = "std")] +type Mutex = std::sync::Mutex; +#[cfg(not(feature = "std"))] +type Mutex = spin::Mutex; + +/// Future for the [`shared`](super::FutureExt::shared) method. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Shared { + inner: Option>>, + waker_key: usize, +} + +struct Inner { + future_or_output: UnsafeCell>, + notifier: Arc, +} + +struct Notifier { + state: AtomicUsize, + wakers: Mutex>>>, +} + +/// A weak reference to a [`Shared`] that can be upgraded much like an `Arc`. +pub struct WeakShared(Weak>); + +impl Clone for WeakShared { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl fmt::Debug for Shared { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Shared") + .field("inner", &self.inner) + .field("waker_key", &self.waker_key) + .finish() + } +} + +impl fmt::Debug for Inner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Inner").finish() + } +} + +impl fmt::Debug for WeakShared { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WeakShared").finish() + } +} + +enum FutureOrOutput { + Future(Fut), + Output(Fut::Output), +} + +unsafe impl Send for Inner +where + Fut: Future + Send, + Fut::Output: Send + Sync, +{ +} + +unsafe impl Sync for Inner +where + Fut: Future + Send, + Fut::Output: Send + Sync, +{ +} + +const IDLE: usize = 0; +const POLLING: usize = 1; +const COMPLETE: usize = 2; +const POISONED: usize = 3; + +const NULL_WAKER_KEY: usize = usize::MAX; + +impl Shared { + pub(super) fn new(future: Fut) -> Self { + let inner = Inner { + future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)), + notifier: Arc::new(Notifier { + state: AtomicUsize::new(IDLE), + wakers: Mutex::new(Some(Slab::new())), + }), + }; + + Self { inner: Some(Arc::new(inner)), waker_key: NULL_WAKER_KEY } + } +} + +impl Shared +where + Fut: Future, +{ + /// Returns [`Some`] containing a reference to this [`Shared`]'s output if + /// it has already been computed by a clone or [`None`] if it hasn't been + /// computed yet or this [`Shared`] already returned its output from + /// [`poll`](Future::poll). + pub fn peek(&self) -> Option<&Fut::Output> { + if let Some(inner) = self.inner.as_ref() { + match inner.notifier.state.load(SeqCst) { + COMPLETE => unsafe { return Some(inner.output()) }, + POISONED => panic!("inner future panicked during poll"), + _ => {} + } + } + None + } + + /// Creates a new [`WeakShared`] for this [`Shared`]. + /// + /// Returns [`None`] if it has already been polled to completion. + pub fn downgrade(&self) -> Option> { + if let Some(inner) = self.inner.as_ref() { + return Some(WeakShared(Arc::downgrade(inner))); + } + None + } + + /// Gets the number of strong pointers to this allocation. + /// + /// Returns [`None`] if it has already been polled to completion. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. Another thread + /// can change the strong count at any time, including potentially between calling this method + /// and acting on the result. + #[allow(clippy::unnecessary_safety_doc)] + pub fn strong_count(&self) -> Option { + self.inner.as_ref().map(|arc| Arc::strong_count(arc)) + } + + /// Gets the number of weak pointers to this allocation. + /// + /// Returns [`None`] if it has already been polled to completion. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. Another thread + /// can change the weak count at any time, including potentially between calling this method + /// and acting on the result. + #[allow(clippy::unnecessary_safety_doc)] + pub fn weak_count(&self) -> Option { + self.inner.as_ref().map(|arc| Arc::weak_count(arc)) + } + + /// Hashes the internal state of this `Shared` in a way that's compatible with `ptr_eq`. + pub fn ptr_hash(&self, state: &mut H) { + match self.inner.as_ref() { + Some(arc) => { + state.write_u8(1); + ptr::hash(Arc::as_ptr(arc), state); + } + None => { + state.write_u8(0); + } + } + } + + /// Returns `true` if the two `Shared`s point to the same future (in a vein similar to + /// `Arc::ptr_eq`). + /// + /// Returns `false` if either `Shared` has terminated. + pub fn ptr_eq(&self, rhs: &Self) -> bool { + let lhs = match self.inner.as_ref() { + Some(lhs) => lhs, + None => return false, + }; + let rhs = match rhs.inner.as_ref() { + Some(rhs) => rhs, + None => return false, + }; + Arc::ptr_eq(lhs, rhs) + } +} + +impl Inner +where + Fut: Future, +{ + /// Safety: callers must first ensure that `self.inner.state` + /// is `COMPLETE` + unsafe fn output(&self) -> &Fut::Output { + match unsafe { &*self.future_or_output.get() } { + FutureOrOutput::Output(item) => item, + FutureOrOutput::Future(_) => unreachable!(), + } + } +} + +impl Inner +where + Fut: Future, + Fut::Output: Clone, +{ + /// Registers the current task to receive a wakeup when we are awoken. + fn record_waker(&self, waker_key: &mut usize, cx: &mut Context<'_>) { + #[cfg(feature = "std")] + let mut wakers_guard = self.notifier.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let mut wakers_guard = self.notifier.wakers.lock(); + + let wakers = match wakers_guard.as_mut() { + Some(wakers) => wakers, + None => return, + }; + + let new_waker = cx.waker(); + + if *waker_key == NULL_WAKER_KEY { + *waker_key = wakers.insert(Some(new_waker.clone())); + } else { + match wakers[*waker_key] { + Some(ref old_waker) if new_waker.will_wake(old_waker) => {} + // Could use clone_from here, but Waker doesn't specialize it. + ref mut slot => *slot = Some(new_waker.clone()), + } + } + debug_assert!(*waker_key != NULL_WAKER_KEY); + } + + /// Safety: callers must first ensure that `inner.state` + /// is `COMPLETE` + unsafe fn take_or_clone_output(self: Arc) -> Fut::Output { + match Arc::try_unwrap(self) { + Ok(inner) => match inner.future_or_output.into_inner() { + FutureOrOutput::Output(item) => item, + FutureOrOutput::Future(_) => unreachable!(), + }, + Err(inner) => unsafe { inner.output().clone() }, + } + } +} + +impl FusedFuture for Shared +where + Fut: Future, + Fut::Output: Clone, +{ + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl Future for Shared +where + Fut: Future, + Fut::Output: Clone, +{ + type Output = Fut::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + + let inner = this.inner.take().expect("Shared future polled again after completion"); + + // Fast path for when the wrapped future has already completed + if inner.notifier.state.load(Acquire) == COMPLETE { + // Safety: We're in the COMPLETE state + return unsafe { Poll::Ready(inner.take_or_clone_output()) }; + } + + inner.record_waker(&mut this.waker_key, cx); + + match inner + .notifier + .state + .compare_exchange(IDLE, POLLING, SeqCst, SeqCst) + .unwrap_or_else(|x| x) + { + IDLE => { + // Lock acquired, fall through + } + POLLING => { + // Another task is currently polling, at this point we just want + // to ensure that the waker for this task is registered + this.inner = Some(inner); + return Poll::Pending; + } + COMPLETE => { + // Safety: We're in the COMPLETE state + return unsafe { Poll::Ready(inner.take_or_clone_output()) }; + } + POISONED => panic!("inner future panicked during poll"), + _ => unreachable!(), + } + + let waker = waker_ref(&inner.notifier); + let mut cx = Context::from_waker(&waker); + + struct Reset<'a> { + state: &'a AtomicUsize, + did_not_panic: bool, + } + + impl Drop for Reset<'_> { + fn drop(&mut self) { + if !self.did_not_panic { + self.state.store(POISONED, SeqCst); + } + } + } + + let mut reset = Reset { state: &inner.notifier.state, did_not_panic: false }; + + let output = { + let future = unsafe { + match &mut *inner.future_or_output.get() { + FutureOrOutput::Future(fut) => Pin::new_unchecked(fut), + _ => unreachable!(), + } + }; + + let poll_result = future.poll(&mut cx); + reset.did_not_panic = true; + + match poll_result { + Poll::Pending => { + if inner.notifier.state.compare_exchange(POLLING, IDLE, SeqCst, SeqCst).is_ok() + { + // Success + drop(reset); + this.inner = Some(inner); + return Poll::Pending; + } else { + unreachable!() + } + } + Poll::Ready(output) => output, + } + }; + + unsafe { + *inner.future_or_output.get() = FutureOrOutput::Output(output); + } + + inner.notifier.state.store(COMPLETE, SeqCst); + + // Wake all tasks and drop the slab + #[cfg(feature = "std")] + let mut wakers_guard = inner.notifier.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let mut wakers_guard = inner.notifier.wakers.lock(); + + let mut wakers = wakers_guard.take().unwrap(); + for waker in wakers.drain().flatten() { + waker.wake(); + } + + drop(reset); // Make borrow checker happy + drop(wakers_guard); + + // Safety: We're in the COMPLETE state + unsafe { Poll::Ready(inner.take_or_clone_output()) } + } +} + +impl Clone for Shared +where + Fut: Future, +{ + fn clone(&self) -> Self { + Self { inner: self.inner.clone(), waker_key: NULL_WAKER_KEY } + } +} + +impl Drop for Shared +where + Fut: Future, +{ + fn drop(&mut self) { + if self.waker_key != NULL_WAKER_KEY { + if let Some(ref inner) = self.inner { + #[cfg(feature = "std")] + if let Ok(mut wakers) = inner.notifier.wakers.lock() { + if let Some(wakers) = wakers.as_mut() { + wakers.remove(self.waker_key); + } + } + #[cfg(not(feature = "std"))] + if let Some(wakers) = inner.notifier.wakers.lock().as_mut() { + wakers.remove(self.waker_key); + } + } + } + } +} + +impl ArcWake for Notifier { + fn wake_by_ref(arc_self: &Arc) { + #[cfg(feature = "std")] + let wakers = &mut *arc_self.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let wakers = &mut *arc_self.wakers.lock(); + + if let Some(wakers) = wakers.as_mut() { + for (_key, opt_waker) in wakers { + if let Some(waker) = opt_waker.take() { + waker.wake(); + } + } + } + } +} + +impl WeakShared { + /// Attempts to upgrade this [`WeakShared`] into a [`Shared`]. + /// + /// Returns [`None`] if all clones of the [`Shared`] have been dropped or polled + /// to completion. + pub fn upgrade(&self) -> Option> { + Some(Shared { inner: Some(self.0.upgrade()?), waker_key: NULL_WAKER_KEY }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/join.rs b/anneal/v2/vendor/futures-util/src/future/join.rs new file mode 100644 index 0000000000..740ffbc988 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/join.rs @@ -0,0 +1,217 @@ +#![allow(non_snake_case)] + +use super::assert_future; +use crate::future::{maybe_done, MaybeDone}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +macro_rules! generate { + ($( + $(#[$doc:meta])* + ($Join:ident, <$($Fut:ident),*>), + )*) => ($( + pin_project! { + $(#[$doc])* + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct $Join<$($Fut: Future),*> { + $(#[pin] $Fut: MaybeDone<$Fut>,)* + } + } + + impl<$($Fut),*> fmt::Debug for $Join<$($Fut),*> + where + $( + $Fut: Future + fmt::Debug, + $Fut::Output: fmt::Debug, + )* + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(stringify!($Join)) + $(.field(stringify!($Fut), &self.$Fut))* + .finish() + } + } + + impl<$($Fut: Future),*> $Join<$($Fut),*> { + fn new($($Fut: $Fut),*) -> Self { + Self { + $($Fut: maybe_done($Fut)),* + } + } + } + + impl<$($Fut: Future),*> Future for $Join<$($Fut),*> { + type Output = ($($Fut::Output),*); + + fn poll( + self: Pin<&mut Self>, cx: &mut Context<'_> + ) -> Poll { + let mut all_done = true; + let mut futures = self.project(); + $( + all_done &= futures.$Fut.as_mut().poll(cx).is_ready(); + )* + + if all_done { + Poll::Ready(($(futures.$Fut.take_output().unwrap()), *)) + } else { + Poll::Pending + } + } + } + + impl<$($Fut: FusedFuture),*> FusedFuture for $Join<$($Fut),*> { + fn is_terminated(&self) -> bool { + $( + self.$Fut.is_terminated() + ) && * + } + } + )*) +} + +generate! { + /// Future for the [`join`](join()) function. + (Join, ), + + /// Future for the [`join3`] function. + (Join3, ), + + /// Future for the [`join4`] function. + (Join4, ), + + /// Future for the [`join5`] function. + (Join5, ), +} + +/// Joins the result of two futures, waiting for them both to complete. +/// +/// This function will return a new future which awaits both futures to +/// complete. The returned future will finish with a tuple of both results. +/// +/// Note that this function consumes the passed futures and returns a +/// wrapped version of it. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let pair = future::join(a, b); +/// +/// assert_eq!(pair.await, (1, 2)); +/// # }); +/// ``` +pub fn join(future1: Fut1, future2: Fut2) -> Join +where + Fut1: Future, + Fut2: Future, +{ + let f = Join::new(future1, future2); + assert_future::<(Fut1::Output, Fut2::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let tuple = future::join3(a, b, c); +/// +/// assert_eq!(tuple.await, (1, 2, 3)); +/// # }); +/// ``` +pub fn join3( + future1: Fut1, + future2: Fut2, + future3: Fut3, +) -> Join3 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, +{ + let f = Join3::new(future1, future2, future3); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let d = async { 4 }; +/// let tuple = future::join4(a, b, c, d); +/// +/// assert_eq!(tuple.await, (1, 2, 3, 4)); +/// # }); +/// ``` +pub fn join4( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, +) -> Join4 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, + Fut4: Future, +{ + let f = Join4::new(future1, future2, future3, future4); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output, Fut4::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let d = async { 4 }; +/// let e = async { 5 }; +/// let tuple = future::join5(a, b, c, d, e); +/// +/// assert_eq!(tuple.await, (1, 2, 3, 4, 5)); +/// # }); +/// ``` +pub fn join5( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, + future5: Fut5, +) -> Join5 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, + Fut4: Future, + Fut5: Future, +{ + let f = Join5::new(future1, future2, future3, future4, future5); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output, Fut4::Output, Fut5::Output), _>(f) +} diff --git a/anneal/v2/vendor/futures-util/src/future/join_all.rs b/anneal/v2/vendor/futures-util/src/future/join_all.rs new file mode 100644 index 0000000000..79eee8dffc --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/join_all.rs @@ -0,0 +1,167 @@ +//! Definition of the `JoinAll` combinator, waiting for all of a list of futures +//! to finish. + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Context, Poll}; + +use super::{assert_future, MaybeDone}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +use crate::stream::{Collect, FuturesOrdered, StreamExt}; + +pub(crate) fn iter_pin_mut(slice: Pin<&mut [T]>) -> impl Iterator> { + // Safety: `std` _could_ make this unsound if it were to decide Pin's + // invariants aren't required to transmit through slices. Otherwise this has + // the same safety as a normal field pin projection. + unsafe { slice.get_unchecked_mut() }.iter_mut().map(|t| unsafe { Pin::new_unchecked(t) }) +} + +#[must_use = "futures do nothing unless you `.await` or poll them"] +/// Future for the [`join_all`] function. +pub struct JoinAll +where + F: Future, +{ + kind: JoinAllKind, +} + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +pub(crate) const SMALL: usize = 30; + +enum JoinAllKind +where + F: Future, +{ + Small { + elems: Pin]>>, + }, + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + Big { + fut: Collect, Vec>, + }, +} + +impl fmt::Debug for JoinAll +where + F: Future + fmt::Debug, + F::Output: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + JoinAllKind::Small { ref elems } => { + f.debug_struct("JoinAll").field("elems", elems).finish() + } + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + JoinAllKind::Big { ref fut, .. } => fmt::Debug::fmt(fut, f), + } + } +} + +/// Creates a future which represents a collection of the outputs of the futures +/// given. +/// +/// The returned future will drive execution for all of its underlying futures, +/// collecting the results into a destination `Vec` in the same order as they +/// were provided. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # See Also +/// +/// `join_all` will switch to the more powerful [`FuturesOrdered`] for performance +/// reasons if the number of futures is large. You may want to look into using it or +/// its counterpart [`FuturesUnordered`][crate::stream::FuturesUnordered] directly. +/// +/// Some examples for additional functionality provided by these are: +/// +/// * Adding new futures to the set even after it has been started. +/// +/// * Only polling the specific futures that have been woken. In cases where +/// you have a lot of futures this will result in much more efficient polling. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::join_all; +/// +/// async fn foo(i: u32) -> u32 { i } +/// +/// let futures = vec![foo(1), foo(2), foo(3)]; +/// +/// assert_eq!(join_all(futures).await, [1, 2, 3]); +/// # }); +/// ``` +pub fn join_all(iter: I) -> JoinAll +where + I: IntoIterator, + I::Item: Future, +{ + let iter = iter.into_iter(); + + #[cfg(target_os = "none")] + #[cfg_attr(target_os = "none", cfg(not(target_has_atomic = "ptr")))] + { + let kind = + JoinAllKind::Small { elems: iter.map(MaybeDone::Future).collect::>().into() }; + + assert_future::::Output>, _>(JoinAll { kind }) + } + + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + { + let kind = match iter.size_hint().1 { + Some(max) if max <= SMALL => JoinAllKind::Small { + elems: iter.map(MaybeDone::Future).collect::>().into(), + }, + _ => JoinAllKind::Big { fut: iter.collect::>().collect() }, + }; + + assert_future::::Output>, _>(JoinAll { kind }) + } +} + +impl Future for JoinAll +where + F: Future, +{ + type Output = Vec; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match &mut self.kind { + JoinAllKind::Small { elems } => { + let mut all_done = true; + + for elem in iter_pin_mut(elems.as_mut()) { + if elem.poll(cx).is_pending() { + all_done = false; + } + } + + if all_done { + let mut elems = mem::replace(elems, Box::pin([])); + let result = + iter_pin_mut(elems.as_mut()).map(|e| e.take_output().unwrap()).collect(); + Poll::Ready(result) + } else { + Poll::Pending + } + } + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + JoinAllKind::Big { fut } => Pin::new(fut).poll(cx), + } + } +} + +impl FromIterator for JoinAll { + fn from_iter>(iter: T) -> Self { + join_all(iter) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/lazy.rs b/anneal/v2/vendor/futures-util/src/future/lazy.rs new file mode 100644 index 0000000000..e9a8cf2fa9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/lazy.rs @@ -0,0 +1,60 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`lazy`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Lazy { + f: Option, +} + +// safe because we never generate `Pin<&mut F>` +impl Unpin for Lazy {} + +/// Creates a new future that allows delayed execution of a closure. +/// +/// The provided closure is only run once the future is polled. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::lazy(|_| 1); +/// assert_eq!(a.await, 1); +/// +/// let b = future::lazy(|_| -> i32 { +/// panic!("oh no!") +/// }); +/// drop(b); // closure is never run +/// # }); +/// ``` +pub fn lazy(f: F) -> Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + assert_future::(Lazy { f: Some(f) }) +} + +impl FusedFuture for Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + fn is_terminated(&self) -> bool { + self.f.is_none() + } +} + +impl Future for Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + type Output = R; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready((self.f.take().expect("Lazy polled after completion"))(cx)) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/maybe_done.rs b/anneal/v2/vendor/futures-util/src/future/maybe_done.rs new file mode 100644 index 0000000000..fa8787a874 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/maybe_done.rs @@ -0,0 +1,105 @@ +//! Definition of the MaybeDone combinator + +use super::assert_future; +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; + +/// A future that may have completed. +/// +/// This is created by the [`maybe_done()`] function. +#[derive(Debug)] +pub enum MaybeDone { + /// A not-yet-completed future + Future(/* #[pin] */ Fut), + /// The output of the completed future + Done(Fut::Output), + /// The empty variant after the result of a [`MaybeDone`] has been + /// taken using the [`take_output`](MaybeDone::take_output) method. + Gone, +} + +impl Unpin for MaybeDone {} + +/// Wraps a future into a `MaybeDone` +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use core::pin::pin; +/// +/// use futures::future; +/// +/// let future = future::maybe_done(async { 5 }); +/// let mut future = pin!(future); +/// assert_eq!(future.as_mut().take_output(), None); +/// let () = future.as_mut().await; +/// assert_eq!(future.as_mut().take_output(), Some(5)); +/// assert_eq!(future.as_mut().take_output(), None); +/// # }); +/// ``` +pub fn maybe_done(future: Fut) -> MaybeDone { + assert_future::<(), _>(MaybeDone::Future(future)) +} + +impl MaybeDone { + /// Returns an [`Option`] containing a mutable reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has been completed and [`take_output`](MaybeDone::take_output) + /// has not yet been called. + #[inline] + pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { + unsafe { + match self.get_unchecked_mut() { + Self::Done(res) => Some(res), + _ => None, + } + } + } + + /// Attempt to take the output of a `MaybeDone` without driving it + /// towards completion. + #[inline] + pub fn take_output(self: Pin<&mut Self>) -> Option { + match &*self { + Self::Done(_) => {} + Self::Future(_) | Self::Gone => return None, + } + unsafe { + match mem::replace(self.get_unchecked_mut(), Self::Gone) { + Self::Done(output) => Some(output), + _ => unreachable!(), + } + } + } +} + +impl FusedFuture for MaybeDone { + fn is_terminated(&self) -> bool { + match self { + Self::Future(_) => false, + Self::Done(_) | Self::Gone => true, + } + } +} + +impl Future for MaybeDone { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unsafe { + match self.as_mut().get_unchecked_mut() { + Self::Future(f) => { + let res = ready!(Pin::new_unchecked(f).poll(cx)); + self.set(Self::Done(res)); + } + Self::Done(_) => {} + Self::Gone => panic!("MaybeDone polled after value taken"), + } + } + Poll::Ready(()) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/mod.rs b/anneal/v2/vendor/futures-util/src/future/mod.rs new file mode 100644 index 0000000000..6913c928c5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/mod.rs @@ -0,0 +1,134 @@ +//! Asynchronous values. +//! +//! This module contains: +//! +//! - The [`Future`] trait. +//! - The [`FutureExt`] and [`TryFutureExt`] trait, which provides adapters for +//! chaining and composing futures. +//! - Top-level future combinators like [`lazy`](lazy()) which creates a future +//! from a closure that defines its return value, and [`ready`](ready()), +//! which constructs a future with an immediate defined value. + +#[doc(no_inline)] +pub use core::future::Future; + +#[cfg(feature = "alloc")] +pub use futures_core::future::{BoxFuture, LocalBoxFuture}; +pub use futures_core::future::{FusedFuture, TryFuture}; +pub use futures_task::{FutureObj, LocalFutureObj, UnsafeFutureObj}; + +// Extension traits and combinators +#[allow(clippy::module_inception)] +mod future; +pub use self::future::{ + Flatten, Fuse, FutureExt, Inspect, IntoStream, Map, MapInto, NeverError, Then, UnitError, +}; + +#[deprecated(note = "This is now an alias for [Flatten](Flatten)")] +pub use self::future::FlattenStream; + +#[cfg(feature = "std")] +pub use self::future::CatchUnwind; + +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +pub use self::future::{Remote, RemoteHandle}; + +#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))] +pub use self::future::{Shared, WeakShared}; + +mod try_future; +pub use self::try_future::{ + AndThen, ErrInto, InspectErr, InspectOk, IntoFuture, MapErr, MapOk, MapOkOrElse, OkInto, + OrElse, TryFlatten, TryFlattenStream, TryFutureExt, UnwrapOrElse, +}; + +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::try_future::FlattenSink; + +// Primitive futures + +mod lazy; +pub use self::lazy::{lazy, Lazy}; + +mod pending; +pub use self::pending::{pending, Pending}; + +mod maybe_done; +pub use self::maybe_done::{maybe_done, MaybeDone}; + +mod try_maybe_done; +pub use self::try_maybe_done::{try_maybe_done, TryMaybeDone}; + +mod option; +pub use self::option::OptionFuture; + +mod poll_fn; +pub use self::poll_fn::{poll_fn, PollFn}; + +mod poll_immediate; +pub use self::poll_immediate::{poll_immediate, PollImmediate}; + +mod ready; +pub use self::ready::{err, ok, ready, Ready}; + +mod always_ready; +pub use self::always_ready::{always_ready, AlwaysReady}; + +mod join; +pub use self::join::{join, join3, join4, join5, Join, Join3, Join4, Join5}; + +#[cfg(feature = "alloc")] +mod join_all; +#[cfg(feature = "alloc")] +pub use self::join_all::{join_all, JoinAll}; + +mod select; +pub use self::select::{select, Select}; + +#[cfg(feature = "alloc")] +mod select_all; +#[cfg(feature = "alloc")] +pub use self::select_all::{select_all, SelectAll}; + +mod try_join; +pub use self::try_join::{ + try_join, try_join3, try_join4, try_join5, TryJoin, TryJoin3, TryJoin4, TryJoin5, +}; + +#[cfg(feature = "alloc")] +mod try_join_all; +#[cfg(feature = "alloc")] +pub use self::try_join_all::{try_join_all, TryJoinAll}; + +mod try_select; +pub use self::try_select::{try_select, TrySelect}; + +#[cfg(feature = "alloc")] +mod select_ok; +#[cfg(feature = "alloc")] +pub use self::select_ok::{select_ok, SelectOk}; + +mod either; +pub use self::either::Either; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod abortable; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use crate::abortable::{AbortHandle, AbortRegistration, Abortable, Aborted}; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use abortable::abortable; + +// Just a helper function to ensure the futures we're returning all have the +// right implementations. +pub(crate) fn assert_future(future: F) -> F +where + F: Future, +{ + future +} diff --git a/anneal/v2/vendor/futures-util/src/future/option.rs b/anneal/v2/vendor/futures-util/src/future/option.rs new file mode 100644 index 0000000000..0bc377758a --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/option.rs @@ -0,0 +1,64 @@ +//! Definition of the `Option` (optional step) combinator + +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// A future representing a value which may or may not be present. + /// + /// Created by the [`From`] implementation for [`Option`](std::option::Option). + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::OptionFuture; + /// + /// let mut a: OptionFuture<_> = Some(async { 123 }).into(); + /// assert_eq!(a.await, Some(123)); + /// + /// a = None.into(); + /// assert_eq!(a.await, None); + /// # }); + /// ``` + #[derive(Debug, Clone)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct OptionFuture { + #[pin] + inner: Option, + } +} + +impl Default for OptionFuture { + fn default() -> Self { + Self { inner: None } + } +} + +impl Future for OptionFuture { + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.project().inner.as_pin_mut() { + Some(x) => x.poll(cx).map(Some), + None => Poll::Ready(None), + } + } +} + +impl FusedFuture for OptionFuture { + fn is_terminated(&self) -> bool { + match &self.inner { + Some(x) => x.is_terminated(), + None => true, + } + } +} + +impl From> for OptionFuture { + fn from(option: Option) -> Self { + Self { inner: option } + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/pending.rs b/anneal/v2/vendor/futures-util/src/future/pending.rs new file mode 100644 index 0000000000..b8e28686e1 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/pending.rs @@ -0,0 +1,55 @@ +use super::assert_future; +use core::marker; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`pending()`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Pending { + _data: marker::PhantomData, +} + +impl FusedFuture for Pending { + fn is_terminated(&self) -> bool { + true + } +} + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// The returned future will forever return [`Poll::Pending`]. +/// +/// # Examples +/// +/// ```ignore +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let future = future::pending(); +/// let () = future.await; +/// unreachable!(); +/// # }); +/// ``` +#[cfg_attr(docsrs, doc(alias = "never"))] +pub fn pending() -> Pending { + assert_future::(Pending { _data: marker::PhantomData }) +} + +impl Future for Pending { + type Output = T; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +impl Unpin for Pending {} + +impl Clone for Pending { + fn clone(&self) -> Self { + pending() + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/poll_fn.rs b/anneal/v2/vendor/futures-util/src/future/poll_fn.rs new file mode 100644 index 0000000000..19311570b5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/poll_fn.rs @@ -0,0 +1,58 @@ +//! Definition of the `PollFn` adapter combinator + +use super::assert_future; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; + +/// Future for the [`poll_fn`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct PollFn { + f: F, +} + +impl Unpin for PollFn {} + +/// Creates a new future wrapping around a function returning [`Poll`]. +/// +/// Polling the returned future delegates to the wrapped function. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::poll_fn; +/// use futures::task::{Context, Poll}; +/// +/// fn read_line(_cx: &mut Context<'_>) -> Poll { +/// Poll::Ready("Hello, World!".into()) +/// } +/// +/// let read_future = poll_fn(read_line); +/// assert_eq!(read_future.await, "Hello, World!".to_owned()); +/// # }); +/// ``` +pub fn poll_fn(f: F) -> PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + assert_future::(PollFn { f }) +} + +impl fmt::Debug for PollFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PollFn").finish() + } +} + +impl Future for PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + (&mut self.f)(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/poll_immediate.rs b/anneal/v2/vendor/futures-util/src/future/poll_immediate.rs new file mode 100644 index 0000000000..8247011375 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/poll_immediate.rs @@ -0,0 +1,131 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::task::{Context, Poll}; +use futures_core::{FusedFuture, Future, Stream}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`poll_immediate`](poll_immediate()) function. + /// + /// It will never return [Poll::Pending](core::task::Poll::Pending) + #[derive(Debug, Clone)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct PollImmediate { + #[pin] + future: Option + } +} + +impl Future for PollImmediate +where + F: Future, +{ + type Output = Option; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + let inner = + this.future.as_mut().as_pin_mut().expect("PollImmediate polled after completion"); + match inner.poll(cx) { + Poll::Ready(t) => { + this.future.set(None); + Poll::Ready(Some(t)) + } + Poll::Pending => Poll::Ready(None), + } + } +} + +impl FusedFuture for PollImmediate { + fn is_terminated(&self) -> bool { + self.future.is_none() + } +} + +/// A [Stream](crate::stream::Stream) implementation that can be polled repeatedly until the future is done. +/// The stream will never return [Poll::Pending](core::task::Poll::Pending) +/// so polling it in a tight loop is worse than using a blocking synchronous function. +/// ``` +/// # futures::executor::block_on(async { +/// use core::pin::pin; +/// +/// use futures::task::Poll; +/// use futures::{StreamExt, future}; +/// use future::FusedFuture; +/// +/// let f = async { 1_u32 }; +/// let f = pin!(f); +/// let mut r = future::poll_immediate(f); +/// assert_eq!(r.next().await, Some(Poll::Ready(1))); +/// +/// let f = async {futures::pending!(); 42_u8}; +/// let f = pin!(f); +/// let mut p = future::poll_immediate(f); +/// assert_eq!(p.next().await, Some(Poll::Pending)); +/// assert!(!p.is_terminated()); +/// assert_eq!(p.next().await, Some(Poll::Ready(42))); +/// assert!(p.is_terminated()); +/// assert_eq!(p.next().await, None); +/// # }); +/// ``` +impl Stream for PollImmediate +where + F: Future, +{ + type Item = Poll; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + match this.future.as_mut().as_pin_mut() { + // inner is gone, so we can signal that the stream is closed. + None => Poll::Ready(None), + Some(fut) => Poll::Ready(Some(fut.poll(cx).map(|t| { + this.future.set(None); + t + }))), + } + } +} + +/// Creates a future that is immediately ready with an Option of a value. +/// Specifically this means that [poll](core::future::Future::poll()) always returns [Poll::Ready](core::task::Poll::Ready). +/// +/// # Caution +/// +/// When consuming the future by this function, note the following: +/// +/// - This function does not guarantee that the future will run to completion, so it is generally incompatible with passing the non-cancellation-safe future by value. +/// - Even if the future is cancellation-safe, creating and dropping new futures frequently may lead to performance problems. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let r = future::poll_immediate(async { 1_u32 }); +/// assert_eq!(r.await, Some(1)); +/// +/// let p = future::poll_immediate(future::pending::()); +/// assert_eq!(p.await, None); +/// # }); +/// ``` +/// +/// ### Reusing a future +/// +/// ``` +/// # futures::executor::block_on(async { +/// use core::pin::pin; +/// +/// use futures::future; +/// +/// let f = async {futures::pending!(); 42_u8}; +/// let mut f = pin!(f); +/// assert_eq!(None, future::poll_immediate(&mut f).await); +/// assert_eq!(42, f.await); +/// # }); +/// ``` +pub fn poll_immediate(f: F) -> PollImmediate { + assert_future::, PollImmediate>(PollImmediate { future: Some(f) }) +} diff --git a/anneal/v2/vendor/futures-util/src/future/ready.rs b/anneal/v2/vendor/futures-util/src/future/ready.rs new file mode 100644 index 0000000000..e3d791b3cf --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/ready.rs @@ -0,0 +1,82 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`ready`](ready()) function. +#[derive(Debug, Clone)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Ready(Option); + +impl Ready { + /// Unwraps the value from this immediately ready future. + #[inline] + pub fn into_inner(mut self) -> T { + self.0.take().unwrap() + } +} + +impl Unpin for Ready {} + +impl FusedFuture for Ready { + fn is_terminated(&self) -> bool { + self.0.is_none() + } +} + +impl Future for Ready { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().expect("Ready polled after completion")) + } +} + +/// Creates a future that is immediately ready with a value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(1); +/// assert_eq!(a.await, 1); +/// # }); +/// ``` +pub fn ready(t: T) -> Ready { + assert_future::(Ready(Some(t))) +} + +/// Create a future that is immediately ready with a success value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ok::(1); +/// assert_eq!(a.await, Ok(1)); +/// # }); +/// ``` +pub fn ok(t: T) -> Ready> { + Ready(Some(Ok(t))) +} + +/// Create a future that is immediately ready with an error value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::err::(1); +/// assert_eq!(a.await, Err(1)); +/// # }); +/// ``` +pub fn err(err: E) -> Ready> { + Ready(Some(Err(err))) +} diff --git a/anneal/v2/vendor/futures-util/src/future/select.rs b/anneal/v2/vendor/futures-util/src/future/select.rs new file mode 100644 index 0000000000..4aa539e8ab --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/select.rs @@ -0,0 +1,133 @@ +use super::assert_future; +use crate::future::{Either, FutureExt}; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select()`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +pub struct Select { + inner: Option<(A, B)>, +} + +impl Unpin for Select {} + +/// Waits for either one of two differently-typed futures to complete. +/// +/// This function will return a new future which awaits for either one of both +/// futures to complete. The returned future will finish with both the value +/// resolved and a future representing the completion of the other work. +/// +/// Note that this function consumes the receiving futures and returns a +/// wrapped version of them. +/// +/// Also note that if both this and the second future have the same +/// output type you can use the `Either::factor_first` method to +/// conveniently extract out the value at the end. +/// +/// # Examples +/// +/// A simple example +/// +/// ``` +/// # futures::executor::block_on(async { +/// use core::pin::pin; +/// +/// use futures::future; +/// use futures::future::Either; +/// +/// // These two futures have different types even though their outputs have the same type. +/// let future1 = async { +/// future::pending::<()>().await; // will never finish +/// 1 +/// }; +/// let future2 = async { +/// future::ready(2).await +/// }; +/// +/// // 'select' requires Future + Unpin bounds +/// let future1 = pin!(future1); +/// let future2 = pin!(future2); +/// +/// let value = match future::select(future1, future2).await { +/// Either::Left((value1, _)) => value1, // `value1` is resolved from `future1` +/// // `_` represents `future2` +/// Either::Right((value2, _)) => value2, // `value2` is resolved from `future2` +/// // `_` represents `future1` +/// }; +/// +/// assert!(value == 2); +/// # }); +/// ``` +/// +/// A more complex example +/// +/// ``` +/// use futures::future::{self, Either, Future, FutureExt}; +/// +/// // A poor-man's join implemented on top of select +/// +/// fn join(a: A, b: B) -> impl Future +/// where A: Future + Unpin, +/// B: Future + Unpin, +/// { +/// future::select(a, b).then(|either| { +/// match either { +/// Either::Left((x, b)) => b.map(move |y| (x, y)).left_future(), +/// Either::Right((y, a)) => a.map(move |x| (x, y)).right_future(), +/// } +/// }) +/// } +/// ``` +pub fn select(future1: A, future2: B) -> Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + assert_future::, _>(Select { + inner: Some((future1, future2)), + }) +} + +impl Future for Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + type Output = Either<(A::Output, B), (B::Output, A)>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + /// When compiled with `-C opt-level=z`, this function will help the compiler eliminate the `None` branch, where + /// `Option::unwrap` does not. + #[inline(always)] + fn unwrap_option(value: Option) -> T { + match value { + None => unreachable!(), + Some(value) => value, + } + } + + let (a, b) = self.inner.as_mut().expect("cannot poll Select twice"); + + if let Poll::Ready(val) = a.poll_unpin(cx) { + return Poll::Ready(Either::Left((val, unwrap_option(self.inner.take()).1))); + } + + if let Poll::Ready(val) = b.poll_unpin(cx) { + return Poll::Ready(Either::Right((val, unwrap_option(self.inner.take()).0))); + } + + Poll::Pending + } +} + +impl FusedFuture for Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/select_all.rs b/anneal/v2/vendor/futures-util/src/future/select_all.rs new file mode 100644 index 0000000000..0a51d0da6c --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/select_all.rs @@ -0,0 +1,75 @@ +use super::assert_future; +use crate::future::FutureExt; +use alloc::vec::Vec; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select_all`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SelectAll { + inner: Vec, +} + +impl Unpin for SelectAll {} + +/// Creates a new future which will select over a list of futures. +/// +/// The returned future will wait for any future within `iter` to be ready. Upon +/// completion the item resolved will be returned, along with the index of the +/// future that was ready and the list of all the remaining futures. +/// +/// There are no guarantees provided on the order of the list with the remaining +/// futures. They might be swapped around, reversed, or completely random. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # Panics +/// +/// This function will panic if the iterator specified contains no items. +pub fn select_all(iter: I) -> SelectAll +where + I: IntoIterator, + I::Item: Future + Unpin, +{ + let ret = SelectAll { inner: iter.into_iter().collect() }; + assert!(!ret.inner.is_empty()); + assert_future::<(::Output, usize, Vec), _>(ret) +} + +impl SelectAll { + /// Consumes this combinator, returning the underlying futures. + pub fn into_inner(self) -> Vec { + self.inner + } +} + +impl Future for SelectAll { + type Output = (Fut::Output, usize, Vec); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| match f.poll_unpin(cx) { + Poll::Pending => None, + Poll::Ready(e) => Some((i, e)), + }); + match item { + Some((idx, res)) => { + #[allow(clippy::let_underscore_future)] + let _ = self.inner.swap_remove(idx); + let rest = mem::take(&mut self.inner); + Poll::Ready((res, idx, rest)) + } + None => Poll::Pending, + } + } +} + +impl FromIterator for SelectAll { + fn from_iter>(iter: T) -> Self { + select_all(iter) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/select_ok.rs b/anneal/v2/vendor/futures-util/src/future/select_ok.rs new file mode 100644 index 0000000000..5d5579930b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/select_ok.rs @@ -0,0 +1,85 @@ +use super::assert_future; +use crate::future::TryFutureExt; +use alloc::vec::Vec; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select_ok`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SelectOk { + inner: Vec, +} + +impl Unpin for SelectOk {} + +/// Creates a new future which will select the first successful future over a list of futures. +/// +/// The returned future will wait for any future within `iter` to be ready and Ok. Unlike +/// `select_all`, this will only return the first successful completion, or the last +/// failure. This is useful in contexts where any success is desired and failures +/// are ignored, unless all the futures fail. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # Panics +/// +/// This function will panic if the iterator specified contains no items. +pub fn select_ok(iter: I) -> SelectOk +where + I: IntoIterator, + I::Item: TryFuture + Unpin, +{ + let ret = SelectOk { inner: iter.into_iter().collect() }; + assert!(!ret.inner.is_empty(), "iterator provided to select_ok was empty"); + assert_future::< + Result<(::Ok, Vec), ::Error>, + _, + >(ret) +} + +impl Future for SelectOk { + type Output = Result<(Fut::Ok, Vec), Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // loop until we've either exhausted all errors, a success was hit, or nothing is ready + loop { + let item = + self.inner.iter_mut().enumerate().find_map(|(i, f)| match f.try_poll_unpin(cx) { + Poll::Pending => None, + Poll::Ready(e) => Some((i, e)), + }); + match item { + Some((idx, res)) => { + // always remove Ok or Err, if it's not the last Err continue looping + drop(self.inner.remove(idx)); + match res { + Ok(e) => { + let rest = mem::take(&mut self.inner); + return Poll::Ready(Ok((e, rest))); + } + Err(e) => { + if self.inner.is_empty() { + return Poll::Ready(Err(e)); + } + } + } + } + None => { + // based on the filter above, nothing is ready, return + return Poll::Pending; + } + } + } + } +} + +impl FromIterator for SelectOk { + fn from_iter>(iter: T) -> Self { + select_ok(iter) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_future/into_future.rs b/anneal/v2/vendor/futures-util/src/future/try_future/into_future.rs new file mode 100644 index 0000000000..9f093d0e2e --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_future/into_future.rs @@ -0,0 +1,36 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`into_future`](super::TryFutureExt::into_future) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct IntoFuture { + #[pin] + future: Fut, + } +} + +impl IntoFuture { + #[inline] + pub(crate) fn new(future: Fut) -> Self { + Self { future } + } +} + +impl FusedFuture for IntoFuture { + fn is_terminated(&self) -> bool { + self.future.is_terminated() + } +} + +impl Future for IntoFuture { + type Output = Result; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.project().future.try_poll(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_future/mod.rs b/anneal/v2/vendor/futures-util/src/future/try_future/mod.rs new file mode 100644 index 0000000000..e5bc700714 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_future/mod.rs @@ -0,0 +1,625 @@ +//! Futures +//! +//! This module contains a number of functions for working with `Future`s, +//! including the `FutureExt` trait which adds methods to `Future` types. + +#[cfg(feature = "compat")] +use crate::compat::Compat; +use core::pin::Pin; +use futures_core::{ + future::TryFuture, + stream::TryStream, + task::{Context, Poll}, +}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +use crate::fns::{ + inspect_err_fn, inspect_ok_fn, into_fn, map_err_fn, map_ok_fn, map_ok_or_else_fn, + unwrap_or_else_fn, InspectErrFn, InspectOkFn, IntoFn, MapErrFn, MapOkFn, MapOkOrElseFn, + UnwrapOrElseFn, +}; +use crate::future::{assert_future, Inspect, Map}; +use crate::stream::assert_stream; + +// Combinators +mod into_future; +mod try_flatten; +mod try_flatten_err; + +delegate_all!( + /// Future for the [`try_flatten`](TryFutureExt::try_flatten) method. + TryFlatten( + try_flatten::TryFlatten + ): Debug + Future + FusedFuture + New[|x: Fut1| try_flatten::TryFlatten::new(x)] +); + +delegate_all!( + /// Future for the [`try_flatten_err`](TryFutureExt::try_flatten_err) method. + TryFlattenErr( + try_flatten_err::TryFlattenErr + ): Debug + Future + FusedFuture + New[|x: Fut1| try_flatten_err::TryFlattenErr::new(x)] +); + +delegate_all!( + /// Future for the [`try_flatten_stream`](TryFutureExt::try_flatten_stream) method. + TryFlattenStream( + try_flatten::TryFlatten + ): Debug + Sink + Stream + FusedStream + New[|x: Fut| try_flatten::TryFlatten::new(x)] + where Fut: TryFuture +); + +#[cfg(feature = "sink")] +delegate_all!( + /// Sink for the [`flatten_sink`](TryFutureExt::flatten_sink) method. + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + FlattenSink( + try_flatten::TryFlatten + ): Debug + Sink + Stream + FusedStream + New[|x: Fut| try_flatten::TryFlatten::new(x)] +); + +delegate_all!( + /// Future for the [`and_then`](TryFutureExt::and_then) method. + AndThen( + TryFlatten, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, f: F| TryFlatten::new(MapOk::new(x, f))] +); + +delegate_all!( + /// Future for the [`or_else`](TryFutureExt::or_else) method. + OrElse( + TryFlattenErr, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, f: F| TryFlattenErr::new(MapErr::new(x, f))] +); + +delegate_all!( + /// Future for the [`err_into`](TryFutureExt::err_into) method. + ErrInto( + MapErr> + ): Debug + Future + FusedFuture + New[|x: Fut| MapErr::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`ok_into`](TryFutureExt::ok_into) method. + OkInto( + MapOk> + ): Debug + Future + FusedFuture + New[|x: Fut| MapOk::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`inspect_ok`](super::TryFutureExt::inspect_ok) method. + InspectOk( + Inspect, InspectOkFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Inspect::new(IntoFuture::new(x), inspect_ok_fn(f))] +); + +delegate_all!( + /// Future for the [`inspect_err`](super::TryFutureExt::inspect_err) method. + InspectErr( + Inspect, InspectErrFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Inspect::new(IntoFuture::new(x), inspect_err_fn(f))] +); + +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::into_future::IntoFuture; + +delegate_all!( + /// Future for the [`map_ok`](TryFutureExt::map_ok) method. + MapOk( + Map, MapOkFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), map_ok_fn(f))] +); + +delegate_all!( + /// Future for the [`map_err`](TryFutureExt::map_err) method. + MapErr( + Map, MapErrFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), map_err_fn(f))] +); + +delegate_all!( + /// Future for the [`map_ok_or_else`](TryFutureExt::map_ok_or_else) method. + MapOkOrElse( + Map, MapOkOrElseFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F, g: G| Map::new(IntoFuture::new(x), map_ok_or_else_fn(f, g))] +); + +delegate_all!( + /// Future for the [`unwrap_or_else`](TryFutureExt::unwrap_or_else) method. + UnwrapOrElse( + Map, UnwrapOrElseFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), unwrap_or_else_fn(f))] +); + +impl TryFutureExt for Fut {} + +/// Adapters specific to [`Result`]-returning futures +pub trait TryFutureExt: TryFuture { + /// Flattens the execution of this future when the successful result of this + /// future is a [`Sink`]. + /// + /// This can be useful when sink initialization is deferred, and it is + /// convenient to work with that sink as if the sink was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::{Future, TryFutureExt}; + /// use futures::sink::Sink; + /// # use futures::channel::mpsc::{self, SendError}; + /// # type T = i32; + /// # type E = SendError; + /// + /// fn make_sink_async() -> impl Future, + /// E, + /// >> { // ... } + /// # let (tx, _rx) = mpsc::unbounded::(); + /// # futures::future::ready(Ok(tx)) + /// # } + /// fn take_sink(sink: impl Sink) { /* ... */ } + /// + /// let fut = make_sink_async(); + /// take_sink(fut.flatten_sink()) + /// ``` + #[cfg(feature = "sink")] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + fn flatten_sink(self) -> FlattenSink + where + Self::Ok: Sink, + Self: Sized, + { + crate::sink::assert_sink::(FlattenSink::new(self)) + } + + /// Maps this future's success value to a different value. + /// + /// This method can be used to change the [`Ok`](TryFuture::Ok) type of the + /// future into a different type. It is similar to the [`Result::map`] + /// method. You can use this method to chain along a computation once the + /// future has been resolved. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If it resolves to an [`Err`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.map_ok(|x| x + 3); + /// assert_eq!(future.await, Ok(4)); + /// # }); + /// ``` + /// + /// Calling [`map_ok`](TryFutureExt::map_ok) on an errored future has no + /// effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.map_ok(|x| x + 3); + /// assert_eq!(future.await, Err(1)); + /// # }); + /// ``` + fn map_ok(self, f: F) -> MapOk + where + F: FnOnce(Self::Ok) -> T, + Self: Sized, + { + assert_future::, _>(MapOk::new(self, f)) + } + + /// Maps this future's success value to a different value, and permits for error handling resulting in the same type. + /// + /// This method can be used to coalesce your [`Ok`](TryFuture::Ok) type and [`Error`](TryFuture::Error) into another type, + /// where that type is the same for both outcomes. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If it resolves to an [`Err`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// The provided closure `e` will only be called if this future is resolved + /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(5) }; + /// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3); + /// assert_eq!(future.await, 8); + /// + /// let future = async { Err::(5) }; + /// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3); + /// assert_eq!(future.await, 10); + /// # }); + /// ``` + /// + fn map_ok_or_else(self, e: E, f: F) -> MapOkOrElse + where + F: FnOnce(Self::Ok) -> T, + E: FnOnce(Self::Error) -> T, + Self: Sized, + { + assert_future::(MapOkOrElse::new(self, f, e)) + } + + /// Maps this future's error value to a different value. + /// + /// This method can be used to change the [`Error`](TryFuture::Error) type + /// of the future into a different type. It is similar to the + /// [`Result::map_err`] method. You can use this method for example to + /// ensure that futures have the same [`Error`](TryFuture::Error) type when + /// using [`select!`] or [`join!`]. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.map_err(|x| x + 3); + /// assert_eq!(future.await, Err(4)); + /// # }); + /// ``` + /// + /// Calling [`map_err`](TryFutureExt::map_err) on a successful future has + /// no effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.map_err(|x| x + 3); + /// assert_eq!(future.await, Ok(1)); + /// # }); + /// ``` + /// + /// [`join!`]: crate::join + /// [`select!`]: crate::select + fn map_err(self, f: F) -> MapErr + where + F: FnOnce(Self::Error) -> E, + Self: Sized, + { + assert_future::, _>(MapErr::new(self, f)) + } + + /// Maps this future's [`Error`](TryFuture::Error) to a new error type + /// using the [`Into`](std::convert::Into) trait. + /// + /// This method does for futures what the `?`-operator does for + /// [`Result`]: It lets the compiler infer the type of the resulting + /// error. Just as [`map_err`](TryFutureExt::map_err), this is useful for + /// example to ensure that futures have the same [`Error`](TryFuture::Error) + /// type when using [`select!`] or [`join!`]. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future_err_u8 = async { Err::<(), u8>(1) }; + /// let future_err_i32 = future_err_u8.err_into::(); + /// # }); + /// ``` + /// + /// [`join!`]: crate::join + /// [`select!`]: crate::select + fn err_into(self) -> ErrInto + where + Self: Sized, + Self::Error: Into, + { + assert_future::, _>(ErrInto::new(self)) + } + + /// Maps this future's [`Ok`](TryFuture::Ok) to a new type + /// using the [`Into`](std::convert::Into) trait. + fn ok_into(self) -> OkInto + where + Self: Sized, + Self::Ok: Into, + { + assert_future::, _>(OkInto::new(self)) + } + + /// Executes another future after this one resolves successfully. The + /// success value is passed to a closure to create this subsequent future. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If this future resolves to an [`Err`], panics, or is + /// dropped, then the provided closure will never be invoked. The + /// [`Error`](TryFuture::Error) type of this future and the future + /// returned by `f` have to match. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.and_then(|x| async move { Ok::(x + 3) }); + /// assert_eq!(future.await, Ok(4)); + /// # }); + /// ``` + /// + /// Calling [`and_then`](TryFutureExt::and_then) on an errored future has no + /// effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.and_then(|x| async move { Err::(x + 3) }); + /// assert_eq!(future.await, Err(1)); + /// # }); + /// ``` + fn and_then(self, f: F) -> AndThen + where + F: FnOnce(Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(AndThen::new(self, f)) + } + + /// Executes another future if this one resolves to an error. The + /// error value is passed to a closure to create this subsequent future. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Err`]. If this future resolves to an [`Ok`], panics, or is + /// dropped, then the provided closure will never be invoked. The + /// [`Ok`](TryFuture::Ok) type of this future and the future returned by `f` + /// have to match. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.or_else(|x| async move { Err::(x + 3) }); + /// assert_eq!(future.await, Err(4)); + /// # }); + /// ``` + /// + /// Calling [`or_else`](TryFutureExt::or_else) on a successful future has + /// no effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.or_else(|x| async move { Ok::(x + 3) }); + /// assert_eq!(future.await, Ok(1)); + /// # }); + /// ``` + fn or_else(self, f: F) -> OrElse + where + F: FnOnce(Self::Error) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(OrElse::new(self, f)) + } + + /// Do something with the success value of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect_ok`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// + /// let future = async { Ok::<_, ()>(1) }; + /// let new_future = future.inspect_ok(|&x| println!("about to resolve: {}", x)); + /// assert_eq!(new_future.await, Ok(1)); + /// # }); + /// ``` + fn inspect_ok(self, f: F) -> InspectOk + where + F: FnOnce(&Self::Ok), + Self: Sized, + { + assert_future::, _>(InspectOk::new(self, f)) + } + + /// Do something with the error value of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect_err`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// + /// let future = async { Err::<(), _>(1) }; + /// let new_future = future.inspect_err(|&x| println!("about to error: {}", x)); + /// assert_eq!(new_future.await, Err(1)); + /// # }); + /// ``` + fn inspect_err(self, f: F) -> InspectErr + where + F: FnOnce(&Self::Error), + Self: Sized, + { + assert_future::, _>(InspectErr::new(self, f)) + } + + /// Flatten the execution of this future when the successful result of this + /// future is another future. + /// + /// This is equivalent to `future.and_then(|x| x)`. + fn try_flatten(self) -> TryFlatten + where + Self::Ok: TryFuture, + Self: Sized, + { + assert_future::::Ok, Self::Error>, _>(TryFlatten::new(self)) + } + + /// Flatten the execution of this future when the successful result of this + /// future is a stream. + /// + /// This can be useful when stream initialization is deferred, and it is + /// convenient to work with that stream as if stream was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// use futures::stream::{self, TryStreamExt}; + /// + /// let stream_items = vec![17, 18, 19].into_iter().map(Ok); + /// let future_of_a_stream = async { Ok::<_, ()>(stream::iter(stream_items)) }; + /// + /// let stream = future_of_a_stream.try_flatten_stream(); + /// let list = stream.try_collect::>().await; + /// assert_eq!(list, Ok(vec![17, 18, 19])); + /// # }); + /// ``` + fn try_flatten_stream(self) -> TryFlattenStream + where + Self::Ok: TryStream, + Self: Sized, + { + assert_stream::::Ok, Self::Error>, _>(TryFlattenStream::new( + self, + )) + } + + /// Unwraps this future's output, producing a future with this future's + /// [`Ok`](TryFuture::Ok) type as its + /// [`Output`](std::future::Future::Output) type. + /// + /// If this future is resolved successfully, the returned future will + /// contain the original future's success value as output. Otherwise, the + /// closure `f` is called with the error value to produce an alternate + /// success value. + /// + /// This method is similar to the [`Result::unwrap_or_else`] method. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::<(), &str>("Boom!") }; + /// let future = future.unwrap_or_else(|_| ()); + /// assert_eq!(future.await, ()); + /// # }); + /// ``` + fn unwrap_or_else(self, f: F) -> UnwrapOrElse + where + Self: Sized, + F: FnOnce(Self::Error) -> Self::Ok, + { + assert_future::(UnwrapOrElse::new(self, f)) + } + + /// Wraps a [`TryFuture`] into a future compatible with libraries using + /// futures 0.1 future definitions. Requires the `compat` feature to enable. + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> Compat + where + Self: Sized + Unpin, + { + Compat::new(self) + } + + /// Wraps a [`TryFuture`] into a type that implements + /// [`Future`](std::future::Future). + /// + /// [`TryFuture`]s currently do not implement the + /// [`Future`](std::future::Future) trait due to limitations of the + /// compiler. + /// + /// # Examples + /// + /// ``` + /// use futures::future::{Future, TryFuture, TryFutureExt}; + /// + /// # type T = i32; + /// # type E = (); + /// fn make_try_future() -> impl TryFuture { // ... } + /// # async { Ok::(1) } + /// # } + /// fn take_future(future: impl Future>) { /* ... */ } + /// + /// take_future(make_try_future().into_future()); + /// ``` + fn into_future(self) -> IntoFuture + where + Self: Sized, + { + assert_future::, _>(IntoFuture::new(self)) + } + + /// A convenience method for calling [`TryFuture::try_poll`] on [`Unpin`] + /// future types. + fn try_poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).try_poll(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten.rs b/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten.rs new file mode 100644 index 0000000000..1ce4559ac2 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten.rs @@ -0,0 +1,162 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + #[project = TryFlattenProj] + #[derive(Debug)] + pub enum TryFlatten { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl TryFlatten { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryFuture, +{ + type Output = Result<::Ok, Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Err(e); + } + }, + TryFlattenProj::Second { f } => { + let output = ready!(f.try_poll(cx)); + self.set(Self::Empty); + break output; + } + TryFlattenProj::Empty => panic!("TryFlatten polled after completion"), + } + }) + } +} + +impl FusedStream for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryStream, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Stream for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryStream, +{ + type Item = Result<::Ok, Fut::Error>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Some(Err(e)); + } + }, + TryFlattenProj::Second { f } => { + let output = ready!(f.try_poll_next(cx)); + if output.is_none() { + self.set(Self::Empty); + } + break output; + } + TryFlattenProj::Empty => break None, + } + }) + } +} + +#[cfg(feature = "sink")] +impl Sink for TryFlatten +where + Fut: TryFuture, + Fut::Ok: Sink, +{ + type Error = Fut::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Err(e); + } + }, + TryFlattenProj::Second { f } => { + break ready!(f.poll_ready(cx)); + } + TryFlattenProj::Empty => panic!("poll_ready called after eof"), + } + }) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.project() { + TryFlattenProj::First { .. } => panic!("poll_ready not called first"), + TryFlattenProj::Second { f } => f.start_send(item), + TryFlattenProj::Empty => panic!("start_send called after eof"), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project() { + TryFlattenProj::First { .. } => Poll::Ready(Ok(())), + TryFlattenProj::Second { f } => f.poll_flush(cx), + TryFlattenProj::Empty => panic!("poll_flush called after eof"), + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let res = match self.as_mut().project() { + TryFlattenProj::Second { f } => f.poll_close(cx), + _ => Poll::Ready(Ok(())), + }; + if res.is_ready() { + self.set(Self::Empty); + } + res + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten_err.rs b/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten_err.rs new file mode 100644 index 0000000000..39b7d9f5f6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_future/try_flatten_err.rs @@ -0,0 +1,62 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + #[project = TryFlattenErrProj] + #[derive(Debug)] + pub enum TryFlattenErr { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl TryFlattenErr { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for TryFlattenErr +where + Fut: TryFuture, + Fut::Error: TryFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for TryFlattenErr +where + Fut: TryFuture, + Fut::Error: TryFuture, +{ + type Output = Result::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenErrProj::First { f } => match ready!(f.try_poll(cx)) { + Err(f) => self.set(Self::Second { f }), + Ok(e) => { + self.set(Self::Empty); + break Ok(e); + } + }, + TryFlattenErrProj::Second { f } => { + let output = ready!(f.try_poll(cx)); + self.set(Self::Empty); + break output; + } + TryFlattenErrProj::Empty => panic!("TryFlattenErr polled after completion"), + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_join.rs b/anneal/v2/vendor/futures-util/src/future/try_join.rs new file mode 100644 index 0000000000..6af1f0ccbf --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_join.rs @@ -0,0 +1,256 @@ +#![allow(non_snake_case)] + +use crate::future::{assert_future, try_maybe_done, TryMaybeDone}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +macro_rules! generate { + ($( + $(#[$doc:meta])* + ($Join:ident, ), + )*) => ($( + pin_project! { + $(#[$doc])* + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct $Join { + #[pin] Fut1: TryMaybeDone, + $(#[pin] $Fut: TryMaybeDone<$Fut>,)* + } + } + + impl fmt::Debug for $Join + where + Fut1: TryFuture + fmt::Debug, + Fut1::Ok: fmt::Debug, + Fut1::Error: fmt::Debug, + $( + $Fut: TryFuture + fmt::Debug, + $Fut::Ok: fmt::Debug, + $Fut::Error: fmt::Debug, + )* + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(stringify!($Join)) + .field("Fut1", &self.Fut1) + $(.field(stringify!($Fut), &self.$Fut))* + .finish() + } + } + + impl $Join + where + Fut1: TryFuture, + $( + $Fut: TryFuture + ),* + { + fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self { + Self { + Fut1: try_maybe_done(Fut1), + $($Fut: try_maybe_done($Fut)),* + } + } + } + + impl Future for $Join + where + Fut1: TryFuture, + $( + $Fut: TryFuture + ),* + { + type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>; + + fn poll( + self: Pin<&mut Self>, cx: &mut Context<'_> + ) -> Poll { + let mut all_done = true; + let mut futures = self.project(); + all_done &= futures.Fut1.as_mut().poll(cx)?.is_ready(); + $( + all_done &= futures.$Fut.as_mut().poll(cx)?.is_ready(); + )* + + if all_done { + Poll::Ready(Ok(( + futures.Fut1.take_output().unwrap(), + $( + futures.$Fut.take_output().unwrap() + ),* + ))) + } else { + Poll::Pending + } + } + } + )*) +} + +generate! { + /// Future for the [`try_join`](try_join()) function. + (TryJoin, ), + + /// Future for the [`try_join3`] function. + (TryJoin3, ), + + /// Future for the [`try_join4`] function. + (TryJoin4, ), + + /// Future for the [`try_join5`] function. + (TryJoin5, ), +} + +/// Joins the result of two futures, waiting for them both to complete or +/// for one to produce an error. +/// +/// This function will return a new future which awaits both futures to +/// complete. If successful, the returned future will finish with a tuple of +/// both results. If unsuccessful, it will complete with the first error +/// encountered. +/// +/// Note that this function consumes the passed futures and returns a +/// wrapped version of it. +/// +/// # Examples +/// +/// When used on multiple futures that return [`Ok`], `try_join` will return +/// [`Ok`] of a tuple of the values: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let pair = future::try_join(a, b); +/// +/// assert_eq!(pair.await, Ok((1, 2))); +/// # }); +/// ``` +/// +/// If one of the futures resolves to an error, `try_join` will return +/// that error: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Err::(2)); +/// let pair = future::try_join(a, b); +/// +/// assert_eq!(pair.await, Err(2)); +/// # }); +/// ``` +pub fn try_join(future1: Fut1, future2: Fut2) -> TryJoin +where + Fut1: TryFuture, + Fut2: TryFuture, +{ + assert_future::, _>(TryJoin::new(future1, future2)) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let tuple = future::try_join3(a, b, c); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3))); +/// # }); +/// ``` +pub fn try_join3( + future1: Fut1, + future2: Fut2, + future3: Fut3, +) -> TryJoin3 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, +{ + assert_future::, _>(TryJoin3::new( + future1, future2, future3, + )) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let d = future::ready(Ok::(4)); +/// let tuple = future::try_join4(a, b, c, d); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3, 4))); +/// # }); +/// ``` +pub fn try_join4( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, +) -> TryJoin4 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, + Fut4: TryFuture, +{ + assert_future::, _>( + TryJoin4::new(future1, future2, future3, future4), + ) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let d = future::ready(Ok::(4)); +/// let e = future::ready(Ok::(5)); +/// let tuple = future::try_join5(a, b, c, d, e); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3, 4, 5))); +/// # }); +/// ``` +pub fn try_join5( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, + future5: Fut5, +) -> TryJoin5 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, + Fut4: TryFuture, + Fut5: TryFuture, +{ + assert_future::, _>( + TryJoin5::new(future1, future2, future3, future4, future5), + ) +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_join_all.rs b/anneal/v2/vendor/futures-util/src/future/try_join_all.rs new file mode 100644 index 0000000000..2d6a2a02cb --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_join_all.rs @@ -0,0 +1,201 @@ +//! Definition of the `TryJoinAll` combinator, waiting for all of a list of +//! futures to finish with either success or error. + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Context, Poll}; + +use super::{assert_future, join_all, IntoFuture, TryFuture, TryMaybeDone}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +use crate::stream::{FuturesOrdered, TryCollect, TryStreamExt}; +use crate::TryFutureExt; + +enum FinalState { + Pending, + AllDone, + Error(E), +} + +/// Future for the [`try_join_all`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct TryJoinAll +where + F: TryFuture, +{ + kind: TryJoinAllKind, +} + +enum TryJoinAllKind +where + F: TryFuture, +{ + Small { + elems: Pin>]>>, + }, + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + Big { + fut: TryCollect>, Vec>, + }, +} + +impl fmt::Debug for TryJoinAll +where + F: TryFuture + fmt::Debug, + F::Ok: fmt::Debug, + F::Error: fmt::Debug, + F::Output: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + TryJoinAllKind::Small { ref elems } => { + f.debug_struct("TryJoinAll").field("elems", elems).finish() + } + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + TryJoinAllKind::Big { ref fut, .. } => fmt::Debug::fmt(fut, f), + } + } +} + +/// Creates a future which represents either a collection of the results of the +/// futures given or an error. +/// +/// The returned future will drive execution for all of its underlying futures, +/// collecting the results into a destination `Vec` in the same order as they +/// were provided. +/// +/// If any future returns an error then all other futures will be canceled and +/// an error will be returned immediately. If all futures complete successfully, +/// however, then the returned future will succeed with a `Vec` of all the +/// successful results. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # See Also +/// +/// `try_join_all` will switch to the more powerful [`FuturesOrdered`] for performance +/// reasons if the number of futures is large. You may want to look into using it or +/// it's counterpart [`FuturesUnordered`][crate::stream::FuturesUnordered] directly. +/// +/// Some examples for additional functionality provided by these are: +/// +/// * Adding new futures to the set even after it has been started. +/// +/// * Only polling the specific futures that have been woken. In cases where +/// you have a lot of futures this will result in much more efficient polling. +/// +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::{self, try_join_all}; +/// +/// let futures = vec![ +/// future::ok::(1), +/// future::ok::(2), +/// future::ok::(3), +/// ]; +/// +/// assert_eq!(try_join_all(futures).await, Ok(vec![1, 2, 3])); +/// +/// let futures = vec![ +/// future::ok::(1), +/// future::err::(2), +/// future::ok::(3), +/// ]; +/// +/// assert_eq!(try_join_all(futures).await, Err(2)); +/// # }); +/// ``` +pub fn try_join_all(iter: I) -> TryJoinAll +where + I: IntoIterator, + I::Item: TryFuture, +{ + let iter = iter.into_iter().map(TryFutureExt::into_future); + + #[cfg(target_os = "none")] + #[cfg_attr(target_os = "none", cfg(not(target_has_atomic = "ptr")))] + { + let kind = TryJoinAllKind::Small { + elems: iter.map(TryMaybeDone::Future).collect::>().into(), + }; + + assert_future::::Ok>, ::Error>, _>( + TryJoinAll { kind }, + ) + } + + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + { + let kind = match iter.size_hint().1 { + Some(max) if max <= join_all::SMALL => TryJoinAllKind::Small { + elems: iter.map(TryMaybeDone::Future).collect::>().into(), + }, + _ => TryJoinAllKind::Big { fut: iter.collect::>().try_collect() }, + }; + + assert_future::::Ok>, ::Error>, _>( + TryJoinAll { kind }, + ) + } +} + +impl Future for TryJoinAll +where + F: TryFuture, +{ + type Output = Result, F::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match &mut self.kind { + TryJoinAllKind::Small { elems } => { + let mut state = FinalState::AllDone; + + for elem in join_all::iter_pin_mut(elems.as_mut()) { + match elem.try_poll(cx) { + Poll::Pending => state = FinalState::Pending, + Poll::Ready(Ok(())) => {} + Poll::Ready(Err(e)) => { + state = FinalState::Error(e); + break; + } + } + } + + match state { + FinalState::Pending => Poll::Pending, + FinalState::AllDone => { + let mut elems = mem::replace(elems, Box::pin([])); + let results = join_all::iter_pin_mut(elems.as_mut()) + .map(|e| e.take_output().unwrap()) + .collect(); + Poll::Ready(Ok(results)) + } + FinalState::Error(e) => { + let _ = mem::replace(elems, Box::pin([])); + Poll::Ready(Err(e)) + } + } + } + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + TryJoinAllKind::Big { fut } => Pin::new(fut).poll(cx), + } + } +} + +impl FromIterator for TryJoinAll +where + F: TryFuture, +{ + fn from_iter>(iter: T) -> Self { + try_join_all(iter) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_maybe_done.rs b/anneal/v2/vendor/futures-util/src/future/try_maybe_done.rs new file mode 100644 index 0000000000..97af6ad437 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_maybe_done.rs @@ -0,0 +1,92 @@ +//! Definition of the TryMaybeDone combinator + +use super::assert_future; +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; + +/// A future that may have completed with an error. +/// +/// This is created by the [`try_maybe_done()`] function. +#[derive(Debug)] +pub enum TryMaybeDone { + /// A not-yet-completed future + Future(/* #[pin] */ Fut), + /// The output of the completed future + Done(Fut::Ok), + /// The empty variant after the result of a [`TryMaybeDone`] has been + /// taken using the [`take_output`](TryMaybeDone::take_output) method, + /// or if the future returned an error. + Gone, +} + +impl Unpin for TryMaybeDone {} + +/// Wraps a future into a `TryMaybeDone` +pub fn try_maybe_done(future: Fut) -> TryMaybeDone { + assert_future::, _>(TryMaybeDone::Future(future)) +} + +impl TryMaybeDone { + /// Returns an [`Option`] containing a mutable reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has completed successfully and [`take_output`](TryMaybeDone::take_output) + /// has not yet been called. + #[inline] + pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Ok> { + unsafe { + match self.get_unchecked_mut() { + Self::Done(res) => Some(res), + _ => None, + } + } + } + + /// Attempt to take the output of a `TryMaybeDone` without driving it + /// towards completion. + #[inline] + pub fn take_output(self: Pin<&mut Self>) -> Option { + match &*self { + Self::Done(_) => {} + Self::Future(_) | Self::Gone => return None, + } + unsafe { + match mem::replace(self.get_unchecked_mut(), Self::Gone) { + Self::Done(output) => Some(output), + _ => unreachable!(), + } + } + } +} + +impl FusedFuture for TryMaybeDone { + fn is_terminated(&self) -> bool { + match self { + Self::Future(_) => false, + Self::Done(_) | Self::Gone => true, + } + } +} + +impl Future for TryMaybeDone { + type Output = Result<(), Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unsafe { + match self.as_mut().get_unchecked_mut() { + Self::Future(f) => match ready!(Pin::new_unchecked(f).try_poll(cx)) { + Ok(res) => self.set(Self::Done(res)), + Err(e) => { + self.set(Self::Gone); + return Poll::Ready(Err(e)); + } + }, + Self::Done(_) => {} + Self::Gone => panic!("TryMaybeDone polled after value taken"), + } + } + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/future/try_select.rs b/anneal/v2/vendor/futures-util/src/future/try_select.rs new file mode 100644 index 0000000000..bc282f7db1 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/future/try_select.rs @@ -0,0 +1,85 @@ +use crate::future::{Either, TryFutureExt}; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`try_select()`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +pub struct TrySelect { + inner: Option<(A, B)>, +} + +impl Unpin for TrySelect {} + +type EitherOk = Either<(::Ok, B), (::Ok, A)>; +type EitherErr = Either<(::Error, B), (::Error, A)>; + +/// Waits for either one of two differently-typed futures to complete. +/// +/// This function will return a new future which awaits for either one of both +/// futures to complete. The returned future will finish with both the value +/// resolved and a future representing the completion of the other work. +/// +/// Note that this function consumes the receiving futures and returns a +/// wrapped version of them. +/// +/// Also note that if both this and the second future have the same +/// success/error type you can use the `Either::factor_first` method to +/// conveniently extract out the value at the end. +/// +/// # Examples +/// +/// ``` +/// use futures::future::{self, Either, Future, FutureExt, TryFuture, TryFutureExt}; +/// +/// // A poor-man's try_join implemented on top of select +/// +/// fn try_join(a: A, b: B) -> impl TryFuture +/// where A: TryFuture + Unpin + 'static, +/// B: TryFuture + Unpin + 'static, +/// E: 'static, +/// { +/// future::try_select(a, b).then(|res| -> Box> + Unpin> { +/// match res { +/// Ok(Either::Left((x, b))) => Box::new(b.map_ok(move |y| (x, y))), +/// Ok(Either::Right((y, a))) => Box::new(a.map_ok(move |x| (x, y))), +/// Err(Either::Left((e, _))) => Box::new(future::err(e)), +/// Err(Either::Right((e, _))) => Box::new(future::err(e)), +/// } +/// }) +/// } +/// ``` +pub fn try_select(future1: A, future2: B) -> TrySelect +where + A: TryFuture + Unpin, + B: TryFuture + Unpin, +{ + super::assert_future::, EitherErr>, _>(TrySelect { + inner: Some((future1, future2)), + }) +} + +impl Future for TrySelect +where + A: TryFuture, + B: TryFuture, +{ + type Output = Result, EitherErr>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let (mut a, mut b) = self.inner.take().expect("cannot poll Select twice"); + match a.try_poll_unpin(cx) { + Poll::Ready(Err(x)) => Poll::Ready(Err(Either::Left((x, b)))), + Poll::Ready(Ok(x)) => Poll::Ready(Ok(Either::Left((x, b)))), + Poll::Pending => match b.try_poll_unpin(cx) { + Poll::Ready(Err(x)) => Poll::Ready(Err(Either::Right((x, a)))), + Poll::Ready(Ok(x)) => Poll::Ready(Ok(Either::Right((x, a)))), + Poll::Pending => { + self.inner = Some((a, b)); + Poll::Pending + } + }, + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/allow_std.rs b/anneal/v2/vendor/futures-util/src/io/allow_std.rs new file mode 100644 index 0000000000..96133cbc6f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/allow_std.rs @@ -0,0 +1,202 @@ +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom}; +use std::pin::Pin; +use std::string::String; +use std::vec::Vec; +use std::{fmt, io}; + +/// A simple wrapper type which allows types which implement only +/// implement `std::io::Read` or `std::io::Write` +/// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`. +/// +/// If these types issue an error with the kind `io::ErrorKind::WouldBlock`, +/// it is expected that they will notify the current task on readiness. +/// Synchronous `std` types should not issue errors of this kind and +/// are safe to use in this context. However, using these types with +/// `AllowStdIo` will cause the event loop to block, so they should be used +/// with care. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct AllowStdIo(T); + +impl Unpin for AllowStdIo {} + +macro_rules! try_with_interrupt { + ($e:expr) => { + loop { + match $e { + Ok(e) => { + break e; + } + Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => { + continue; + } + Err(e) => { + return Poll::Ready(Err(e)); + } + } + } + }; +} + +impl AllowStdIo { + /// Creates a new `AllowStdIo` from an existing IO object. + pub fn new(io: T) -> Self { + Self(io) + } + + /// Returns a reference to the contained IO object. + pub fn get_ref(&self) -> &T { + &self.0 + } + + /// Returns a mutable reference to the contained IO object. + pub fn get_mut(&mut self) -> &mut T { + &mut self.0 + } + + /// Consumes self and returns the contained IO object. + pub fn into_inner(self) -> T { + self.0 + } +} + +impl io::Write for AllowStdIo +where + T: io::Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.0.write_all(buf) + } + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + self.0.write_fmt(fmt) + } +} + +impl AsyncWrite for AllowStdIo +where + T: io::Write, +{ + fn poll_write( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Poll::Ready(Ok(try_with_interrupt!(self.0.write(buf)))) + } + + fn poll_write_vectored( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + Poll::Ready(Ok(try_with_interrupt!(self.0.write_vectored(bufs)))) + } + + fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + try_with_interrupt!(self.0.flush()); + Poll::Ready(Ok(())) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_flush(cx) + } +} + +impl io::Read for AllowStdIo +where + T: io::Read, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.0.read_to_string(buf) + } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.0.read_exact(buf) + } +} + +impl AsyncRead for AllowStdIo +where + T: io::Read, +{ + fn poll_read( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + Poll::Ready(Ok(try_with_interrupt!(self.0.read(buf)))) + } + + fn poll_read_vectored( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + Poll::Ready(Ok(try_with_interrupt!(self.0.read_vectored(bufs)))) + } +} + +impl io::Seek for AllowStdIo +where + T: io::Seek, +{ + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.0.seek(pos) + } +} + +impl AsyncSeek for AllowStdIo +where + T: io::Seek, +{ + fn poll_seek( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + Poll::Ready(Ok(try_with_interrupt!(self.0.seek(pos)))) + } +} + +impl io::BufRead for AllowStdIo +where + T: io::BufRead, +{ + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.0.fill_buf() + } + fn consume(&mut self, amt: usize) { + self.0.consume(amt) + } +} + +impl AsyncBufRead for AllowStdIo +where + T: io::BufRead, +{ + fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + let this: *mut Self = &mut *self as *mut _; + Poll::Ready(Ok(try_with_interrupt!(unsafe { &mut *this }.0.fill_buf()))) + } + + fn consume(mut self: Pin<&mut Self>, amt: usize) { + self.0.consume(amt) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/buf_reader.rs b/anneal/v2/vendor/futures-util/src/io/buf_reader.rs new file mode 100644 index 0000000000..9a919f7183 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/buf_reader.rs @@ -0,0 +1,264 @@ +use super::DEFAULT_BUF_SIZE; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSliceMut, SeekFrom}; +use pin_project_lite::pin_project; +use std::boxed::Box; +use std::io::{self, Read}; +use std::pin::Pin; +use std::vec; +use std::{cmp, fmt}; + +pin_project! { + /// The `BufReader` struct adds buffering to any reader. + /// + /// It can be excessively inefficient to work directly with a [`AsyncRead`] + /// instance. A `BufReader` performs large, infrequent reads on the underlying + /// [`AsyncRead`] and maintains an in-memory buffer of the results. + /// + /// `BufReader` can improve the speed of programs that make *small* and + /// *repeated* read calls to the same file or network socket. It does not + /// help when reading very large amounts at once, or reading just one or a few + /// times. It also provides no advantage when reading from a source that is + /// already in memory, like a `Vec`. + /// + /// When the `BufReader` is dropped, the contents of its buffer will be + /// discarded. Creating multiple instances of a `BufReader` on the same + /// stream can cause data loss. + /// + /// [`AsyncRead`]: futures_io::AsyncRead + /// + // TODO: Examples + pub struct BufReader { + #[pin] + inner: R, + buffer: Box<[u8]>, + pos: usize, + cap: usize, + } +} + +impl BufReader { + /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. + pub fn new(inner: R) -> Self { + Self::with_capacity(DEFAULT_BUF_SIZE, inner) + } + + /// Creates a new `BufReader` with the specified buffer capacity. + pub fn with_capacity(capacity: usize, inner: R) -> Self { + // TODO: consider using Box<[u8]>::new_uninit_slice once it stabilized + let buffer = vec![0; capacity]; + Self { inner, buffer: buffer.into_boxed_slice(), pos: 0, cap: 0 } + } +} + +impl BufReader { + delegate_access_inner!(inner, R, ()); + + /// Returns a reference to the internally buffered data. + /// + /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty. + pub fn buffer(&self) -> &[u8] { + &self.buffer[self.pos..self.cap] + } + + /// Invalidates all data in the internal buffer. + #[inline] + fn discard_buffer(self: Pin<&mut Self>) { + let this = self.project(); + *this.pos = 0; + *this.cap = 0; + } +} + +impl BufReader { + /// Seeks relative to the current position. If the new position lies within the buffer, + /// the buffer will not be flushed, allowing for more efficient seeks. + /// This method does not return the location of the underlying reader, so the caller + /// must track this information themselves if it is required. + pub fn seek_relative(self: Pin<&mut Self>, offset: i64) -> SeeKRelative<'_, R> { + SeeKRelative { inner: self, offset, first: true } + } + + /// Attempts to seek relative to the current position. If the new position lies within the buffer, + /// the buffer will not be flushed, allowing for more efficient seeks. + /// This method does not return the location of the underlying reader, so the caller + /// must track this information themselves if it is required. + pub fn poll_seek_relative( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + offset: i64, + ) -> Poll> { + let pos = self.pos as u64; + if offset < 0 { + if let Some(new_pos) = pos.checked_sub((-offset) as u64) { + *self.project().pos = new_pos as usize; + return Poll::Ready(Ok(())); + } + } else if let Some(new_pos) = pos.checked_add(offset as u64) { + if new_pos <= self.cap as u64 { + *self.project().pos = new_pos as usize; + return Poll::Ready(Ok(())); + } + } + self.poll_seek(cx, SeekFrom::Current(offset)).map(|res| res.map(|_| ())) + } +} + +impl AsyncRead for BufReader { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= self.buffer.len() { + let res = ready!(self.as_mut().project().inner.poll_read(cx, buf)); + self.discard_buffer(); + return Poll::Ready(res); + } + let mut rem = ready!(self.as_mut().poll_fill_buf(cx))?; + let nread = rem.read(buf)?; + self.consume(nread); + Poll::Ready(Ok(nread)) + } + + fn poll_read_vectored( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + let total_len = bufs.iter().map(|b| b.len()).sum::(); + if self.pos == self.cap && total_len >= self.buffer.len() { + let res = ready!(self.as_mut().project().inner.poll_read_vectored(cx, bufs)); + self.discard_buffer(); + return Poll::Ready(res); + } + let mut rem = ready!(self.as_mut().poll_fill_buf(cx))?; + let nread = rem.read_vectored(bufs)?; + self.consume(nread); + Poll::Ready(Ok(nread)) + } +} + +impl AsyncBufRead for BufReader { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + // Branch using `>=` instead of the more correct `==` + // to tell the compiler that the pos..cap slice is always valid. + if *this.pos >= *this.cap { + debug_assert!(*this.pos == *this.cap); + *this.cap = ready!(this.inner.poll_read(cx, this.buffer))?; + *this.pos = 0; + } + Poll::Ready(Ok(&this.buffer[*this.pos..*this.cap])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + *self.project().pos = cmp::min(self.pos + amt, self.cap); + } +} + +impl AsyncWrite for BufReader { + delegate_async_write!(inner); +} + +impl fmt::Debug for BufReader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BufReader") + .field("reader", &self.inner) + .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buffer.len())) + .finish() + } +} + +impl AsyncSeek for BufReader { + /// Seek to an offset, in bytes, in the underlying reader. + /// + /// The position used for seeking with `SeekFrom::Current(_)` is the + /// position the underlying reader would be at if the `BufReader` had no + /// internal buffer. + /// + /// Seeking always discards the internal buffer, even if the seek position + /// would otherwise fall within it. This guarantees that calling + /// `.into_inner()` immediately after a seek yields the underlying reader + /// at the same position. + /// + /// To seek without discarding the internal buffer, use + /// [`BufReader::seek_relative`](BufReader::seek_relative) or + /// [`BufReader::poll_seek_relative`](BufReader::poll_seek_relative). + /// + /// See [`AsyncSeek`](futures_io::AsyncSeek) for more details. + /// + /// Note: In the edge case where you're seeking with `SeekFrom::Current(n)` + /// where `n` minus the internal buffer length overflows an `i64`, two + /// seeks will be performed instead of one. If the second seek returns + /// `Err`, the underlying reader will be left at the same position it would + /// have if you called `seek` with `SeekFrom::Current(0)`. + fn poll_seek( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + let result: u64; + if let SeekFrom::Current(n) = pos { + let remainder = (self.cap - self.pos) as i64; + // it should be safe to assume that remainder fits within an i64 as the alternative + // means we managed to allocate 8 exbibytes and that's absurd. + // But it's not out of the realm of possibility for some weird underlying reader to + // support seeking by i64::MIN so we need to handle underflow when subtracting + // remainder. + if let Some(offset) = n.checked_sub(remainder) { + result = + ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(offset)))?; + } else { + // seek backwards by our remainder, and then by the offset + ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(-remainder)))?; + self.as_mut().discard_buffer(); + result = ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(n)))?; + } + } else { + // Seeking with Start/End doesn't care about our buffer length. + result = ready!(self.as_mut().project().inner.poll_seek(cx, pos))?; + } + self.discard_buffer(); + Poll::Ready(Ok(result)) + } +} + +/// Future for the [`BufReader::seek_relative`](self::BufReader::seek_relative) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless polled"] +pub struct SeeKRelative<'a, R> { + inner: Pin<&'a mut BufReader>, + offset: i64, + first: bool, +} + +impl Future for SeeKRelative<'_, R> +where + R: AsyncRead + AsyncSeek, +{ + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let offset = self.offset; + if self.first { + self.first = false; + self.inner.as_mut().poll_seek_relative(cx, offset) + } else { + self.inner + .as_mut() + .as_mut() + .poll_seek(cx, SeekFrom::Current(offset)) + .map(|res| res.map(|_| ())) + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/buf_writer.rs b/anneal/v2/vendor/futures-util/src/io/buf_writer.rs new file mode 100644 index 0000000000..ddcf5e1b4d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/buf_writer.rs @@ -0,0 +1,229 @@ +use super::DEFAULT_BUF_SIZE; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, SeekFrom}; +use pin_project_lite::pin_project; +use std::fmt; +use std::io::{self, Write}; +use std::pin::Pin; +use std::ptr; +use std::vec::Vec; + +pin_project! { + /// Wraps a writer and buffers its output. + /// + /// It can be excessively inefficient to work directly with something that + /// implements [`AsyncWrite`]. A `BufWriter` keeps an in-memory buffer of data and + /// writes it to an underlying writer in large, infrequent batches. + /// + /// `BufWriter` can improve the speed of programs that make *small* and + /// *repeated* write calls to the same file or network socket. It does not + /// help when writing very large amounts at once, or writing just one or a few + /// times. It also provides no advantage when writing to a destination that is + /// in memory, like a `Vec`. + /// + /// When the `BufWriter` is dropped, the contents of its buffer will be + /// discarded. Creating multiple instances of a `BufWriter` on the same + /// stream can cause data loss. If you need to write out the contents of its + /// buffer, you must manually call flush before the writer is dropped. + /// + /// [`AsyncWrite`]: futures_io::AsyncWrite + /// [`flush`]: super::AsyncWriteExt::flush + /// + // TODO: Examples + pub struct BufWriter { + #[pin] + inner: W, + buf: Vec, + written: usize, + } +} + +impl BufWriter { + /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. + pub fn new(inner: W) -> Self { + Self::with_capacity(DEFAULT_BUF_SIZE, inner) + } + + /// Creates a new `BufWriter` with the specified buffer capacity. + pub fn with_capacity(cap: usize, inner: W) -> Self { + Self { inner, buf: Vec::with_capacity(cap), written: 0 } + } + + pub(super) fn flush_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + let len = this.buf.len(); + let mut ret = Ok(()); + while *this.written < len { + match ready!(this.inner.as_mut().poll_write(cx, &this.buf[*this.written..])) { + Ok(0) => { + ret = Err(io::Error::new( + io::ErrorKind::WriteZero, + "failed to write the buffered data", + )); + break; + } + Ok(n) => *this.written += n, + Err(e) => { + ret = Err(e); + break; + } + } + } + if *this.written > 0 { + this.buf.drain(..*this.written); + } + *this.written = 0; + Poll::Ready(ret) + } + + /// Write directly using `inner`, bypassing buffering + pub(super) fn inner_poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + self.project().inner.poll_write(cx, buf) + } + + /// Write directly using `inner`, bypassing buffering + pub(super) fn inner_poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + self.project().inner.poll_write_vectored(cx, bufs) + } +} + +impl BufWriter { + delegate_access_inner!(inner, W, ()); + + /// Returns a reference to the internally buffered data. + pub fn buffer(&self) -> &[u8] { + &self.buf + } + + /// Capacity of `buf`. how many chars can be held in buffer + pub(super) fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Remaining number of bytes to reach `buf` 's capacity + #[inline] + pub(super) fn spare_capacity(&self) -> usize { + self.buf.capacity() - self.buf.len() + } + + /// Write a byte slice directly into buffer + /// + /// Will truncate the number of bytes written to `spare_capacity()` so you want to + /// calculate the size of your slice to avoid losing bytes + /// + /// Based on `std::io::BufWriter` + pub(super) fn write_to_buf(self: Pin<&mut Self>, buf: &[u8]) -> usize { + let available = self.spare_capacity(); + let amt_to_buffer = available.min(buf.len()); + + // SAFETY: `amt_to_buffer` is <= buffer's spare capacity by construction. + unsafe { + self.write_to_buffer_unchecked(&buf[..amt_to_buffer]); + } + + amt_to_buffer + } + + /// Write byte slice directly into `self.buf` + /// + /// Based on `std::io::BufWriter` + #[inline] + unsafe fn write_to_buffer_unchecked(self: Pin<&mut Self>, buf: &[u8]) { + debug_assert!(buf.len() <= self.spare_capacity()); + let this = self.project(); + let old_len = this.buf.len(); + let buf_len = buf.len(); + let src = buf.as_ptr(); + unsafe { + let dst = this.buf.as_mut_ptr().add(old_len); + ptr::copy_nonoverlapping(src, dst, buf_len); + this.buf.set_len(old_len + buf_len); + } + } +} + +impl AsyncWrite for BufWriter { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + if self.buf.len() + buf.len() > self.buf.capacity() { + ready!(self.as_mut().flush_buf(cx))?; + } + if buf.len() >= self.buf.capacity() { + self.project().inner.poll_write(cx, buf) + } else { + Poll::Ready(self.project().buf.write(buf)) + } + } + + fn poll_write_vectored( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + let total_len = bufs.iter().map(|b| b.len()).sum::(); + if self.buf.len() + total_len > self.buf.capacity() { + ready!(self.as_mut().flush_buf(cx))?; + } + if total_len >= self.buf.capacity() { + self.project().inner.poll_write_vectored(cx, bufs) + } else { + Poll::Ready(self.project().buf.write_vectored(bufs)) + } + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().flush_buf(cx))?; + self.project().inner.poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().flush_buf(cx))?; + self.project().inner.poll_close(cx) + } +} + +impl AsyncRead for BufWriter { + delegate_async_read!(inner); +} + +impl AsyncBufRead for BufWriter { + delegate_async_buf_read!(inner); +} + +impl fmt::Debug for BufWriter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BufWriter") + .field("writer", &self.inner) + .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) + .field("written", &self.written) + .finish() + } +} + +impl AsyncSeek for BufWriter { + /// Seek to the offset, in bytes, in the underlying writer. + /// + /// Seeking always writes out the internal buffer before seeking. + fn poll_seek( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + ready!(self.as_mut().flush_buf(cx))?; + self.project().inner.poll_seek(cx, pos) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/chain.rs b/anneal/v2/vendor/futures-util/src/io/chain.rs new file mode 100644 index 0000000000..728a3d2dc0 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/chain.rs @@ -0,0 +1,142 @@ +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, IoSliceMut}; +use pin_project_lite::pin_project; +use std::fmt; +use std::io; +use std::pin::Pin; + +pin_project! { + /// Reader for the [`chain`](super::AsyncReadExt::chain) method. + #[must_use = "readers do nothing unless polled"] + pub struct Chain { + #[pin] + first: T, + #[pin] + second: U, + done_first: bool, + } +} + +impl Chain +where + T: AsyncRead, + U: AsyncRead, +{ + pub(super) fn new(first: T, second: U) -> Self { + Self { first, second, done_first: false } + } + + /// Gets references to the underlying readers in this `Chain`. + pub fn get_ref(&self) -> (&T, &U) { + (&self.first, &self.second) + } + + /// Gets mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + pub fn get_mut(&mut self) -> (&mut T, &mut U) { + (&mut self.first, &mut self.second) + } + + /// Gets pinned mutable references to the underlying readers in this `Chain`. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) { + let this = self.project(); + (this.first, this.second) + } + + /// Consumes the `Chain`, returning the wrapped readers. + pub fn into_inner(self) -> (T, U) { + (self.first, self.second) + } +} + +impl fmt::Debug for Chain +where + T: fmt::Debug, + U: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Chain") + .field("t", &self.first) + .field("u", &self.second) + .field("done_first", &self.done_first) + .finish() + } +} + +impl AsyncRead for Chain +where + T: AsyncRead, + U: AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let this = self.project(); + + if !*this.done_first { + match ready!(this.first.poll_read(cx, buf)?) { + 0 if !buf.is_empty() => *this.done_first = true, + n => return Poll::Ready(Ok(n)), + } + } + this.second.poll_read(cx, buf) + } + + fn poll_read_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + let this = self.project(); + + if !*this.done_first { + let n = ready!(this.first.poll_read_vectored(cx, bufs)?); + if n == 0 && bufs.iter().any(|b| !b.is_empty()) { + *this.done_first = true + } else { + return Poll::Ready(Ok(n)); + } + } + this.second.poll_read_vectored(cx, bufs) + } +} + +impl AsyncBufRead for Chain +where + T: AsyncBufRead, + U: AsyncBufRead, +{ + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + if !*this.done_first { + match ready!(this.first.poll_fill_buf(cx)?) { + buf if buf.is_empty() => { + *this.done_first = true; + } + buf => return Poll::Ready(Ok(buf)), + } + } + this.second.poll_fill_buf(cx) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + let this = self.project(); + + if !*this.done_first { + this.first.consume(amt) + } else { + this.second.consume(amt) + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/close.rs b/anneal/v2/vendor/futures-util/src/io/close.rs new file mode 100644 index 0000000000..b94459279a --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/close.rs @@ -0,0 +1,28 @@ +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use std::io; +use std::pin::Pin; + +/// Future for the [`close`](super::AsyncWriteExt::close) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Close<'a, W: ?Sized> { + writer: &'a mut W, +} + +impl Unpin for Close<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> Close<'a, W> { + pub(super) fn new(writer: &'a mut W) -> Self { + Self { writer } + } +} + +impl Future for Close<'_, W> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut *self.writer).poll_close(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/copy.rs b/anneal/v2/vendor/futures-util/src/io/copy.rs new file mode 100644 index 0000000000..c80add271b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/copy.rs @@ -0,0 +1,58 @@ +use super::{copy_buf, BufReader, CopyBuf}; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncRead, AsyncWrite}; +use pin_project_lite::pin_project; +use std::io; +use std::pin::Pin; + +/// Creates a future which copies all the bytes from one object to another. +/// +/// The returned future will copy all the bytes read from this `AsyncRead` into the +/// `writer` specified. This future will only complete once the `reader` has hit +/// EOF and all bytes have been written to and flushed from the `writer` +/// provided. +/// +/// On success the number of bytes is returned. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncWriteExt, Cursor}; +/// +/// let reader = Cursor::new([1, 2, 3, 4]); +/// let mut writer = Cursor::new(vec![0u8; 5]); +/// +/// let bytes = io::copy(reader, &mut writer).await?; +/// writer.close().await?; +/// +/// assert_eq!(bytes, 4); +/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); +/// # Ok::<(), Box>(()) }).unwrap(); +/// ``` +pub fn copy(reader: R, writer: &mut W) -> Copy<'_, R, W> +where + R: AsyncRead, + W: AsyncWrite + Unpin + ?Sized, +{ + Copy { inner: copy_buf(BufReader::new(reader), writer) } +} + +pin_project! { + /// Future for the [`copy()`] function. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Copy<'a, R, W: ?Sized> { + #[pin] + inner: CopyBuf<'a, BufReader, W>, + } +} + +impl Future for Copy<'_, R, W> { + type Output = io::Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.project().inner.poll(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/copy_buf.rs b/anneal/v2/vendor/futures-util/src/io/copy_buf.rs new file mode 100644 index 0000000000..50f7abdca9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/copy_buf.rs @@ -0,0 +1,78 @@ +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncWrite}; +use pin_project_lite::pin_project; +use std::io; +use std::pin::Pin; + +/// Creates a future which copies all the bytes from one object to another. +/// +/// The returned future will copy all the bytes read from this `AsyncBufRead` into the +/// `writer` specified. This future will only complete once the `reader` has hit +/// EOF and all bytes have been written to and flushed from the `writer` +/// provided. +/// +/// On success the number of bytes is returned. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncWriteExt, Cursor}; +/// +/// let reader = Cursor::new([1, 2, 3, 4]); +/// let mut writer = Cursor::new(vec![0u8; 5]); +/// +/// let bytes = io::copy_buf(reader, &mut writer).await?; +/// writer.close().await?; +/// +/// assert_eq!(bytes, 4); +/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); +/// # Ok::<(), Box>(()) }).unwrap(); +/// ``` +pub fn copy_buf(reader: R, writer: &mut W) -> CopyBuf<'_, R, W> +where + R: AsyncBufRead, + W: AsyncWrite + Unpin + ?Sized, +{ + CopyBuf { reader, writer, amt: 0 } +} + +pin_project! { + /// Future for the [`copy_buf()`] function. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct CopyBuf<'a, R, W: ?Sized> { + #[pin] + reader: R, + writer: &'a mut W, + amt: u64, + } +} + +impl Future for CopyBuf<'_, R, W> +where + R: AsyncBufRead, + W: AsyncWrite + Unpin + ?Sized, +{ + type Output = io::Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + loop { + let buffer = ready!(this.reader.as_mut().poll_fill_buf(cx))?; + if buffer.is_empty() { + ready!(Pin::new(&mut this.writer).poll_flush(cx))?; + return Poll::Ready(Ok(*this.amt)); + } + + let i = ready!(Pin::new(&mut this.writer).poll_write(cx, buffer))?; + if i == 0 { + return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); + } + *this.amt += i as u64; + this.reader.as_mut().consume(i); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/copy_buf_abortable.rs b/anneal/v2/vendor/futures-util/src/io/copy_buf_abortable.rs new file mode 100644 index 0000000000..ed22d62338 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/copy_buf_abortable.rs @@ -0,0 +1,124 @@ +use crate::abortable::{AbortHandle, AbortInner, Aborted}; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncWrite}; +use pin_project_lite::pin_project; +use std::io; +use std::pin::Pin; +use std::sync::atomic::Ordering; +use std::sync::Arc; + +/// Creates a future which copies all the bytes from one object to another, with its `AbortHandle`. +/// +/// The returned future will copy all the bytes read from this `AsyncBufRead` into the +/// `writer` specified. This future will only complete once abort has been requested or the `reader` has hit +/// EOF and all bytes have been written to and flushed from the `writer` +/// provided. +/// +/// On success the number of bytes is returned. If aborted, `Aborted` is returned. Otherwise, the underlying error is returned. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncWriteExt, Cursor}; +/// use futures::future::Aborted; +/// +/// let reader = Cursor::new([1, 2, 3, 4]); +/// let mut writer = Cursor::new(vec![0u8; 5]); +/// +/// let (fut, abort_handle) = io::copy_buf_abortable(reader, &mut writer); +/// let bytes = fut.await; +/// abort_handle.abort(); +/// writer.close().await.unwrap(); +/// match bytes { +/// Ok(Ok(n)) => { +/// assert_eq!(n, 4); +/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); +/// Ok(n) +/// }, +/// Ok(Err(a)) => { +/// Err::(a) +/// } +/// Err(e) => panic!("{}", e) +/// } +/// # }).unwrap(); +/// ``` +pub fn copy_buf_abortable( + reader: R, + writer: &mut W, +) -> (CopyBufAbortable<'_, R, W>, AbortHandle) +where + R: AsyncBufRead, + W: AsyncWrite + Unpin + ?Sized, +{ + let (handle, reg) = AbortHandle::new_pair(); + (CopyBufAbortable { reader, writer, amt: 0, inner: reg.inner }, handle) +} + +pin_project! { + /// Future for the [`copy_buf_abortable()`] function. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct CopyBufAbortable<'a, R, W: ?Sized> { + #[pin] + reader: R, + writer: &'a mut W, + amt: u64, + inner: Arc + } +} + +macro_rules! ready_or_break { + ($e:expr $(,)?) => { + match $e { + $crate::task::Poll::Ready(t) => t, + $crate::task::Poll::Pending => break, + } + }; +} + +impl Future for CopyBufAbortable<'_, R, W> +where + R: AsyncBufRead, + W: AsyncWrite + Unpin + Sized, +{ + type Output = Result, io::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + loop { + // Check if the task has been aborted + if this.inner.aborted.load(Ordering::Relaxed) { + return Poll::Ready(Ok(Err(Aborted))); + } + + // Read some bytes from the reader, and if we have reached EOF, return total bytes read + let buffer = ready_or_break!(this.reader.as_mut().poll_fill_buf(cx))?; + if buffer.is_empty() { + ready_or_break!(Pin::new(&mut this.writer).poll_flush(cx))?; + return Poll::Ready(Ok(Ok(*this.amt))); + } + + // Pass the buffer to the writer, and update the amount written + let i = ready_or_break!(Pin::new(&mut this.writer).poll_write(cx, buffer))?; + if i == 0 { + return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); + } + *this.amt += i as u64; + this.reader.as_mut().consume(i); + } + // Schedule the task to be woken up again. + // Never called unless Poll::Pending is returned from io objects. + this.inner.waker.register(cx.waker()); + + // Check to see if the task was aborted between the first check and + // registration. + // Checking with `Relaxed` is sufficient because + // `register` introduces an `AcqRel` barrier. + if this.inner.aborted.load(Ordering::Relaxed) { + return Poll::Ready(Ok(Err(Aborted))); + } + Poll::Pending + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/cursor.rs b/anneal/v2/vendor/futures-util/src/io/cursor.rs new file mode 100644 index 0000000000..01c8e5f4dc --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/cursor.rs @@ -0,0 +1,234 @@ +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom}; +use std::boxed::Box; +use std::io; +use std::pin::Pin; +use std::vec::Vec; + +/// A `Cursor` wraps an in-memory buffer and provides it with a +/// [`AsyncSeek`] implementation. +/// +/// `Cursor`s are used with in-memory buffers, anything implementing +/// `AsRef<[u8]>`, to allow them to implement [`AsyncRead`] and/or [`AsyncWrite`], +/// allowing these buffers to be used anywhere you might use a reader or writer +/// that does actual I/O. +/// +/// This library implements some I/O traits on various types which +/// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and +/// `Cursor<`[`&[u8]`][bytes]`>`. +/// +/// [`AsyncSeek`]: trait.AsyncSeek.html +/// [`AsyncRead`]: trait.AsyncRead.html +/// [`AsyncWrite`]: trait.AsyncWrite.html +/// [bytes]: https://doc.rust-lang.org/std/primitive.slice.html +#[derive(Clone, Debug, Default)] +pub struct Cursor { + inner: io::Cursor, +} + +impl Cursor { + /// Creates a new cursor wrapping the provided underlying in-memory buffer. + /// + /// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`) + /// is not empty. So writing to cursor starts with overwriting `Vec` + /// content, not with appending to it. + /// + /// # Examples + /// + /// ``` + /// use futures::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// ``` + pub fn new(inner: T) -> Self { + Self { inner: io::Cursor::new(inner) } + } + + /// Consumes this cursor, returning the underlying value. + /// + /// # Examples + /// + /// ``` + /// use futures::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let vec = buff.into_inner(); + /// ``` + pub fn into_inner(self) -> T { + self.inner.into_inner() + } + + /// Gets a reference to the underlying value in this cursor. + /// + /// # Examples + /// + /// ``` + /// use futures::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_ref(); + /// ``` + pub fn get_ref(&self) -> &T { + self.inner.get_ref() + } + + /// Gets a mutable reference to the underlying value in this cursor. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying value as it may corrupt this cursor's position. + /// + /// # Examples + /// + /// ``` + /// use futures::io::Cursor; + /// + /// let mut buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_mut(); + /// ``` + pub fn get_mut(&mut self) -> &mut T { + self.inner.get_mut() + } + + /// Returns the current position of this cursor. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncSeekExt, Cursor, SeekFrom}; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.seek(SeekFrom::Current(2)).await?; + /// assert_eq!(buff.position(), 2); + /// + /// buff.seek(SeekFrom::Current(-1)).await?; + /// assert_eq!(buff.position(), 1); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + pub fn position(&self) -> u64 { + self.inner.position() + } + + /// Sets the position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use futures::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.set_position(2); + /// assert_eq!(buff.position(), 2); + /// + /// buff.set_position(4); + /// assert_eq!(buff.position(), 4); + /// ``` + pub fn set_position(&mut self, pos: u64) { + self.inner.set_position(pos) + } +} + +impl AsyncSeek for Cursor +where + T: AsRef<[u8]> + Unpin, +{ + fn poll_seek( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + Poll::Ready(io::Seek::seek(&mut self.inner, pos)) + } +} + +impl + Unpin> AsyncRead for Cursor { + fn poll_read( + mut self: Pin<&mut Self>, + _cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + Poll::Ready(io::Read::read(&mut self.inner, buf)) + } + + fn poll_read_vectored( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + Poll::Ready(io::Read::read_vectored(&mut self.inner, bufs)) + } +} + +impl AsyncBufRead for Cursor +where + T: AsRef<[u8]> + Unpin, +{ + fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(io::BufRead::fill_buf(&mut self.get_mut().inner)) + } + + fn consume(mut self: Pin<&mut Self>, amt: usize) { + io::BufRead::consume(&mut self.inner, amt) + } +} + +macro_rules! delegate_async_write_to_stdio { + () => { + fn poll_write( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Poll::Ready(io::Write::write(&mut self.inner, buf)) + } + + fn poll_write_vectored( + mut self: Pin<&mut Self>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + Poll::Ready(io::Write::write_vectored(&mut self.inner, bufs)) + } + + fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(io::Write::flush(&mut self.inner)) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_flush(cx) + } + }; +} + +impl AsyncWrite for Cursor<&mut [u8]> { + delegate_async_write_to_stdio!(); +} + +impl AsyncWrite for Cursor<&mut Vec> { + delegate_async_write_to_stdio!(); +} + +impl AsyncWrite for Cursor> { + delegate_async_write_to_stdio!(); +} + +impl AsyncWrite for Cursor> { + delegate_async_write_to_stdio!(); +} diff --git a/anneal/v2/vendor/futures-util/src/io/empty.rs b/anneal/v2/vendor/futures-util/src/io/empty.rs new file mode 100644 index 0000000000..02f6103f54 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/empty.rs @@ -0,0 +1,59 @@ +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead}; +use std::fmt; +use std::io; +use std::pin::Pin; + +/// Reader for the [`empty()`] function. +#[must_use = "readers do nothing unless polled"] +pub struct Empty { + _priv: (), +} + +/// Constructs a new handle to an empty reader. +/// +/// All reads from the returned reader will return `Poll::Ready(Ok(0))`. +/// +/// # Examples +/// +/// A slightly sad example of not reading anything into a buffer: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncReadExt}; +/// +/// let mut buffer = String::new(); +/// let mut reader = io::empty(); +/// reader.read_to_string(&mut buffer).await?; +/// assert!(buffer.is_empty()); +/// # Ok::<(), Box>(()) }).unwrap(); +/// ``` +pub fn empty() -> Empty { + Empty { _priv: () } +} + +impl AsyncRead for Empty { + #[inline] + fn poll_read( + self: Pin<&mut Self>, + _: &mut Context<'_>, + _: &mut [u8], + ) -> Poll> { + Poll::Ready(Ok(0)) + } +} + +impl AsyncBufRead for Empty { + #[inline] + fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(&[])) + } + #[inline] + fn consume(self: Pin<&mut Self>, _: usize) {} +} + +impl fmt::Debug for Empty { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Empty { .. }") + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/fill_buf.rs b/anneal/v2/vendor/futures-util/src/io/fill_buf.rs new file mode 100644 index 0000000000..45862b8e29 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/fill_buf.rs @@ -0,0 +1,47 @@ +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncBufRead; +use std::io; +use std::pin::Pin; +use std::slice; + +/// Future for the [`fill_buf`](super::AsyncBufReadExt::fill_buf) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct FillBuf<'a, R: ?Sized> { + reader: Option<&'a mut R>, +} + +impl Unpin for FillBuf<'_, R> {} + +impl<'a, R: AsyncBufRead + ?Sized + Unpin> FillBuf<'a, R> { + pub(super) fn new(reader: &'a mut R) -> Self { + Self { reader: Some(reader) } + } +} + +impl<'a, R> Future for FillBuf<'a, R> +where + R: AsyncBufRead + ?Sized + Unpin, +{ + type Output = io::Result<&'a [u8]>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + let reader = this.reader.take().expect("Polled FillBuf after completion"); + + match Pin::new(&mut *reader).poll_fill_buf(cx) { + Poll::Ready(Ok(slice)) => { + // With polonius it is possible to remove this lifetime transmutation and just have + // the correct lifetime of the reference inferred based on which branch is taken + let slice: &'a [u8] = unsafe { slice::from_raw_parts(slice.as_ptr(), slice.len()) }; + Poll::Ready(Ok(slice)) + } + Poll::Ready(Err(err)) => Poll::Ready(Err(err)), + Poll::Pending => { + this.reader = Some(reader); + Poll::Pending + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/flush.rs b/anneal/v2/vendor/futures-util/src/io/flush.rs new file mode 100644 index 0000000000..b75d14c5d3 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/flush.rs @@ -0,0 +1,31 @@ +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use std::io; +use std::pin::Pin; + +/// Future for the [`flush`](super::AsyncWriteExt::flush) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Flush<'a, W: ?Sized> { + writer: &'a mut W, +} + +impl Unpin for Flush<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> Flush<'a, W> { + pub(super) fn new(writer: &'a mut W) -> Self { + Self { writer } + } +} + +impl Future for Flush<'_, W> +where + W: AsyncWrite + ?Sized + Unpin, +{ + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut *self.writer).poll_flush(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/into_sink.rs b/anneal/v2/vendor/futures-util/src/io/into_sink.rs new file mode 100644 index 0000000000..6a41ee2269 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/into_sink.rs @@ -0,0 +1,82 @@ +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use futures_sink::Sink; +use pin_project_lite::pin_project; +use std::io; +use std::pin::Pin; + +#[derive(Debug)] +struct Block { + offset: usize, + bytes: Item, +} + +pin_project! { + /// Sink for the [`into_sink`](super::AsyncWriteExt::into_sink) method. + #[must_use = "sinks do nothing unless polled"] + #[derive(Debug)] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + pub struct IntoSink { + #[pin] + writer: W, + // An outstanding block for us to push into the underlying writer, along with an offset of how + // far into this block we have written already. + buffer: Option>, + } +} + +impl> IntoSink { + pub(super) fn new(writer: W) -> Self { + Self { writer, buffer: None } + } + + /// If we have an outstanding block in `buffer` attempt to push it into the writer, does _not_ + /// flush the writer after it succeeds in pushing the block into it. + fn poll_flush_buffer( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let mut this = self.project(); + + if let Some(buffer) = this.buffer { + loop { + let bytes = buffer.bytes.as_ref(); + let written = ready!(this.writer.as_mut().poll_write(cx, &bytes[buffer.offset..]))?; + buffer.offset += written; + if buffer.offset == bytes.len() { + break; + } + } + } + *this.buffer = None; + Poll::Ready(Ok(())) + } +} + +impl> Sink for IntoSink { + type Error = io::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.poll_flush_buffer(cx))?; + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + debug_assert!(self.buffer.is_none()); + *self.project().buffer = Some(Block { offset: 0, bytes: item }); + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().poll_flush_buffer(cx))?; + ready!(self.project().writer.poll_flush(cx))?; + Poll::Ready(Ok(())) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().poll_flush_buffer(cx))?; + ready!(self.project().writer.poll_close(cx))?; + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/line_writer.rs b/anneal/v2/vendor/futures-util/src/io/line_writer.rs new file mode 100644 index 0000000000..de1bb53924 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/line_writer.rs @@ -0,0 +1,155 @@ +use super::buf_writer::BufWriter; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use futures_io::IoSlice; +use pin_project_lite::pin_project; +use std::io; +use std::pin::Pin; + +pin_project! { +/// Wrap a writer, like [`BufWriter`] does, but prioritizes buffering lines +/// +/// This was written based on `std::io::LineWriter` which goes into further details +/// explaining the code. +/// +/// Buffering is actually done using `BufWriter`. This class will leverage `BufWriter` +/// to write on-each-line. +#[derive(Debug)] +pub struct LineWriter { + #[pin] + buf_writer: BufWriter, +} +} + +impl LineWriter { + /// Create a new `LineWriter` with default buffer capacity. The default is currently 1KB + /// which was taken from `std::io::LineWriter` + pub fn new(inner: W) -> Self { + Self::with_capacity(1024, inner) + } + + /// Creates a new `LineWriter` with the specified buffer capacity. + pub fn with_capacity(capacity: usize, inner: W) -> Self { + Self { buf_writer: BufWriter::with_capacity(capacity, inner) } + } + + /// Flush `buf_writer` if last char is "new line" + fn flush_if_completed_line(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + match this.buf_writer.buffer().last().copied() { + Some(b'\n') => this.buf_writer.flush_buf(cx), + _ => Poll::Ready(Ok(())), + } + } + + /// Returns a reference to `buf_writer`'s internally buffered data. + pub fn buffer(&self) -> &[u8] { + self.buf_writer.buffer() + } + + /// Acquires a reference to the underlying sink or stream that this combinator is + /// pulling from. + pub fn get_ref(&self) -> &W { + self.buf_writer.get_ref() + } +} + +impl AsyncWrite for LineWriter { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + let mut this = self.as_mut().project(); + let newline_index = match memchr::memrchr(b'\n', buf) { + None => { + ready!(self.as_mut().flush_if_completed_line(cx)?); + return self.project().buf_writer.poll_write(cx, buf); + } + Some(newline_index) => newline_index + 1, + }; + + ready!(this.buf_writer.as_mut().poll_flush(cx)?); + + let lines = &buf[..newline_index]; + + let flushed = { ready!(this.buf_writer.as_mut().inner_poll_write(cx, lines))? }; + + if flushed == 0 { + return Poll::Ready(Ok(0)); + } + + let tail = if flushed >= newline_index { + &buf[flushed..] + } else if newline_index - flushed <= this.buf_writer.capacity() { + &buf[flushed..newline_index] + } else { + let scan_area = &buf[flushed..]; + let scan_area = &scan_area[..this.buf_writer.capacity()]; + match memchr::memrchr(b'\n', scan_area) { + Some(newline_index) => &scan_area[..newline_index + 1], + None => scan_area, + } + }; + + let buffered = this.buf_writer.as_mut().write_to_buf(tail); + Poll::Ready(Ok(flushed + buffered)) + } + + fn poll_write_vectored( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + let mut this = self.as_mut().project(); + // `is_write_vectored()` is handled in original code, but not in this crate + // see https://github.com/rust-lang/rust/issues/70436 + + let last_newline_buf_idx = bufs + .iter() + .enumerate() + .rev() + .find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i)); + let last_newline_buf_idx = match last_newline_buf_idx { + None => { + ready!(self.as_mut().flush_if_completed_line(cx)?); + return self.project().buf_writer.poll_write_vectored(cx, bufs); + } + Some(i) => i, + }; + + ready!(this.buf_writer.as_mut().poll_flush(cx)?); + + let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1); + + let flushed = { ready!(this.buf_writer.as_mut().inner_poll_write_vectored(cx, lines))? }; + if flushed == 0 { + return Poll::Ready(Ok(0)); + } + + let lines_len = lines.iter().map(|buf| buf.len()).sum(); + if flushed < lines_len { + return Poll::Ready(Ok(flushed)); + } + + let buffered: usize = tail + .iter() + .filter(|buf| !buf.is_empty()) + .map(|buf| this.buf_writer.as_mut().write_to_buf(buf)) + .take_while(|&n| n > 0) + .sum(); + + Poll::Ready(Ok(flushed + buffered)) + } + + /// Forward to `buf_writer` 's `BufWriter::poll_flush()` + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().project().buf_writer.poll_flush(cx) + } + + /// Forward to `buf_writer` 's `BufWriter::poll_close()` + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().project().buf_writer.poll_close(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/lines.rs b/anneal/v2/vendor/futures-util/src/io/lines.rs new file mode 100644 index 0000000000..0a1abf4bf6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/lines.rs @@ -0,0 +1,50 @@ +use super::read_line::read_line_internal; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncBufRead; +use pin_project_lite::pin_project; +use std::io; +use std::mem; +use std::pin::Pin; +use std::string::String; +use std::vec::Vec; + +pin_project! { + /// Stream for the [`lines`](super::AsyncBufReadExt::lines) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Lines { + #[pin] + reader: R, + buf: String, + bytes: Vec, + read: usize, + } +} + +impl Lines { + pub(super) fn new(reader: R) -> Self { + Self { reader, buf: String::new(), bytes: Vec::new(), read: 0 } + } +} + +impl Stream for Lines { + type Item = io::Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + let n = ready!(read_line_internal(this.reader, cx, this.buf, this.bytes, this.read))?; + *this.read = 0; + if n == 0 && this.buf.is_empty() { + return Poll::Ready(None); + } + if this.buf.ends_with('\n') { + this.buf.pop(); + if this.buf.ends_with('\r') { + this.buf.pop(); + } + } + Poll::Ready(Some(Ok(mem::take(this.buf)))) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/mod.rs b/anneal/v2/vendor/futures-util/src/io/mod.rs new file mode 100644 index 0000000000..923109cce5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/mod.rs @@ -0,0 +1,833 @@ +//! Asynchronous I/O. +//! +//! This module is the asynchronous version of `std::io`. It defines four +//! traits, [`AsyncRead`], [`AsyncWrite`], [`AsyncSeek`], and [`AsyncBufRead`], +//! which mirror the `Read`, `Write`, `Seek`, and `BufRead` traits of the +//! standard library. However, these traits integrate with the asynchronous +//! task system, so that if an I/O object isn't ready for reading (or writing), +//! the thread is not blocked, and instead the current task is queued to be +//! woken when I/O is ready. +//! +//! In addition, the [`AsyncReadExt`], [`AsyncWriteExt`], [`AsyncSeekExt`], and +//! [`AsyncBufReadExt`] extension traits offer a variety of useful combinators +//! for operating with asynchronous I/O objects, including ways to work with +//! them using futures, streams and sinks. +//! +//! This module is only available when the `std` feature of this +//! library is activated, and it is activated by default. + +#[cfg(feature = "io-compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] +use crate::compat::Compat; +use crate::future::assert_future; +use crate::stream::assert_stream; +use std::{pin::Pin, string::String, vec::Vec}; + +// Re-export some types from `std::io` so that users don't have to deal +// with conflicts when `use`ing `futures::io` and `std::io`. +#[doc(no_inline)] +pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom}; + +pub use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite}; + +// used by `BufReader` and `BufWriter` +// https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/io.rs#L1 +const DEFAULT_BUF_SIZE: usize = 8 * 1024; + +mod allow_std; +pub use self::allow_std::AllowStdIo; + +mod buf_reader; +pub use self::buf_reader::{BufReader, SeeKRelative}; + +mod buf_writer; +pub use self::buf_writer::BufWriter; + +mod line_writer; +pub use self::line_writer::LineWriter; + +mod chain; +pub use self::chain::Chain; + +mod close; +pub use self::close::Close; + +mod copy; +pub use self::copy::{copy, Copy}; + +mod copy_buf; +pub use self::copy_buf::{copy_buf, CopyBuf}; + +mod copy_buf_abortable; +pub use self::copy_buf_abortable::{copy_buf_abortable, CopyBufAbortable}; + +mod cursor; +pub use self::cursor::Cursor; + +mod empty; +pub use self::empty::{empty, Empty}; + +mod fill_buf; +pub use self::fill_buf::FillBuf; + +mod flush; +pub use self::flush::Flush; + +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +mod into_sink; +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::into_sink::IntoSink; + +mod lines; +pub use self::lines::Lines; + +mod read; +pub use self::read::Read; + +mod read_vectored; +pub use self::read_vectored::ReadVectored; + +mod read_exact; +pub use self::read_exact::ReadExact; + +mod read_line; +pub use self::read_line::ReadLine; + +mod read_to_end; +pub use self::read_to_end::ReadToEnd; + +mod read_to_string; +pub use self::read_to_string::ReadToString; + +mod read_until; +pub use self::read_until::ReadUntil; + +mod repeat; +pub use self::repeat::{repeat, Repeat}; + +mod seek; +pub use self::seek::Seek; + +mod sink; +pub use self::sink::{sink, Sink}; + +mod split; +pub use self::split::{ReadHalf, ReuniteError, WriteHalf}; + +mod take; +pub use self::take::Take; + +mod window; +pub use self::window::Window; + +mod write; +pub use self::write::Write; + +mod write_vectored; +pub use self::write_vectored::WriteVectored; + +mod write_all; +pub use self::write_all::WriteAll; + +#[cfg(feature = "write-all-vectored")] +mod write_all_vectored; +#[cfg(feature = "write-all-vectored")] +pub use self::write_all_vectored::WriteAllVectored; + +/// An extension trait which adds utility methods to `AsyncRead` types. +pub trait AsyncReadExt: AsyncRead { + /// Creates an adaptor which will chain this stream with another. + /// + /// The returned `AsyncRead` instance will first read all bytes from this object + /// until EOF is encountered. Afterwards the output is equivalent to the + /// output of `next`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let reader1 = Cursor::new([1, 2, 3, 4]); + /// let reader2 = Cursor::new([5, 6, 7, 8]); + /// + /// let mut reader = reader1.chain(reader2); + /// let mut buffer = Vec::new(); + /// + /// // read the value into a Vec. + /// reader.read_to_end(&mut buffer).await?; + /// assert_eq!(buffer, [1, 2, 3, 4, 5, 6, 7, 8]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn chain(self, next: R) -> Chain + where + Self: Sized, + R: AsyncRead, + { + assert_read(Chain::new(self, next)) + } + + /// Tries to read some bytes directly into the given `buf` in asynchronous + /// manner, returning a future type. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let mut reader = Cursor::new([1, 2, 3, 4]); + /// let mut output = [0u8; 5]; + /// + /// let bytes = reader.read(&mut output[..]).await?; + /// + /// // This is only guaranteed to be 4 because `&[u8]` is a synchronous + /// // reader. In a real system you could get anywhere from 1 to + /// // `output.len()` bytes in a single read. + /// assert_eq!(bytes, 4); + /// assert_eq!(output, [1, 2, 3, 4, 0]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(Read::new(self, buf)) + } + + /// Creates a future which will read from the `AsyncRead` into `bufs` using vectored + /// IO operations. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + fn read_vectored<'a>(&'a mut self, bufs: &'a mut [IoSliceMut<'a>]) -> ReadVectored<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadVectored::new(self, bufs)) + } + + /// Creates a future which will read exactly enough bytes to fill `buf`, + /// returning an error if end of file (EOF) is hit sooner. + /// + /// The returned future will resolve once the read operation is completed. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let mut reader = Cursor::new([1, 2, 3, 4]); + /// let mut output = [0u8; 4]; + /// + /// reader.read_exact(&mut output).await?; + /// + /// assert_eq!(output, [1, 2, 3, 4]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + /// + /// ## EOF is hit before `buf` is filled + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{self, AsyncReadExt, Cursor}; + /// + /// let mut reader = Cursor::new([1, 2, 3, 4]); + /// let mut output = [0u8; 5]; + /// + /// let result = reader.read_exact(&mut output).await; + /// + /// assert_eq!(result.unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + /// # }); + /// ``` + fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadExact::new(self, buf)) + } + + /// Creates a future which will read all the bytes from this `AsyncRead`. + /// + /// On success the total number of bytes read is returned. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let mut reader = Cursor::new([1, 2, 3, 4]); + /// let mut output = Vec::with_capacity(4); + /// + /// let bytes = reader.read_to_end(&mut output).await?; + /// + /// assert_eq!(bytes, 4); + /// assert_eq!(output, vec![1, 2, 3, 4]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec) -> ReadToEnd<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadToEnd::new(self, buf)) + } + + /// Creates a future which will read all the bytes from this `AsyncRead`. + /// + /// On success the total number of bytes read is returned. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let mut reader = Cursor::new(&b"1234"[..]); + /// let mut buffer = String::with_capacity(4); + /// + /// let bytes = reader.read_to_string(&mut buffer).await?; + /// + /// assert_eq!(bytes, 4); + /// assert_eq!(buffer, String::from("1234")); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn read_to_string<'a>(&'a mut self, buf: &'a mut String) -> ReadToString<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadToString::new(self, buf)) + } + + /// Helper method for splitting this read/write object into two halves. + /// + /// The two halves returned implement the `AsyncRead` and `AsyncWrite` + /// traits, respectively. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{self, AsyncReadExt, Cursor}; + /// + /// // Note that for `Cursor` the read and write halves share a single + /// // seek position. This may or may not be true for other types that + /// // implement both `AsyncRead` and `AsyncWrite`. + /// + /// let reader = Cursor::new([1, 2, 3, 4]); + /// let mut buffer = Cursor::new(vec![0, 0, 0, 0, 5, 6, 7, 8]); + /// let mut writer = Cursor::new(vec![0u8; 5]); + /// + /// { + /// let (buffer_reader, mut buffer_writer) = (&mut buffer).split(); + /// io::copy(reader, &mut buffer_writer).await?; + /// io::copy(buffer_reader, &mut writer).await?; + /// } + /// + /// assert_eq!(buffer.into_inner(), [1, 2, 3, 4, 5, 6, 7, 8]); + /// assert_eq!(writer.into_inner(), [5, 6, 7, 8, 0]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn split(self) -> (ReadHalf, WriteHalf) + where + Self: AsyncWrite + Sized, + { + let (r, w) = split::split(self); + (assert_read(r), assert_write(w)) + } + + /// Creates an AsyncRead adapter which will read at most `limit` bytes + /// from the underlying reader. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let reader = Cursor::new(&b"12345678"[..]); + /// let mut buffer = [0; 5]; + /// + /// let mut take = reader.take(4); + /// let n = take.read(&mut buffer).await?; + /// + /// assert_eq!(n, 4); + /// assert_eq!(&buffer, b"1234\0"); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn take(self, limit: u64) -> Take + where + Self: Sized, + { + assert_read(Take::new(self, limit)) + } + + /// Wraps an [`AsyncRead`] in a compatibility wrapper that allows it to be + /// used as a futures 0.1 / tokio-io 0.1 `AsyncRead`. If the wrapped type + /// implements [`AsyncWrite`] as well, the result will also implement the + /// futures 0.1 / tokio 0.1 `AsyncWrite` trait. + /// + /// Requires the `io-compat` feature to enable. + #[cfg(feature = "io-compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] + fn compat(self) -> Compat + where + Self: Sized + Unpin, + { + Compat::new(self) + } +} + +impl AsyncReadExt for R {} + +/// An extension trait which adds utility methods to `AsyncWrite` types. +pub trait AsyncWriteExt: AsyncWrite { + /// Creates a future which will entirely flush this `AsyncWrite`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AllowStdIo, AsyncWriteExt}; + /// use std::io::{BufWriter, Cursor}; + /// + /// let mut output = vec![0u8; 5]; + /// + /// { + /// let writer = Cursor::new(&mut output); + /// let mut buffered = AllowStdIo::new(BufWriter::new(writer)); + /// buffered.write_all(&[1, 2]).await?; + /// buffered.write_all(&[3, 4]).await?; + /// buffered.flush().await?; + /// } + /// + /// assert_eq!(output, [1, 2, 3, 4, 0]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn flush(&mut self) -> Flush<'_, Self> + where + Self: Unpin, + { + assert_future::, _>(Flush::new(self)) + } + + /// Creates a future which will entirely close this `AsyncWrite`. + fn close(&mut self) -> Close<'_, Self> + where + Self: Unpin, + { + assert_future::, _>(Close::new(self)) + } + + /// Creates a future which will write bytes from `buf` into the object. + /// + /// The returned future will resolve to the number of bytes written once the write + /// operation is completed. + fn write<'a>(&'a mut self, buf: &'a [u8]) -> Write<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(Write::new(self, buf)) + } + + /// Creates a future which will write bytes from `bufs` into the object using vectored + /// IO operations. + /// + /// The returned future will resolve to the number of bytes written once the write + /// operation is completed. + fn write_vectored<'a>(&'a mut self, bufs: &'a [IoSlice<'a>]) -> WriteVectored<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(WriteVectored::new(self, bufs)) + } + + /// Write data into this object. + /// + /// Creates a future that will write the entire contents of the buffer `buf` into + /// this `AsyncWrite`. + /// + /// The returned future will not complete until all the data has been written. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncWriteExt, Cursor}; + /// + /// let mut writer = Cursor::new(vec![0u8; 5]); + /// + /// writer.write_all(&[1, 2, 3, 4]).await?; + /// + /// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(WriteAll::new(self, buf)) + } + + /// Attempts to write multiple buffers into this writer. + /// + /// Creates a future that will write the entire contents of `bufs` into this + /// `AsyncWrite` using [vectored writes]. + /// + /// The returned future will not complete until all the data has been + /// written. + /// + /// [vectored writes]: std::io::Write::write_vectored + /// + /// # Notes + /// + /// Unlike `io::Write::write_vectored`, this takes a *mutable* reference to + /// a slice of `IoSlice`s, not an immutable one. That's because we need to + /// modify the slice to keep track of the bytes already written. + /// + /// Once this futures returns, the contents of `bufs` are unspecified, as + /// this depends on how many calls to `write_vectored` were necessary. It is + /// best to understand this function as taking ownership of `bufs` and to + /// not use `bufs` afterwards. The underlying buffers, to which the + /// `IoSlice`s point (but not the `IoSlice`s themselves), are unchanged and + /// can be reused. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::AsyncWriteExt; + /// use futures_util::io::Cursor; + /// use std::io::IoSlice; + /// + /// let mut writer = Cursor::new(Vec::new()); + /// let bufs = &mut [ + /// IoSlice::new(&[1]), + /// IoSlice::new(&[2, 3]), + /// IoSlice::new(&[4, 5, 6]), + /// ]; + /// + /// writer.write_all_vectored(bufs).await?; + /// // Note: the contents of `bufs` is now unspecified, see the Notes section. + /// + /// assert_eq!(writer.into_inner(), &[1, 2, 3, 4, 5, 6]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + #[cfg(feature = "write-all-vectored")] + fn write_all_vectored<'a>( + &'a mut self, + bufs: &'a mut [IoSlice<'a>], + ) -> WriteAllVectored<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(WriteAllVectored::new(self, bufs)) + } + + /// Wraps an [`AsyncWrite`] in a compatibility wrapper that allows it to be + /// used as a futures 0.1 / tokio-io 0.1 `AsyncWrite`. + /// Requires the `io-compat` feature to enable. + #[cfg(feature = "io-compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))] + fn compat_write(self) -> Compat + where + Self: Sized + Unpin, + { + Compat::new(self) + } + + /// Allow using an [`AsyncWrite`] as a [`Sink`](futures_sink::Sink)`>`. + /// + /// This adapter produces a sink that will write each value passed to it + /// into the underlying writer. + /// + /// Note that this function consumes the given writer, returning a wrapped + /// version. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::AsyncWriteExt; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(vec![Ok([1, 2, 3]), Ok([4, 5, 6])]); + /// + /// let mut writer = vec![]; + /// + /// stream.forward((&mut writer).into_sink()).await?; + /// + /// assert_eq!(writer, vec![1, 2, 3, 4, 5, 6]); + /// # Ok::<(), Box>(()) + /// # })?; + /// # Ok::<(), Box>(()) + /// ``` + #[cfg(feature = "sink")] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + fn into_sink>(self) -> IntoSink + where + Self: Sized, + { + crate::sink::assert_sink::(IntoSink::new(self)) + } +} + +impl AsyncWriteExt for W {} + +/// An extension trait which adds utility methods to `AsyncSeek` types. +pub trait AsyncSeekExt: AsyncSeek { + /// Creates a future which will seek an IO object, and then yield the + /// new position in the object and the object itself. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + fn seek(&mut self, pos: SeekFrom) -> Seek<'_, Self> + where + Self: Unpin, + { + assert_future::, _>(Seek::new(self, pos)) + } + + /// Creates a future which will return the current seek position from the + /// start of the stream. + /// + /// This is equivalent to `self.seek(SeekFrom::Current(0))`. + fn stream_position(&mut self) -> Seek<'_, Self> + where + Self: Unpin, + { + self.seek(SeekFrom::Current(0)) + } +} + +impl AsyncSeekExt for S {} + +/// An extension trait which adds utility methods to `AsyncBufRead` types. +pub trait AsyncBufReadExt: AsyncBufRead { + /// Creates a future which will wait for a non-empty buffer to be available from this I/O + /// object or EOF to be reached. + /// + /// This method is the async equivalent to [`BufRead::fill_buf`](std::io::BufRead::fill_buf). + /// + /// ```rust + /// # futures::executor::block_on(async { + /// use futures::{io::AsyncBufReadExt as _, stream::{iter, TryStreamExt as _}}; + /// + /// let mut stream = iter(vec![Ok(vec![1, 2, 3]), Ok(vec![4, 5, 6])]).into_async_read(); + /// + /// assert_eq!(stream.fill_buf().await?, vec![1, 2, 3]); + /// stream.consume_unpin(2); + /// + /// assert_eq!(stream.fill_buf().await?, vec![3]); + /// stream.consume_unpin(1); + /// + /// assert_eq!(stream.fill_buf().await?, vec![4, 5, 6]); + /// stream.consume_unpin(3); + /// + /// assert_eq!(stream.fill_buf().await?, vec![]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn fill_buf(&mut self) -> FillBuf<'_, Self> + where + Self: Unpin, + { + assert_future::, _>(FillBuf::new(self)) + } + + /// A convenience for calling [`AsyncBufRead::consume`] on [`Unpin`] IO types. + /// + /// ```rust + /// # futures::executor::block_on(async { + /// use futures::{io::AsyncBufReadExt as _, stream::{iter, TryStreamExt as _}}; + /// + /// let mut stream = iter(vec![Ok(vec![1, 2, 3])]).into_async_read(); + /// + /// assert_eq!(stream.fill_buf().await?, vec![1, 2, 3]); + /// stream.consume_unpin(2); + /// + /// assert_eq!(stream.fill_buf().await?, vec![3]); + /// stream.consume_unpin(1); + /// + /// assert_eq!(stream.fill_buf().await?, vec![]); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn consume_unpin(&mut self, amt: usize) + where + Self: Unpin, + { + Pin::new(self).consume(amt) + } + + /// Creates a future which will read all the bytes associated with this I/O + /// object into `buf` until the delimiter `byte` or EOF is reached. + /// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until). + /// + /// This function will read bytes from the underlying stream until the + /// delimiter or EOF is found. Once found, all bytes up to, and including, + /// the delimiter (if found) will be appended to `buf`. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncBufReadExt, Cursor}; + /// + /// let mut cursor = Cursor::new(b"lorem-ipsum"); + /// let mut buf = vec![]; + /// + /// // cursor is at 'l' + /// let num_bytes = cursor.read_until(b'-', &mut buf).await?; + /// assert_eq!(num_bytes, 6); + /// assert_eq!(buf, b"lorem-"); + /// buf.clear(); + /// + /// // cursor is at 'i' + /// let num_bytes = cursor.read_until(b'-', &mut buf).await?; + /// assert_eq!(num_bytes, 5); + /// assert_eq!(buf, b"ipsum"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_until(b'-', &mut buf).await?; + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, b""); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec) -> ReadUntil<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadUntil::new(self, byte, buf)) + } + + /// Creates a future which will read all the bytes associated with this I/O + /// object into `buf` until a newline (the 0xA byte) or EOF is reached, + /// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line). + /// + /// This function will read bytes from the underlying stream until the + /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes + /// up to, and including, the delimiter (if found) will be appended to + /// `buf`. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + /// + /// # Errors + /// + /// This function has the same error semantics as [`read_until`] and will + /// also return an error if the read bytes are not valid UTF-8. If an I/O + /// error is encountered then `buf` may contain some bytes already read in + /// the event that all data read so far was valid UTF-8. + /// + /// [`read_until`]: AsyncBufReadExt::read_until + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncBufReadExt, Cursor}; + /// + /// let mut cursor = Cursor::new(b"foo\nbar"); + /// let mut buf = String::new(); + /// + /// // cursor is at 'f' + /// let num_bytes = cursor.read_line(&mut buf).await?; + /// assert_eq!(num_bytes, 4); + /// assert_eq!(buf, "foo\n"); + /// buf.clear(); + /// + /// // cursor is at 'b' + /// let num_bytes = cursor.read_line(&mut buf).await?; + /// assert_eq!(num_bytes, 3); + /// assert_eq!(buf, "bar"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_line(&mut buf).await?; + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, ""); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self> + where + Self: Unpin, + { + assert_future::, _>(ReadLine::new(self, buf)) + } + + /// Returns a stream over the lines of this reader. + /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines). + /// + /// The stream returned from this function will yield instances of + /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline + /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. + /// + /// [`io::Result`]: std::io::Result + /// [`String`]: String + /// + /// # Errors + /// + /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`]. + /// + /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncBufReadExt, Cursor}; + /// use futures::stream::StreamExt; + /// + /// let cursor = Cursor::new(b"lorem\nipsum\xc2\r\ndolor"); + /// + /// let mut lines_stream = cursor.lines().map(|l| l.unwrap_or(String::from("invalid UTF_8"))); + /// assert_eq!(lines_stream.next().await, Some(String::from("lorem"))); + /// assert_eq!(lines_stream.next().await, Some(String::from("invalid UTF_8"))); + /// assert_eq!(lines_stream.next().await, Some(String::from("dolor"))); + /// assert_eq!(lines_stream.next().await, None); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + fn lines(self) -> Lines + where + Self: Sized, + { + assert_stream::, _>(Lines::new(self)) + } +} + +impl AsyncBufReadExt for R {} + +// Just a helper function to ensure the reader we're returning all have the +// right implementations. +pub(crate) fn assert_read(reader: R) -> R +where + R: AsyncRead, +{ + reader +} +// Just a helper function to ensure the writer we're returning all have the +// right implementations. +pub(crate) fn assert_write(writer: W) -> W +where + W: AsyncWrite, +{ + writer +} diff --git a/anneal/v2/vendor/futures-util/src/io/read.rs b/anneal/v2/vendor/futures-util/src/io/read.rs new file mode 100644 index 0000000000..677ba818d9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read.rs @@ -0,0 +1,30 @@ +use crate::io::AsyncRead; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use std::io; +use std::pin::Pin; + +/// Future for the [`read`](super::AsyncReadExt::read) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Read<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut [u8], +} + +impl Unpin for Read<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized + Unpin> Read<'a, R> { + pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { + Self { reader, buf } + } +} + +impl Future for Read<'_, R> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + Pin::new(&mut this.reader).poll_read(cx, this.buf) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_exact.rs b/anneal/v2/vendor/futures-util/src/io/read_exact.rs new file mode 100644 index 0000000000..cd0b20e597 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_exact.rs @@ -0,0 +1,42 @@ +use crate::io::AsyncRead; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use std::io; +use std::mem; +use std::pin::Pin; + +/// Future for the [`read_exact`](super::AsyncReadExt::read_exact) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadExact<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut [u8], +} + +impl Unpin for ReadExact<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized + Unpin> ReadExact<'a, R> { + pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self { + Self { reader, buf } + } +} + +impl Future for ReadExact<'_, R> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + while !this.buf.is_empty() { + let n = ready!(Pin::new(&mut this.reader).poll_read(cx, this.buf))?; + { + let (_, rest) = mem::take(&mut this.buf).split_at_mut(n); + this.buf = rest; + } + if n == 0 { + return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into())); + } + } + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_line.rs b/anneal/v2/vendor/futures-util/src/io/read_line.rs new file mode 100644 index 0000000000..43942add54 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_line.rs @@ -0,0 +1,77 @@ +use super::read_until::read_until_internal; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncBufRead; +use std::io; +use std::mem; +use std::pin::Pin; +use std::str; +use std::string::String; +use std::vec::Vec; + +/// Future for the [`read_line`](super::AsyncBufReadExt::read_line) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadLine<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut String, + bytes: Vec, + read: usize, + finished: bool, +} + +impl Unpin for ReadLine<'_, R> {} + +impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadLine<'a, R> { + pub(super) fn new(reader: &'a mut R, buf: &'a mut String) -> Self { + Self { reader, bytes: mem::take(buf).into_bytes(), buf, read: 0, finished: false } + } +} + +pub(super) fn read_line_internal( + reader: Pin<&mut R>, + cx: &mut Context<'_>, + buf: &mut String, + bytes: &mut Vec, + read: &mut usize, +) -> Poll> { + let mut ret = ready!(read_until_internal(reader, cx, b'\n', bytes, read)); + if str::from_utf8(&bytes[bytes.len() - *read..bytes.len()]).is_err() { + bytes.truncate(bytes.len() - *read); + if ret.is_ok() { + ret = Err(io::Error::new( + io::ErrorKind::InvalidData, + "stream did not contain valid UTF-8", + )); + } + } + *read = 0; + // Safety: `bytes` is valid UTF-8 because it was taken from a String + // and the newly read bytes are either valid UTF-8 or have been removed. + mem::swap(unsafe { buf.as_mut_vec() }, bytes); + Poll::Ready(ret) +} + +impl Future for ReadLine<'_, R> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let Self { reader, buf, bytes, read, finished: _ } = &mut *self; + let ret = ready!(read_line_internal(Pin::new(reader), cx, buf, bytes, read)); + self.finished = true; + Poll::Ready(ret) + } +} + +impl Drop for ReadLine<'_, R> { + fn drop(&mut self) { + // restore old string contents + if !self.finished { + self.bytes.truncate(self.bytes.len() - self.read); + // Safety: `bytes` is valid UTF-8 because it was taken from a String + // and the newly read bytes have been removed. + mem::swap(unsafe { self.buf.as_mut_vec() }, &mut self.bytes); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_to_end.rs b/anneal/v2/vendor/futures-util/src/io/read_to_end.rs new file mode 100644 index 0000000000..82a36d2164 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_to_end.rs @@ -0,0 +1,90 @@ +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncRead; +use std::io; +use std::iter; +use std::pin::Pin; +use std::vec::Vec; + +/// Future for the [`read_to_end`](super::AsyncReadExt::read_to_end) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadToEnd<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut Vec, + start_len: usize, +} + +impl Unpin for ReadToEnd<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized + Unpin> ReadToEnd<'a, R> { + pub(super) fn new(reader: &'a mut R, buf: &'a mut Vec) -> Self { + let start_len = buf.len(); + Self { reader, buf, start_len } + } +} + +struct Guard<'a> { + buf: &'a mut Vec, + len: usize, +} + +impl Drop for Guard<'_> { + fn drop(&mut self) { + unsafe { + self.buf.set_len(self.len); + } + } +} + +// This uses an adaptive system to extend the vector when it fills. We want to +// avoid paying to allocate and zero a huge chunk of memory if the reader only +// has 4 bytes while still making large reads if the reader does have a ton +// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every +// time is 4,500 times (!) slower than this if the reader has a very small +// amount of data to return. +// +// Because we're extending the buffer with uninitialized data for trusted +// readers, we need to make sure to truncate that if any of this panics. +pub(super) fn read_to_end_internal( + mut rd: Pin<&mut R>, + cx: &mut Context<'_>, + buf: &mut Vec, + start_len: usize, +) -> Poll> { + let mut g = Guard { len: buf.len(), buf }; + loop { + if g.len == g.buf.len() { + g.buf.reserve(32); + let spare_capacity = g.buf.capacity() - g.buf.len(); + // FIXME: switch to `Vec::resize` once rust-lang/rust#120050 is fixed + g.buf.extend(iter::repeat(0).take(spare_capacity)); + } + + let buf = &mut g.buf[g.len..]; + match ready!(rd.as_mut().poll_read(cx, buf)) { + Ok(0) => return Poll::Ready(Ok(g.len - start_len)), + Ok(n) => { + // We can't allow bogus values from read. If it is too large, the returned vec could have its length + // set past its capacity, or if it overflows the vec could be shortened which could create an invalid + // string if this is called via read_to_string. + assert!(n <= buf.len()); + g.len += n; + } + Err(e) => return Poll::Ready(Err(e)), + } + } +} + +impl Future for ReadToEnd<'_, A> +where + A: AsyncRead + ?Sized + Unpin, +{ + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + read_to_end_internal(Pin::new(&mut this.reader), cx, this.buf, this.start_len) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_to_string.rs b/anneal/v2/vendor/futures-util/src/io/read_to_string.rs new file mode 100644 index 0000000000..a075ca2662 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_to_string.rs @@ -0,0 +1,60 @@ +use super::read_to_end::read_to_end_internal; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncRead; +use std::pin::Pin; +use std::string::String; +use std::vec::Vec; +use std::{io, mem, str}; + +/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadToString<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut String, + bytes: Vec, + start_len: usize, +} + +impl Unpin for ReadToString<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized + Unpin> ReadToString<'a, R> { + pub(super) fn new(reader: &'a mut R, buf: &'a mut String) -> Self { + let start_len = buf.len(); + Self { reader, bytes: mem::take(buf).into_bytes(), buf, start_len } + } +} + +fn read_to_string_internal( + reader: Pin<&mut R>, + cx: &mut Context<'_>, + buf: &mut String, + bytes: &mut Vec, + start_len: usize, +) -> Poll> { + let ret = ready!(read_to_end_internal(reader, cx, bytes, start_len)); + if str::from_utf8(bytes).is_err() { + Poll::Ready(ret.and_then(|_| { + Err(io::Error::new(io::ErrorKind::InvalidData, "stream did not contain valid UTF-8")) + })) + } else { + debug_assert!(buf.is_empty()); + // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`. + mem::swap(unsafe { buf.as_mut_vec() }, bytes); + Poll::Ready(ret) + } +} + +impl Future for ReadToString<'_, A> +where + A: AsyncRead + ?Sized + Unpin, +{ + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let Self { reader, buf, bytes, start_len } = &mut *self; + read_to_string_internal(Pin::new(reader), cx, buf, bytes, *start_len) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_until.rs b/anneal/v2/vendor/futures-util/src/io/read_until.rs new file mode 100644 index 0000000000..adc359db51 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_until.rs @@ -0,0 +1,60 @@ +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncBufRead; +use std::io; +use std::pin::Pin; +use std::vec::Vec; + +/// Future for the [`read_until`](super::AsyncBufReadExt::read_until) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadUntil<'a, R: ?Sized> { + reader: &'a mut R, + byte: u8, + buf: &'a mut Vec, + read: usize, +} + +impl Unpin for ReadUntil<'_, R> {} + +impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadUntil<'a, R> { + pub(super) fn new(reader: &'a mut R, byte: u8, buf: &'a mut Vec) -> Self { + Self { reader, byte, buf, read: 0 } + } +} + +pub(super) fn read_until_internal( + mut reader: Pin<&mut R>, + cx: &mut Context<'_>, + byte: u8, + buf: &mut Vec, + read: &mut usize, +) -> Poll> { + loop { + let (done, used) = { + let available = ready!(reader.as_mut().poll_fill_buf(cx))?; + if let Some(i) = memchr::memchr(byte, available) { + buf.extend_from_slice(&available[..=i]); + (true, i + 1) + } else { + buf.extend_from_slice(available); + (false, available.len()) + } + }; + reader.as_mut().consume(used); + *read += used; + if done || used == 0 { + return Poll::Ready(Ok(*read)); + } + } +} + +impl Future for ReadUntil<'_, R> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let Self { reader, byte, buf, read } = &mut *self; + read_until_internal(Pin::new(reader), cx, *byte, buf, read) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/read_vectored.rs b/anneal/v2/vendor/futures-util/src/io/read_vectored.rs new file mode 100644 index 0000000000..4e22df57e9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/read_vectored.rs @@ -0,0 +1,30 @@ +use crate::io::AsyncRead; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use std::io::{self, IoSliceMut}; +use std::pin::Pin; + +/// Future for the [`read_vectored`](super::AsyncReadExt::read_vectored) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct ReadVectored<'a, R: ?Sized> { + reader: &'a mut R, + bufs: &'a mut [IoSliceMut<'a>], +} + +impl Unpin for ReadVectored<'_, R> {} + +impl<'a, R: AsyncRead + ?Sized + Unpin> ReadVectored<'a, R> { + pub(super) fn new(reader: &'a mut R, bufs: &'a mut [IoSliceMut<'a>]) -> Self { + Self { reader, bufs } + } +} + +impl Future for ReadVectored<'_, R> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + Pin::new(&mut this.reader).poll_read_vectored(cx, this.bufs) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/repeat.rs b/anneal/v2/vendor/futures-util/src/io/repeat.rs new file mode 100644 index 0000000000..2828bf0114 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/repeat.rs @@ -0,0 +1,66 @@ +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncRead, IoSliceMut}; +use std::fmt; +use std::io; +use std::pin::Pin; + +/// Reader for the [`repeat()`] function. +#[must_use = "readers do nothing unless polled"] +pub struct Repeat { + byte: u8, +} + +/// Creates an instance of a reader that infinitely repeats one byte. +/// +/// All reads from this reader will succeed by filling the specified buffer with +/// the given byte. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncReadExt}; +/// +/// let mut buffer = [0; 3]; +/// let mut reader = io::repeat(0b101); +/// reader.read_exact(&mut buffer).await.unwrap(); +/// assert_eq!(buffer, [0b101, 0b101, 0b101]); +/// # Ok::<(), Box>(()) }).unwrap(); +/// ``` +pub fn repeat(byte: u8) -> Repeat { + Repeat { byte } +} + +impl AsyncRead for Repeat { + #[inline] + fn poll_read( + self: Pin<&mut Self>, + _: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + for slot in &mut *buf { + *slot = self.byte; + } + Poll::Ready(Ok(buf.len())) + } + + #[inline] + fn poll_read_vectored( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + let mut nwritten = 0; + for buf in bufs { + nwritten += ready!(self.as_mut().poll_read(cx, buf))?; + } + Poll::Ready(Ok(nwritten)) + } +} + +impl fmt::Debug for Repeat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Repeat { .. }") + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/seek.rs b/anneal/v2/vendor/futures-util/src/io/seek.rs new file mode 100644 index 0000000000..0aa2371393 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/seek.rs @@ -0,0 +1,30 @@ +use crate::io::{AsyncSeek, SeekFrom}; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use std::io; +use std::pin::Pin; + +/// Future for the [`seek`](crate::io::AsyncSeekExt::seek) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Seek<'a, S: ?Sized> { + seek: &'a mut S, + pos: SeekFrom, +} + +impl Unpin for Seek<'_, S> {} + +impl<'a, S: AsyncSeek + ?Sized + Unpin> Seek<'a, S> { + pub(super) fn new(seek: &'a mut S, pos: SeekFrom) -> Self { + Self { seek, pos } + } +} + +impl Future for Seek<'_, S> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + Pin::new(&mut this.seek).poll_seek(cx, this.pos) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/sink.rs b/anneal/v2/vendor/futures-util/src/io/sink.rs new file mode 100644 index 0000000000..4a32ca7041 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/sink.rs @@ -0,0 +1,67 @@ +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncWrite, IoSlice}; +use std::fmt; +use std::io; +use std::pin::Pin; + +/// Writer for the [`sink()`] function. +#[must_use = "writers do nothing unless polled"] +pub struct Sink { + _priv: (), +} + +/// Creates an instance of a writer which will successfully consume all data. +/// +/// All calls to `poll_write` on the returned instance will return `Poll::Ready(Ok(buf.len()))` +/// and the contents of the buffer will not be inspected. +/// +/// # Examples +/// +/// ```rust +/// # futures::executor::block_on(async { +/// use futures::io::{self, AsyncWriteExt}; +/// +/// let buffer = vec![1, 2, 3, 5, 8]; +/// let mut writer = io::sink(); +/// let num_bytes = writer.write(&buffer).await?; +/// assert_eq!(num_bytes, 5); +/// # Ok::<(), Box>(()) }).unwrap(); +/// ``` +pub fn sink() -> Sink { + Sink { _priv: () } +} + +impl AsyncWrite for Sink { + #[inline] + fn poll_write( + self: Pin<&mut Self>, + _: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Poll::Ready(Ok(buf.len())) + } + + #[inline] + fn poll_write_vectored( + self: Pin<&mut Self>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + Poll::Ready(Ok(bufs.iter().map(|b| b.len()).sum())) + } + + #[inline] + fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + #[inline] + fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } +} + +impl fmt::Debug for Sink { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Sink { .. }") + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/split.rs b/anneal/v2/vendor/futures-util/src/io/split.rs new file mode 100644 index 0000000000..5b6bc18937 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/split.rs @@ -0,0 +1,129 @@ +use crate::lock::BiLock; +use core::fmt; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncRead, AsyncWrite, IoSlice, IoSliceMut}; +use std::io; +use std::pin::Pin; + +/// The readable half of an object returned from `AsyncRead::split`. +#[derive(Debug)] +pub struct ReadHalf { + handle: BiLock, +} + +/// The writable half of an object returned from `AsyncRead::split`. +#[derive(Debug)] +pub struct WriteHalf { + handle: BiLock, +} + +fn lock_and_then(lock: &BiLock, cx: &mut Context<'_>, f: F) -> Poll> +where + F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> Poll>, +{ + let mut l = ready!(lock.poll_lock(cx)); + f(l.as_pin_mut(), cx) +} + +pub(super) fn split(t: T) -> (ReadHalf, WriteHalf) { + let (a, b) = BiLock::new(t); + (ReadHalf { handle: a }, WriteHalf { handle: b }) +} + +impl ReadHalf { + /// Checks if this `ReadHalf` and some `WriteHalf` were split from the same stream. + pub fn is_pair_of(&self, other: &WriteHalf) -> bool { + self.handle.is_pair_of(&other.handle) + } +} + +impl ReadHalf { + /// Attempts to put the two "halves" of a split `AsyncRead + AsyncWrite` back + /// together. Succeeds only if the `ReadHalf` and `WriteHalf` are + /// a matching pair originating from the same call to `AsyncReadExt::split`. + pub fn reunite(self, other: WriteHalf) -> Result> { + self.handle + .reunite(other.handle) + .map_err(|err| ReuniteError(Self { handle: err.0 }, WriteHalf { handle: err.1 })) + } +} + +impl WriteHalf { + /// Checks if this `WriteHalf` and some `ReadHalf` were split from the same stream. + pub fn is_pair_of(&self, other: &ReadHalf) -> bool { + self.handle.is_pair_of(&other.handle) + } +} + +impl WriteHalf { + /// Attempts to put the two "halves" of a split `AsyncRead + AsyncWrite` back + /// together. Succeeds only if the `ReadHalf` and `WriteHalf` are + /// a matching pair originating from the same call to `AsyncReadExt::split`. + pub fn reunite(self, other: ReadHalf) -> Result> { + other.reunite(self) + } +} + +impl AsyncRead for ReadHalf { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_read(cx, buf)) + } + + fn poll_read_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_read_vectored(cx, bufs)) + } +} + +impl AsyncWrite for WriteHalf { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_write(cx, buf)) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_write_vectored(cx, bufs)) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_flush(cx)) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + lock_and_then(&self.handle, cx, |l, cx| l.poll_close(cx)) + } +} + +/// Error indicating a `ReadHalf` and `WriteHalf` were not two halves +/// of a `AsyncRead + AsyncWrite`, and thus could not be `reunite`d. +pub struct ReuniteError(pub ReadHalf, pub WriteHalf); + +impl fmt::Debug for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ReuniteError").field(&"...").finish() + } +} + +impl fmt::Display for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "tried to reunite a ReadHalf and WriteHalf that don't form a pair") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ReuniteError {} diff --git a/anneal/v2/vendor/futures-util/src/io/take.rs b/anneal/v2/vendor/futures-util/src/io/take.rs new file mode 100644 index 0000000000..2c494804d9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/take.rs @@ -0,0 +1,125 @@ +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead}; +use pin_project_lite::pin_project; +use std::pin::Pin; +use std::{cmp, io}; + +pin_project! { + /// Reader for the [`take`](super::AsyncReadExt::take) method. + #[derive(Debug)] + #[must_use = "readers do nothing unless you `.await` or poll them"] + pub struct Take { + #[pin] + inner: R, + limit: u64, + } +} + +impl Take { + pub(super) fn new(inner: R, limit: u64) -> Self { + Self { inner, limit } + } + + /// Returns the remaining number of bytes that can be + /// read before this instance will return EOF. + /// + /// # Note + /// + /// This instance may reach `EOF` after reading fewer bytes than indicated by + /// this method if the underlying [`AsyncRead`] instance reaches EOF. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let reader = Cursor::new(&b"12345678"[..]); + /// let mut buffer = [0; 2]; + /// + /// let mut take = reader.take(4); + /// let n = take.read(&mut buffer).await?; + /// + /// assert_eq!(take.limit(), 2); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + pub fn limit(&self) -> u64 { + self.limit + } + + /// Sets the number of bytes that can be read before this instance will + /// return EOF. This is the same as constructing a new `Take` instance, so + /// the amount of bytes read and the previous limit value don't matter when + /// calling this method. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::io::{AsyncReadExt, Cursor}; + /// + /// let reader = Cursor::new(&b"12345678"[..]); + /// let mut buffer = [0; 4]; + /// + /// let mut take = reader.take(4); + /// let n = take.read(&mut buffer).await?; + /// + /// assert_eq!(n, 4); + /// assert_eq!(take.limit(), 0); + /// + /// take.set_limit(10); + /// let n = take.read(&mut buffer).await?; + /// assert_eq!(n, 4); + /// + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + pub fn set_limit(&mut self, limit: u64) { + self.limit = limit + } + + delegate_access_inner!(inner, R, ()); +} + +impl AsyncRead for Take { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let this = self.project(); + + if *this.limit == 0 { + return Poll::Ready(Ok(0)); + } + + let max = cmp::min(buf.len() as u64, *this.limit) as usize; + let n = ready!(this.inner.poll_read(cx, &mut buf[..max]))?; + *this.limit -= n as u64; + Poll::Ready(Ok(n)) + } +} + +impl AsyncBufRead for Take { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + // Don't call into inner reader at all at EOF because it may still block + if *this.limit == 0 { + return Poll::Ready(Ok(&[])); + } + + let buf = ready!(this.inner.poll_fill_buf(cx)?); + let cap = cmp::min(buf.len() as u64, *this.limit) as usize; + Poll::Ready(Ok(&buf[..cap])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + let this = self.project(); + + // Don't let callers reset the limit by passing an overlarge value + let amt = cmp::min(amt as u64, *this.limit) as usize; + *this.limit -= amt as u64; + this.inner.consume(amt); + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/window.rs b/anneal/v2/vendor/futures-util/src/io/window.rs new file mode 100644 index 0000000000..d857282383 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/window.rs @@ -0,0 +1,104 @@ +use std::ops::{Bound, Range, RangeBounds}; + +/// An owned window around an underlying buffer. +/// +/// Normally slices work great for considering sub-portions of a buffer, but +/// unfortunately a slice is a *borrowed* type in Rust which has an associated +/// lifetime. When working with future and async I/O these lifetimes are not +/// always appropriate, and are sometimes difficult to store in tasks. This +/// type strives to fill this gap by providing an "owned slice" around an +/// underlying buffer of bytes. +/// +/// A `Window` wraps an underlying buffer, `T`, and has configurable +/// start/end indexes to alter the behavior of the `AsRef<[u8]>` implementation +/// that this type carries. +/// +/// This type can be particularly useful when working with the `write_all` +/// combinator in this crate. Data can be sliced via `Window`, consumed by +/// `write_all`, and then earned back once the write operation finishes through +/// the `into_inner` method on this type. +#[derive(Debug)] +pub struct Window { + inner: T, + range: Range, +} + +impl> Window { + /// Creates a new window around the buffer `t` defaulting to the entire + /// slice. + /// + /// Further methods can be called on the returned `Window` to alter the + /// window into the data provided. + pub fn new(t: T) -> Self { + Self { range: 0..t.as_ref().len(), inner: t } + } + + /// Gets a shared reference to the underlying buffer inside of this + /// `Window`. + pub fn get_ref(&self) -> &T { + &self.inner + } + + /// Gets a mutable reference to the underlying buffer inside of this + /// `Window`. + pub fn get_mut(&mut self) -> &mut T { + &mut self.inner + } + + /// Consumes this `Window`, returning the underlying buffer. + pub fn into_inner(self) -> T { + self.inner + } + + /// Returns the starting index of this window into the underlying buffer + /// `T`. + pub fn start(&self) -> usize { + self.range.start + } + + /// Returns the end index of this window into the underlying buffer + /// `T`. + pub fn end(&self) -> usize { + self.range.end + } + + /// Changes the range of this window to the range specified. + /// + /// # Panics + /// + /// This method will panic if `range` is out of bounds for the underlying + /// slice or if [`start_bound()`] of `range` comes after the [`end_bound()`]. + /// + /// [`start_bound()`]: std::ops::RangeBounds::start_bound + /// [`end_bound()`]: std::ops::RangeBounds::end_bound + pub fn set>(&mut self, range: R) { + let start = match range.start_bound() { + Bound::Included(n) => *n, + Bound::Excluded(n) => *n + 1, + Bound::Unbounded => 0, + }; + let end = match range.end_bound() { + Bound::Included(n) => *n + 1, + Bound::Excluded(n) => *n, + Bound::Unbounded => self.inner.as_ref().len(), + }; + + assert!(end <= self.inner.as_ref().len()); + assert!(start <= end); + + self.range.start = start; + self.range.end = end; + } +} + +impl> AsRef<[u8]> for Window { + fn as_ref(&self) -> &[u8] { + &self.inner.as_ref()[self.range.start..self.range.end] + } +} + +impl> AsMut<[u8]> for Window { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.inner.as_mut()[self.range.start..self.range.end] + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/write.rs b/anneal/v2/vendor/futures-util/src/io/write.rs new file mode 100644 index 0000000000..c47ef9e2eb --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/write.rs @@ -0,0 +1,30 @@ +use crate::io::AsyncWrite; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use std::io; +use std::pin::Pin; + +/// Future for the [`write`](super::AsyncWriteExt::write) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Write<'a, W: ?Sized> { + writer: &'a mut W, + buf: &'a [u8], +} + +impl Unpin for Write<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> Write<'a, W> { + pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { + Self { writer, buf } + } +} + +impl Future for Write<'_, W> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + Pin::new(&mut this.writer).poll_write(cx, this.buf) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/write_all.rs b/anneal/v2/vendor/futures-util/src/io/write_all.rs new file mode 100644 index 0000000000..08c025f94d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/write_all.rs @@ -0,0 +1,43 @@ +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use std::io; +use std::mem; +use std::pin::Pin; + +/// Future for the [`write_all`](super::AsyncWriteExt::write_all) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct WriteAll<'a, W: ?Sized> { + writer: &'a mut W, + buf: &'a [u8], +} + +impl Unpin for WriteAll<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAll<'a, W> { + pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self { + Self { writer, buf } + } +} + +impl Future for WriteAll<'_, W> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = &mut *self; + while !this.buf.is_empty() { + let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?; + { + let (_, rest) = mem::take(&mut this.buf).split_at(n); + this.buf = rest; + } + if n == 0 { + return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); + } + } + + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/write_all_vectored.rs b/anneal/v2/vendor/futures-util/src/io/write_all_vectored.rs new file mode 100644 index 0000000000..26b3f25d92 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/write_all_vectored.rs @@ -0,0 +1,195 @@ +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_io::AsyncWrite; +use futures_io::IoSlice; +use std::io; +use std::pin::Pin; + +/// Future for the +/// [`write_all_vectored`](super::AsyncWriteExt::write_all_vectored) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct WriteAllVectored<'a, W: ?Sized + Unpin> { + writer: &'a mut W, + bufs: &'a mut [IoSlice<'a>], +} + +impl Unpin for WriteAllVectored<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAllVectored<'a, W> { + pub(super) fn new(writer: &'a mut W, mut bufs: &'a mut [IoSlice<'a>]) -> Self { + IoSlice::advance_slices(&mut bufs, 0); + Self { writer, bufs } + } +} + +impl Future for WriteAllVectored<'_, W> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = &mut *self; + while !this.bufs.is_empty() { + let n = ready!(Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs))?; + if n == 0 { + return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); + } else { + IoSlice::advance_slices(&mut this.bufs, n); + } + } + + Poll::Ready(Ok(())) + } +} + +#[cfg(test)] +mod tests { + use std::cmp::min; + use std::future::Future; + use std::io; + use std::pin::Pin; + use std::task::{Context, Poll}; + use std::vec; + use std::vec::Vec; + + use crate::io::{AsyncWrite, AsyncWriteExt, IoSlice}; + use crate::task::noop_waker; + + /// Create a new writer that reads from at most `n_bufs` and reads + /// `per_call` bytes (in total) per call to write. + fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter { + TestWriter { n_bufs, per_call, written: Vec::new() } + } + + // TODO: maybe move this the future-test crate? + struct TestWriter { + n_bufs: usize, + per_call: usize, + written: Vec, + } + + impl AsyncWrite for TestWriter { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + self.poll_write_vectored(cx, &[IoSlice::new(buf)]) + } + + fn poll_write_vectored( + mut self: Pin<&mut Self>, + _cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + let mut left = self.per_call; + let mut written = 0; + for buf in bufs.iter().take(self.n_bufs) { + let n = min(left, buf.len()); + self.written.extend_from_slice(&buf[0..n]); + left -= n; + written += n; + } + Poll::Ready(Ok(written)) + } + + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + } + + // TODO: maybe move this the future-test crate? + macro_rules! assert_poll_ok { + ($e:expr, $expected:expr) => { + let expected = $expected; + match $e { + Poll::Ready(Ok(ok)) if ok == expected => {} + got => { + panic!("unexpected result, got: {:?}, wanted: Ready(Ok({:?}))", got, expected) + } + } + }; + } + + #[test] + fn test_writer_read_from_one_buf() { + let waker = noop_waker(); + let mut cx = Context::from_waker(&waker); + + let mut dst = test_writer(1, 2); + let mut dst = Pin::new(&mut dst); + + assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[]), 0); + assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, &[]), 0); + + // Read at most 2 bytes. + assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[1, 1, 1]), 2); + let bufs = &[IoSlice::new(&[2, 2, 2])]; + assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 2); + + // Only read from first buf. + let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])]; + assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 1); + + assert_eq!(dst.written, &[1, 1, 2, 2, 3]); + } + + #[test] + fn test_writer_read_from_multiple_bufs() { + let waker = noop_waker(); + let mut cx = Context::from_waker(&waker); + + let mut dst = test_writer(3, 3); + let mut dst = Pin::new(&mut dst); + + // Read at most 3 bytes from two buffers. + let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])]; + assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3); + + // Read at most 3 bytes from three buffers. + let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])]; + assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3); + + assert_eq!(dst.written, &[1, 2, 2, 3, 4, 5]); + } + + #[test] + fn test_write_all_vectored() { + let waker = noop_waker(); + let mut cx = Context::from_waker(&waker); + + #[rustfmt::skip] // Becomes unreadable otherwise. + let tests: Vec<(_, &'static [u8])> = vec![ + (vec![], &[]), + (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]), + (vec![IoSlice::new(&[1])], &[1]), + (vec![IoSlice::new(&[1, 2])], &[1, 2]), + (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]), + (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]), + (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]), + (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]), + (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]), + (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]), + (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]), + (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]), + (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]), + (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]), + ]; + + for (mut input, wanted) in tests { + let mut dst = test_writer(2, 2); + { + let mut future = dst.write_all_vectored(&mut *input); + match Pin::new(&mut future).poll(&mut cx) { + Poll::Ready(Ok(())) => {} + other => panic!("unexpected result polling future: {:?}", other), + } + } + assert_eq!(&*dst.written, &*wanted); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/io/write_vectored.rs b/anneal/v2/vendor/futures-util/src/io/write_vectored.rs new file mode 100644 index 0000000000..14a01d7302 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/io/write_vectored.rs @@ -0,0 +1,30 @@ +use crate::io::AsyncWrite; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use std::io::{self, IoSlice}; +use std::pin::Pin; + +/// Future for the [`write_vectored`](super::AsyncWriteExt::write_vectored) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct WriteVectored<'a, W: ?Sized> { + writer: &'a mut W, + bufs: &'a [IoSlice<'a>], +} + +impl Unpin for WriteVectored<'_, W> {} + +impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteVectored<'a, W> { + pub(super) fn new(writer: &'a mut W, bufs: &'a [IoSlice<'a>]) -> Self { + Self { writer, bufs } + } +} + +impl Future for WriteVectored<'_, W> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs) + } +} diff --git a/anneal/v2/vendor/futures-util/src/lib.rs b/anneal/v2/vendor/futures-util/src/lib.rs new file mode 100644 index 0000000000..1949e5a630 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/lib.rs @@ -0,0 +1,332 @@ +//! Combinators and utilities for working with `Future`s, `Stream`s, `Sink`s, +//! and the `AsyncRead` and `AsyncWrite` traits. + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms, single_use_lifetimes), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn(missing_docs, unsafe_op_in_unsafe_fn)] +#![cfg_attr(docsrs, feature(doc_cfg))] + +#[cfg(all(feature = "bilock", not(feature = "unstable")))] +compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +// Macro re-exports +pub use futures_core::ready; + +#[cfg(feature = "async-await")] +#[macro_use] +mod async_await; +#[cfg(feature = "async-await")] +#[doc(hidden)] +pub use self::async_await::*; + +// Not public API. +#[doc(hidden)] +pub mod __private { + pub use crate::*; + pub use core::{ + option::Option::{self, None, Some}, + pin::Pin, + result::Result::{Err, Ok}, + }; + + #[cfg(feature = "async-await")] + pub mod async_await { + pub use crate::async_await::*; + } +} + +#[cfg(feature = "sink")] +macro_rules! delegate_sink { + ($field:ident, $item:ty) => { + fn poll_ready( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_ready(cx) + } + + fn start_send(self: core::pin::Pin<&mut Self>, item: $item) -> Result<(), Self::Error> { + self.project().$field.start_send(item) + } + + fn poll_flush( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_flush(cx) + } + + fn poll_close( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_close(cx) + } + }; +} + +macro_rules! delegate_future { + ($field:ident) => { + fn poll( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll { + self.project().$field.poll(cx) + } + }; +} + +macro_rules! delegate_stream { + ($field:ident) => { + fn poll_next( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_next(cx) + } + fn size_hint(&self) -> (usize, Option) { + self.$field.size_hint() + } + }; +} + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +macro_rules! delegate_async_write { + ($field:ident) => { + fn poll_write( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + buf: &[u8], + ) -> core::task::Poll> { + self.project().$field.poll_write(cx, buf) + } + fn poll_write_vectored( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> core::task::Poll> { + self.project().$field.poll_write_vectored(cx, bufs) + } + fn poll_flush( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_flush(cx) + } + fn poll_close( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_close(cx) + } + }; +} + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +macro_rules! delegate_async_read { + ($field:ident) => { + fn poll_read( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + buf: &mut [u8], + ) -> core::task::Poll> { + self.project().$field.poll_read(cx, buf) + } + + fn poll_read_vectored( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + bufs: &mut [std::io::IoSliceMut<'_>], + ) -> core::task::Poll> { + self.project().$field.poll_read_vectored(cx, bufs) + } + }; +} + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +macro_rules! delegate_async_buf_read { + ($field:ident) => { + fn poll_fill_buf( + self: core::pin::Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll> { + self.project().$field.poll_fill_buf(cx) + } + + fn consume(self: core::pin::Pin<&mut Self>, amt: usize) { + self.project().$field.consume(amt) + } + }; +} + +macro_rules! delegate_access_inner { + ($field:ident, $inner:ty, ($($ind:tt)*)) => { + /// Acquires a reference to the underlying sink or stream that this combinator is + /// pulling from. + pub fn get_ref(&self) -> &$inner { + (&self.$field) $($ind get_ref())* + } + + /// Acquires a mutable reference to the underlying sink or stream that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// sink or stream which may otherwise confuse this combinator. + pub fn get_mut(&mut self) -> &mut $inner { + (&mut self.$field) $($ind get_mut())* + } + + /// Acquires a pinned mutable reference to the underlying sink or stream that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// sink or stream which may otherwise confuse this combinator. + pub fn get_pin_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut $inner> { + self.project().$field $($ind get_pin_mut())* + } + + /// Consumes this combinator, returning the underlying sink or stream. + /// + /// Note that this may discard intermediate state of this combinator, so + /// care should be taken to avoid losing resources when this is called. + pub fn into_inner(self) -> $inner { + self.$field $($ind into_inner())* + } + } +} + +macro_rules! delegate_all { + (@trait Future $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> futures_core::future::Future for $name<$($arg),*> where $t: futures_core::future::Future $(, $($bound)*)* { + type Output = <$t as futures_core::future::Future>::Output; + + delegate_future!(inner); + } + }; + (@trait FusedFuture $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> futures_core::future::FusedFuture for $name<$($arg),*> where $t: futures_core::future::FusedFuture $(, $($bound)*)* { + fn is_terminated(&self) -> bool { + self.inner.is_terminated() + } + } + }; + (@trait Stream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> futures_core::stream::Stream for $name<$($arg),*> where $t: futures_core::stream::Stream $(, $($bound)*)* { + type Item = <$t as futures_core::stream::Stream>::Item; + + delegate_stream!(inner); + } + }; + (@trait FusedStream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> futures_core::stream::FusedStream for $name<$($arg),*> where $t: futures_core::stream::FusedStream $(, $($bound)*)* { + fn is_terminated(&self) -> bool { + self.inner.is_terminated() + } + } + }; + (@trait Sink $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + #[cfg(feature = "sink")] + impl<_Item, $($arg),*> futures_sink::Sink<_Item> for $name<$($arg),*> where $t: futures_sink::Sink<_Item> $(, $($bound)*)* { + type Error = <$t as futures_sink::Sink<_Item>>::Error; + + delegate_sink!(inner, _Item); + } + }; + (@trait Debug $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> core::fmt::Debug for $name<$($arg),*> where $t: core::fmt::Debug $(, $($bound)*)* { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Debug::fmt(&self.inner, f) + } + } + }; + (@trait AccessInner[$inner:ty, ($($ind:tt)*)] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* { + delegate_access_inner!(inner, $inner, ($($ind)*)); + } + }; + (@trait New[|$($param:ident: $paramt:ty),*| $cons:expr] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { + impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* { + pub(crate) fn new($($param: $paramt),*) -> Self { + Self { inner: $cons } + } + } + }; + ($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($targs:tt)*])* $({$($item:tt)*})* $(where $($bound:tt)*)*) => { + pin_project_lite::pin_project! { + #[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"] + $(#[$attr])* + pub struct $name< $($arg),* > $(where $($bound)*)* { #[pin] inner: $t } + } + + impl<$($arg),*> $name< $($arg),* > $(where $($bound)*)* { + $($($item)*)* + } + + delegate_all!(@trait $ftrait $([$($targs)*])* $name<$($arg),*>($t) $(where $($bound)*)*); + }; + ($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($ftargs:tt)*])* + $strait:ident $([$($stargs:tt)*])* $(+ $trait:ident $([$($targs:tt)*])*)* $({$($item:tt)*})* $(where $($bound:tt)*)*) => { + delegate_all!($(#[$attr])* $name<$($arg),*>($t) : $strait $([$($stargs)*])* $(+ $trait $([$($targs)*])*)* $({$($item)*})* $(where $($bound)*)*); + + delegate_all!(@trait $ftrait $([$($ftargs)*])* $name<$($arg),*>($t) $(where $($bound)*)*); + }; +} + +pub mod future; +#[doc(no_inline)] +pub use crate::future::{Future, FutureExt, TryFuture, TryFutureExt}; + +pub mod stream; +#[doc(no_inline)] +pub use crate::stream::{Stream, StreamExt, TryStream, TryStreamExt}; + +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub mod sink; +#[cfg(feature = "sink")] +#[doc(no_inline)] +pub use crate::sink::{Sink, SinkExt}; + +pub mod task; + +pub mod never; + +#[cfg(feature = "compat")] +#[cfg_attr(docsrs, doc(cfg(feature = "compat")))] +pub mod compat; + +#[cfg(feature = "io")] +#[cfg_attr(docsrs, doc(cfg(feature = "io")))] +#[cfg(feature = "std")] +pub mod io; +#[cfg(feature = "io")] +#[cfg(feature = "std")] +#[doc(no_inline)] +pub use crate::io::{ + AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWrite, + AsyncWriteExt, +}; + +#[cfg(feature = "alloc")] +pub mod lock; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod abortable; + +mod fns; +mod macros; +mod unfold_state; diff --git a/anneal/v2/vendor/futures-util/src/lock/bilock.rs b/anneal/v2/vendor/futures-util/src/lock/bilock.rs new file mode 100644 index 0000000000..7c740f878f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/lock/bilock.rs @@ -0,0 +1,297 @@ +//! Futures-powered synchronization primitives. + +use alloc::boxed::Box; +use alloc::sync::Arc; +use core::cell::UnsafeCell; +use core::ops::{Deref, DerefMut}; +use core::pin::Pin; +use core::sync::atomic::AtomicPtr; +use core::sync::atomic::Ordering::SeqCst; +use core::{fmt, ptr}; +#[cfg(feature = "bilock")] +use futures_core::future::Future; +use futures_core::task::{Context, Poll, Waker}; + +/// A type of futures-powered synchronization primitive which is a mutex between +/// two possible owners. +/// +/// This primitive is not as generic as a full-blown mutex but is sufficient for +/// many use cases where there are only two possible owners of a resource. The +/// implementation of `BiLock` can be more optimized for just the two possible +/// owners. +/// +/// Note that it's possible to use this lock through a poll-style interface with +/// the `poll_lock` method but you can also use it as a future with the `lock` +/// method that consumes a `BiLock` and returns a future that will resolve when +/// it's locked. +/// +/// A `BiLock` is typically used for "split" operations where data which serves +/// two purposes wants to be split into two to be worked with separately. For +/// example a TCP stream could be both a reader and a writer or a framing layer +/// could be both a stream and a sink for messages. A `BiLock` enables splitting +/// these two and then using each independently in a futures-powered fashion. +/// +/// This type is only available when the `bilock` feature of this +/// library is activated. +#[derive(Debug)] +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +pub struct BiLock { + arc: Arc>, +} + +#[derive(Debug)] +struct Inner { + state: AtomicPtr, + value: Option>, +} + +unsafe impl Send for Inner {} +unsafe impl Sync for Inner {} + +impl BiLock { + /// Creates a new `BiLock` protecting the provided data. + /// + /// Two handles to the lock are returned, and these are the only two handles + /// that will ever be available to the lock. These can then be sent to separate + /// tasks to be managed there. + /// + /// The data behind the bilock is considered to be pinned, which allows `Pin` + /// references to locked data. However, this means that the locked value + /// will only be available through `Pin<&mut T>` (not `&mut T`) unless `T` is `Unpin`. + /// Similarly, reuniting the lock and extracting the inner value is only + /// possible when `T` is `Unpin`. + pub fn new(t: T) -> (Self, Self) { + let arc = Arc::new(Inner { + state: AtomicPtr::new(ptr::null_mut()), + value: Some(UnsafeCell::new(t)), + }); + + (Self { arc: arc.clone() }, Self { arc }) + } + + /// Attempt to acquire this lock, returning `Pending` if it can't be + /// acquired. + /// + /// This function will acquire the lock in a nonblocking fashion, returning + /// immediately if the lock is already held. If the lock is successfully + /// acquired then `Poll::Ready` is returned with a value that represents + /// the locked value (and can be used to access the protected data). The + /// lock is unlocked when the returned `BiLockGuard` is dropped. + /// + /// If the lock is already held then this function will return + /// `Poll::Pending`. In this case the current task will also be scheduled + /// to receive a notification when the lock would otherwise become + /// available. + /// + /// # Panics + /// + /// This function will panic if called outside the context of a future's + /// task. + pub fn poll_lock(&self, cx: &mut Context<'_>) -> Poll> { + let mut waker = None; + loop { + let n = self.arc.state.swap(invalid_ptr(1), SeqCst); + match n as usize { + // Woohoo, we grabbed the lock! + 0 => return Poll::Ready(BiLockGuard { bilock: self }), + + // Oops, someone else has locked the lock + 1 => {} + + // A task was previously blocked on this lock, likely our task, + // so we need to update that task. + _ => unsafe { + let mut prev = Box::from_raw(n); + *prev = cx.waker().clone(); + waker = Some(prev); + }, + } + + // type ascription for safety's sake! + let me: Box = waker.take().unwrap_or_else(|| Box::new(cx.waker().clone())); + let me = Box::into_raw(me); + + match self.arc.state.compare_exchange(invalid_ptr(1), me, SeqCst, SeqCst) { + // The lock is still locked, but we've now parked ourselves, so + // just report that we're scheduled to receive a notification. + Ok(_) => return Poll::Pending, + + // Oops, looks like the lock was unlocked after our swap above + // and before the compare_exchange. Deallocate what we just + // allocated and go through the loop again. + Err(n) if n.is_null() => unsafe { + waker = Some(Box::from_raw(me)); + }, + + // The top of this loop set the previous state to 1, so if we + // failed the CAS above then it's because the previous value was + // *not* zero or one. This indicates that a task was blocked, + // but we're trying to acquire the lock and there's only one + // other reference of the lock, so it should be impossible for + // that task to ever block itself. + Err(n) => panic!("invalid state: {}", n as usize), + } + } + } + + /// Perform a "blocking lock" of this lock, consuming this lock handle and + /// returning a future to the acquired lock. + /// + /// This function consumes the `BiLock` and returns a sentinel future, + /// `BiLockAcquire`. The returned future will resolve to + /// `BiLockGuard`. + /// + /// Note that the returned future will never resolve to an error. + #[cfg(feature = "bilock")] + #[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] + pub fn lock(&self) -> BiLockAcquire<'_, T> { + BiLockAcquire { bilock: self } + } + + /// Returns `true` only if the other `BiLock` originated from the same call to `BiLock::new`. + pub fn is_pair_of(&self, other: &Self) -> bool { + Arc::ptr_eq(&self.arc, &other.arc) + } + + /// Attempts to put the two "halves" of a `BiLock` back together and + /// recover the original value. Succeeds only if the two `BiLock`s + /// originated from the same call to `BiLock::new`. + pub fn reunite(self, other: Self) -> Result> + where + T: Unpin, + { + if self.is_pair_of(&other) { + drop(other); + let inner = Arc::try_unwrap(self.arc) + .ok() + .expect("futures: try_unwrap failed in BiLock::reunite"); + Ok(unsafe { inner.into_value() }) + } else { + Err(ReuniteError(self, other)) + } + } + + fn unlock(&self) { + let n = self.arc.state.swap(ptr::null_mut(), SeqCst); + match n as usize { + // we've locked the lock, shouldn't be possible for us to see an + // unlocked lock. + 0 => panic!("invalid unlocked state"), + + // Ok, no one else tried to get the lock, we're done. + 1 => {} + + // Another task has parked themselves on this lock, let's wake them + // up as its now their turn. + _ => unsafe { + Box::from_raw(n).wake(); + }, + } + } +} + +impl Inner { + unsafe fn into_value(mut self) -> T { + self.value.take().unwrap().into_inner() + } +} + +impl Drop for Inner { + fn drop(&mut self) { + assert!(self.state.load(SeqCst).is_null()); + } +} + +/// Error indicating two `BiLock`s were not two halves of a whole, and +/// thus could not be `reunite`d. +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +pub struct ReuniteError(pub BiLock, pub BiLock); + +impl fmt::Debug for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ReuniteError").field(&"...").finish() + } +} + +impl fmt::Display for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "tried to reunite two BiLocks that don't form a pair") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ReuniteError {} + +/// Returned RAII guard from the `poll_lock` method. +/// +/// This structure acts as a sentinel to the data in the `BiLock` itself, +/// implementing `Deref` and `DerefMut` to `T`. When dropped, the lock will be +/// unlocked. +#[derive(Debug)] +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +pub struct BiLockGuard<'a, T> { + bilock: &'a BiLock, +} + +// We allow parallel access to T via Deref, so Sync bound is also needed here. +unsafe impl Sync for BiLockGuard<'_, T> {} + +impl Deref for BiLockGuard<'_, T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.bilock.arc.value.as_ref().unwrap().get() } + } +} + +impl DerefMut for BiLockGuard<'_, T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.bilock.arc.value.as_ref().unwrap().get() } + } +} + +impl BiLockGuard<'_, T> { + /// Get a mutable pinned reference to the locked value. + pub fn as_pin_mut(&mut self) -> Pin<&mut T> { + // Safety: we never allow moving a !Unpin value out of a bilock, nor + // allow mutable access to it + unsafe { Pin::new_unchecked(&mut *self.bilock.arc.value.as_ref().unwrap().get()) } + } +} + +impl Drop for BiLockGuard<'_, T> { + fn drop(&mut self) { + self.bilock.unlock(); + } +} + +/// Future returned by `BiLock::lock` which will resolve when the lock is +/// acquired. +#[cfg(feature = "bilock")] +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +pub struct BiLockAcquire<'a, T> { + bilock: &'a BiLock, +} + +// Pinning is never projected to fields +#[cfg(feature = "bilock")] +impl Unpin for BiLockAcquire<'_, T> {} + +#[cfg(feature = "bilock")] +impl<'a, T> Future for BiLockAcquire<'a, T> { + type Output = BiLockGuard<'a, T>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.bilock.poll_lock(cx) + } +} + +// Based on core::ptr::invalid_mut. Equivalent to `addr as *mut T`, but is strict-provenance compatible. +#[allow(clippy::useless_transmute)] +#[inline] +fn invalid_ptr(addr: usize) -> *mut T { + // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that + // pointer). + unsafe { core::mem::transmute(addr) } +} diff --git a/anneal/v2/vendor/futures-util/src/lock/mod.rs b/anneal/v2/vendor/futures-util/src/lock/mod.rs new file mode 100644 index 0000000000..8ca0ff6255 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/lock/mod.rs @@ -0,0 +1,27 @@ +//! Futures-powered synchronization primitives. +//! +//! This module is only available when the `std` or `alloc` feature of this +//! library is activated, and it is activated by default. + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(any(feature = "sink", feature = "io"))] +#[cfg(not(feature = "bilock"))] +pub(crate) use self::bilock::BiLock; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "bilock")] +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +pub use self::bilock::{BiLock, BiLockAcquire, BiLockGuard, ReuniteError}; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "std")] +pub use self::mutex::{ + MappedMutexGuard, Mutex, MutexGuard, MutexLockFuture, OwnedMutexGuard, OwnedMutexLockFuture, +}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(any(feature = "bilock", feature = "sink", feature = "io"))] +#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))] +#[cfg_attr(not(feature = "bilock"), allow(unreachable_pub))] +mod bilock; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "std")] +mod mutex; diff --git a/anneal/v2/vendor/futures-util/src/lock/mutex.rs b/anneal/v2/vendor/futures-util/src/lock/mutex.rs new file mode 100644 index 0000000000..24acb0b727 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/lock/mutex.rs @@ -0,0 +1,560 @@ +use std::cell::UnsafeCell; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex as StdMutex}; +use std::{fmt, mem}; + +use slab::Slab; + +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll, Waker}; + +/// A futures-aware mutex. +/// +/// # Fairness +/// +/// This mutex provides no fairness guarantees. Tasks may not acquire the mutex +/// in the order that they requested the lock, and it's possible for a single task +/// which repeatedly takes the lock to starve other tasks, which may be left waiting +/// indefinitely. +pub struct Mutex { + state: AtomicUsize, + waiters: StdMutex>, + value: UnsafeCell, +} + +impl fmt::Debug for Mutex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let state = self.state.load(Ordering::SeqCst); + f.debug_struct("Mutex") + .field("is_locked", &((state & IS_LOCKED) != 0)) + .field("has_waiters", &((state & HAS_WAITERS) != 0)) + .finish() + } +} + +impl From for Mutex { + fn from(t: T) -> Self { + Self::new(t) + } +} + +impl Default for Mutex { + fn default() -> Self { + Self::new(Default::default()) + } +} + +enum Waiter { + Waiting(Waker), + Woken, +} + +impl Waiter { + fn register(&mut self, waker: &Waker) { + match self { + Self::Waiting(w) if waker.will_wake(w) => {} + _ => *self = Self::Waiting(waker.clone()), + } + } + + fn wake(&mut self) { + match mem::replace(self, Self::Woken) { + Self::Waiting(waker) => waker.wake(), + Self::Woken => {} + } + } +} + +const IS_LOCKED: usize = 1 << 0; +const HAS_WAITERS: usize = 1 << 1; + +impl Mutex { + /// Creates a new futures-aware mutex. + pub const fn new(t: T) -> Self { + Self { + state: AtomicUsize::new(0), + waiters: StdMutex::new(Slab::new()), + value: UnsafeCell::new(t), + } + } + + /// Consumes this mutex, returning the underlying data. + /// + /// # Examples + /// + /// ``` + /// use futures::lock::Mutex; + /// + /// let mutex = Mutex::new(0); + /// assert_eq!(mutex.into_inner(), 0); + /// ``` + pub fn into_inner(self) -> T { + self.value.into_inner() + } +} + +impl Mutex { + /// Attempt to acquire the lock immediately. + /// + /// If the lock is currently held, this will return `None`. + pub fn try_lock(&self) -> Option> { + let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire); + if (old_state & IS_LOCKED) == 0 { + Some(MutexGuard { mutex: self }) + } else { + None + } + } + + /// Attempt to acquire the lock immediately. + /// + /// If the lock is currently held, this will return `None`. + pub fn try_lock_owned(self: &Arc) -> Option> { + let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire); + if (old_state & IS_LOCKED) == 0 { + Some(OwnedMutexGuard { mutex: self.clone() }) + } else { + None + } + } + + /// Acquire the lock asynchronously. + /// + /// This method returns a future that will resolve once the lock has been + /// successfully acquired. + pub fn lock(&self) -> MutexLockFuture<'_, T> { + MutexLockFuture { mutex: Some(self), wait_key: WAIT_KEY_NONE } + } + + /// Acquire the lock asynchronously. + /// + /// This method returns a future that will resolve once the lock has been + /// successfully acquired. + pub fn lock_owned(self: Arc) -> OwnedMutexLockFuture { + OwnedMutexLockFuture { mutex: Some(self), wait_key: WAIT_KEY_NONE } + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this call borrows the `Mutex` mutably, no actual locking needs to + /// take place -- the mutable borrow statically guarantees no locks exist. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::lock::Mutex; + /// + /// let mut mutex = Mutex::new(0); + /// *mutex.get_mut() = 10; + /// assert_eq!(*mutex.lock().await, 10); + /// # }); + /// ``` + pub fn get_mut(&mut self) -> &mut T { + // We know statically that there are no other references to `self`, so + // there's no need to lock the inner mutex. + unsafe { &mut *self.value.get() } + } + + fn remove_waker(&self, wait_key: usize, wake_another: bool) { + if wait_key != WAIT_KEY_NONE { + let mut waiters = self.waiters.lock().unwrap(); + match waiters.remove(wait_key) { + Waiter::Waiting(_) => {} + Waiter::Woken => { + // We were awoken, but then dropped before we could + // wake up to acquire the lock. Wake up another + // waiter. + if wake_another { + if let Some((_i, waiter)) = waiters.iter_mut().next() { + waiter.wake(); + } + } + } + } + if waiters.is_empty() { + self.state.fetch_and(!HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock + } + } + } + + // Unlocks the mutex. Called by MutexGuard and MappedMutexGuard when they are + // dropped. + fn unlock(&self) { + let old_state = self.state.fetch_and(!IS_LOCKED, Ordering::AcqRel); + if (old_state & HAS_WAITERS) != 0 { + let mut waiters = self.waiters.lock().unwrap(); + if let Some((_i, waiter)) = waiters.iter_mut().next() { + waiter.wake(); + } + } + } +} + +// Sentinel for when no slot in the `Slab` has been dedicated to this object. +const WAIT_KEY_NONE: usize = usize::MAX; + +/// A future which resolves when the target mutex has been successfully acquired, owned version. +pub struct OwnedMutexLockFuture { + // `None` indicates that the mutex was successfully acquired. + mutex: Option>>, + wait_key: usize, +} + +impl fmt::Debug for OwnedMutexLockFuture { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedMutexLockFuture") + .field("was_acquired", &self.mutex.is_none()) + .field("mutex", &self.mutex) + .field( + "wait_key", + &(if self.wait_key == WAIT_KEY_NONE { None } else { Some(self.wait_key) }), + ) + .finish() + } +} + +impl FusedFuture for OwnedMutexLockFuture { + fn is_terminated(&self) -> bool { + self.mutex.is_none() + } +} + +impl Future for OwnedMutexLockFuture { + type Output = OwnedMutexGuard; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + + let mutex = this.mutex.as_ref().expect("polled OwnedMutexLockFuture after completion"); + + if let Some(lock) = mutex.try_lock_owned() { + mutex.remove_waker(this.wait_key, false); + this.mutex = None; + return Poll::Ready(lock); + } + + { + let mut waiters = mutex.waiters.lock().unwrap(); + if this.wait_key == WAIT_KEY_NONE { + this.wait_key = waiters.insert(Waiter::Waiting(cx.waker().clone())); + if waiters.len() == 1 { + mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock + } + } else { + waiters[this.wait_key].register(cx.waker()); + } + } + + // Ensure that we haven't raced `MutexGuard::drop`'s unlock path by + // attempting to acquire the lock again. + if let Some(lock) = mutex.try_lock_owned() { + mutex.remove_waker(this.wait_key, false); + this.mutex = None; + return Poll::Ready(lock); + } + + Poll::Pending + } +} + +impl Drop for OwnedMutexLockFuture { + fn drop(&mut self) { + if let Some(mutex) = self.mutex.as_ref() { + // This future was dropped before it acquired the mutex. + // + // Remove ourselves from the map, waking up another waiter if we + // had been awoken to acquire the lock. + mutex.remove_waker(self.wait_key, true); + } + } +} + +/// An RAII guard returned by the `lock_owned` and `try_lock_owned` methods. +/// When this structure is dropped (falls out of scope), the lock will be +/// unlocked. +#[clippy::has_significant_drop] +pub struct OwnedMutexGuard { + mutex: Arc>, +} + +impl fmt::Debug for OwnedMutexGuard { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedMutexGuard") + .field("value", &&**self) + .field("mutex", &self.mutex) + .finish() + } +} + +impl Drop for OwnedMutexGuard { + fn drop(&mut self) { + self.mutex.unlock() + } +} + +impl Deref for OwnedMutexGuard { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.mutex.value.get() } + } +} + +impl DerefMut for OwnedMutexGuard { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.mutex.value.get() } + } +} + +/// A future which resolves when the target mutex has been successfully acquired. +pub struct MutexLockFuture<'a, T: ?Sized> { + // `None` indicates that the mutex was successfully acquired. + mutex: Option<&'a Mutex>, + wait_key: usize, +} + +impl fmt::Debug for MutexLockFuture<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MutexLockFuture") + .field("was_acquired", &self.mutex.is_none()) + .field("mutex", &self.mutex) + .field( + "wait_key", + &(if self.wait_key == WAIT_KEY_NONE { None } else { Some(self.wait_key) }), + ) + .finish() + } +} + +impl FusedFuture for MutexLockFuture<'_, T> { + fn is_terminated(&self) -> bool { + self.mutex.is_none() + } +} + +impl<'a, T: ?Sized> Future for MutexLockFuture<'a, T> { + type Output = MutexGuard<'a, T>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mutex = self.mutex.expect("polled MutexLockFuture after completion"); + + if let Some(lock) = mutex.try_lock() { + mutex.remove_waker(self.wait_key, false); + self.mutex = None; + return Poll::Ready(lock); + } + + { + let mut waiters = mutex.waiters.lock().unwrap(); + if self.wait_key == WAIT_KEY_NONE { + self.wait_key = waiters.insert(Waiter::Waiting(cx.waker().clone())); + if waiters.len() == 1 { + mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock + } + } else { + waiters[self.wait_key].register(cx.waker()); + } + } + + // Ensure that we haven't raced `MutexGuard::drop`'s unlock path by + // attempting to acquire the lock again. + if let Some(lock) = mutex.try_lock() { + mutex.remove_waker(self.wait_key, false); + self.mutex = None; + return Poll::Ready(lock); + } + + Poll::Pending + } +} + +impl Drop for MutexLockFuture<'_, T> { + fn drop(&mut self) { + if let Some(mutex) = self.mutex { + // This future was dropped before it acquired the mutex. + // + // Remove ourselves from the map, waking up another waiter if we + // had been awoken to acquire the lock. + mutex.remove_waker(self.wait_key, true); + } + } +} + +/// An RAII guard returned by the `lock` and `try_lock` methods. +/// When this structure is dropped (falls out of scope), the lock will be +/// unlocked. +#[clippy::has_significant_drop] +pub struct MutexGuard<'a, T: ?Sized> { + mutex: &'a Mutex, +} + +impl<'a, T: ?Sized> MutexGuard<'a, T> { + /// Returns a locked view over a portion of the locked data. + /// + /// # Example + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::lock::{Mutex, MutexGuard}; + /// + /// let data = Mutex::new(Some("value".to_string())); + /// { + /// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap()); + /// assert_eq!(&*locked_str, "value"); + /// } + /// # }); + /// ``` + #[inline] + pub fn map(this: Self, f: F) -> MappedMutexGuard<'a, T, U> + where + F: FnOnce(&mut T) -> &mut U, + { + let mutex = this.mutex; + let value = f(unsafe { &mut *this.mutex.value.get() }); + // Don't run the `drop` method for MutexGuard. The ownership of the underlying + // locked state is being moved to the returned MappedMutexGuard. + mem::forget(this); + MappedMutexGuard { mutex, value, _marker: PhantomData } + } +} + +impl fmt::Debug for MutexGuard<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MutexGuard").field("value", &&**self).field("mutex", &self.mutex).finish() + } +} + +impl Drop for MutexGuard<'_, T> { + fn drop(&mut self) { + self.mutex.unlock() + } +} + +impl Deref for MutexGuard<'_, T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.mutex.value.get() } + } +} + +impl DerefMut for MutexGuard<'_, T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.mutex.value.get() } + } +} + +/// An RAII guard returned by the `MutexGuard::map` and `MappedMutexGuard::map` methods. +/// When this structure is dropped (falls out of scope), the lock will be unlocked. +#[clippy::has_significant_drop] +pub struct MappedMutexGuard<'a, T: ?Sized, U: ?Sized> { + mutex: &'a Mutex, + value: *mut U, + _marker: PhantomData<&'a mut U>, +} + +impl<'a, T: ?Sized, U: ?Sized> MappedMutexGuard<'a, T, U> { + /// Returns a locked view over a portion of the locked data. + /// + /// # Example + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::lock::{MappedMutexGuard, Mutex, MutexGuard}; + /// + /// let data = Mutex::new(Some("value".to_string())); + /// { + /// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap()); + /// let locked_char = MappedMutexGuard::map(locked_str, |s| s.get_mut(0..1).unwrap()); + /// assert_eq!(&*locked_char, "v"); + /// } + /// # }); + /// ``` + #[inline] + pub fn map(this: Self, f: F) -> MappedMutexGuard<'a, T, V> + where + F: FnOnce(&mut U) -> &mut V, + { + let mutex = this.mutex; + let value = f(unsafe { &mut *this.value }); + // Don't run the `drop` method for MappedMutexGuard. The ownership of the underlying + // locked state is being moved to the returned MappedMutexGuard. + mem::forget(this); + MappedMutexGuard { mutex, value, _marker: PhantomData } + } +} + +impl fmt::Debug for MappedMutexGuard<'_, T, U> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MappedMutexGuard") + .field("value", &&**self) + .field("mutex", &self.mutex) + .finish() + } +} + +impl Drop for MappedMutexGuard<'_, T, U> { + fn drop(&mut self) { + self.mutex.unlock() + } +} + +impl Deref for MappedMutexGuard<'_, T, U> { + type Target = U; + fn deref(&self) -> &U { + unsafe { &*self.value } + } +} + +impl DerefMut for MappedMutexGuard<'_, T, U> { + fn deref_mut(&mut self) -> &mut U { + unsafe { &mut *self.value } + } +} + +// Mutexes can be moved freely between threads and acquired on any thread so long +// as the inner value can be safely sent between threads. +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +// It's safe to switch which thread the acquire is being attempted on so long as +// `T` can be accessed on that thread. +unsafe impl Send for MutexLockFuture<'_, T> {} + +// doesn't have any interesting `&self` methods (only Debug) +unsafe impl Sync for MutexLockFuture<'_, T> {} + +// It's safe to switch which thread the acquire is being attempted on so long as +// `T` can be accessed on that thread. +unsafe impl Send for OwnedMutexLockFuture {} + +// doesn't have any interesting `&self` methods (only Debug) +unsafe impl Sync for OwnedMutexLockFuture {} + +// Safe to send since we don't track any thread-specific details-- the inner +// lock is essentially spinlock-equivalent (attempt to flip an atomic bool) +unsafe impl Send for MutexGuard<'_, T> {} +unsafe impl Sync for MutexGuard<'_, T> {} + +unsafe impl Send for OwnedMutexGuard {} +unsafe impl Sync for OwnedMutexGuard {} + +unsafe impl Send for MappedMutexGuard<'_, T, U> {} +unsafe impl Sync for MappedMutexGuard<'_, T, U> {} + +#[cfg(test)] +mod tests { + use super::*; + use std::format; + + #[test] + fn test_mutex_guard_debug_not_recurse() { + let mutex = Mutex::new(42); + let guard = mutex.try_lock().unwrap(); + let _ = format!("{guard:?}"); + let guard = MutexGuard::map(guard, |n| n); + let _ = format!("{guard:?}"); + } +} diff --git a/anneal/v2/vendor/futures-util/src/macros.rs b/anneal/v2/vendor/futures-util/src/macros.rs new file mode 100644 index 0000000000..0f5cba99e3 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/macros.rs @@ -0,0 +1,31 @@ +/// Pins a value on the stack. +/// +/// Can safely pin values that are not `Unpin` by taking ownership. +/// +/// **Note:** Since Rust 1.68, this macro is soft-deprecated in favor of +/// [`pin!`](https://doc.rust-lang.org/std/pin/macro.pin.html) macro +/// in the standard library. +/// +/// # Example +/// +/// ```rust +/// # use futures_util::pin_mut; +/// # use core::pin::Pin; +/// # struct Foo {} +/// let foo = Foo { /* ... */ }; +/// pin_mut!(foo); +/// let _: Pin<&mut Foo> = foo; +/// ``` +#[macro_export] +macro_rules! pin_mut { + ($($x:ident),* $(,)?) => { $( + // Move the value to ensure that it is owned + let mut $x = $x; + // Shadow the original binding so that it can't be directly accessed + // ever again. + #[allow(unused_mut)] + let mut $x = unsafe { + $crate::__private::Pin::new_unchecked(&mut $x) + }; + )* } +} diff --git a/anneal/v2/vendor/futures-util/src/never.rs b/anneal/v2/vendor/futures-util/src/never.rs new file mode 100644 index 0000000000..e811f97df7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/never.rs @@ -0,0 +1,18 @@ +//! This module contains the `Never` type. +//! +//! Values of this type can never be created and will never exist. + +/// A type with no possible values. +/// +/// This is used to indicate values which can never be created, such as the +/// error type of infallible futures. +/// +/// This type is a stable equivalent to the `!` type from `std`. +/// +/// This is currently an alias for [`std::convert::Infallible`], but in +/// the future it may be an alias for [`!`][never]. +/// See ["Future compatibility" section of `std::convert::Infallible`][infallible] for more. +/// +/// [never]: https://doc.rust-lang.org/nightly/std/primitive.never.html +/// [infallible]: https://doc.rust-lang.org/nightly/std/convert/enum.Infallible.html#future-compatibility +pub type Never = core::convert::Infallible; diff --git a/anneal/v2/vendor/futures-util/src/sink/buffer.rs b/anneal/v2/vendor/futures-util/src/sink/buffer.rs new file mode 100644 index 0000000000..4aa6c36033 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/buffer.rs @@ -0,0 +1,105 @@ +use alloc::collections::VecDeque; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`buffer`](super::SinkExt::buffer) method. + #[derive(Debug)] + #[must_use = "sinks do nothing unless polled"] + pub struct Buffer { + #[pin] + sink: Si, + buf: VecDeque, + + // Track capacity separately from the `VecDeque`, which may be rounded up + capacity: usize, + } +} + +impl, Item> Buffer { + pub(super) fn new(sink: Si, capacity: usize) -> Self { + Self { sink, buf: VecDeque::with_capacity(capacity), capacity } + } + + delegate_access_inner!(sink, Si, ()); + + fn try_empty_buffer(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + ready!(this.sink.as_mut().poll_ready(cx))?; + while let Some(item) = this.buf.pop_front() { + this.sink.as_mut().start_send(item)?; + if !this.buf.is_empty() { + ready!(this.sink.as_mut().poll_ready(cx))?; + } + } + Poll::Ready(Ok(())) + } +} + +// Forwarding impl of Stream from the underlying sink +impl Stream for Buffer +where + S: Sink + Stream, +{ + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().sink.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + self.sink.size_hint() + } +} + +impl FusedStream for Buffer +where + S: Sink + FusedStream, +{ + fn is_terminated(&self) -> bool { + self.sink.is_terminated() + } +} + +impl, Item> Sink for Buffer { + type Error = Si::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.capacity == 0 { + return self.project().sink.poll_ready(cx); + } + + let _ = self.as_mut().try_empty_buffer(cx)?; + + if self.buf.len() >= self.capacity { + Poll::Pending + } else { + Poll::Ready(Ok(())) + } + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + if self.capacity == 0 { + self.project().sink.start_send(item) + } else { + self.project().buf.push_back(item); + Ok(()) + } + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().try_empty_buffer(cx))?; + debug_assert!(self.buf.is_empty()); + self.project().sink.poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().try_empty_buffer(cx))?; + debug_assert!(self.buf.is_empty()); + self.project().sink.poll_close(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/close.rs b/anneal/v2/vendor/futures-util/src/sink/close.rs new file mode 100644 index 0000000000..43eea74b0f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/close.rs @@ -0,0 +1,32 @@ +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Future for the [`close`](super::SinkExt::close) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Close<'a, Si: ?Sized, Item> { + sink: &'a mut Si, + _phantom: PhantomData, +} + +impl Unpin for Close<'_, Si, Item> {} + +/// A future that completes when the sink has finished closing. +/// +/// The sink itself is returned after closing is complete. +impl<'a, Si: Sink + Unpin + ?Sized, Item> Close<'a, Si, Item> { + pub(super) fn new(sink: &'a mut Si) -> Self { + Self { sink, _phantom: PhantomData } + } +} + +impl + Unpin + ?Sized, Item> Future for Close<'_, Si, Item> { + type Output = Result<(), Si::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.sink).poll_close(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/drain.rs b/anneal/v2/vendor/futures-util/src/sink/drain.rs new file mode 100644 index 0000000000..1a5480c0d6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/drain.rs @@ -0,0 +1,59 @@ +use super::assert_sink; +use crate::never::Never; +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Sink for the [`drain`] function. +#[derive(Debug)] +#[must_use = "sinks do nothing unless polled"] +pub struct Drain { + marker: PhantomData, +} + +/// Create a sink that will just discard all items given to it. +/// +/// Similar to [`io::Sink`](::std::io::Sink). +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::sink::{self, SinkExt}; +/// +/// let mut drain = sink::drain(); +/// drain.send(5).await?; +/// # Ok::<(), futures::never::Never>(()) }).unwrap(); +/// ``` +pub fn drain() -> Drain { + assert_sink::(Drain { marker: PhantomData }) +} + +impl Unpin for Drain {} + +impl Clone for Drain { + fn clone(&self) -> Self { + drain() + } +} + +impl Sink for Drain { + type Error = Never; + + fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, _item: T) -> Result<(), Self::Error> { + Ok(()) + } + + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/err_into.rs b/anneal/v2/vendor/futures-util/src/sink/err_into.rs new file mode 100644 index 0000000000..a64d1337ba --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/err_into.rs @@ -0,0 +1,57 @@ +use crate::sink::{SinkExt, SinkMapErr}; +use futures_core::stream::{FusedStream, Stream}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`sink_err_into`](super::SinkExt::sink_err_into) method. + #[derive(Debug)] + #[must_use = "sinks do nothing unless polled"] + pub struct SinkErrInto, Item, E> { + #[pin] + sink: SinkMapErr E>, + } +} + +impl SinkErrInto +where + Si: Sink, + Si::Error: Into, +{ + pub(super) fn new(sink: Si) -> Self { + Self { sink: SinkExt::sink_map_err(sink, Into::into) } + } + + delegate_access_inner!(sink, Si, (.)); +} + +impl Sink for SinkErrInto +where + Si: Sink, + Si::Error: Into, +{ + type Error = E; + + delegate_sink!(sink, Item); +} + +// Forwarding impl of Stream from the underlying sink +impl Stream for SinkErrInto +where + S: Sink + Stream, + S::Error: Into, +{ + type Item = S::Item; + + delegate_stream!(sink); +} + +impl FusedStream for SinkErrInto +where + S: Sink + FusedStream, + S::Error: Into, +{ + fn is_terminated(&self) -> bool { + self.sink.is_terminated() + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/fanout.rs b/anneal/v2/vendor/futures-util/src/sink/fanout.rs new file mode 100644 index 0000000000..fe2038f27f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/fanout.rs @@ -0,0 +1,111 @@ +use core::fmt::{Debug, Formatter, Result as FmtResult}; +use core::pin::Pin; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink that clones incoming items and forwards them to two sinks at the same time. + /// + /// Backpressure from any downstream sink propagates up, which means that this sink + /// can only process items as fast as its _slowest_ downstream sink. + #[must_use = "sinks do nothing unless polled"] + pub struct Fanout { + #[pin] + sink1: Si1, + #[pin] + sink2: Si2 + } +} + +impl Fanout { + pub(super) fn new(sink1: Si1, sink2: Si2) -> Self { + Self { sink1, sink2 } + } + + /// Get a shared reference to the inner sinks. + pub fn get_ref(&self) -> (&Si1, &Si2) { + (&self.sink1, &self.sink2) + } + + /// Get a mutable reference to the inner sinks. + pub fn get_mut(&mut self) -> (&mut Si1, &mut Si2) { + (&mut self.sink1, &mut self.sink2) + } + + /// Get a pinned mutable reference to the inner sinks. + pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut Si1>, Pin<&mut Si2>) { + let this = self.project(); + (this.sink1, this.sink2) + } + + /// Consumes this combinator, returning the underlying sinks. + /// + /// Note that this may discard intermediate state of this combinator, + /// so care should be taken to avoid losing resources when this is called. + pub fn into_inner(self) -> (Si1, Si2) { + (self.sink1, self.sink2) + } +} + +impl Debug for Fanout { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + f.debug_struct("Fanout").field("sink1", &self.sink1).field("sink2", &self.sink2).finish() + } +} + +impl Sink for Fanout +where + Si1: Sink, + Item: Clone, + Si2: Sink, +{ + type Error = Si1::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + let sink1_ready = this.sink1.poll_ready(cx)?.is_ready(); + let sink2_ready = this.sink2.poll_ready(cx)?.is_ready(); + let ready = sink1_ready && sink2_ready; + if ready { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + let this = self.project(); + + this.sink1.start_send(item.clone())?; + this.sink2.start_send(item)?; + Ok(()) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + let sink1_ready = this.sink1.poll_flush(cx)?.is_ready(); + let sink2_ready = this.sink2.poll_flush(cx)?.is_ready(); + let ready = sink1_ready && sink2_ready; + if ready { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + let sink1_ready = this.sink1.poll_close(cx)?.is_ready(); + let sink2_ready = this.sink2.poll_close(cx)?.is_ready(); + let ready = sink1_ready && sink2_ready; + if ready { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/feed.rs b/anneal/v2/vendor/futures-util/src/sink/feed.rs new file mode 100644 index 0000000000..6701f7a1b4 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/feed.rs @@ -0,0 +1,43 @@ +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Future for the [`feed`](super::SinkExt::feed) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Feed<'a, Si: ?Sized, Item> { + sink: &'a mut Si, + item: Option, +} + +// Pinning is never projected to children +impl Unpin for Feed<'_, Si, Item> {} + +impl<'a, Si: Sink + Unpin + ?Sized, Item> Feed<'a, Si, Item> { + pub(super) fn new(sink: &'a mut Si, item: Item) -> Self { + Feed { sink, item: Some(item) } + } + + pub(super) fn sink_pin_mut(&mut self) -> Pin<&mut Si> { + Pin::new(self.sink) + } + + pub(super) fn is_item_pending(&self) -> bool { + self.item.is_some() + } +} + +impl + Unpin + ?Sized, Item> Future for Feed<'_, Si, Item> { + type Output = Result<(), Si::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + let mut sink = Pin::new(&mut this.sink); + ready!(sink.as_mut().poll_ready(cx))?; + let item = this.item.take().expect("polled Feed after completion"); + sink.as_mut().start_send(item)?; + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/flush.rs b/anneal/v2/vendor/futures-util/src/sink/flush.rs new file mode 100644 index 0000000000..35a8372de7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/flush.rs @@ -0,0 +1,36 @@ +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Future for the [`flush`](super::SinkExt::flush) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Flush<'a, Si: ?Sized, Item> { + sink: &'a mut Si, + _phantom: PhantomData, +} + +// Pin is never projected to a field. +impl Unpin for Flush<'_, Si, Item> {} + +/// A future that completes when the sink has finished processing all +/// pending requests. +/// +/// The sink itself is returned after flushing is complete; this adapter is +/// intended to be used when you want to stop sending to the sink until +/// all current requests are processed. +impl<'a, Si: Sink + Unpin + ?Sized, Item> Flush<'a, Si, Item> { + pub(super) fn new(sink: &'a mut Si) -> Self { + Self { sink, _phantom: PhantomData } + } +} + +impl + Unpin + ?Sized, Item> Future for Flush<'_, Si, Item> { + type Output = Result<(), Si::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.sink).poll_flush(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/map_err.rs b/anneal/v2/vendor/futures-util/src/sink/map_err.rs new file mode 100644 index 0000000000..9d2ab7b24b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/map_err.rs @@ -0,0 +1,65 @@ +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`sink_map_err`](super::SinkExt::sink_map_err) method. + #[derive(Debug, Clone)] + #[must_use = "sinks do nothing unless polled"] + pub struct SinkMapErr { + #[pin] + sink: Si, + f: Option, + } +} + +impl SinkMapErr { + pub(super) fn new(sink: Si, f: F) -> Self { + Self { sink, f: Some(f) } + } + + delegate_access_inner!(sink, Si, ()); + + fn take_f(self: Pin<&mut Self>) -> F { + self.project().f.take().expect("polled MapErr after completion") + } +} + +impl Sink for SinkMapErr +where + Si: Sink, + F: FnOnce(Si::Error) -> E, +{ + type Error = E; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().project().sink.poll_ready(cx).map_err(|e| self.as_mut().take_f()(e)) + } + + fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + self.as_mut().project().sink.start_send(item).map_err(|e| self.as_mut().take_f()(e)) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().project().sink.poll_flush(cx).map_err(|e| self.as_mut().take_f()(e)) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().project().sink.poll_close(cx).map_err(|e| self.as_mut().take_f()(e)) + } +} + +// Forwarding impl of Stream from the underlying sink +impl Stream for SinkMapErr { + type Item = S::Item; + + delegate_stream!(sink); +} + +impl FusedStream for SinkMapErr { + fn is_terminated(&self) -> bool { + self.sink.is_terminated() + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/mod.rs b/anneal/v2/vendor/futures-util/src/sink/mod.rs new file mode 100644 index 0000000000..147e9adc93 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/mod.rs @@ -0,0 +1,344 @@ +//! Asynchronous sinks. +//! +//! This module contains: +//! +//! - The [`Sink`] trait, which allows you to asynchronously write data. +//! - The [`SinkExt`] trait, which provides adapters for chaining and composing +//! sinks. + +use crate::future::{assert_future, Either}; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::stream::{Stream, TryStream}; +use futures_core::task::{Context, Poll}; + +#[cfg(feature = "compat")] +use crate::compat::CompatSink; + +pub use futures_sink::Sink; + +mod close; +pub use self::close::Close; + +mod drain; +pub use self::drain::{drain, Drain}; + +mod fanout; +pub use self::fanout::Fanout; + +mod feed; +pub use self::feed::Feed; + +mod flush; +pub use self::flush::Flush; + +mod err_into; +pub use self::err_into::SinkErrInto; + +mod map_err; +pub use self::map_err::SinkMapErr; + +mod send; +pub use self::send::Send; + +mod send_all; +pub use self::send_all::SendAll; + +mod unfold; +pub use self::unfold::{unfold, Unfold}; + +mod with; +pub use self::with::With; + +mod with_flat_map; +pub use self::with_flat_map::WithFlatMap; + +#[cfg(feature = "alloc")] +mod buffer; +#[cfg(feature = "alloc")] +pub use self::buffer::Buffer; + +impl SinkExt for T where T: Sink {} + +/// An extension trait for `Sink`s that provides a variety of convenient +/// combinator functions. +pub trait SinkExt: Sink { + /// Composes a function *in front of* the sink. + /// + /// This adapter produces a new sink that passes each value through the + /// given function `f` before sending it to `self`. + /// + /// To process each value, `f` produces a *future*, which is then polled to + /// completion before passing its result down to the underlying sink. If the + /// future produces an error, that error is returned by the new sink. + /// + /// Note that this function consumes the given sink, returning a wrapped + /// version, much like `Iterator::map`. + fn with(self, f: F) -> With + where + F: FnMut(U) -> Fut, + Fut: Future>, + E: From, + Self: Sized, + { + assert_sink::(With::new(self, f)) + } + + /// Composes a function *in front of* the sink. + /// + /// This adapter produces a new sink that passes each value through the + /// given function `f` before sending it to `self`. + /// + /// To process each value, `f` produces a *stream*, of which each value + /// is passed to the underlying sink. A new value will not be accepted until + /// the stream has been drained + /// + /// Note that this function consumes the given sink, returning a wrapped + /// version, much like `Iterator::flat_map`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::sink::SinkExt; + /// use futures::stream::{self, StreamExt}; + /// + /// let (tx, rx) = mpsc::channel(5); + /// + /// let mut tx = tx.with_flat_map(|x| { + /// stream::iter(vec![Ok(42); x]) + /// }); + /// + /// tx.send(5).await.unwrap(); + /// drop(tx); + /// let received: Vec = rx.collect().await; + /// assert_eq!(received, vec![42, 42, 42, 42, 42]); + /// # }); + /// ``` + fn with_flat_map(self, f: F) -> WithFlatMap + where + F: FnMut(U) -> St, + St: Stream>, + Self: Sized, + { + assert_sink::(WithFlatMap::new(self, f)) + } + + /* + fn with_map(self, f: F) -> WithMap + where F: FnMut(U) -> Self::SinkItem, + Self: Sized; + + fn with_filter(self, f: F) -> WithFilter + where F: FnMut(Self::SinkItem) -> bool, + Self: Sized; + + fn with_filter_map(self, f: F) -> WithFilterMap + where F: FnMut(U) -> Option, + Self: Sized; + */ + + /// Transforms the error returned by the sink. + fn sink_map_err(self, f: F) -> SinkMapErr + where + F: FnOnce(Self::Error) -> E, + Self: Sized, + { + assert_sink::(SinkMapErr::new(self, f)) + } + + /// Map this sink's error to a different error type using the `Into` trait. + /// + /// If wanting to map errors of a `Sink + Stream`, use `.sink_err_into().err_into()`. + fn sink_err_into(self) -> err_into::SinkErrInto + where + Self: Sized, + Self::Error: Into, + { + assert_sink::(SinkErrInto::new(self)) + } + + /// Adds a fixed-size buffer to the current sink. + /// + /// The resulting sink will buffer up to `capacity` items when the + /// underlying sink is unwilling to accept additional items. Calling `flush` + /// on the buffered sink will attempt to both empty the buffer and complete + /// processing on the underlying sink. + /// + /// Note that this function consumes the given sink, returning a wrapped + /// version, much like `Iterator::map`. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn buffer(self, capacity: usize) -> Buffer + where + Self: Sized, + { + assert_sink::(Buffer::new(self, capacity)) + } + + /// Close the sink. + fn close(&mut self) -> Close<'_, Self, Item> + where + Self: Unpin, + { + assert_future::, _>(Close::new(self)) + } + + /// Fanout items to multiple sinks. + /// + /// This adapter clones each incoming item and forwards it to both this as well as + /// the other sink at the same time. + fn fanout(self, other: Si) -> Fanout + where + Self: Sized, + Item: Clone, + Si: Sink, + { + assert_sink::(Fanout::new(self, other)) + } + + /// Flush the sink, processing all pending items. + /// + /// This adapter is intended to be used when you want to stop sending to the sink + /// until all current requests are processed. + fn flush(&mut self) -> Flush<'_, Self, Item> + where + Self: Unpin, + { + assert_future::, _>(Flush::new(self)) + } + + /// A future that completes after the given item has been fully processed + /// into the sink, including flushing. + /// + /// Note that, **because of the flushing requirement, it is usually better + /// to batch together items to send via `feed` or `send_all`, + /// rather than flushing between each item.** + fn send(&mut self, item: Item) -> Send<'_, Self, Item> + where + Self: Unpin, + { + assert_future::, _>(Send::new(self, item)) + } + + /// A future that completes after the given item has been received + /// by the sink. + /// + /// Unlike `send`, the returned future does not flush the sink. + /// It is the caller's responsibility to ensure all pending items + /// are processed, which can be done via `flush` or `close`. + fn feed(&mut self, item: Item) -> Feed<'_, Self, Item> + where + Self: Unpin, + { + assert_future::, _>(Feed::new(self, item)) + } + + /// A future that completes after the given stream has been fully processed + /// into the sink, including flushing. + /// + /// This future will drive the stream to keep producing items until it is + /// exhausted, sending each item to the sink. It will complete once both the + /// stream is exhausted, the sink has received all items, and the sink has + /// been flushed. Note that the sink is **not** closed. If the stream produces + /// an error, that error will be returned by this future without flushing the sink. + /// + /// Doing `sink.send_all(stream)` is roughly equivalent to + /// `stream.forward(sink)`. The returned future will exhaust all items from + /// `stream` and send them to `self`. + fn send_all<'a, St>(&'a mut self, stream: &'a mut St) -> SendAll<'a, Self, St> + where + St: TryStream + Stream + Unpin + ?Sized, + // St: Stream> + Unpin + ?Sized, + Self: Unpin, + { + // TODO: type mismatch resolving `::Item == std::result::Result>::Error>` + // assert_future::, _>(SendAll::new(self, stream)) + SendAll::new(self, stream) + } + + /// Wrap this sink in an `Either` sink, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_sink` method to write `if` + /// statements that evaluate to different streams in different branches. + fn left_sink(self) -> Either + where + Si2: Sink, + Self: Sized, + { + assert_sink::(Either::Left(self)) + } + + /// Wrap this stream in an `Either` stream, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_sink` method to write `if` + /// statements that evaluate to different streams in different branches. + fn right_sink(self) -> Either + where + Si1: Sink, + Self: Sized, + { + assert_sink::(Either::Right(self)) + } + + /// Wraps a [`Sink`] into a sink compatible with libraries using + /// futures 0.1 `Sink`. Requires the `compat` feature to be enabled. + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> CompatSink + where + Self: Sized + Unpin, + { + CompatSink::new(self) + } + + /// A convenience method for calling [`Sink::poll_ready`] on [`Unpin`] + /// sink types. + fn poll_ready_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).poll_ready(cx) + } + + /// A convenience method for calling [`Sink::start_send`] on [`Unpin`] + /// sink types. + fn start_send_unpin(&mut self, item: Item) -> Result<(), Self::Error> + where + Self: Unpin, + { + Pin::new(self).start_send(item) + } + + /// A convenience method for calling [`Sink::poll_flush`] on [`Unpin`] + /// sink types. + fn poll_flush_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).poll_flush(cx) + } + + /// A convenience method for calling [`Sink::poll_close`] on [`Unpin`] + /// sink types. + fn poll_close_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).poll_close(cx) + } +} + +// Just a helper function to ensure the sinks we're returning all have the +// right implementations. +pub(crate) fn assert_sink(sink: S) -> S +where + S: Sink, +{ + sink +} diff --git a/anneal/v2/vendor/futures-util/src/sink/send.rs b/anneal/v2/vendor/futures-util/src/sink/send.rs new file mode 100644 index 0000000000..6d21f33fe4 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/send.rs @@ -0,0 +1,41 @@ +use super::Feed; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Future for the [`send`](super::SinkExt::send) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Send<'a, Si: ?Sized, Item> { + feed: Feed<'a, Si, Item>, +} + +// Pinning is never projected to children +impl Unpin for Send<'_, Si, Item> {} + +impl<'a, Si: Sink + Unpin + ?Sized, Item> Send<'a, Si, Item> { + pub(super) fn new(sink: &'a mut Si, item: Item) -> Self { + Self { feed: Feed::new(sink, item) } + } +} + +impl + Unpin + ?Sized, Item> Future for Send<'_, Si, Item> { + type Output = Result<(), Si::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + + if this.feed.is_item_pending() { + ready!(Pin::new(&mut this.feed).poll(cx))?; + debug_assert!(!this.feed.is_item_pending()); + } + + // we're done sending the item, but want to block on flushing the + // sink + ready!(this.feed.sink_pin_mut().poll_flush(cx))?; + + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/send_all.rs b/anneal/v2/vendor/futures-util/src/sink/send_all.rs new file mode 100644 index 0000000000..1302dd2148 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/send_all.rs @@ -0,0 +1,100 @@ +use crate::stream::{Fuse, StreamExt, TryStreamExt}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{Stream, TryStream}; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +/// Future for the [`send_all`](super::SinkExt::send_all) method. +#[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SendAll<'a, Si, St> +where + Si: ?Sized, + St: ?Sized + TryStream, +{ + sink: &'a mut Si, + stream: Fuse<&'a mut St>, + buffered: Option, +} + +impl fmt::Debug for SendAll<'_, Si, St> +where + Si: fmt::Debug + ?Sized, + St: fmt::Debug + ?Sized + TryStream, + St::Ok: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SendAll") + .field("sink", &self.sink) + .field("stream", &self.stream) + .field("buffered", &self.buffered) + .finish() + } +} + +// Pinning is never projected to any fields +impl Unpin for SendAll<'_, Si, St> +where + Si: Unpin + ?Sized, + St: TryStream + Unpin + ?Sized, +{ +} + +impl<'a, Si, St, Ok, Error> SendAll<'a, Si, St> +where + Si: Sink + Unpin + ?Sized, + St: TryStream + Stream + Unpin + ?Sized, +{ + pub(super) fn new(sink: &'a mut Si, stream: &'a mut St) -> Self { + Self { sink, stream: stream.fuse(), buffered: None } + } + + fn try_start_send( + &mut self, + cx: &mut Context<'_>, + item: St::Ok, + ) -> Poll> { + debug_assert!(self.buffered.is_none()); + match Pin::new(&mut self.sink).poll_ready(cx)? { + Poll::Ready(()) => Poll::Ready(Pin::new(&mut self.sink).start_send(item)), + Poll::Pending => { + self.buffered = Some(item); + Poll::Pending + } + } + } +} + +impl Future for SendAll<'_, Si, St> +where + Si: Sink + Unpin + ?Sized, + St: Stream> + Unpin + ?Sized, +{ + type Output = Result<(), Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + // If we've got an item buffered already, we need to write it to the + // sink before we can do anything else + if let Some(item) = this.buffered.take() { + ready!(this.try_start_send(cx, item))? + } + + loop { + match this.stream.try_poll_next_unpin(cx)? { + Poll::Ready(Some(item)) => ready!(this.try_start_send(cx, item))?, + Poll::Ready(None) => { + ready!(Pin::new(&mut this.sink).poll_flush(cx))?; + return Poll::Ready(Ok(())); + } + Poll::Pending => { + ready!(Pin::new(&mut this.sink).poll_flush(cx))?; + return Poll::Pending; + } + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/unfold.rs b/anneal/v2/vendor/futures-util/src/sink/unfold.rs new file mode 100644 index 0000000000..008962ebab --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/unfold.rs @@ -0,0 +1,92 @@ +use super::assert_sink; +use crate::unfold_state::UnfoldState; +use core::{future::Future, pin::Pin}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`unfold`] function. + #[derive(Debug)] + #[must_use = "sinks do nothing unless polled"] + pub struct Unfold { + function: F, + #[pin] + state: UnfoldState, + } +} + +/// Create a sink from a function which processes one item at a time. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use core::pin::pin; +/// +/// use futures::sink; +/// use futures::sink::SinkExt; +/// +/// let unfold = sink::unfold(0, |mut sum, i: i32| { +/// async move { +/// sum += i; +/// eprintln!("{}", i); +/// Ok::<_, futures::never::Never>(sum) +/// } +/// }); +/// let mut unfold = pin!(unfold); +/// unfold.send(5).await?; +/// # Ok::<(), futures::never::Never>(()) }).unwrap(); +/// ``` +pub fn unfold(init: T, function: F) -> Unfold +where + F: FnMut(T, Item) -> R, + R: Future>, +{ + assert_sink::(Unfold { function, state: UnfoldState::Value { value: init } }) +} + +impl Sink for Unfold +where + F: FnMut(T, Item) -> R, + R: Future>, +{ + type Error = E; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_flush(cx) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + let mut this = self.project(); + let future = match this.state.as_mut().take_value() { + Some(value) => (this.function)(value, item), + None => panic!("start_send called without poll_ready being called first"), + }; + this.state.set(UnfoldState::Future { future }); + Ok(()) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + Poll::Ready(if let Some(future) = this.state.as_mut().project_future() { + match ready!(future.poll(cx)) { + Ok(state) => { + this.state.set(UnfoldState::Value { value: state }); + Ok(()) + } + Err(err) => { + this.state.set(UnfoldState::Empty); + Err(err) + } + } + } else { + Ok(()) + }) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.poll_flush(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/with.rs b/anneal/v2/vendor/futures-util/src/sink/with.rs new file mode 100644 index 0000000000..5a2c8a089f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/with.rs @@ -0,0 +1,145 @@ +use core::fmt; +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`with`](super::SinkExt::with) method. + #[must_use = "sinks do nothing unless polled"] + pub struct With { + #[pin] + sink: Si, + f: F, + #[pin] + state: Option, + _phantom: PhantomData Item>, + } +} + +impl fmt::Debug for With +where + Si: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("With").field("sink", &self.sink).field("state", &self.state).finish() + } +} + +impl With +where + Si: Sink, + F: FnMut(U) -> Fut, + Fut: Future, +{ + pub(super) fn new(sink: Si, f: F) -> Self + where + Fut: Future>, + E: From, + { + Self { state: None, sink, f, _phantom: PhantomData } + } +} + +impl Clone for With +where + Si: Clone, + F: Clone, + Fut: Clone, +{ + fn clone(&self) -> Self { + Self { + state: self.state.clone(), + sink: self.sink.clone(), + f: self.f.clone(), + _phantom: PhantomData, + } + } +} + +// Forwarding impl of Stream from the underlying sink +impl Stream for With +where + S: Stream + Sink, + F: FnMut(U) -> Fut, + Fut: Future, +{ + type Item = S::Item; + + delegate_stream!(sink); +} + +impl FusedStream for With +where + S: FusedStream + Sink, + F: FnMut(U) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.sink.is_terminated() + } +} + +impl With +where + Si: Sink, + F: FnMut(U) -> Fut, + Fut: Future>, + E: From, +{ + delegate_access_inner!(sink, Si, ()); + + /// Completes the processing of previous item if any. + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + let item = match this.state.as_mut().as_pin_mut() { + None => return Poll::Ready(Ok(())), + Some(fut) => ready!(fut.poll(cx))?, + }; + this.state.set(None); + this.sink.start_send(item)?; + Poll::Ready(Ok(())) + } +} + +impl Sink for With +where + Si: Sink, + F: FnMut(U) -> Fut, + Fut: Future>, + E: From, +{ + type Error = E; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().poll(cx))?; + ready!(self.project().sink.poll_ready(cx)?); + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, item: U) -> Result<(), Self::Error> { + let mut this = self.project(); + + assert!(this.state.is_none()); + this.state.set(Some((this.f)(item))); + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().poll(cx))?; + ready!(self.project().sink.poll_flush(cx)?); + Poll::Ready(Ok(())) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().poll(cx))?; + ready!(self.project().sink.poll_close(cx)?); + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/sink/with_flat_map.rs b/anneal/v2/vendor/futures-util/src/sink/with_flat_map.rs new file mode 100644 index 0000000000..2ae877a24b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/sink/with_flat_map.rs @@ -0,0 +1,127 @@ +use core::fmt; +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Sink for the [`with_flat_map`](super::SinkExt::with_flat_map) method. + #[must_use = "sinks do nothing unless polled"] + pub struct WithFlatMap { + #[pin] + sink: Si, + f: F, + #[pin] + stream: Option, + buffer: Option, + _marker: PhantomData, + } +} + +impl fmt::Debug for WithFlatMap +where + Si: fmt::Debug, + St: fmt::Debug, + Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WithFlatMap") + .field("sink", &self.sink) + .field("stream", &self.stream) + .field("buffer", &self.buffer) + .finish() + } +} + +impl WithFlatMap +where + Si: Sink, + F: FnMut(U) -> St, + St: Stream>, +{ + pub(super) fn new(sink: Si, f: F) -> Self { + Self { sink, f, stream: None, buffer: None, _marker: PhantomData } + } + + delegate_access_inner!(sink, Si, ()); + + fn try_empty_stream(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if this.buffer.is_some() { + ready!(this.sink.as_mut().poll_ready(cx))?; + let item = this.buffer.take().unwrap(); + this.sink.as_mut().start_send(item)?; + } + if let Some(mut some_stream) = this.stream.as_mut().as_pin_mut() { + while let Some(item) = ready!(some_stream.as_mut().poll_next(cx)?) { + match this.sink.as_mut().poll_ready(cx)? { + Poll::Ready(()) => this.sink.as_mut().start_send(item)?, + Poll::Pending => { + *this.buffer = Some(item); + return Poll::Pending; + } + }; + } + } + this.stream.set(None); + Poll::Ready(Ok(())) + } +} + +// Forwarding impl of Stream from the underlying sink +impl Stream for WithFlatMap +where + S: Stream + Sink, + F: FnMut(U) -> St, + St: Stream>, +{ + type Item = S::Item; + + delegate_stream!(sink); +} + +impl FusedStream for WithFlatMap +where + S: FusedStream + Sink, + F: FnMut(U) -> St, + St: Stream>, +{ + fn is_terminated(&self) -> bool { + self.sink.is_terminated() + } +} + +impl Sink for WithFlatMap +where + Si: Sink, + F: FnMut(U) -> St, + St: Stream>, +{ + type Error = Si::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.try_empty_stream(cx) + } + + fn start_send(self: Pin<&mut Self>, item: U) -> Result<(), Self::Error> { + let mut this = self.project(); + + assert!(this.stream.is_none()); + this.stream.set(Some((this.f)(item))); + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().try_empty_stream(cx)?); + self.project().sink.poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.as_mut().try_empty_stream(cx)?); + self.project().sink.poll_close(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/abortable.rs b/anneal/v2/vendor/futures-util/src/stream/abortable.rs new file mode 100644 index 0000000000..1fea895822 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/abortable.rs @@ -0,0 +1,19 @@ +use super::assert_stream; +use crate::stream::{AbortHandle, Abortable}; +use crate::Stream; + +/// Creates a new `Abortable` stream and an `AbortHandle` which can be used to stop it. +/// +/// This function is a convenient (but less flexible) alternative to calling +/// `AbortHandle::new` and `Abortable::new` manually. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +pub fn abortable(stream: St) -> (Abortable, AbortHandle) +where + St: Stream, +{ + let (handle, reg) = AbortHandle::new_pair(); + let abortable = assert_stream::(Abortable::new(stream, reg)); + (abortable, handle) +} diff --git a/anneal/v2/vendor/futures-util/src/stream/empty.rs b/anneal/v2/vendor/futures-util/src/stream/empty.rs new file mode 100644 index 0000000000..e4fd87326b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/empty.rs @@ -0,0 +1,45 @@ +use super::assert_stream; +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +/// Stream for the [`empty`] function. +#[derive(Debug)] +#[must_use = "streams do nothing unless polled"] +pub struct Empty { + _phantom: PhantomData, +} + +/// Creates a stream which contains no elements. +/// +/// The returned stream will always return `Ready(None)` when polled. +pub fn empty() -> Empty { + assert_stream::(Empty { _phantom: PhantomData }) +} + +impl Unpin for Empty {} + +impl FusedStream for Empty { + fn is_terminated(&self) -> bool { + true + } +} + +impl Stream for Empty { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(None) + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +impl Clone for Empty { + fn clone(&self) -> Self { + empty() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_ordered.rs b/anneal/v2/vendor/futures-util/src/stream/futures_ordered.rs new file mode 100644 index 0000000000..460b352676 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_ordered.rs @@ -0,0 +1,260 @@ +use crate::stream::{FuturesUnordered, StreamExt}; +use alloc::collections::binary_heap::{BinaryHeap, PeekMut}; +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::{ + task::{Context, Poll}, + FusedStream, +}; +use pin_project_lite::pin_project; + +pin_project! { + #[must_use = "futures do nothing unless you `.await` or poll them"] + #[derive(Debug)] + struct OrderWrapper { + #[pin] + data: T, // A future or a future's output + // Use i64 for index since isize may overflow in 32-bit targets. + index: i64, + } +} + +impl PartialEq for OrderWrapper { + fn eq(&self, other: &Self) -> bool { + self.index == other.index + } +} + +impl Eq for OrderWrapper {} + +impl PartialOrd for OrderWrapper { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for OrderWrapper { + fn cmp(&self, other: &Self) -> Ordering { + // BinaryHeap is a max heap, so compare backwards here. + other.index.cmp(&self.index) + } +} + +impl Future for OrderWrapper +where + T: Future, +{ + type Output = OrderWrapper; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let index = self.index; + self.project().data.poll(cx).map(|output| OrderWrapper { data: output, index }) + } +} + +/// An unbounded queue of futures. +/// +/// This "combinator" is similar to [`FuturesUnordered`], but it imposes a FIFO +/// order on top of the set of futures. While futures in the set will race to +/// completion in parallel, results will only be returned in the order their +/// originating futures were added to the queue. +/// +/// Futures are pushed into this queue and their realized values are yielded in +/// order. This structure is optimized to manage a large number of futures. +/// Futures managed by [`FuturesOrdered`] will only be polled when they generate +/// notifications. This reduces the required amount of work needed to coordinate +/// large numbers of futures. +/// +/// When a [`FuturesOrdered`] is first created, it does not contain any futures. +/// Calling [`poll_next`](FuturesOrdered::poll_next) in this state will result +/// in [`Poll::Ready(None)`](Poll::Ready) to be returned. Futures are submitted +/// to the queue using [`push_back`](FuturesOrdered::push_back) (or +/// [`push_front`](FuturesOrdered::push_front)); however, the future will +/// **not** be polled at this point. [`FuturesOrdered`] will only poll managed +/// futures when [`FuturesOrdered::poll_next`] is called. As such, it +/// is important to call [`poll_next`](FuturesOrdered::poll_next) after pushing +/// new futures. +/// +/// If [`FuturesOrdered::poll_next`] returns [`Poll::Ready(None)`](Poll::Ready) +/// this means that the queue is currently not managing any futures. A future +/// may be submitted to the queue at a later time. At that point, a call to +/// [`FuturesOrdered::poll_next`] will either return the future's resolved value +/// **or** [`Poll::Pending`] if the future has not yet completed. When +/// multiple futures are submitted to the queue, [`FuturesOrdered::poll_next`] +/// will return [`Poll::Pending`] until the first future completes, even if +/// some of the later futures have already completed. +/// +/// Note that you can create a ready-made [`FuturesOrdered`] via the +/// [`collect`](Iterator::collect) method, or you can start with an empty queue +/// with the [`FuturesOrdered::new`] constructor. +/// +/// This type is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +#[must_use = "streams do nothing unless polled"] +pub struct FuturesOrdered { + in_progress_queue: FuturesUnordered>, + queued_outputs: BinaryHeap>, + next_incoming_index: i64, + next_outgoing_index: i64, +} + +impl Unpin for FuturesOrdered {} + +impl FuturesOrdered { + /// Constructs a new, empty `FuturesOrdered` + /// + /// The returned [`FuturesOrdered`] does not contain any futures and, in + /// this state, [`FuturesOrdered::poll_next`] will return + /// [`Poll::Ready(None)`](Poll::Ready). + pub fn new() -> Self { + Self { + in_progress_queue: FuturesUnordered::new(), + queued_outputs: BinaryHeap::new(), + next_incoming_index: 0, + next_outgoing_index: 0, + } + } + + /// Returns the number of futures contained in the queue. + /// + /// This represents the total number of in-flight futures, both + /// those currently processing and those that have completed but + /// which are waiting for earlier futures to complete. + pub fn len(&self) -> usize { + self.in_progress_queue.len() + self.queued_outputs.len() + } + + /// Returns `true` if the queue contains no futures + pub fn is_empty(&self) -> bool { + self.in_progress_queue.is_empty() && self.queued_outputs.is_empty() + } + + /// Push a future into the queue. + /// + /// This function submits the given future to the internal set for managing. + /// This function will not call [`poll`](Future::poll) on the submitted + /// future. The caller must ensure that [`FuturesOrdered::poll_next`] is + /// called in order to receive task notifications. + #[deprecated(note = "use `push_back` instead")] + pub fn push(&mut self, future: Fut) { + self.push_back(future); + } + + /// Pushes a future to the back of the queue. + /// + /// This function submits the given future to the internal set for managing. + /// This function will not call [`poll`](Future::poll) on the submitted + /// future. The caller must ensure that [`FuturesOrdered::poll_next`] is + /// called in order to receive task notifications. + pub fn push_back(&mut self, future: Fut) { + let wrapped = OrderWrapper { data: future, index: self.next_incoming_index }; + self.next_incoming_index += 1; + self.in_progress_queue.push(wrapped); + } + + /// Pushes a future to the front of the queue. + /// + /// This function submits the given future to the internal set for managing. + /// This function will not call [`poll`](Future::poll) on the submitted + /// future. The caller must ensure that [`FuturesOrdered::poll_next`] is + /// called in order to receive task notifications. This future will be + /// the next future to be returned complete. + pub fn push_front(&mut self, future: Fut) { + let wrapped = OrderWrapper { data: future, index: self.next_outgoing_index - 1 }; + self.next_outgoing_index -= 1; + self.in_progress_queue.push(wrapped); + } + + /// Clear the whole `FuturesOrdered` queue. + /// + /// This function clears the pending futures and the queued outputs + /// to make it fully empty. + pub fn clear(&mut self) { + self.in_progress_queue.clear(); + self.queued_outputs.clear(); + self.next_incoming_index = 0; + self.next_outgoing_index = 0; + } +} + +impl Default for FuturesOrdered { + fn default() -> Self { + Self::new() + } +} + +impl Stream for FuturesOrdered { + type Item = Fut::Output; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = &mut *self; + + // Check to see if we've already received the next value + if let Some(next_output) = this.queued_outputs.peek_mut() { + if next_output.index == this.next_outgoing_index { + this.next_outgoing_index += 1; + return Poll::Ready(Some(PeekMut::pop(next_output).data)); + } + } + + loop { + match ready!(this.in_progress_queue.poll_next_unpin(cx)) { + Some(output) => { + if output.index == this.next_outgoing_index { + this.next_outgoing_index += 1; + return Poll::Ready(Some(output.data)); + } else { + this.queued_outputs.push(output) + } + } + None => return Poll::Ready(None), + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl Debug for FuturesOrdered { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "FuturesOrdered {{ ... }}") + } +} + +impl FromIterator for FuturesOrdered { + fn from_iter(iter: T) -> Self + where + T: IntoIterator, + { + let acc = Self::new(); + iter.into_iter().fold(acc, |mut acc, item| { + acc.push_back(item); + acc + }) + } +} + +impl FusedStream for FuturesOrdered { + fn is_terminated(&self) -> bool { + self.in_progress_queue.is_terminated() && self.queued_outputs.is_empty() + } +} + +impl Extend for FuturesOrdered { + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + for item in iter { + self.push_back(item); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_unordered/abort.rs b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/abort.rs new file mode 100644 index 0000000000..1a42d24369 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/abort.rs @@ -0,0 +1,12 @@ +pub(super) fn abort(s: &str) -> ! { + struct DoublePanic; + + impl Drop for DoublePanic { + fn drop(&mut self) { + panic!("panicking twice to abort the program"); + } + } + + let _bomb = DoublePanic; + panic!("{}", s); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_unordered/iter.rs b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/iter.rs new file mode 100644 index 0000000000..20248c70fe --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/iter.rs @@ -0,0 +1,172 @@ +use super::task::Task; +use super::FuturesUnordered; +use core::marker::PhantomData; +use core::pin::Pin; +use core::ptr; +use core::sync::atomic::Ordering::Relaxed; + +/// Mutable iterator over all futures in the unordered set. +#[derive(Debug)] +pub struct IterPinMut<'a, Fut> { + pub(super) task: *const Task, + pub(super) len: usize, + pub(super) _marker: PhantomData<&'a mut FuturesUnordered>, +} + +/// Mutable iterator over all futures in the unordered set. +#[derive(Debug)] +pub struct IterMut<'a, Fut: Unpin>(pub(super) IterPinMut<'a, Fut>); + +/// Immutable iterator over all futures in the unordered set. +#[derive(Debug)] +pub struct IterPinRef<'a, Fut> { + pub(super) task: *const Task, + pub(super) len: usize, + pub(super) pending_next_all: *mut Task, + pub(super) _marker: PhantomData<&'a FuturesUnordered>, +} + +/// Immutable iterator over all the futures in the unordered set. +#[derive(Debug)] +pub struct Iter<'a, Fut: Unpin>(pub(super) IterPinRef<'a, Fut>); + +/// Owned iterator over all futures in the unordered set. +#[derive(Debug)] +pub struct IntoIter { + pub(super) len: usize, + pub(super) inner: FuturesUnordered, +} + +impl Iterator for IntoIter { + type Item = Fut; + + fn next(&mut self) -> Option { + // `head_all` can be accessed directly and we don't need to spin on + // `Task::next_all` since we have exclusive access to the set. + let task = self.inner.head_all.get_mut(); + + if (*task).is_null() { + return None; + } + + unsafe { + // Moving out of the future is safe because it is `Unpin` + let future = (*(**task).future.get()).take().unwrap(); + + // Mutable access to a previously shared `FuturesUnordered` implies + // that the other threads already released the object before the + // current thread acquired it, so relaxed ordering can be used and + // valid `next_all` checks can be skipped. + let next = (**task).next_all.load(Relaxed); + *task = next; + if !task.is_null() { + *(**task).prev_all.get() = ptr::null_mut(); + } + self.len -= 1; + Some(future) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +impl ExactSizeIterator for IntoIter {} + +impl<'a, Fut> Iterator for IterPinMut<'a, Fut> { + type Item = Pin<&'a mut Fut>; + + fn next(&mut self) -> Option { + if self.task.is_null() { + return None; + } + + unsafe { + let future = (*(*self.task).future.get()).as_mut().unwrap(); + + // Mutable access to a previously shared `FuturesUnordered` implies + // that the other threads already released the object before the + // current thread acquired it, so relaxed ordering can be used and + // valid `next_all` checks can be skipped. + let next = (*self.task).next_all.load(Relaxed); + self.task = next; + self.len -= 1; + Some(Pin::new_unchecked(future)) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +impl ExactSizeIterator for IterPinMut<'_, Fut> {} + +impl<'a, Fut: Unpin> Iterator for IterMut<'a, Fut> { + type Item = &'a mut Fut; + + fn next(&mut self) -> Option { + self.0.next().map(Pin::get_mut) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for IterMut<'_, Fut> {} + +impl<'a, Fut> Iterator for IterPinRef<'a, Fut> { + type Item = Pin<&'a Fut>; + + fn next(&mut self) -> Option { + if self.task.is_null() { + return None; + } + + unsafe { + let future = (*(*self.task).future.get()).as_ref().unwrap(); + + // Relaxed ordering can be used since acquire ordering when + // `head_all` was initially read for this iterator implies acquire + // ordering for all previously inserted nodes (and we don't need to + // read `len_all` again for any other nodes). + let next = (*self.task).spin_next_all(self.pending_next_all, Relaxed); + self.task = next; + self.len -= 1; + Some(Pin::new_unchecked(future)) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +impl ExactSizeIterator for IterPinRef<'_, Fut> {} + +impl<'a, Fut: Unpin> Iterator for Iter<'a, Fut> { + type Item = &'a Fut; + + fn next(&mut self) -> Option { + self.0.next().map(Pin::get_ref) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for Iter<'_, Fut> {} + +// SAFETY: we do nothing thread-local and there is no interior mutability, +// so the usual structural `Send`/`Sync` apply. +unsafe impl Send for IterPinRef<'_, Fut> {} +unsafe impl Sync for IterPinRef<'_, Fut> {} + +unsafe impl Send for IterPinMut<'_, Fut> {} +unsafe impl Sync for IterPinMut<'_, Fut> {} + +unsafe impl Send for IntoIter {} +unsafe impl Sync for IntoIter {} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_unordered/mod.rs b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/mod.rs new file mode 100644 index 0000000000..ca62b10b91 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/mod.rs @@ -0,0 +1,674 @@ +//! An unbounded set of futures. +//! +//! This module is only available when the `std` or `alloc` feature of this +//! library is activated, and it is activated by default. + +use crate::task::AtomicWaker; +use alloc::sync::{Arc, Weak}; +use core::cell::UnsafeCell; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::marker::PhantomData; +use core::mem; +use core::pin::Pin; +use core::ptr; +use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst}; +use core::sync::atomic::{AtomicBool, AtomicPtr}; +use futures_core::future::Future; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError}; + +mod abort; + +mod iter; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/102352 +pub use self::iter::{IntoIter, Iter, IterMut, IterPinMut, IterPinRef}; + +mod task; +use self::task::Task; + +mod ready_to_run_queue; +use self::ready_to_run_queue::{Dequeue, ReadyToRunQueue}; + +/// A set of futures which may complete in any order. +/// +/// See [`FuturesOrdered`](crate::stream::FuturesOrdered) for a version of this +/// type that preserves a FIFO order. +/// +/// This structure is optimized to manage a large number of futures. +/// Futures managed by [`FuturesUnordered`] will only be polled when they +/// generate wake-up notifications. This reduces the required amount of work +/// needed to poll large numbers of futures. +/// +/// [`FuturesUnordered`] can be filled by [`collect`](Iterator::collect)ing an +/// iterator of futures into a [`FuturesUnordered`], or by +/// [`push`](FuturesUnordered::push)ing futures onto an existing +/// [`FuturesUnordered`]. When new futures are added, +/// [`poll_next`](Stream::poll_next) must be called in order to begin receiving +/// wake-ups for new futures. +/// +/// Note that you can create a ready-made [`FuturesUnordered`] via the +/// [`collect`](Iterator::collect) method, or you can start with an empty set +/// with the [`FuturesUnordered::new`] constructor. +/// +/// This type is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +#[must_use = "streams do nothing unless polled"] +pub struct FuturesUnordered { + ready_to_run_queue: Arc>, + head_all: AtomicPtr>, + is_terminated: AtomicBool, +} + +unsafe impl Send for FuturesUnordered {} +unsafe impl Sync for FuturesUnordered {} +impl Unpin for FuturesUnordered {} + +impl Spawn for FuturesUnordered> { + fn spawn_obj(&self, future_obj: FutureObj<'static, ()>) -> Result<(), SpawnError> { + self.push(future_obj); + Ok(()) + } +} + +impl LocalSpawn for FuturesUnordered> { + fn spawn_local_obj(&self, future_obj: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { + self.push(future_obj); + Ok(()) + } +} + +// FuturesUnordered is implemented using two linked lists. One which links all +// futures managed by a `FuturesUnordered` and one that tracks futures that have +// been scheduled for polling. The first linked list allows for thread safe +// insertion of nodes at the head as well as forward iteration, but is otherwise +// not thread safe and is only accessed by the thread that owns the +// `FuturesUnordered` value for any other operations. The second linked list is +// an implementation of the intrusive MPSC queue algorithm described by +// 1024cores.net. +// +// When a future is submitted to the set, a task is allocated and inserted in +// both linked lists. The next call to `poll_next` will (eventually) see this +// task and call `poll` on the future. +// +// Before a managed future is polled, the current context's waker is replaced +// with one that is aware of the specific future being run. This ensures that +// wake-up notifications generated by that specific future are visible to +// `FuturesUnordered`. When a wake-up notification is received, the task is +// inserted into the ready to run queue, so that its future can be polled later. +// +// Each task is wrapped in an `Arc` and thereby atomically reference counted. +// Also, each task contains an `AtomicBool` which acts as a flag that indicates +// whether the task is currently inserted in the atomic queue. When a wake-up +// notification is received, the task will only be inserted into the ready to +// run queue if it isn't inserted already. + +impl Default for FuturesUnordered { + fn default() -> Self { + Self::new() + } +} + +impl FuturesUnordered { + /// Constructs a new, empty [`FuturesUnordered`]. + /// + /// The returned [`FuturesUnordered`] does not contain any futures. + /// In this state, [`FuturesUnordered::poll_next`](Stream::poll_next) will + /// return [`Poll::Ready(None)`](Poll::Ready). + pub fn new() -> Self { + let stub = Arc::new(Task { + future: UnsafeCell::new(None), + next_all: AtomicPtr::new(ptr::null_mut()), + prev_all: UnsafeCell::new(ptr::null()), + len_all: UnsafeCell::new(0), + next_ready_to_run: AtomicPtr::new(ptr::null_mut()), + queued: AtomicBool::new(true), + ready_to_run_queue: Weak::new(), + woken: AtomicBool::new(false), + }); + let stub_ptr = Arc::as_ptr(&stub); + let ready_to_run_queue = Arc::new(ReadyToRunQueue { + waker: AtomicWaker::new(), + head: AtomicPtr::new(stub_ptr as *mut _), + tail: UnsafeCell::new(stub_ptr), + stub, + }); + + Self { + head_all: AtomicPtr::new(ptr::null_mut()), + ready_to_run_queue, + is_terminated: AtomicBool::new(false), + } + } + + /// Returns the number of futures contained in the set. + /// + /// This represents the total number of in-flight futures. + pub fn len(&self) -> usize { + let (_, len) = self.atomic_load_head_and_len_all(); + len + } + + /// Returns `true` if the set contains no futures. + pub fn is_empty(&self) -> bool { + // Relaxed ordering can be used here since we don't need to read from + // the head pointer, only check whether it is null. + self.head_all.load(Relaxed).is_null() + } + + /// Push a future into the set. + /// + /// This method adds the given future to the set. This method will not + /// call [`poll`](core::future::Future::poll) on the submitted future. The caller must + /// ensure that [`FuturesUnordered::poll_next`](Stream::poll_next) is called + /// in order to receive wake-up notifications for the given future. + pub fn push(&self, future: Fut) { + let task = Arc::new(Task { + future: UnsafeCell::new(Some(future)), + next_all: AtomicPtr::new(self.pending_next_all()), + prev_all: UnsafeCell::new(ptr::null_mut()), + len_all: UnsafeCell::new(0), + next_ready_to_run: AtomicPtr::new(ptr::null_mut()), + queued: AtomicBool::new(true), + ready_to_run_queue: Arc::downgrade(&self.ready_to_run_queue), + woken: AtomicBool::new(false), + }); + + // Reset the `is_terminated` flag if we've previously marked ourselves + // as terminated. + self.is_terminated.store(false, Relaxed); + + // Right now our task has a strong reference count of 1. We transfer + // ownership of this reference count to our internal linked list + // and we'll reclaim ownership through the `unlink` method below. + let ptr = self.link(task); + + // We'll need to get the future "into the system" to start tracking it, + // e.g. getting its wake-up notifications going to us tracking which + // futures are ready. To do that we unconditionally enqueue it for + // polling here. + self.ready_to_run_queue.enqueue(ptr); + } + + /// Returns an iterator that allows inspecting each future in the set. + pub fn iter(&self) -> Iter<'_, Fut> + where + Fut: Unpin, + { + Iter(Pin::new(self).iter_pin_ref()) + } + + /// Returns an iterator that allows inspecting each future in the set. + pub fn iter_pin_ref(self: Pin<&Self>) -> IterPinRef<'_, Fut> { + let (task, len) = self.atomic_load_head_and_len_all(); + let pending_next_all = self.pending_next_all(); + + IterPinRef { task, len, pending_next_all, _marker: PhantomData } + } + + /// Returns an iterator that allows modifying each future in the set. + pub fn iter_mut(&mut self) -> IterMut<'_, Fut> + where + Fut: Unpin, + { + IterMut(Pin::new(self).iter_pin_mut()) + } + + /// Returns an iterator that allows modifying each future in the set. + pub fn iter_pin_mut(mut self: Pin<&mut Self>) -> IterPinMut<'_, Fut> { + // `head_all` can be accessed directly and we don't need to spin on + // `Task::next_all` since we have exclusive access to the set. + let task = *self.head_all.get_mut(); + let len = if task.is_null() { 0 } else { unsafe { *(*task).len_all.get() } }; + + IterPinMut { task, len, _marker: PhantomData } + } + + /// Returns the current head node and number of futures in the list of all + /// futures within a context where access is shared with other threads + /// (mostly for use with the `len` and `iter_pin_ref` methods). + fn atomic_load_head_and_len_all(&self) -> (*const Task, usize) { + let task = self.head_all.load(Acquire); + let len = if task.is_null() { + 0 + } else { + unsafe { + (*task).spin_next_all(self.pending_next_all(), Acquire); + *(*task).len_all.get() + } + }; + + (task, len) + } + + /// Releases the task. It destroys the future inside and either drops + /// the `Arc` or transfers ownership to the ready to run queue. + /// The task this method is called on must have been unlinked before. + fn release_task(&mut self, task: Arc>) { + // `release_task` must only be called on unlinked tasks + debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all()); + unsafe { + debug_assert!((*task.prev_all.get()).is_null()); + } + + // The future is done, try to reset the queued flag. This will prevent + // `wake` from doing any work in the future + let prev = task.queued.swap(true, SeqCst); + + // If the queued flag was previously set, then it means that this task + // is still in our internal ready to run queue. We then transfer + // ownership of our reference count to the ready to run queue, and it'll + // come along and free it later, noticing that the future is `None`. + // + // If, however, the queued flag was *not* set then we're safe to + // release our reference count on the task. The queued flag was set + // above so all future `enqueue` operations will not actually + // enqueue the task, so our task will never see the ready to run queue + // again. The task itself will be deallocated once all reference counts + // have been dropped elsewhere by the various wakers that contain it. + // + // Use ManuallyDrop to transfer the reference count ownership before + // dropping the future so unwinding won't release the reference count. + let md_slot; + let task = if prev { + md_slot = mem::ManuallyDrop::new(task); + &*md_slot + } else { + &task + }; + + // Drop the future, even if it hasn't finished yet. This is safe + // because we're dropping the future on the thread that owns + // `FuturesUnordered`, which correctly tracks `Fut`'s lifetimes and + // such. + unsafe { + // Set to `None` rather than `take()`ing to prevent moving the + // future. + *task.future.get() = None; + } + } + + /// Insert a new task into the internal linked list. + fn link(&self, task: Arc>) -> *const Task { + // `next_all` should already be reset to the pending state before this + // function is called. + debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all()); + let ptr = Arc::into_raw(task); + + // Atomically swap out the old head node to get the node that should be + // assigned to `next_all`. + let next = self.head_all.swap(ptr as *mut _, AcqRel); + + unsafe { + // Store the new list length in the new node. + let new_len = if next.is_null() { + 1 + } else { + // Make sure `next_all` has been written to signal that it is + // safe to read `len_all`. + (*next).spin_next_all(self.pending_next_all(), Acquire); + *(*next).len_all.get() + 1 + }; + *(*ptr).len_all.get() = new_len; + + // Write the old head as the next node pointer, signaling to other + // threads that `len_all` and `next_all` are ready to read. + (*ptr).next_all.store(next, Release); + + // `prev_all` updates don't need to be synchronized, as the field is + // only ever used after exclusive access has been acquired. + if !next.is_null() { + *(*next).prev_all.get() = ptr; + } + } + + ptr + } + + /// Remove the task from the linked list tracking all tasks currently + /// managed by `FuturesUnordered`. + /// This method is unsafe because it has be guaranteed that `task` is a + /// valid pointer. + unsafe fn unlink(&mut self, task: *const Task) -> Arc> { + unsafe { + // Compute the new list length now in case we're removing the head node + // and won't be able to retrieve the correct length later. + let head = *self.head_all.get_mut(); + debug_assert!(!head.is_null()); + let new_len = *(*head).len_all.get() - 1; + + let task = Arc::from_raw(task); + let next = task.next_all.load(Relaxed); + let prev = *task.prev_all.get(); + task.next_all.store(self.pending_next_all(), Relaxed); + *task.prev_all.get() = ptr::null_mut(); + + if !next.is_null() { + *(*next).prev_all.get() = prev; + } + + if !prev.is_null() { + (*prev).next_all.store(next, Relaxed); + } else { + *self.head_all.get_mut() = next; + } + + // Store the new list length in the head node. + let head = *self.head_all.get_mut(); + if !head.is_null() { + *(*head).len_all.get() = new_len; + } + + task + } + } + + /// Returns the reserved value for `Task::next_all` to indicate a pending + /// assignment from the thread that inserted the task. + /// + /// `FuturesUnordered::link` needs to update `Task` pointers in an order + /// that ensures any iterators created on other threads can correctly + /// traverse the entire `Task` list using the chain of `next_all` pointers. + /// This could be solved with a compare-exchange loop that stores the + /// current `head_all` in `next_all` and swaps out `head_all` with the new + /// `Task` pointer if the head hasn't already changed. Under heavy thread + /// contention, this compare-exchange loop could become costly. + /// + /// An alternative is to initialize `next_all` to a reserved pending state + /// first, perform an atomic swap on `head_all`, and finally update + /// `next_all` with the old head node. Iterators will then either see the + /// pending state value or the correct next node pointer, and can reload + /// `next_all` as needed until the correct value is loaded. The number of + /// retries needed (if any) would be small and will always be finite, so + /// this should generally perform better than the compare-exchange loop. + /// + /// A valid `Task` pointer in the `head_all` list is guaranteed to never be + /// this value, so it is safe to use as a reserved value until the correct + /// value can be written. + fn pending_next_all(&self) -> *mut Task { + // The `ReadyToRunQueue` stub is never inserted into the `head_all` + // list, and its pointer value will remain valid for the lifetime of + // this `FuturesUnordered`, so we can make use of its value here. + Arc::as_ptr(&self.ready_to_run_queue.stub) as *mut _ + } +} + +impl Stream for FuturesUnordered { + type Item = Fut::Output; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let len = self.len(); + + // Keep track of how many child futures we have polled, + // in case we want to forcibly yield. + let mut polled = 0; + let mut yielded = 0; + + // Ensure `parent` is correctly set. + self.ready_to_run_queue.waker.register(cx.waker()); + + loop { + // Safety: &mut self guarantees the mutual exclusion `dequeue` + // expects + let task = match unsafe { self.ready_to_run_queue.dequeue() } { + Dequeue::Empty => { + if self.is_empty() { + // We can only consider ourselves terminated once we + // have yielded a `None` + *self.is_terminated.get_mut() = true; + return Poll::Ready(None); + } else { + return Poll::Pending; + } + } + Dequeue::Inconsistent => { + // At this point, it may be worth yielding the thread & + // spinning a few times... but for now, just yield using the + // task system. + cx.waker().wake_by_ref(); + return Poll::Pending; + } + Dequeue::Data(task) => task, + }; + + debug_assert!(task != self.ready_to_run_queue.stub()); + + // Safety: + // - `task` is a valid pointer. + // - We are the only thread that accesses the `UnsafeCell` that + // contains the future + let future = match unsafe { &mut *(*task).future.get() } { + Some(future) => future, + + // If the future has already gone away then we're just + // cleaning out this task. See the comment in + // `release_task` for more information, but we're basically + // just taking ownership of our reference count here. + None => { + // This case only happens when `release_task` was called + // for this task before and couldn't drop the task + // because it was already enqueued in the ready to run + // queue. + + // Safety: `task` is a valid pointer + let task = unsafe { Arc::from_raw(task) }; + + // Double check that the call to `release_task` really + // happened. Calling it required the task to be unlinked. + debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all()); + unsafe { + debug_assert!((*task.prev_all.get()).is_null()); + } + continue; + } + }; + + // Safety: `task` is a valid pointer + let task = unsafe { self.unlink(task) }; + + // Unset queued flag: This must be done before polling to ensure + // that the future's task gets rescheduled if it sends a wake-up + // notification **during** the call to `poll`. + let prev = task.queued.swap(false, SeqCst); + assert!(prev); + + // We're going to need to be very careful if the `poll` + // method below panics. We need to (a) not leak memory and + // (b) ensure that we still don't have any use-after-frees. To + // manage this we do a few things: + // + // * A "bomb" is created which if dropped abnormally will call + // `release_task`. That way we'll be sure the memory management + // of the `task` is managed correctly. In particular + // `release_task` will drop the future. This ensures that it is + // dropped on this thread and not accidentally on a different + // thread (bad). + // * We unlink the task from our internal queue to preemptively + // assume it'll panic, in which case we'll want to discard it + // regardless. + struct Bomb<'a, Fut> { + queue: &'a mut FuturesUnordered, + task: Option>>, + } + + impl Drop for Bomb<'_, Fut> { + fn drop(&mut self) { + if let Some(task) = self.task.take() { + self.queue.release_task(task); + } + } + } + + let mut bomb = Bomb { task: Some(task), queue: &mut *self }; + + // Poll the underlying future with the appropriate waker + // implementation. This is where a large bit of the unsafety + // starts to stem from internally. The waker is basically just + // our `Arc>` and can schedule the future for polling by + // enqueuing itself in the ready to run queue. + // + // Critically though `Task` won't actually access `Fut`, the + // future, while it's floating around inside of wakers. + // These structs will basically just use `Fut` to size + // the internal allocation, appropriately accessing fields and + // deallocating the task if need be. + let res = { + let task = bomb.task.as_ref().unwrap(); + // We are only interested in whether the future is awoken before it + // finishes polling, so reset the flag here. + task.woken.store(false, Relaxed); + // SAFETY: see the comments of Bomb and this block. + let waker = unsafe { Task::waker_ref(task) }; + let mut cx = Context::from_waker(&waker); + + // Safety: We won't move the future ever again + let future = unsafe { Pin::new_unchecked(future) }; + + future.poll(&mut cx) + }; + polled += 1; + + match res { + Poll::Pending => { + let task = bomb.task.take().unwrap(); + // If the future was awoken during polling, we assume + // the future wanted to explicitly yield. + yielded += task.woken.load(Relaxed) as usize; + bomb.queue.link(task); + + // If a future yields, we respect it and yield here. + // If all futures have been polled, we also yield here to + // avoid starving other tasks waiting on the executor. + // (polling the same future twice per iteration may cause + // the problem: https://github.com/rust-lang/futures-rs/pull/2333) + if yielded >= 2 || polled == len { + cx.waker().wake_by_ref(); + return Poll::Pending; + } + continue; + } + Poll::Ready(output) => return Poll::Ready(Some(output)), + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl Debug for FuturesUnordered { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "FuturesUnordered {{ ... }}") + } +} + +impl FuturesUnordered { + /// Clears the set, removing all futures. + pub fn clear(&mut self) { + *self = Self::new(); + } +} + +impl Drop for FuturesUnordered { + fn drop(&mut self) { + // Before the strong reference to the queue is dropped we need all + // futures to be dropped. See note at the bottom of this method. + // + // If there is a panic before this completes, we leak the queue. + struct LeakQueueOnDrop<'a, Fut>(&'a mut FuturesUnordered); + impl Drop for LeakQueueOnDrop<'_, Fut> { + fn drop(&mut self) { + mem::forget(Arc::clone(&self.0.ready_to_run_queue)); + } + } + let guard = LeakQueueOnDrop(self); + // When a `FuturesUnordered` is dropped we want to drop all futures + // associated with it. At the same time though there may be tons of + // wakers flying around which contain `Task` references + // inside them. We'll let those naturally get deallocated. + while !guard.0.head_all.get_mut().is_null() { + let head = *guard.0.head_all.get_mut(); + let task = unsafe { guard.0.unlink(head) }; + guard.0.release_task(task); + } + mem::forget(guard); // safe to release strong reference to queue + + // Note that at this point we could still have a bunch of tasks in the + // ready to run queue. None of those tasks, however, have futures + // associated with them so they're safe to destroy on any thread. At + // this point the `FuturesUnordered` struct, the owner of the one strong + // reference to the ready to run queue will drop the strong reference. + // At that point whichever thread releases the strong refcount last (be + // it this thread or some other thread as part of an `upgrade`) will + // clear out the ready to run queue and free all remaining tasks. + // + // While that freeing operation isn't guaranteed to happen here, it's + // guaranteed to happen "promptly" as no more "blocking work" will + // happen while there's a strong refcount held. + } +} + +impl<'a, Fut: Unpin> IntoIterator for &'a FuturesUnordered { + type Item = &'a Fut; + type IntoIter = Iter<'a, Fut>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, Fut: Unpin> IntoIterator for &'a mut FuturesUnordered { + type Item = &'a mut Fut; + type IntoIter = IterMut<'a, Fut>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl IntoIterator for FuturesUnordered { + type Item = Fut; + type IntoIter = IntoIter; + + fn into_iter(mut self) -> Self::IntoIter { + // `head_all` can be accessed directly and we don't need to spin on + // `Task::next_all` since we have exclusive access to the set. + let task = *self.head_all.get_mut(); + let len = if task.is_null() { 0 } else { unsafe { *(*task).len_all.get() } }; + + IntoIter { len, inner: self } + } +} + +impl FromIterator for FuturesUnordered { + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + let acc = Self::new(); + iter.into_iter().fold(acc, |acc, item| { + acc.push(item); + acc + }) + } +} + +impl FusedStream for FuturesUnordered { + fn is_terminated(&self) -> bool { + self.is_terminated.load(Relaxed) + } +} + +impl Extend for FuturesUnordered { + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + for item in iter { + self.push(item); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs new file mode 100644 index 0000000000..e35418dfa5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs @@ -0,0 +1,113 @@ +use crate::task::AtomicWaker; +use alloc::sync::Arc; +use core::cell::UnsafeCell; +use core::ptr; +use core::sync::atomic::AtomicPtr; +use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release}; + +use super::abort::abort; +use super::task::Task; + +pub(super) enum Dequeue { + Data(*const Task), + Empty, + Inconsistent, +} + +pub(super) struct ReadyToRunQueue { + // The waker of the task using `FuturesUnordered`. + pub(super) waker: AtomicWaker, + + // Head/tail of the readiness queue + pub(super) head: AtomicPtr>, + pub(super) tail: UnsafeCell<*const Task>, + pub(super) stub: Arc>, +} + +/// An MPSC queue into which the tasks containing the futures are inserted +/// whenever the future inside is scheduled for polling. +impl ReadyToRunQueue { + // FIXME: this takes raw pointer without safety conditions. + + /// The enqueue function from the 1024cores intrusive MPSC queue algorithm. + pub(super) fn enqueue(&self, task: *const Task) { + unsafe { + debug_assert!((*task).queued.load(Relaxed)); + + // This action does not require any coordination + (*task).next_ready_to_run.store(ptr::null_mut(), Relaxed); + + // Note that these atomic orderings come from 1024cores + let task = task as *mut _; + let prev = self.head.swap(task, AcqRel); + (*prev).next_ready_to_run.store(task, Release); + } + } + + /// The dequeue function from the 1024cores intrusive MPSC queue algorithm + /// + /// Note that this is unsafe as it required mutual exclusion (only one + /// thread can call this) to be guaranteed elsewhere. + pub(super) unsafe fn dequeue(&self) -> Dequeue { + unsafe { + let mut tail = *self.tail.get(); + let mut next = (*tail).next_ready_to_run.load(Acquire); + + if tail == self.stub() { + if next.is_null() { + return Dequeue::Empty; + } + + *self.tail.get() = next; + tail = next; + next = (*next).next_ready_to_run.load(Acquire); + } + + if !next.is_null() { + *self.tail.get() = next; + debug_assert!(tail != self.stub()); + return Dequeue::Data(tail); + } + + if !core::ptr::eq(self.head.load(Acquire), tail) { + return Dequeue::Inconsistent; + } + + self.enqueue(self.stub()); + + next = (*tail).next_ready_to_run.load(Acquire); + + if !next.is_null() { + *self.tail.get() = next; + return Dequeue::Data(tail); + } + + Dequeue::Inconsistent + } + } + + pub(super) fn stub(&self) -> *const Task { + Arc::as_ptr(&self.stub) + } +} + +impl Drop for ReadyToRunQueue { + fn drop(&mut self) { + // Once we're in the destructor for `Inner` we need to clear out + // the ready to run queue of tasks if there's anything left in there. + // + // Note that each task has a strong reference count associated with it + // which is owned by the ready to run queue. All tasks should have had + // their futures dropped already by the `FuturesUnordered` destructor + // above, so we're just pulling out tasks and dropping their refcounts. + unsafe { + loop { + match self.dequeue() { + Dequeue::Empty => break, + Dequeue::Inconsistent => abort("inconsistent in drop"), + Dequeue::Data(ptr) => drop(Arc::from_raw(ptr)), + } + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/futures_unordered/task.rs b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/task.rs new file mode 100644 index 0000000000..2ae4cb7d85 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/futures_unordered/task.rs @@ -0,0 +1,214 @@ +use alloc::sync::{Arc, Weak}; +use core::cell::UnsafeCell; +use core::sync::atomic::Ordering::{self, Relaxed, SeqCst}; +use core::sync::atomic::{AtomicBool, AtomicPtr}; + +use super::abort::abort; +use super::ReadyToRunQueue; +use crate::task::ArcWake; + +pub(super) struct Task { + // The future + pub(super) future: UnsafeCell>, + + // Next pointer for linked list tracking all active tasks (use + // `spin_next_all` to read when access is shared across threads) + pub(super) next_all: AtomicPtr>, + + // Previous task in linked list tracking all active tasks + pub(super) prev_all: UnsafeCell<*const Task>, + + // Length of the linked list tracking all active tasks when this node was + // inserted (use `spin_next_all` to synchronize before reading when access + // is shared across threads) + pub(super) len_all: UnsafeCell, + + // Next pointer in ready to run queue + pub(super) next_ready_to_run: AtomicPtr>, + + // Queue that we'll be enqueued to when woken + pub(super) ready_to_run_queue: Weak>, + + // Whether or not this task is currently in the ready to run queue + pub(super) queued: AtomicBool, + + // Whether the future was awoken during polling + // It is possible for this flag to be set to true after the polling, + // but it will be ignored. + pub(super) woken: AtomicBool, +} + +// `Task` can be sent across threads safely because it ensures that +// the underlying `Fut` type isn't touched from any of its methods. +// +// The parent (`super`) module is trusted not to access `future` +// across different threads. +unsafe impl Send for Task {} +unsafe impl Sync for Task {} + +impl ArcWake for Task { + fn wake_by_ref(arc_self: &Arc) { + let inner = match arc_self.ready_to_run_queue.upgrade() { + Some(inner) => inner, + None => return, + }; + + arc_self.woken.store(true, Relaxed); + + // It's our job to enqueue this task it into the ready to run queue. To + // do this we set the `queued` flag, and if successful we then do the + // actual queueing operation, ensuring that we're only queued once. + // + // Once the task is inserted call `wake` to notify the parent task, + // as it'll want to come along and run our task later. + // + // Note that we don't change the reference count of the task here, + // we merely enqueue the raw pointer. The `FuturesUnordered` + // implementation guarantees that if we set the `queued` flag that + // there's a reference count held by the main `FuturesUnordered` queue + // still. + let prev = arc_self.queued.swap(true, SeqCst); + if !prev { + inner.enqueue(Arc::as_ptr(arc_self)); + inner.waker.wake(); + } + } +} + +impl Task { + /// Returns a waker reference for this task without cloning the Arc. + pub(super) unsafe fn waker_ref(this: &Arc) -> waker_ref::WakerRef<'_> { + unsafe { waker_ref::waker_ref(this) } + } + + /// Spins until `next_all` is no longer set to `pending_next_all`. + /// + /// The temporary `pending_next_all` value is typically overwritten fairly + /// quickly after a node is inserted into the list of all futures, so this + /// should rarely spin much. + /// + /// When it returns, the correct `next_all` value is returned. + /// + /// `Relaxed` or `Acquire` ordering can be used. `Acquire` ordering must be + /// used before `len_all` can be safely read. + #[inline] + pub(super) fn spin_next_all( + &self, + pending_next_all: *mut Self, + ordering: Ordering, + ) -> *const Self { + loop { + let next = self.next_all.load(ordering); + if next != pending_next_all { + return next; + } + } + } +} + +impl Drop for Task { + fn drop(&mut self) { + // Since `Task` is sent across all threads for any lifetime, + // regardless of `Fut`, we, to guarantee memory safety, can't actually + // touch `Fut` at any time except when we have a reference to the + // `FuturesUnordered` itself . + // + // Consequently it *should* be the case that we always drop futures from + // the `FuturesUnordered` instance. This is a bomb, just in case there's + // a bug in that logic. + unsafe { + if (*self.future.get()).is_some() { + abort("future still here when dropping"); + } + } + } +} + +mod waker_ref { + use alloc::sync::Arc; + use core::marker::PhantomData; + use core::mem; + use core::mem::ManuallyDrop; + use core::ops::Deref; + use core::task::{RawWaker, RawWakerVTable, Waker}; + use futures_task::ArcWake; + + pub(crate) struct WakerRef<'a> { + waker: ManuallyDrop, + _marker: PhantomData<&'a ()>, + } + + impl WakerRef<'_> { + #[inline] + fn new_unowned(waker: ManuallyDrop) -> Self { + Self { waker, _marker: PhantomData } + } + } + + impl Deref for WakerRef<'_> { + type Target = Waker; + + #[inline] + fn deref(&self) -> &Waker { + &self.waker + } + } + + /// Copy of `future_task::waker_ref` without `W: 'static` bound. + /// + /// # Safety + /// + /// The caller must guarantee that use-after-free will not occur. + #[inline] + pub(crate) unsafe fn waker_ref(wake: &Arc) -> WakerRef<'_> + where + W: ArcWake, + { + // simply copy the pointer instead of using Arc::into_raw, + // as we don't actually keep a refcount by using ManuallyDrop.< + let ptr = Arc::as_ptr(wake).cast::<()>(); + + let waker = + ManuallyDrop::new(unsafe { Waker::from_raw(RawWaker::new(ptr, waker_vtable::())) }); + WakerRef::new_unowned(waker) + } + + fn waker_vtable() -> &'static RawWakerVTable { + &RawWakerVTable::new( + clone_arc_raw::, + wake_arc_raw::, + wake_by_ref_arc_raw::, + drop_arc_raw::, + ) + } + + // FIXME: panics on Arc::clone / refcount changes could wreak havoc on the + // code here. We should guard against this by aborting. + + unsafe fn increase_refcount(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); + } + + unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { + unsafe { increase_refcount::(data) } + RawWaker::new(data, waker_vtable::()) + } + + unsafe fn wake_arc_raw(data: *const ()) { + let arc: Arc = unsafe { Arc::from_raw(data.cast::()) }; + ArcWake::wake(arc); + } + + unsafe fn wake_by_ref_arc_raw(data: *const ()) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = mem::ManuallyDrop::new(unsafe { Arc::::from_raw(data.cast::()) }); + ArcWake::wake_by_ref(&arc); + } + + unsafe fn drop_arc_raw(data: *const ()) { + drop(unsafe { Arc::::from_raw(data.cast::()) }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/iter.rs b/anneal/v2/vendor/futures-util/src/stream/iter.rs new file mode 100644 index 0000000000..48b6519a39 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/iter.rs @@ -0,0 +1,66 @@ +use super::assert_stream; +use core::pin::Pin; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; + +/// Stream for the [`iter`] function. +#[derive(Debug, Clone)] +#[must_use = "streams do nothing unless polled"] +pub struct Iter { + iter: I, +} + +impl Iter { + /// Acquires a reference to the underlying iterator that this stream is pulling from. + pub fn get_ref(&self) -> &I { + &self.iter + } + + /// Acquires a mutable reference to the underlying iterator that this stream is pulling from. + pub fn get_mut(&mut self) -> &mut I { + &mut self.iter + } + + /// Consumes this stream, returning the underlying iterator. + pub fn into_inner(self) -> I { + self.iter + } +} + +impl Unpin for Iter {} + +/// Converts an `Iterator` into a `Stream` which is always ready +/// to yield the next value. +/// +/// Iterators in Rust don't express the ability to block, so this adapter +/// simply always calls `iter.next()` and returns that. +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// let stream = stream::iter(vec![17, 19]); +/// assert_eq!(vec![17, 19], stream.collect::>().await); +/// # }); +/// ``` +pub fn iter(i: I) -> Iter +where + I: IntoIterator, +{ + assert_stream::(Iter { iter: i.into_iter() }) +} + +impl Stream for Iter +where + I: Iterator, +{ + type Item = I::Item; + + fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/mod.rs b/anneal/v2/vendor/futures-util/src/stream/mod.rs new file mode 100644 index 0000000000..2438e58b62 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/mod.rs @@ -0,0 +1,148 @@ +//! Asynchronous streams. +//! +//! This module contains: +//! +//! - The [`Stream`] trait, for objects that can asynchronously produce a +//! sequence of values. +//! - The [`StreamExt`] and [`TryStreamExt`] trait, which provides adapters for +//! chaining and composing streams. +//! - Top-level stream constructors like [`iter`](iter()) which creates a +//! stream from an iterator. + +#[cfg(feature = "alloc")] +pub use futures_core::stream::{BoxStream, LocalBoxStream}; +pub use futures_core::stream::{FusedStream, Stream, TryStream}; + +// Extension traits and combinators + +#[allow(clippy::module_inception)] +mod stream; +pub use self::stream::{ + All, Any, Chain, Collect, Concat, Count, Cycle, Enumerate, Filter, FilterMap, FlatMap, Flatten, + Fold, ForEach, Fuse, Inspect, Map, Next, NextIf, NextIfEq, Peek, PeekMut, Peekable, Scan, + SelectNextSome, Skip, SkipWhile, StreamExt, StreamFuture, Take, TakeUntil, TakeWhile, Then, + Unzip, Zip, +}; + +#[cfg(feature = "std")] +pub use self::stream::CatchUnwind; + +#[cfg(feature = "alloc")] +pub use self::stream::Chunks; + +#[cfg(feature = "alloc")] +pub use self::stream::ReadyChunks; + +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::stream::Forward; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use self::stream::{ + BufferUnordered, Buffered, FlatMapUnordered, FlattenUnordered, ForEachConcurrent, +}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +#[cfg(feature = "alloc")] +pub use self::stream::{ReuniteError, SplitSink, SplitStream}; + +mod try_stream; +pub use self::try_stream::{ + try_unfold, AndThen, ErrInto, InspectErr, InspectOk, IntoStream, MapErr, MapOk, OrElse, TryAll, + TryAny, TryCollect, TryConcat, TryFilter, TryFilterMap, TryFlatten, TryFold, TryForEach, + TryNext, TrySkipWhile, TryStreamExt, TryTakeWhile, TryUnfold, +}; + +#[cfg(feature = "io")] +#[cfg_attr(docsrs, doc(cfg(feature = "io")))] +#[cfg(feature = "std")] +pub use self::try_stream::IntoAsyncRead; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use self::try_stream::{ + TryBufferUnordered, TryBuffered, TryFlattenUnordered, TryForEachConcurrent, +}; + +#[cfg(feature = "alloc")] +pub use self::try_stream::{TryChunks, TryChunksError, TryReadyChunks, TryReadyChunksError}; + +// Primitive streams + +mod iter; +pub use self::iter::{iter, Iter}; + +mod repeat; +pub use self::repeat::{repeat, Repeat}; + +mod repeat_with; +pub use self::repeat_with::{repeat_with, RepeatWith}; + +mod empty; +pub use self::empty::{empty, Empty}; + +mod once; +pub use self::once::{once, Once}; + +mod pending; +pub use self::pending::{pending, Pending}; + +mod poll_fn; +pub use self::poll_fn::{poll_fn, PollFn}; + +mod poll_immediate; +pub use self::poll_immediate::{poll_immediate, PollImmediate}; + +mod select; +pub use self::select::{select, Select}; + +mod select_with_strategy; +pub use self::select_with_strategy::{select_with_strategy, PollNext, SelectWithStrategy}; + +mod unfold; +pub use self::unfold::{unfold, Unfold}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod futures_ordered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use self::futures_ordered::FuturesOrdered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub mod futures_unordered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[doc(inline)] +pub use self::futures_unordered::FuturesUnordered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub mod select_all; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[doc(inline)] +pub use self::select_all::{select_all, SelectAll}; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod abortable; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use crate::abortable::{AbortHandle, AbortRegistration, Abortable, Aborted}; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use abortable::abortable; + +// Just a helper function to ensure the streams we're returning all have the +// right implementations. +pub(crate) fn assert_stream(stream: S) -> S +where + S: Stream, +{ + stream +} diff --git a/anneal/v2/vendor/futures-util/src/stream/once.rs b/anneal/v2/vendor/futures-util/src/stream/once.rs new file mode 100644 index 0000000000..ee21c8b594 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/once.rs @@ -0,0 +1,67 @@ +use super::assert_stream; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +/// Creates a stream of a single element. +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// let stream = stream::once(async { 17 }); +/// let collected = stream.collect::>().await; +/// assert_eq!(collected, vec![17]); +/// # }); +/// ``` +pub fn once(future: Fut) -> Once { + assert_stream::(Once::new(future)) +} + +pin_project! { + /// A stream which emits single element and then EOF. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Once { + #[pin] + future: Option + } +} + +impl Once { + pub(crate) fn new(future: Fut) -> Self { + Self { future: Some(future) } + } +} + +impl Stream for Once { + type Item = Fut::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + let v = match this.future.as_mut().as_pin_mut() { + Some(fut) => ready!(fut.poll(cx)), + None => return Poll::Ready(None), + }; + + this.future.set(None); + Poll::Ready(Some(v)) + } + + fn size_hint(&self) -> (usize, Option) { + if self.future.is_some() { + (1, Some(1)) + } else { + (0, Some(0)) + } + } +} + +impl FusedStream for Once { + fn is_terminated(&self) -> bool { + self.future.is_none() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/pending.rs b/anneal/v2/vendor/futures-util/src/stream/pending.rs new file mode 100644 index 0000000000..d7030ff3cc --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/pending.rs @@ -0,0 +1,45 @@ +use super::assert_stream; +use core::marker; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +/// Stream for the [`pending()`] function. +#[derive(Debug)] +#[must_use = "streams do nothing unless polled"] +pub struct Pending { + _data: marker::PhantomData, +} + +/// Creates a stream which never returns any elements. +/// +/// The returned stream will always return `Pending` when polled. +pub fn pending() -> Pending { + assert_stream::(Pending { _data: marker::PhantomData }) +} + +impl Unpin for Pending {} + +impl FusedStream for Pending { + fn is_terminated(&self) -> bool { + true + } +} + +impl Stream for Pending { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Pending + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +impl Clone for Pending { + fn clone(&self) -> Self { + pending() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/poll_fn.rs b/anneal/v2/vendor/futures-util/src/stream/poll_fn.rs new file mode 100644 index 0000000000..b9bd7d1664 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/poll_fn.rs @@ -0,0 +1,57 @@ +//! Definition of the `PollFn` combinator + +use super::assert_stream; +use core::fmt; +use core::pin::Pin; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; + +/// Stream for the [`poll_fn`] function. +#[must_use = "streams do nothing unless polled"] +pub struct PollFn { + f: F, +} + +impl Unpin for PollFn {} + +impl fmt::Debug for PollFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PollFn").finish() + } +} + +/// Creates a new stream wrapping a function returning `Poll>`. +/// +/// Polling the returned stream calls the wrapped function. +/// +/// # Examples +/// +/// ``` +/// use futures::stream::poll_fn; +/// use futures::task::Poll; +/// +/// let mut counter = 1usize; +/// +/// let read_stream = poll_fn(move |_| -> Poll> { +/// if counter == 0 { return Poll::Ready(None); } +/// counter -= 1; +/// Poll::Ready(Some("Hello, World!".to_owned())) +/// }); +/// ``` +pub fn poll_fn(f: F) -> PollFn +where + F: FnMut(&mut Context<'_>) -> Poll>, +{ + assert_stream::(PollFn { f }) +} + +impl Stream for PollFn +where + F: FnMut(&mut Context<'_>) -> Poll>, +{ + type Item = T; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + (&mut self.f)(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/poll_immediate.rs b/anneal/v2/vendor/futures-util/src/stream/poll_immediate.rs new file mode 100644 index 0000000000..c7e8a5b3c6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/poll_immediate.rs @@ -0,0 +1,80 @@ +use core::pin::Pin; +use futures_core::task::{Context, Poll}; +use futures_core::Stream; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [poll_immediate](poll_immediate()) function. + /// + /// It will never return [Poll::Pending](core::task::Poll::Pending) + #[derive(Debug, Clone)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct PollImmediate { + #[pin] + stream: Option + } +} + +impl Stream for PollImmediate +where + S: Stream, +{ + type Item = Poll; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + let stream = match this.stream.as_mut().as_pin_mut() { + // inner is gone, so we can continue to signal that the stream is closed. + None => return Poll::Ready(None), + Some(inner) => inner, + }; + + match stream.poll_next(cx) { + Poll::Ready(Some(t)) => Poll::Ready(Some(Poll::Ready(t))), + Poll::Ready(None) => { + this.stream.set(None); + Poll::Ready(None) + } + Poll::Pending => Poll::Ready(Some(Poll::Pending)), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.stream.as_ref().map_or((0, Some(0)), Stream::size_hint) + } +} + +impl super::FusedStream for PollImmediate { + fn is_terminated(&self) -> bool { + self.stream.is_none() + } +} + +/// Creates a new stream that always immediately returns [Poll::Ready](core::task::Poll::Ready) when awaiting it. +/// +/// This is useful when immediacy is more important than waiting for the next item to be ready. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// use futures::task::Poll; +/// +/// let mut r = stream::poll_immediate(Box::pin(stream::iter(1_u32..3))); +/// assert_eq!(r.next().await, Some(Poll::Ready(1))); +/// assert_eq!(r.next().await, Some(Poll::Ready(2))); +/// assert_eq!(r.next().await, None); +/// +/// let mut p = stream::poll_immediate(Box::pin(stream::once(async { +/// futures::pending!(); +/// 42_u8 +/// }))); +/// assert_eq!(p.next().await, Some(Poll::Pending)); +/// assert_eq!(p.next().await, Some(Poll::Ready(42))); +/// assert_eq!(p.next().await, None); +/// # }); +/// ``` +pub fn poll_immediate(s: S) -> PollImmediate { + super::assert_stream::, PollImmediate>(PollImmediate { stream: Some(s) }) +} diff --git a/anneal/v2/vendor/futures-util/src/stream/repeat.rs b/anneal/v2/vendor/futures-util/src/stream/repeat.rs new file mode 100644 index 0000000000..e09cfa2e41 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/repeat.rs @@ -0,0 +1,58 @@ +use super::assert_stream; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +/// Stream for the [`repeat`] function. +#[derive(Debug, Clone)] +#[must_use = "streams do nothing unless polled"] +pub struct Repeat { + item: T, +} + +/// Create a stream which produces the same item repeatedly. +/// +/// The stream never terminates. Note that you likely want to avoid +/// usage of `collect` or such on the returned stream as it will exhaust +/// available memory as it tries to just fill up all RAM. +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// let stream = stream::repeat(9); +/// assert_eq!(vec![9, 9, 9], stream.take(3).collect::>().await); +/// # }); +/// ``` +pub fn repeat(item: T) -> Repeat +where + T: Clone, +{ + assert_stream::(Repeat { item }) +} + +impl Unpin for Repeat {} + +impl Stream for Repeat +where + T: Clone, +{ + type Item = T; + + fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Some(self.item.clone())) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + +impl FusedStream for Repeat +where + T: Clone, +{ + fn is_terminated(&self) -> bool { + false + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/repeat_with.rs b/anneal/v2/vendor/futures-util/src/stream/repeat_with.rs new file mode 100644 index 0000000000..2190eb9453 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/repeat_with.rs @@ -0,0 +1,93 @@ +use super::assert_stream; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +/// An stream that repeats elements of type `A` endlessly by +/// applying the provided closure `F: FnMut() -> A`. +/// +/// This `struct` is created by the [`repeat_with()`] function. +/// See its documentation for more. +#[derive(Debug, Clone)] +#[must_use = "streams do nothing unless polled"] +pub struct RepeatWith { + repeater: F, +} + +impl A> Unpin for RepeatWith {} + +impl A> Stream for RepeatWith { + type Item = A; + + fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Some((&mut self.repeater)())) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + +impl A> FusedStream for RepeatWith { + fn is_terminated(&self) -> bool { + false + } +} + +/// Creates a new stream that repeats elements of type `A` endlessly by +/// applying the provided closure, the repeater, `F: FnMut() -> A`. +/// +/// The `repeat_with()` function calls the repeater over and over again. +/// +/// Infinite stream like `repeat_with()` are often used with adapters like +/// [`stream.take()`](crate::stream::StreamExt::take), in order to make them finite. +/// +/// If the element type of the stream you need implements [`Clone`], and +/// it is OK to keep the source element in memory, you should instead use +/// the [`stream::repeat()`](crate::stream::repeat) function. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// // let's assume we have some value of a type that is not `Clone` +/// // or which don't want to have in memory just yet because it is expensive: +/// #[derive(PartialEq, Debug)] +/// struct Expensive; +/// +/// // a particular value forever: +/// let mut things = stream::repeat_with(|| Expensive); +/// +/// assert_eq!(Some(Expensive), things.next().await); +/// assert_eq!(Some(Expensive), things.next().await); +/// assert_eq!(Some(Expensive), things.next().await); +/// # }); +/// ``` +/// +/// Using mutation and going finite: +/// +/// ```rust +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// // From the zeroth to the third power of two: +/// let mut curr = 1; +/// let mut pow2 = stream::repeat_with(|| { let tmp = curr; curr *= 2; tmp }) +/// .take(4); +/// +/// assert_eq!(Some(1), pow2.next().await); +/// assert_eq!(Some(2), pow2.next().await); +/// assert_eq!(Some(4), pow2.next().await); +/// assert_eq!(Some(8), pow2.next().await); +/// +/// // ... and now we're done +/// assert_eq!(None, pow2.next().await); +/// # }); +/// ``` +pub fn repeat_with A>(repeater: F) -> RepeatWith { + assert_stream::(RepeatWith { repeater }) +} diff --git a/anneal/v2/vendor/futures-util/src/stream/select.rs b/anneal/v2/vendor/futures-util/src/stream/select.rs new file mode 100644 index 0000000000..0c1e3af782 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/select.rs @@ -0,0 +1,117 @@ +use super::assert_stream; +use crate::stream::{select_with_strategy, PollNext, SelectWithStrategy}; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`select()`] function. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Select { + #[pin] + inner: SelectWithStrategy PollNext, PollNext>, + } +} + +/// This function will attempt to pull items from both streams. Each +/// stream will be polled in a round-robin fashion, and whenever a stream is +/// ready to yield an item that item is yielded. +/// +/// After one of the two input streams completes, the remaining one will be +/// polled exclusively. The returned stream completes when both input +/// streams have completed. +/// +/// Note that this function consumes both streams and returns a wrapped +/// version of them. +/// +/// ## Examples +/// +/// ```rust +/// # futures::executor::block_on(async { +/// use futures::stream::{ repeat, select, StreamExt }; +/// +/// let left = repeat(1); +/// let right = repeat(2); +/// +/// let mut out = select(left, right); +/// +/// for _ in 0..100 { +/// // We should be alternating. +/// assert_eq!(1, out.select_next_some().await); +/// assert_eq!(2, out.select_next_some().await); +/// } +/// # }); +/// ``` +pub fn select(stream1: St1, stream2: St2) -> Select +where + St1: Stream, + St2: Stream, +{ + fn round_robin(last: &mut PollNext) -> PollNext { + last.toggle() + } + + assert_stream::(Select { + inner: select_with_strategy(stream1, stream2, round_robin), + }) +} + +impl Select { + /// Acquires a reference to the underlying streams that this combinator is + /// pulling from. + pub fn get_ref(&self) -> (&St1, &St2) { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_mut(&mut self) -> (&mut St1, &mut St2) { + self.inner.get_mut() + } + + /// Acquires a pinned mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut St1>, Pin<&mut St2>) { + let this = self.project(); + this.inner.get_pin_mut() + } + + /// Consumes this combinator, returning the underlying streams. + /// + /// Note that this may discard intermediate state of this combinator, so + /// care should be taken to avoid losing resources when this is called. + pub fn into_inner(self) -> (St1, St2) { + self.inner.into_inner() + } +} + +impl FusedStream for Select +where + St1: Stream, + St2: Stream, +{ + fn is_terminated(&self) -> bool { + self.inner.is_terminated() + } +} + +impl Stream for Select +where + St1: Stream, + St2: Stream, +{ + type Item = St1::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + this.inner.poll_next(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/select_all.rs b/anneal/v2/vendor/futures-util/src/stream/select_all.rs new file mode 100644 index 0000000000..121b6a0e59 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/select_all.rs @@ -0,0 +1,249 @@ +//! An unbounded set of streams + +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::pin::Pin; + +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +use super::assert_stream; +use crate::stream::{futures_unordered, FuturesUnordered, StreamExt, StreamFuture}; + +/// An unbounded set of streams +/// +/// This "combinator" provides the ability to maintain a set of streams +/// and drive them all to completion. +/// +/// Streams are pushed into this set and their realized values are +/// yielded as they become ready. Streams will only be polled when they +/// generate notifications. This allows to coordinate a large number of streams. +/// +/// Note that you can create a ready-made `SelectAll` via the +/// `select_all` function in the `stream` module, or you can start with an +/// empty set with the `SelectAll::new` constructor. +#[must_use = "streams do nothing unless polled"] +pub struct SelectAll { + inner: FuturesUnordered>, +} + +impl Debug for SelectAll { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "SelectAll {{ ... }}") + } +} + +impl SelectAll { + /// Constructs a new, empty `SelectAll` + /// + /// The returned `SelectAll` does not contain any streams and, in this + /// state, `SelectAll::poll` will return `Poll::Ready(None)`. + pub fn new() -> Self { + Self { inner: FuturesUnordered::new() } + } + + /// Returns the number of streams contained in the set. + /// + /// This represents the total number of in-flight streams. + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Returns `true` if the set contains no streams + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// Push a stream into the set. + /// + /// This function submits the given stream to the set for managing. This + /// function will not call `poll` on the submitted stream. The caller must + /// ensure that `SelectAll::poll` is called in order to receive task + /// notifications. + pub fn push(&mut self, stream: St) { + self.inner.push(stream.into_future()); + } + + /// Returns an iterator that allows inspecting each stream in the set. + pub fn iter(&self) -> Iter<'_, St> { + Iter(self.inner.iter()) + } + + /// Returns an iterator that allows modifying each stream in the set. + pub fn iter_mut(&mut self) -> IterMut<'_, St> { + IterMut(self.inner.iter_mut()) + } + + /// Clears the set, removing all streams. + pub fn clear(&mut self) { + self.inner.clear() + } +} + +impl Default for SelectAll { + fn default() -> Self { + Self::new() + } +} + +impl Stream for SelectAll { + type Item = St::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + loop { + match ready!(self.inner.poll_next_unpin(cx)) { + Some((Some(item), remaining)) => { + self.push(remaining); + return Poll::Ready(Some(item)); + } + Some((None, _)) => { + // `FuturesUnordered` thinks it isn't terminated + // because it yielded a Some. + // We do not return, but poll `FuturesUnordered` + // in the next loop iteration. + } + None => return Poll::Ready(None), + } + } + } +} + +impl FusedStream for SelectAll { + fn is_terminated(&self) -> bool { + self.inner.is_terminated() + } +} + +/// Convert a list of streams into a `Stream` of results from the streams. +/// +/// This essentially takes a list of streams (e.g. a vector, an iterator, etc.) +/// and bundles them together into a single stream. +/// The stream will yield items as they become available on the underlying +/// streams internally, in the order they become available. +/// +/// Note that the returned set can also be used to dynamically push more +/// streams into the set as they become available. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +pub fn select_all(streams: I) -> SelectAll +where + I: IntoIterator, + I::Item: Stream + Unpin, +{ + let mut set = SelectAll::new(); + + for stream in streams { + set.push(stream); + } + + assert_stream::<::Item, _>(set) +} + +impl FromIterator for SelectAll { + fn from_iter>(iter: T) -> Self { + select_all(iter) + } +} + +impl Extend for SelectAll { + fn extend>(&mut self, iter: T) { + for st in iter { + self.push(st) + } + } +} + +impl IntoIterator for SelectAll { + type Item = St; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter(self.inner.into_iter()) + } +} + +impl<'a, St: Stream + Unpin> IntoIterator for &'a SelectAll { + type Item = &'a St; + type IntoIter = Iter<'a, St>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, St: Stream + Unpin> IntoIterator for &'a mut SelectAll { + type Item = &'a mut St; + type IntoIter = IterMut<'a, St>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +/// Immutable iterator over all streams in the unordered set. +#[derive(Debug)] +pub struct Iter<'a, St: Unpin>(futures_unordered::Iter<'a, StreamFuture>); + +/// Mutable iterator over all streams in the unordered set. +#[derive(Debug)] +pub struct IterMut<'a, St: Unpin>(futures_unordered::IterMut<'a, StreamFuture>); + +/// Owned iterator over all streams in the unordered set. +#[derive(Debug)] +pub struct IntoIter(futures_unordered::IntoIter>); + +impl<'a, St: Stream + Unpin> Iterator for Iter<'a, St> { + type Item = &'a St; + + fn next(&mut self) -> Option { + let st = self.0.next()?; + let next = st.get_ref(); + // This should always be true because FuturesUnordered removes completed futures. + debug_assert!(next.is_some()); + next + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for Iter<'_, St> {} + +impl<'a, St: Stream + Unpin> Iterator for IterMut<'a, St> { + type Item = &'a mut St; + + fn next(&mut self) -> Option { + let st = self.0.next()?; + let next = st.get_mut(); + // This should always be true because FuturesUnordered removes completed futures. + debug_assert!(next.is_some()); + next + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for IterMut<'_, St> {} + +impl Iterator for IntoIter { + type Item = St; + + fn next(&mut self) -> Option { + let st = self.0.next()?; + let next = st.into_inner(); + // This should always be true because FuturesUnordered removes completed futures. + debug_assert!(next.is_some()); + next + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for IntoIter {} diff --git a/anneal/v2/vendor/futures-util/src/stream/select_with_strategy.rs b/anneal/v2/vendor/futures-util/src/stream/select_with_strategy.rs new file mode 100644 index 0000000000..d2b49d588f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/select_with_strategy.rs @@ -0,0 +1,304 @@ +use super::assert_stream; +use core::{fmt, pin::Pin}; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +/// Type to tell [`SelectWithStrategy`] which stream to poll next. +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub enum PollNext { + /// Poll the first stream. + Left, + /// Poll the second stream. + Right, +} + +impl PollNext { + /// Toggle the value and return the old one. + pub fn toggle(&mut self) -> Self { + let old = *self; + *self = self.other(); + old + } + + fn other(&self) -> Self { + match self { + Self::Left => Self::Right, + Self::Right => Self::Left, + } + } +} + +impl Default for PollNext { + fn default() -> Self { + Self::Left + } +} + +enum InternalState { + Start, + LeftFinished, + RightFinished, + BothFinished, +} + +impl InternalState { + fn finish(&mut self, ps: PollNext) { + match (&self, ps) { + (Self::Start, PollNext::Left) => { + *self = Self::LeftFinished; + } + (Self::Start, PollNext::Right) => { + *self = Self::RightFinished; + } + (Self::LeftFinished, PollNext::Right) | (Self::RightFinished, PollNext::Left) => { + *self = Self::BothFinished; + } + _ => {} + } + } +} + +pin_project! { + /// Stream for the [`select_with_strategy()`] function. See function docs for details. + #[must_use = "streams do nothing unless polled"] + #[project = SelectWithStrategyProj] + pub struct SelectWithStrategy { + #[pin] + stream1: St1, + #[pin] + stream2: St2, + internal_state: InternalState, + state: State, + clos: Clos, + } +} + +#[allow(clippy::too_long_first_doc_paragraph)] +/// This function will attempt to pull items from both streams. You provide a +/// closure to tell [`SelectWithStrategy`] which stream to poll. The closure can +/// store state on `SelectWithStrategy` to which it will receive a `&mut` on every +/// invocation. This allows basing the strategy on prior choices. +/// +/// After one of the two input streams completes, the remaining one will be +/// polled exclusively. The returned stream completes when both input +/// streams have completed. +/// +/// Note that this function consumes both streams and returns a wrapped +/// version of them. +/// +/// ## Examples +/// +/// ### Priority +/// This example shows how to always prioritize the left stream. +/// +/// ```rust +/// # futures::executor::block_on(async { +/// use futures::stream::{ repeat, select_with_strategy, PollNext, StreamExt }; +/// +/// let left = repeat(1); +/// let right = repeat(2); +/// +/// // We don't need any state, so let's make it an empty tuple. +/// // We must provide some type here, as there is no way for the compiler +/// // to infer it. As we don't need to capture variables, we can just +/// // use a function pointer instead of a closure. +/// fn prio_left(_: &mut ()) -> PollNext { PollNext::Left } +/// +/// let mut out = select_with_strategy(left, right, prio_left); +/// +/// for _ in 0..100 { +/// // Whenever we poll out, we will alwas get `1`. +/// assert_eq!(1, out.select_next_some().await); +/// } +/// # }); +/// ``` +/// +/// ### Round Robin +/// This example shows how to select from both streams round robin. +/// Note: this special case is provided by [`stream::select`](crate::stream::select). +/// +/// ```rust +/// # futures::executor::block_on(async { +/// use futures::stream::{ repeat, select_with_strategy, PollNext, StreamExt }; +/// +/// let left = repeat(1); +/// let right = repeat(2); +/// +/// let rrobin = |last: &mut PollNext| last.toggle(); +/// +/// let mut out = select_with_strategy(left, right, rrobin); +/// +/// for _ in 0..100 { +/// // We should be alternating now. +/// assert_eq!(1, out.select_next_some().await); +/// assert_eq!(2, out.select_next_some().await); +/// } +/// # }); +/// ``` +pub fn select_with_strategy( + stream1: St1, + stream2: St2, + which: Clos, +) -> SelectWithStrategy +where + St1: Stream, + St2: Stream, + Clos: FnMut(&mut State) -> PollNext, + State: Default, +{ + assert_stream::(SelectWithStrategy { + stream1, + stream2, + state: Default::default(), + internal_state: InternalState::Start, + clos: which, + }) +} + +impl SelectWithStrategy { + /// Acquires a reference to the underlying streams that this combinator is + /// pulling from. + pub fn get_ref(&self) -> (&St1, &St2) { + (&self.stream1, &self.stream2) + } + + /// Acquires a mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_mut(&mut self) -> (&mut St1, &mut St2) { + (&mut self.stream1, &mut self.stream2) + } + + /// Acquires a pinned mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut St1>, Pin<&mut St2>) { + let this = self.project(); + (this.stream1, this.stream2) + } + + /// Consumes this combinator, returning the underlying streams. + /// + /// Note that this may discard intermediate state of this combinator, so + /// care should be taken to avoid losing resources when this is called. + pub fn into_inner(self) -> (St1, St2) { + (self.stream1, self.stream2) + } +} + +impl FusedStream for SelectWithStrategy +where + St1: Stream, + St2: Stream, + Clos: FnMut(&mut State) -> PollNext, +{ + fn is_terminated(&self) -> bool { + match self.internal_state { + InternalState::BothFinished => true, + _ => false, + } + } +} + +#[inline] +fn poll_side( + select: &mut SelectWithStrategyProj<'_, St1, St2, Clos, State>, + side: PollNext, + cx: &mut Context<'_>, +) -> Poll> +where + St1: Stream, + St2: Stream, +{ + match side { + PollNext::Left => select.stream1.as_mut().poll_next(cx), + PollNext::Right => select.stream2.as_mut().poll_next(cx), + } +} + +#[inline] +fn poll_inner( + select: &mut SelectWithStrategyProj<'_, St1, St2, Clos, State>, + side: PollNext, + cx: &mut Context<'_>, +) -> Poll> +where + St1: Stream, + St2: Stream, +{ + let first_done = match poll_side(select, side, cx) { + Poll::Ready(Some(item)) => return Poll::Ready(Some(item)), + Poll::Ready(None) => { + select.internal_state.finish(side); + true + } + Poll::Pending => false, + }; + let other = side.other(); + match poll_side(select, other, cx) { + Poll::Ready(None) => { + select.internal_state.finish(other); + if first_done { + Poll::Ready(None) + } else { + Poll::Pending + } + } + a => a, + } +} + +impl Stream for SelectWithStrategy +where + St1: Stream, + St2: Stream, + Clos: FnMut(&mut State) -> PollNext, +{ + type Item = St1::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + match this.internal_state { + InternalState::Start => { + let next_side = (this.clos)(this.state); + poll_inner(&mut this, next_side, cx) + } + InternalState::LeftFinished => match this.stream2.poll_next(cx) { + Poll::Ready(None) => { + *this.internal_state = InternalState::BothFinished; + Poll::Ready(None) + } + a => a, + }, + InternalState::RightFinished => match this.stream1.poll_next(cx) { + Poll::Ready(None) => { + *this.internal_state = InternalState::BothFinished; + Poll::Ready(None) + } + a => a, + }, + InternalState::BothFinished => Poll::Ready(None), + } + } +} + +impl fmt::Debug for SelectWithStrategy +where + St1: fmt::Debug, + St2: fmt::Debug, + State: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SelectWithStrategy") + .field("stream1", &self.stream1) + .field("stream2", &self.stream2) + .field("state", &self.state) + .finish() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/all.rs b/anneal/v2/vendor/futures-util/src/stream/stream/all.rs new file mode 100644 index 0000000000..1435c798f2 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/all.rs @@ -0,0 +1,93 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`all`](super::StreamExt::all) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct All { + #[pin] + stream: St, + f: F, + done: bool, + #[pin] + future: Option, + } +} + +impl fmt::Debug for All +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("All") + .field("stream", &self.stream) + .field("done", &self.done) + .field("future", &self.future) + .finish() + } +} + +impl All +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, done: false, future: None } + } +} + +impl FusedFuture for All +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.done && self.future.is_none() + } +} + +impl Future for All +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + type Output = bool; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new value + let res = ready!(fut.poll(cx)); + this.future.set(None); + if !res { + *this.done = true; + break false; + } // early exit + } else if !*this.done { + // we're waiting on a new item from the stream + match ready!(this.stream.as_mut().poll_next(cx)) { + Some(item) => { + this.future.set(Some((this.f)(item))); + } + None => { + *this.done = true; + break true; + } + } + } else { + panic!("All polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/any.rs b/anneal/v2/vendor/futures-util/src/stream/stream/any.rs new file mode 100644 index 0000000000..cc3d695b9d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/any.rs @@ -0,0 +1,93 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`any`](super::StreamExt::any) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Any { + #[pin] + stream: St, + f: F, + done: bool, + #[pin] + future: Option, + } +} + +impl fmt::Debug for Any +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Any") + .field("stream", &self.stream) + .field("done", &self.done) + .field("future", &self.future) + .finish() + } +} + +impl Any +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, done: false, future: None } + } +} + +impl FusedFuture for Any +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.done && self.future.is_none() + } +} + +impl Future for Any +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + type Output = bool; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new value + let res = ready!(fut.poll(cx)); + this.future.set(None); + if res { + *this.done = true; + break true; + } // early exit + } else if !*this.done { + // we're waiting on a new item from the stream + match ready!(this.stream.as_mut().poll_next(cx)) { + Some(item) => { + this.future.set(Some((this.f)(item))); + } + None => { + *this.done = true; + break false; + } + } + } else { + panic!("Any polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/buffer_unordered.rs b/anneal/v2/vendor/futures-util/src/stream/stream/buffer_unordered.rs new file mode 100644 index 0000000000..91b0f6bcce --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/buffer_unordered.rs @@ -0,0 +1,120 @@ +use crate::stream::{Fuse, FuturesUnordered, StreamExt}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`buffer_unordered`](super::StreamExt::buffer_unordered) + /// method. + #[must_use = "streams do nothing unless polled"] + pub struct BufferUnordered + where + St: Stream, + { + #[pin] + stream: Fuse, + in_progress_queue: FuturesUnordered, + max: usize, + } +} + +impl fmt::Debug for BufferUnordered +where + St: Stream + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BufferUnordered") + .field("stream", &self.stream) + .field("in_progress_queue", &self.in_progress_queue) + .field("max", &self.max) + .finish() + } +} + +impl BufferUnordered +where + St: Stream, + St::Item: Future, +{ + pub(super) fn new(stream: St, n: usize) -> Self { + Self { + stream: super::Fuse::new(stream), + in_progress_queue: FuturesUnordered::new(), + max: n, + } + } + + delegate_access_inner!(stream, St, (.)); +} + +impl Stream for BufferUnordered +where + St: Stream, + St::Item: Future, +{ + type Item = ::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + // First up, try to spawn off as many futures as possible by filling up + // our queue of futures. + while this.in_progress_queue.len() < *this.max { + match this.stream.as_mut().poll_next(cx) { + Poll::Ready(Some(fut)) => this.in_progress_queue.push(fut), + Poll::Ready(None) | Poll::Pending => break, + } + } + + // Attempt to pull the next value from the in_progress_queue + match this.in_progress_queue.poll_next_unpin(cx) { + x @ Poll::Pending | x @ Poll::Ready(Some(_)) => return x, + Poll::Ready(None) => {} + } + + // If more values are still coming from the stream, we're not done yet + if this.stream.is_done() { + Poll::Ready(None) + } else { + Poll::Pending + } + } + + fn size_hint(&self) -> (usize, Option) { + let queue_len = self.in_progress_queue.len(); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(queue_len); + let upper = match upper { + Some(x) => x.checked_add(queue_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for BufferUnordered +where + St: Stream, + St::Item: Future, +{ + fn is_terminated(&self) -> bool { + self.in_progress_queue.is_terminated() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for BufferUnordered +where + S: Stream + Sink, + S::Item: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/buffered.rs b/anneal/v2/vendor/futures-util/src/stream/stream/buffered.rs new file mode 100644 index 0000000000..5854eb7ea5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/buffered.rs @@ -0,0 +1,118 @@ +use crate::stream::{Fuse, FusedStream, FuturesOrdered, StreamExt}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`buffered`](super::StreamExt::buffered) method. + #[must_use = "streams do nothing unless polled"] + pub struct Buffered + where + St: Stream, + St::Item: Future, + { + #[pin] + stream: Fuse, + in_progress_queue: FuturesOrdered, + max: usize, + } +} + +impl fmt::Debug for Buffered +where + St: Stream + fmt::Debug, + St::Item: Future, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Buffered") + .field("stream", &self.stream) + .field("in_progress_queue", &self.in_progress_queue) + .field("max", &self.max) + .finish() + } +} + +impl Buffered +where + St: Stream, + St::Item: Future, +{ + pub(super) fn new(stream: St, n: usize) -> Self { + Self { stream: super::Fuse::new(stream), in_progress_queue: FuturesOrdered::new(), max: n } + } + + delegate_access_inner!(stream, St, (.)); +} + +impl Stream for Buffered +where + St: Stream, + St::Item: Future, +{ + type Item = ::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + // First up, try to spawn off as many futures as possible by filling up + // our queue of futures. + while this.in_progress_queue.len() < *this.max { + match this.stream.as_mut().poll_next(cx) { + Poll::Ready(Some(fut)) => this.in_progress_queue.push_back(fut), + Poll::Ready(None) | Poll::Pending => break, + } + } + + // Attempt to pull the next value from the in_progress_queue + let res = this.in_progress_queue.poll_next_unpin(cx); + if let Some(val) = ready!(res) { + return Poll::Ready(Some(val)); + } + + // If more values are still coming from the stream, we're not done yet + if this.stream.is_done() { + Poll::Ready(None) + } else { + Poll::Pending + } + } + + fn size_hint(&self) -> (usize, Option) { + let queue_len = self.in_progress_queue.len(); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(queue_len); + let upper = match upper { + Some(x) => x.checked_add(queue_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for Buffered +where + St: Stream, + St::Item: Future, +{ + fn is_terminated(&self) -> bool { + self.stream.is_done() && self.in_progress_queue.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Buffered +where + S: Stream + Sink, + S::Item: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/catch_unwind.rs b/anneal/v2/vendor/futures-util/src/stream/stream/catch_unwind.rs new file mode 100644 index 0000000000..dfc388839d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/catch_unwind.rs @@ -0,0 +1,62 @@ +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; +use std::any::Any; +use std::boxed::Box; +use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; +use std::pin::Pin; + +pin_project! { + /// Stream for the [`catch_unwind`](super::StreamExt::catch_unwind) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct CatchUnwind { + #[pin] + stream: St, + caught_unwind: bool, + } +} + +impl CatchUnwind { + pub(super) fn new(stream: St) -> Self { + Self { stream, caught_unwind: false } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for CatchUnwind { + type Item = Result>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if *this.caught_unwind { + Poll::Ready(None) + } else { + let res = catch_unwind(AssertUnwindSafe(|| this.stream.as_mut().poll_next(cx))); + + match res { + Ok(poll) => poll.map(|opt| opt.map(Ok)), + Err(e) => { + *this.caught_unwind = true; + Poll::Ready(Some(Err(e))) + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.caught_unwind { + (0, Some(0)) + } else { + self.stream.size_hint() + } + } +} + +impl FusedStream for CatchUnwind { + fn is_terminated(&self) -> bool { + self.caught_unwind || self.stream.is_terminated() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/chain.rs b/anneal/v2/vendor/futures-util/src/stream/stream/chain.rs new file mode 100644 index 0000000000..36ff1e533d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/chain.rs @@ -0,0 +1,76 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`chain`](super::StreamExt::chain) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Chain { + #[pin] + first: Option, + #[pin] + second: St2, + } +} + +// All interactions with `Pin<&mut Chain<..>>` happen through these methods +impl Chain +where + St1: Stream, + St2: Stream, +{ + pub(super) fn new(stream1: St1, stream2: St2) -> Self { + Self { first: Some(stream1), second: stream2 } + } +} + +impl FusedStream for Chain +where + St1: Stream, + St2: FusedStream, +{ + fn is_terminated(&self) -> bool { + self.first.is_none() && self.second.is_terminated() + } +} + +impl Stream for Chain +where + St1: Stream, + St2: Stream, +{ + type Item = St1::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + if let Some(first) = this.first.as_mut().as_pin_mut() { + if let Some(item) = ready!(first.poll_next(cx)) { + return Poll::Ready(Some(item)); + } + + this.first.set(None); + } + this.second.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + if let Some(first) = &self.first { + let (first_lower, first_upper) = first.size_hint(); + let (second_lower, second_upper) = self.second.size_hint(); + + let lower = first_lower.saturating_add(second_lower); + + let upper = match (first_upper, second_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + + (lower, upper) + } else { + self.second.size_hint() + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/chunks.rs b/anneal/v2/vendor/futures-util/src/stream/stream/chunks.rs new file mode 100644 index 0000000000..2a71ebc6cc --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/chunks.rs @@ -0,0 +1,103 @@ +use crate::stream::Fuse; +use alloc::vec::Vec; +use core::mem; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`chunks`](super::StreamExt::chunks) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Chunks { + #[pin] + stream: Fuse, + items: Vec, + cap: usize, // https://github.com/rust-lang/futures-rs/issues/1475 + } +} + +impl Chunks { + pub(super) fn new(stream: St, capacity: usize) -> Self { + assert!(capacity > 0); + + Self { + stream: super::Fuse::new(stream), + items: Vec::with_capacity(capacity), + cap: capacity, + } + } + + fn take(self: Pin<&mut Self>) -> Vec { + let cap = self.cap; + mem::replace(self.project().items, Vec::with_capacity(cap)) + } + + delegate_access_inner!(stream, St, (.)); +} + +impl Stream for Chunks { + type Item = Vec; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.as_mut().project(); + loop { + match ready!(this.stream.as_mut().poll_next(cx)) { + // Push the item into the buffer and check whether it is full. + // If so, replace our buffer with a new and empty one and return + // the full one. + Some(item) => { + this.items.push(item); + if this.items.len() >= *this.cap { + return Poll::Ready(Some(self.take())); + } + } + + // Since the underlying stream ran out of values, return what we + // have buffered, if we have anything. + None => { + let last = if this.items.is_empty() { + None + } else { + let full_buf = mem::take(this.items); + Some(full_buf) + }; + + return Poll::Ready(last); + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let chunk_len = usize::from(!self.items.is_empty()); + let (lower, upper) = self.stream.size_hint(); + let lower = (lower / self.cap).saturating_add(chunk_len); + let upper = match upper { + Some(x) => x.checked_add(chunk_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for Chunks { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() && self.items.is_empty() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Chunks +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/collect.rs b/anneal/v2/vendor/futures-util/src/stream/stream/collect.rs new file mode 100644 index 0000000000..970ac26dbf --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/collect.rs @@ -0,0 +1,56 @@ +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`collect`](super::StreamExt::collect) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Collect { + #[pin] + stream: St, + collection: C, + } +} + +impl Collect { + fn finish(self: Pin<&mut Self>) -> C { + mem::take(self.project().collection) + } + + pub(super) fn new(stream: St) -> Self { + Self { stream, collection: Default::default() } + } +} + +impl FusedFuture for Collect +where + St: FusedStream, + C: Default + Extend, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for Collect +where + St: Stream, + C: Default + Extend, +{ + type Output = C; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.as_mut().project(); + loop { + match ready!(this.stream.as_mut().poll_next(cx)) { + Some(e) => this.collection.extend(Some(e)), + None => return Poll::Ready(self.finish()), + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/concat.rs b/anneal/v2/vendor/futures-util/src/stream/stream/concat.rs new file mode 100644 index 0000000000..7e058b2315 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/concat.rs @@ -0,0 +1,62 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`concat`](super::StreamExt::concat) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Concat { + #[pin] + stream: St, + accum: Option, + } +} + +impl Concat +where + St: Stream, + St::Item: Extend<::Item> + IntoIterator + Default, +{ + pub(super) fn new(stream: St) -> Self { + Self { stream, accum: None } + } +} + +impl Future for Concat +where + St: Stream, + St::Item: Extend<::Item> + IntoIterator + Default, +{ + type Output = St::Item; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + + loop { + match ready!(this.stream.as_mut().poll_next(cx)) { + None => return Poll::Ready(this.accum.take().unwrap_or_default()), + Some(e) => { + if let Some(a) = this.accum { + a.extend(e) + } else { + *this.accum = Some(e) + } + } + } + } + } +} + +impl FusedFuture for Concat +where + St: FusedStream, + St::Item: Extend<::Item> + IntoIterator + Default, +{ + fn is_terminated(&self) -> bool { + self.accum.is_none() && self.stream.is_terminated() + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/count.rs b/anneal/v2/vendor/futures-util/src/stream/stream/count.rs new file mode 100644 index 0000000000..513cab7b6a --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/count.rs @@ -0,0 +1,53 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`count`](super::StreamExt::count) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Count { + #[pin] + stream: St, + count: usize + } +} + +impl fmt::Debug for Count +where + St: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Count").field("stream", &self.stream).field("count", &self.count).finish() + } +} + +impl Count { + pub(super) fn new(stream: St) -> Self { + Self { stream, count: 0 } + } +} + +impl FusedFuture for Count { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for Count { + type Output = usize; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + + Poll::Ready(loop { + match ready!(this.stream.as_mut().poll_next(cx)) { + Some(_) => *this.count += 1, + None => break *this.count, + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/cycle.rs b/anneal/v2/vendor/futures-util/src/stream/stream/cycle.rs new file mode 100644 index 0000000000..60fe745399 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/cycle.rs @@ -0,0 +1,67 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`cycle`](super::StreamExt::cycle) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Cycle { + orig: St, + #[pin] + stream: St, + } +} + +impl Cycle +where + St: Clone + Stream, +{ + pub(super) fn new(stream: St) -> Self { + Self { orig: stream.clone(), stream } + } +} + +impl Stream for Cycle +where + St: Clone + Stream, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + match ready!(this.stream.as_mut().poll_next(cx)) { + None => { + this.stream.set(this.orig.clone()); + this.stream.poll_next(cx) + } + item => Poll::Ready(item), + } + } + + fn size_hint(&self) -> (usize, Option) { + // the cycle stream is either empty or infinite + match self.orig.size_hint() { + size @ (0, Some(0)) => size, + (0, _) => (0, None), + _ => (usize::MAX, None), + } + } +} + +impl FusedStream for Cycle +where + St: Clone + Stream, +{ + fn is_terminated(&self) -> bool { + // the cycle stream is either empty or infinite + if let (0, Some(0)) = self.size_hint() { + true + } else { + false + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/enumerate.rs b/anneal/v2/vendor/futures-util/src/stream/stream/enumerate.rs new file mode 100644 index 0000000000..1cf9d49aaa --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/enumerate.rs @@ -0,0 +1,64 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`enumerate`](super::StreamExt::enumerate) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Enumerate { + #[pin] + stream: St, + count: usize, + } +} + +impl Enumerate { + pub(super) fn new(stream: St) -> Self { + Self { stream, count: 0 } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Enumerate { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Stream for Enumerate { + type Item = (usize, St::Item); + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + match ready!(this.stream.poll_next(cx)) { + Some(item) => { + let prev_count = *this.count; + *this.count += 1; + Poll::Ready(Some((prev_count, item))) + } + None => Poll::Ready(None), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.stream.size_hint() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Enumerate +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/filter.rs b/anneal/v2/vendor/futures-util/src/stream/stream/filter.rs new file mode 100644 index 0000000000..997fe9977e --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/filter.rs @@ -0,0 +1,117 @@ +use crate::fns::FnMut1; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`filter`](super::StreamExt::filter) method. + #[must_use = "streams do nothing unless polled"] + pub struct Filter + where St: Stream, + { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + } +} + +impl fmt::Debug for Filter +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Filter") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .finish() + } +} + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl Filter +where + St: Stream, + F: for<'a> FnMut1<&'a St::Item, Output = Fut>, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Filter +where + St: Stream + FusedStream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.pending_fut.is_none() && self.stream.is_terminated() + } +} + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl Stream for Filter +where + St: Stream, + F: for<'a> FnMut1<&'a St::Item, Output = Fut>, + Fut: Future, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let res = ready!(fut.poll(cx)); + this.pending_fut.set(None); + if res { + break this.pending_item.take(); + } + *this.pending_item = None; + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + this.pending_fut.set(Some(this.f.call_mut(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let pending_len = usize::from(self.pending_item.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Filter +where + S: Stream + Sink, + F: FnMut(&S::Item) -> Fut, + Fut: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/filter_map.rs b/anneal/v2/vendor/futures-util/src/stream/stream/filter_map.rs new file mode 100644 index 0000000000..6b7d0070df --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/filter_map.rs @@ -0,0 +1,111 @@ +use crate::fns::FnMut1; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`filter_map`](super::StreamExt::filter_map) method. + #[must_use = "streams do nothing unless polled"] + pub struct FilterMap { + #[pin] + stream: St, + f: F, + #[pin] + pending: Option, + } +} + +impl fmt::Debug for FilterMap +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FilterMap") + .field("stream", &self.stream) + .field("pending", &self.pending) + .finish() + } +} + +impl FilterMap +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for FilterMap +where + St: Stream + FusedStream, + F: FnMut1, + Fut: Future>, +{ + fn is_terminated(&self) -> bool { + self.pending.is_none() && self.stream.is_terminated() + } +} + +impl Stream for FilterMap +where + St: Stream, + F: FnMut1, + Fut: Future>, +{ + type Item = T; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(p) = this.pending.as_mut().as_pin_mut() { + // We have an item in progress, poll that until it's done + let item = ready!(p.poll(cx)); + this.pending.set(None); + if item.is_some() { + break item; + } + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + // No item in progress, but the stream is still going + this.pending.set(Some(this.f.call_mut(item))); + } else { + // The stream is done + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let pending_len = usize::from(self.pending.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for FilterMap +where + S: Stream + Sink, + F: FnMut1, + Fut: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/flatten.rs b/anneal/v2/vendor/futures-util/src/stream/stream/flatten.rs new file mode 100644 index 0000000000..9f6b7a472d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/flatten.rs @@ -0,0 +1,73 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`flatten`](super::StreamExt::flatten) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Flatten { + #[pin] + stream: St, + #[pin] + next: Option, + } +} + +impl Flatten { + pub(super) fn new(stream: St) -> Self { + Self { stream, next: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Flatten +where + St: FusedStream, + St::Item: Stream, +{ + fn is_terminated(&self) -> bool { + self.next.is_none() && self.stream.is_terminated() + } +} + +impl Stream for Flatten +where + St: Stream, + St::Item: Stream, +{ + type Item = ::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(s) = this.next.as_mut().as_pin_mut() { + if let Some(item) = ready!(s.poll_next(cx)) { + break Some(item); + } else { + this.next.set(None); + } + } else if let Some(s) = ready!(this.stream.as_mut().poll_next(cx)) { + this.next.set(Some(s)); + } else { + break None; + } + }) + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Flatten +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/flatten_unordered.rs b/anneal/v2/vendor/futures-util/src/stream/stream/flatten_unordered.rs new file mode 100644 index 0000000000..c79edbd213 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/flatten_unordered.rs @@ -0,0 +1,531 @@ +use alloc::sync::Arc; +use core::{ + cell::UnsafeCell, + convert::identity, + fmt, + marker::PhantomData, + num::NonZeroUsize, + pin::Pin, + sync::atomic::{AtomicU8, Ordering}, +}; + +use pin_project_lite::pin_project; + +use futures_core::{ + future::Future, + ready, + stream::{FusedStream, Stream}, + task::{Context, Poll, Waker}, +}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use futures_task::{waker, ArcWake}; + +use crate::stream::FuturesUnordered; + +/// Stream for the [`flatten_unordered`](super::StreamExt::flatten_unordered) +/// method. +pub type FlattenUnordered = FlattenUnorderedWithFlowController; + +/// There is nothing to poll and stream isn't being polled/waking/woken at the moment. +const NONE: u8 = 0; + +/// Inner streams need to be polled. +const NEED_TO_POLL_INNER_STREAMS: u8 = 1; + +/// The base stream needs to be polled. +const NEED_TO_POLL_STREAM: u8 = 0b10; + +/// Both base stream and inner streams need to be polled. +const NEED_TO_POLL_ALL: u8 = NEED_TO_POLL_INNER_STREAMS | NEED_TO_POLL_STREAM; + +/// The current stream is being polled at the moment. +const POLLING: u8 = 0b100; + +/// Stream is being woken at the moment. +const WAKING: u8 = 0b1000; + +/// The stream was waked and will be polled. +const WOKEN: u8 = 0b10000; + +/// Internal polling state of the stream. +#[derive(Clone, Debug)] +struct SharedPollState { + state: Arc, +} + +impl SharedPollState { + /// Constructs new `SharedPollState` with the given state. + fn new(value: u8) -> Self { + Self { state: Arc::new(AtomicU8::new(value)) } + } + + /// Attempts to start polling, returning stored state in case of success. + /// Returns `None` if either waker is waking at the moment. + fn start_polling(&self) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&Self) -> u8>)> { + let value = self + .state + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| { + if value & WAKING == NONE { + Some(POLLING) + } else { + None + } + }) + .ok()?; + let bomb = PollStateBomb::new(self, Self::reset); + + Some((value, bomb)) + } + + /// Attempts to start the waking process and performs bitwise or with the given value. + /// + /// If some waker is already in progress or stream is already woken/being polled, waking process won't start, however + /// state will be disjuncted with the given value. + fn start_waking( + &self, + to_poll: u8, + ) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&Self) -> u8>)> { + let value = self + .state + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| { + let mut next_value = value | to_poll; + if value & (WOKEN | POLLING) == NONE { + next_value |= WAKING; + } + + if next_value != value { + Some(next_value) + } else { + None + } + }) + .ok()?; + + // Only start the waking process if we're not in the polling/waking phase and the stream isn't woken already + if value & (WOKEN | POLLING | WAKING) == NONE { + let bomb = PollStateBomb::new(self, Self::stop_waking); + + Some((value, bomb)) + } else { + None + } + } + + /// Sets current state to + /// - `!POLLING` allowing to use wakers + /// - `WOKEN` if the state was changed during `POLLING` phase as waker will be called, + /// or `will_be_woken` flag supplied + /// - `!WAKING` as + /// * Wakers called during the `POLLING` phase won't propagate their calls + /// * `POLLING` phase can't start if some of the wakers are active + /// So no wrapped waker can touch the inner waker's cell, it's safe to poll again. + fn stop_polling(&self, to_poll: u8, will_be_woken: bool) -> u8 { + self.state + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut value| { + let mut next_value = to_poll; + + value &= NEED_TO_POLL_ALL; + if value != NONE || will_be_woken { + next_value |= WOKEN; + } + next_value |= value; + + Some(next_value & !POLLING & !WAKING) + }) + .unwrap() + } + + /// Toggles state to non-waking, allowing to start polling. + fn stop_waking(&self) -> u8 { + let value = self + .state + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| { + let next_value = value & !WAKING | WOKEN; + + if next_value != value { + Some(next_value) + } else { + None + } + }) + .unwrap_or_else(identity); + + debug_assert!(value & (WOKEN | POLLING | WAKING) == WAKING); + value + } + + /// Resets current state allowing to poll the stream and wake up wakers. + fn reset(&self) -> u8 { + self.state.swap(NEED_TO_POLL_ALL, Ordering::SeqCst) + } +} + +/// Used to execute some function on the given state when dropped. +struct PollStateBomb<'a, F: FnOnce(&SharedPollState) -> u8> { + state: &'a SharedPollState, + drop: Option, +} + +impl<'a, F: FnOnce(&SharedPollState) -> u8> PollStateBomb<'a, F> { + /// Constructs new bomb with the given state. + fn new(state: &'a SharedPollState, drop: F) -> Self { + Self { state, drop: Some(drop) } + } + + /// Deactivates bomb, forces it to not call provided function when dropped. + fn deactivate(mut self) { + self.drop.take(); + } +} + +impl u8> Drop for PollStateBomb<'_, F> { + fn drop(&mut self) { + if let Some(drop) = self.drop.take() { + (drop)(self.state); + } + } +} + +/// Will update state with the provided value on `wake_by_ref` call +/// and then, if there is a need, call `inner_waker`. +struct WrappedWaker { + inner_waker: UnsafeCell>, + poll_state: SharedPollState, + need_to_poll: u8, +} + +unsafe impl Send for WrappedWaker {} +unsafe impl Sync for WrappedWaker {} + +impl WrappedWaker { + /// Replaces given waker's inner_waker for polling stream/futures which will + /// update poll state on `wake_by_ref` call. Use only if you need several + /// contexts. + /// + /// ## Safety + /// + /// This function will modify waker's `inner_waker` via `UnsafeCell`, so + /// it should be used only during `POLLING` phase by one thread at the time. + unsafe fn replace_waker(self_arc: &mut Arc, cx: &Context<'_>) { + unsafe { *self_arc.inner_waker.get() = cx.waker().clone().into() } + } + + /// Attempts to start the waking process for the waker with the given value. + /// If succeeded, then the stream isn't yet woken and not being polled at the moment. + fn start_waking(&self) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&SharedPollState) -> u8>)> { + self.poll_state.start_waking(self.need_to_poll) + } +} + +impl ArcWake for WrappedWaker { + fn wake_by_ref(self_arc: &Arc) { + if let Some((_, state_bomb)) = self_arc.start_waking() { + // Safety: now state is not `POLLING` + let waker_opt = unsafe { self_arc.inner_waker.get().as_ref().unwrap() }; + + if let Some(inner_waker) = waker_opt.clone() { + // Stop waking to allow polling stream + drop(state_bomb); + + // Wake up inner waker + inner_waker.wake(); + } + } + } +} + +pin_project! { + /// Future which polls optional inner stream. + /// + /// If it's `Some`, it will attempt to call `poll_next` on it, + /// returning `Some((item, next_item_fut))` in case of `Poll::Ready(Some(...))` + /// or `None` in case of `Poll::Ready(None)`. + /// + /// If `poll_next` will return `Poll::Pending`, it will be forwarded to + /// the future and current task will be notified by waker. + #[must_use = "futures do nothing unless you `.await` or poll them"] + struct PollStreamFut { + #[pin] + stream: Option, + } +} + +impl PollStreamFut { + /// Constructs new `PollStreamFut` using given `stream`. + fn new(stream: impl Into>) -> Self { + Self { stream: stream.into() } + } +} + +impl Future for PollStreamFut { + type Output = Option<(St::Item, Self)>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut stream = self.project().stream; + + let item = if let Some(stream) = stream.as_mut().as_pin_mut() { + ready!(stream.poll_next(cx)) + } else { + None + }; + let next_item_fut = Self::new(stream.get_mut().take()); + let out = item.map(|item| (item, next_item_fut)); + + Poll::Ready(out) + } +} + +pin_project! { + /// Stream for the [`flatten_unordered`](super::StreamExt::flatten_unordered) + /// method with ability to specify flow controller. + #[project = FlattenUnorderedWithFlowControllerProj] + #[must_use = "streams do nothing unless polled"] + pub struct FlattenUnorderedWithFlowController where St: Stream { + #[pin] + inner_streams: FuturesUnordered>, + #[pin] + stream: St, + poll_state: SharedPollState, + limit: Option, + is_stream_done: bool, + inner_streams_waker: Arc, + stream_waker: Arc, + flow_controller: PhantomData + } +} + +impl fmt::Debug for FlattenUnorderedWithFlowController +where + St: Stream + fmt::Debug, + St::Item: Stream + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FlattenUnorderedWithFlowController") + .field("poll_state", &self.poll_state) + .field("inner_streams", &self.inner_streams) + .field("limit", &self.limit) + .field("stream", &self.stream) + .field("is_stream_done", &self.is_stream_done) + .field("flow_controller", &self.flow_controller) + .finish() + } +} + +impl FlattenUnorderedWithFlowController +where + St: Stream, + Fc: FlowController::Item>, + St::Item: Stream + Unpin, +{ + pub(crate) fn new(stream: St, limit: Option) -> Self { + let poll_state = SharedPollState::new(NEED_TO_POLL_STREAM); + + Self { + inner_streams: FuturesUnordered::new(), + stream, + is_stream_done: false, + limit: limit.and_then(NonZeroUsize::new), + inner_streams_waker: Arc::new(WrappedWaker { + inner_waker: UnsafeCell::new(None), + poll_state: poll_state.clone(), + need_to_poll: NEED_TO_POLL_INNER_STREAMS, + }), + stream_waker: Arc::new(WrappedWaker { + inner_waker: UnsafeCell::new(None), + poll_state: poll_state.clone(), + need_to_poll: NEED_TO_POLL_STREAM, + }), + poll_state, + flow_controller: PhantomData, + } + } + + delegate_access_inner!(stream, St, ()); +} + +/// Returns the next flow step based on the received item. +pub trait FlowController { + /// Handles an item producing `FlowStep` describing the next flow step. + fn next_step(item: I) -> FlowStep; +} + +impl FlowController for () { + fn next_step(item: I) -> FlowStep { + FlowStep::Continue(item) + } +} + +/// Describes the next flow step. +#[derive(Debug, Clone)] +pub enum FlowStep { + /// Just yields an item and continues standard flow. + Continue(C), + /// Immediately returns an underlying item from the function. + Return(R), +} + +impl FlattenUnorderedWithFlowControllerProj<'_, St, Fc> +where + St: Stream, +{ + /// Checks if current `inner_streams` bucket size is greater than optional limit. + fn is_exceeded_limit(&self) -> bool { + self.limit.map_or(false, |limit| self.inner_streams.len() >= limit.get()) + } +} + +impl FusedStream for FlattenUnorderedWithFlowController +where + St: FusedStream, + Fc: FlowController::Item>, + St::Item: Stream + Unpin, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() && self.inner_streams.is_empty() + } +} + +impl Stream for FlattenUnorderedWithFlowController +where + St: Stream, + Fc: FlowController::Item>, + St::Item: Stream + Unpin, +{ + type Item = ::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut next_item = None; + let mut need_to_poll_next = NONE; + + let mut this = self.as_mut().project(); + + // Attempt to start polling, in case some waker is holding the lock, wait in loop + let (mut poll_state_value, state_bomb) = loop { + if let Some(value) = this.poll_state.start_polling() { + break value; + } + }; + + // Safety: now state is `POLLING`. + unsafe { + WrappedWaker::replace_waker(this.stream_waker, cx); + WrappedWaker::replace_waker(this.inner_streams_waker, cx) + }; + + if poll_state_value & NEED_TO_POLL_STREAM != NONE { + let mut stream_waker = None; + + // Here we need to poll the base stream. + // + // To improve performance, we will attempt to place as many items as we can + // to the `FuturesUnordered` bucket before polling inner streams + loop { + if this.is_exceeded_limit() || *this.is_stream_done { + // We either exceeded the limit or the stream is exhausted + if !*this.is_stream_done { + // The stream needs to be polled in the next iteration + need_to_poll_next |= NEED_TO_POLL_STREAM; + } + + break; + } else { + let mut cx = Context::from_waker( + stream_waker.get_or_insert_with(|| waker(this.stream_waker.clone())), + ); + + match this.stream.as_mut().poll_next(&mut cx) { + Poll::Ready(Some(item)) => { + let next_item_fut = match Fc::next_step(item) { + // Propagates an item immediately (the main use-case is for errors) + FlowStep::Return(item) => { + need_to_poll_next |= NEED_TO_POLL_STREAM + | (poll_state_value & NEED_TO_POLL_INNER_STREAMS); + poll_state_value &= !NEED_TO_POLL_INNER_STREAMS; + + next_item = Some(item); + + break; + } + // Yields an item and continues processing (normal case) + FlowStep::Continue(inner_stream) => { + PollStreamFut::new(inner_stream) + } + }; + // Add new stream to the inner streams bucket + this.inner_streams.as_mut().push(next_item_fut); + // Inner streams must be polled afterward + poll_state_value |= NEED_TO_POLL_INNER_STREAMS; + } + Poll::Ready(None) => { + // Mark the base stream as done + *this.is_stream_done = true; + } + Poll::Pending => { + break; + } + } + } + } + } + + if poll_state_value & NEED_TO_POLL_INNER_STREAMS != NONE { + let inner_streams_waker = waker(this.inner_streams_waker.clone()); + let mut cx = Context::from_waker(&inner_streams_waker); + + match this.inner_streams.as_mut().poll_next(&mut cx) { + Poll::Ready(Some(Some((item, next_item_fut)))) => { + // Push next inner stream item future to the list of inner streams futures + this.inner_streams.as_mut().push(next_item_fut); + // Take the received item + next_item = Some(item); + // On the next iteration, inner streams must be polled again + need_to_poll_next |= NEED_TO_POLL_INNER_STREAMS; + } + Poll::Ready(Some(None)) => { + // On the next iteration, inner streams must be polled again + need_to_poll_next |= NEED_TO_POLL_INNER_STREAMS; + } + _ => {} + } + } + + // We didn't have any `poll_next` panic, so it's time to deactivate the bomb + state_bomb.deactivate(); + + // Call the waker at the end of polling if + let mut force_wake = + // we need to poll the stream and didn't reach the limit yet + need_to_poll_next & NEED_TO_POLL_STREAM != NONE && !this.is_exceeded_limit() + // or we need to poll the inner streams again + || need_to_poll_next & NEED_TO_POLL_INNER_STREAMS != NONE; + + // Stop polling and swap the latest state + poll_state_value = this.poll_state.stop_polling(need_to_poll_next, force_wake); + // If state was changed during `POLLING` phase, we also need to manually call a waker + force_wake |= poll_state_value & NEED_TO_POLL_ALL != NONE; + + let is_done = *this.is_stream_done && this.inner_streams.is_empty(); + + if next_item.is_some() || is_done { + Poll::Ready(next_item) + } else { + if force_wake { + cx.waker().wake_by_ref(); + } + + Poll::Pending + } + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for FlattenUnorderedWithFlowController +where + St: Stream + Sink, +{ + type Error = St::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/fold.rs b/anneal/v2/vendor/futures-util/src/stream/stream/fold.rs new file mode 100644 index 0000000000..b8b55ecb67 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/fold.rs @@ -0,0 +1,88 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`fold`](super::StreamExt::fold) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Fold { + #[pin] + stream: St, + f: F, + accum: Option, + #[pin] + future: Option, + } +} + +impl fmt::Debug for Fold +where + St: fmt::Debug, + Fut: fmt::Debug, + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Fold") + .field("stream", &self.stream) + .field("accum", &self.accum) + .field("future", &self.future) + .finish() + } +} + +impl Fold +where + St: Stream, + F: FnMut(T, St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F, t: T) -> Self { + Self { stream, f, accum: Some(t), future: None } + } +} + +impl FusedFuture for Fold +where + St: Stream, + F: FnMut(T, St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.accum.is_none() && self.future.is_none() + } +} + +impl Future for Fold +where + St: Stream, + F: FnMut(T, St::Item) -> Fut, + Fut: Future, +{ + type Output = T; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new accum value + *this.accum = Some(ready!(fut.poll(cx))); + this.future.set(None); + } else if this.accum.is_some() { + // we're waiting on a new item from the stream + let res = ready!(this.stream.as_mut().poll_next(cx)); + let a = this.accum.take().unwrap(); + if let Some(item) = res { + this.future.set(Some((this.f)(a, item))); + } else { + break a; + } + } else { + panic!("Fold polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/for_each.rs b/anneal/v2/vendor/futures-util/src/stream/stream/for_each.rs new file mode 100644 index 0000000000..5302b0e034 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/for_each.rs @@ -0,0 +1,78 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`for_each`](super::StreamExt::for_each) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ForEach { + #[pin] + stream: St, + f: F, + #[pin] + future: Option, + } +} + +impl fmt::Debug for ForEach +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ForEach") + .field("stream", &self.stream) + .field("future", &self.future) + .finish() + } +} + +impl ForEach +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, future: None } + } +} + +impl FusedFuture for ForEach +where + St: FusedStream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.future.is_none() && self.stream.is_terminated() + } +} + +impl Future for ForEach +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + ready!(fut.poll(cx)); + this.future.set(None); + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + this.future.set(Some((this.f)(item))); + } else { + break; + } + } + Poll::Ready(()) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/for_each_concurrent.rs b/anneal/v2/vendor/futures-util/src/stream/stream/for_each_concurrent.rs new file mode 100644 index 0000000000..6c18753eb9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/for_each_concurrent.rs @@ -0,0 +1,119 @@ +use crate::stream::{FuturesUnordered, StreamExt}; +use core::fmt; +use core::num::NonZeroUsize; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`for_each_concurrent`](super::StreamExt::for_each_concurrent) + /// method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ForEachConcurrent { + #[pin] + stream: Option, + f: F, + futures: FuturesUnordered, + limit: Option, + } +} + +impl fmt::Debug for ForEachConcurrent +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ForEachConcurrent") + .field("stream", &self.stream) + .field("futures", &self.futures) + .field("limit", &self.limit) + .finish() + } +} + +impl ForEachConcurrent +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, limit: Option, f: F) -> Self { + Self { + stream: Some(stream), + // Note: `limit` = 0 gets ignored. + limit: limit.and_then(NonZeroUsize::new), + f, + futures: FuturesUnordered::new(), + } + } +} + +impl FusedFuture for ForEachConcurrent +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.stream.is_none() && self.futures.is_empty() + } +} + +impl Future for ForEachConcurrent +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + loop { + let mut made_progress_this_iter = false; + + // Check if we've already created a number of futures greater than `limit` + if this.limit.map(|limit| limit.get() > this.futures.len()).unwrap_or(true) { + let mut stream_completed = false; + let elem = if let Some(stream) = this.stream.as_mut().as_pin_mut() { + match stream.poll_next(cx) { + Poll::Ready(Some(elem)) => { + made_progress_this_iter = true; + Some(elem) + } + Poll::Ready(None) => { + stream_completed = true; + None + } + Poll::Pending => None, + } + } else { + None + }; + if stream_completed { + this.stream.set(None); + } + if let Some(elem) = elem { + this.futures.push((this.f)(elem)); + } + } + + match this.futures.poll_next_unpin(cx) { + Poll::Ready(Some(())) => made_progress_this_iter = true, + Poll::Ready(None) => { + if this.stream.is_none() { + return Poll::Ready(()); + } + } + Poll::Pending => {} + } + + if !made_progress_this_iter { + return Poll::Pending; + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/forward.rs b/anneal/v2/vendor/futures-util/src/stream/stream/forward.rs new file mode 100644 index 0000000000..1fe24273aa --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/forward.rs @@ -0,0 +1,75 @@ +use crate::stream::Fuse; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`forward`](super::StreamExt::forward) method. + #[project = ForwardProj] + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Forward { + #[pin] + sink: Option, + #[pin] + stream: Fuse, + buffered_item: Option, + } +} + +impl Forward { + pub(crate) fn new(stream: St, sink: Si) -> Self { + Self { sink: Some(sink), stream: Fuse::new(stream), buffered_item: None } + } +} + +impl FusedFuture for Forward +where + Si: Sink, + St: Stream>, +{ + fn is_terminated(&self) -> bool { + self.sink.is_none() + } +} + +impl Future for Forward +where + Si: Sink, + St: Stream>, +{ + type Output = Result<(), E>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let ForwardProj { mut sink, mut stream, buffered_item } = self.project(); + let mut si = sink.as_mut().as_pin_mut().expect("polled `Forward` after completion"); + + loop { + // If we've got an item buffered already, we need to write it to the + // sink before we can do anything else + if buffered_item.is_some() { + ready!(si.as_mut().poll_ready(cx))?; + si.as_mut().start_send(buffered_item.take().unwrap())?; + } + + match stream.as_mut().poll_next(cx)? { + Poll::Ready(Some(item)) => { + *buffered_item = Some(item); + } + Poll::Ready(None) => { + ready!(si.poll_close(cx))?; + sink.set(None); + return Poll::Ready(Ok(())); + } + Poll::Pending => { + ready!(si.poll_flush(cx))?; + return Poll::Pending; + } + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/fuse.rs b/anneal/v2/vendor/futures-util/src/stream/stream/fuse.rs new file mode 100644 index 0000000000..fe67813e81 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/fuse.rs @@ -0,0 +1,75 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`fuse`](super::StreamExt::fuse) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Fuse { + #[pin] + stream: St, + done: bool, + } +} + +impl Fuse { + pub(super) fn new(stream: St) -> Self { + Self { stream, done: false } + } + + /// Returns whether the underlying stream has finished or not. + /// + /// If this method returns `true`, then all future calls to poll are + /// guaranteed to return `None`. If this returns `false`, then the + /// underlying stream is still in use. + pub fn is_done(&self) -> bool { + self.done + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Fuse { + fn is_terminated(&self) -> bool { + self.done + } +} + +impl Stream for Fuse { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + + if *this.done { + return Poll::Ready(None); + } + + let item = ready!(this.stream.poll_next(cx)); + if item.is_none() { + *this.done = true; + } + Poll::Ready(item) + } + + fn size_hint(&self) -> (usize, Option) { + if self.done { + (0, Some(0)) + } else { + self.stream.size_hint() + } + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl, Item> Sink for Fuse { + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/into_future.rs b/anneal/v2/vendor/futures-util/src/stream/stream/into_future.rs new file mode 100644 index 0000000000..8abfddcccd --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/into_future.rs @@ -0,0 +1,90 @@ +use crate::stream::StreamExt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; + +/// Future for the [`into_future`](super::StreamExt::into_future) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct StreamFuture { + stream: Option, +} + +impl StreamFuture { + pub(super) fn new(stream: St) -> Self { + Self { stream: Some(stream) } + } + + /// Acquires a reference to the underlying stream that this combinator is + /// pulling from. + /// + /// This method returns an `Option` to account for the fact that `StreamFuture`'s + /// implementation of `Future::poll` consumes the underlying stream during polling + /// in order to return it to the caller of `Future::poll` if the stream yielded + /// an element. + pub fn get_ref(&self) -> Option<&St> { + self.stream.as_ref() + } + + /// Acquires a mutable reference to the underlying stream that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + /// + /// This method returns an `Option` to account for the fact that `StreamFuture`'s + /// implementation of `Future::poll` consumes the underlying stream during polling + /// in order to return it to the caller of `Future::poll` if the stream yielded + /// an element. + pub fn get_mut(&mut self) -> Option<&mut St> { + self.stream.as_mut() + } + + /// Acquires a pinned mutable reference to the underlying stream that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + /// + /// This method returns an `Option` to account for the fact that `StreamFuture`'s + /// implementation of `Future::poll` consumes the underlying stream during polling + /// in order to return it to the caller of `Future::poll` if the stream yielded + /// an element. + pub fn get_pin_mut(self: Pin<&mut Self>) -> Option> { + self.get_mut().stream.as_mut().map(Pin::new) + } + + /// Consumes this combinator, returning the underlying stream. + /// + /// Note that this may discard intermediate state of this combinator, so + /// care should be taken to avoid losing resources when this is called. + /// + /// This method returns an `Option` to account for the fact that `StreamFuture`'s + /// implementation of `Future::poll` consumes the underlying stream during polling + /// in order to return it to the caller of `Future::poll` if the stream yielded + /// an element. + pub fn into_inner(self) -> Option { + self.stream + } +} + +impl FusedFuture for StreamFuture { + fn is_terminated(&self) -> bool { + self.stream.is_none() + } +} + +impl Future for StreamFuture { + type Output = (Option, St); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let item = { + let s = self.stream.as_mut().expect("polling StreamFuture twice"); + ready!(s.poll_next_unpin(cx)) + }; + let stream = self.stream.take().unwrap(); + Poll::Ready((item, stream)) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/map.rs b/anneal/v2/vendor/futures-util/src/stream/stream/map.rs new file mode 100644 index 0000000000..88bb6129d4 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/map.rs @@ -0,0 +1,77 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +use crate::fns::FnMut1; + +pin_project! { + /// Stream for the [`map`](super::StreamExt::map) method. + #[must_use = "streams do nothing unless polled"] + pub struct Map { + #[pin] + stream: St, + f: F, + } +} + +impl fmt::Debug for Map +where + St: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Map").field("stream", &self.stream).finish() + } +} + +impl Map { + pub(crate) fn new(stream: St, f: F) -> Self { + Self { stream, f } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Map +where + St: FusedStream, + F: FnMut1, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Stream for Map +where + St: Stream, + F: FnMut1, +{ + type Item = F::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + let res = ready!(this.stream.as_mut().poll_next(cx)); + Poll::Ready(res.map(|x| this.f.call_mut(x))) + } + + fn size_hint(&self) -> (usize, Option) { + self.stream.size_hint() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Map +where + St: Stream + Sink, + F: FnMut1, +{ + type Error = St::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/mod.rs b/anneal/v2/vendor/futures-util/src/stream/stream/mod.rs new file mode 100644 index 0000000000..d365cfe43f --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/mod.rs @@ -0,0 +1,1697 @@ +//! Streams +//! +//! This module contains a number of functions for working with `Stream`s, +//! including the `StreamExt` trait which adds methods to `Stream` types. + +use crate::future::{assert_future, Either}; +use crate::stream::assert_stream; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::pin::Pin; +#[cfg(feature = "sink")] +use futures_core::stream::TryStream; +#[cfg(feature = "alloc")] +use futures_core::stream::{BoxStream, LocalBoxStream}; +use futures_core::{ + future::Future, + stream::{FusedStream, Stream}, + task::{Context, Poll}, +}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +use crate::fns::{inspect_fn, InspectFn}; + +mod chain; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::chain::Chain; + +mod collect; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::collect::Collect; + +mod unzip; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::unzip::Unzip; + +mod concat; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::concat::Concat; + +mod count; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::count::Count; + +mod cycle; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::cycle::Cycle; + +mod enumerate; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::enumerate::Enumerate; + +mod filter; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::filter::Filter; + +mod filter_map; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::filter_map::FilterMap; + +mod flatten; + +delegate_all!( + /// Stream for the [`flatten`](StreamExt::flatten) method. + Flatten( + flatten::Flatten + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (.)] + New[|x: St| flatten::Flatten::new(x)] + where St: Stream +); + +mod fold; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::fold::Fold; + +mod any; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::any::Any; + +mod all; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::all::All; + +#[cfg(feature = "sink")] +mod forward; + +#[cfg(feature = "sink")] +delegate_all!( + /// Future for the [`forward`](super::StreamExt::forward) method. + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + Forward( + forward::Forward + ): Debug + Future + FusedFuture + New[|x: St, y: Si| forward::Forward::new(x, y)] + where St: TryStream +); + +mod for_each; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::for_each::ForEach; + +mod fuse; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::fuse::Fuse; + +mod into_future; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::into_future::StreamFuture; + +delegate_all!( + /// Stream for the [`inspect`](StreamExt::inspect) method. + Inspect( + map::Map> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (.)] + New[|x: St, f: F| map::Map::new(x, inspect_fn(f))] +); + +mod map; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::map::Map; + +delegate_all!( + /// Stream for the [`flat_map`](StreamExt::flat_map) method. + FlatMap( + flatten::Flatten, U> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, f: F| flatten::Flatten::new(Map::new(x, f))] +); + +mod next; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::next::Next; + +mod select_next_some; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::select_next_some::SelectNextSome; + +mod peek; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::peek::{NextIf, NextIfEq, Peek, PeekMut, Peekable}; + +mod skip; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::skip::Skip; + +mod skip_while; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::skip_while::SkipWhile; + +mod take; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::take::Take; + +mod take_while; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::take_while::TakeWhile; + +mod take_until; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::take_until::TakeUntil; + +mod then; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::then::Then; + +mod zip; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::zip::Zip; + +#[cfg(feature = "alloc")] +mod chunks; +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::chunks::Chunks; + +#[cfg(feature = "alloc")] +mod ready_chunks; +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::ready_chunks::ReadyChunks; + +mod scan; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::scan::Scan; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod buffer_unordered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::buffer_unordered::BufferUnordered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod buffered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::buffered::Buffered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub(crate) mod flatten_unordered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] +pub use self::flatten_unordered::FlattenUnordered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +delegate_all!( + /// Stream for the [`flat_map_unordered`](StreamExt::flat_map_unordered) method. + FlatMapUnordered( + FlattenUnordered> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, limit: Option, f: F| FlattenUnordered::new(Map::new(x, f), limit)] + where St: Stream, U: Stream, U: Unpin, F: FnMut(St::Item) -> U +); + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod for_each_concurrent; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::for_each_concurrent::ForEachConcurrent; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +#[cfg(feature = "alloc")] +mod split; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::split::{ReuniteError, SplitSink, SplitStream}; + +#[cfg(feature = "std")] +mod catch_unwind; +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::catch_unwind::CatchUnwind; + +impl StreamExt for T where T: Stream {} + +/// An extension trait for `Stream`s that provides a variety of convenient +/// combinator functions. +pub trait StreamExt: Stream { + /// Creates a future that resolves to the next item in the stream. + /// + /// Note that because `next` doesn't take ownership over the stream, + /// the [`Stream`] type must be [`Unpin`]. If you want to use `next` with a + /// [`!Unpin`](Unpin) stream, you'll first have to pin the stream. This can + /// be done by boxing the stream using [`Box::pin`] or + /// pinning it to the stack using the `pin_mut!` macro from the `pin_utils` + /// crate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let mut stream = stream::iter(1..=3); + /// + /// assert_eq!(stream.next().await, Some(1)); + /// assert_eq!(stream.next().await, Some(2)); + /// assert_eq!(stream.next().await, Some(3)); + /// assert_eq!(stream.next().await, None); + /// # }); + /// ``` + fn next(&mut self) -> Next<'_, Self> + where + Self: Unpin, + { + assert_future::, _>(Next::new(self)) + } + + /// Converts this stream into a future of `(next_item, tail_of_stream)`. + /// If the stream terminates, then the next item is [`None`]. + /// + /// The returned future can be used to compose streams and futures together + /// by placing everything into the "world of futures". + /// + /// Note that because `into_future` moves the stream, the [`Stream`] type + /// must be [`Unpin`]. If you want to use `into_future` with a + /// [`!Unpin`](Unpin) stream, you'll first have to pin the stream. This can + /// be done by boxing the stream using [`Box::pin`] or + /// pinning it to the stack using the `pin_mut!` macro from the `pin_utils` + /// crate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=3); + /// + /// let (item, stream) = stream.into_future().await; + /// assert_eq!(Some(1), item); + /// + /// let (item, stream) = stream.into_future().await; + /// assert_eq!(Some(2), item); + /// # }); + /// ``` + fn into_future(self) -> StreamFuture + where + Self: Sized + Unpin, + { + assert_future::<(Option, Self), _>(StreamFuture::new(self)) + } + + /// Maps this stream's items to a different type, returning a new stream of + /// the resulting type. + /// + /// The provided closure is executed over all elements of this stream as + /// they are made available. It is executed inline with calls to + /// [`poll_next`](Stream::poll_next). + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `map` methods in the + /// standard library. + /// + /// See [`StreamExt::then`](Self::then) if you want to use a closure that + /// returns a future instead of a value. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=3); + /// let stream = stream.map(|x| x + 3); + /// + /// assert_eq!(vec![4, 5, 6], stream.collect::>().await); + /// # }); + /// ``` + fn map(self, f: F) -> Map + where + F: FnMut(Self::Item) -> T, + Self: Sized, + { + assert_stream::(Map::new(self, f)) + } + + /// Creates a stream which gives the current iteration count as well as + /// the next value. + /// + /// The stream returned yields pairs `(i, val)`, where `i` is the + /// current index of iteration and `val` is the value returned by the + /// stream. + /// + /// `enumerate()` keeps its count as a [`usize`]. If you want to count by a + /// different sized integer, the [`zip`](StreamExt::zip) function provides similar + /// functionality. + /// + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so enumerating more than + /// [`usize::MAX`] elements either produces the wrong result or panics. If + /// debug assertions are enabled, a panic is guaranteed. + /// + /// # Panics + /// + /// The returned stream might panic if the to-be-returned index would + /// overflow a [`usize`]. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(vec!['a', 'b', 'c']); + /// + /// let mut stream = stream.enumerate(); + /// + /// assert_eq!(stream.next().await, Some((0, 'a'))); + /// assert_eq!(stream.next().await, Some((1, 'b'))); + /// assert_eq!(stream.next().await, Some((2, 'c'))); + /// assert_eq!(stream.next().await, None); + /// # }); + /// ``` + fn enumerate(self) -> Enumerate + where + Self: Sized, + { + assert_stream::<(usize, Self::Item), _>(Enumerate::new(self)) + } + + /// Filters the values produced by this stream according to the provided + /// asynchronous predicate. + /// + /// As values of this stream are made available, the provided predicate `f` + /// will be run against them. If the predicate returns a `Future` which + /// resolves to `true`, then the stream will yield the value, but if the + /// predicate returns a `Future` which resolves to `false`, then the value + /// will be discarded and the next value will be produced. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `filter` methods in the + /// standard library. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// let events = stream.filter(|x| future::ready(x % 2 == 0)); + /// + /// assert_eq!(vec![2, 4, 6, 8, 10], events.collect::>().await); + /// # }); + /// ``` + fn filter(self, f: F) -> Filter + where + F: FnMut(&Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_stream::(Filter::new(self, f)) + } + + /// Filters the values produced by this stream while simultaneously mapping + /// them to a different type according to the provided asynchronous closure. + /// + /// As values of this stream are made available, the provided function will + /// be run on them. If the future returned by the predicate `f` resolves to + /// [`Some(item)`](Some) then the stream will yield the value `item`, but if + /// it resolves to [`None`] then the next value will be produced. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `filter_map` methods in + /// the standard library. + /// + /// # Examples + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// let events = stream.filter_map(|x| async move { + /// if x % 2 == 0 { Some(x + 1) } else { None } + /// }); + /// + /// assert_eq!(vec![3, 5, 7, 9, 11], events.collect::>().await); + /// # }); + /// ``` + fn filter_map(self, f: F) -> FilterMap + where + F: FnMut(Self::Item) -> Fut, + Fut: Future>, + Self: Sized, + { + assert_stream::(FilterMap::new(self, f)) + } + + /// Computes from this stream's items new items of a different type using + /// an asynchronous closure. + /// + /// The provided closure `f` will be called with an `Item` once a value is + /// ready, it returns a future which will then be run to completion + /// to produce the next value on this stream. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it. + /// + /// See [`StreamExt::map`](Self::map) if you want to use a closure that + /// returns a value instead of a future. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=3); + /// let stream = stream.then(|x| async move { x + 3 }); + /// + /// assert_eq!(vec![4, 5, 6], stream.collect::>().await); + /// # }); + /// ``` + fn then(self, f: F) -> Then + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_stream::(Then::new(self, f)) + } + + /// Transforms a stream into a collection, returning a + /// future representing the result of that computation. + /// + /// The returned future will be resolved when the stream terminates. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::StreamExt; + /// use std::thread; + /// + /// let (tx, rx) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// for i in 1..=5 { + /// tx.unbounded_send(i).unwrap(); + /// } + /// }); + /// + /// let output = rx.collect::>().await; + /// assert_eq!(output, vec![1, 2, 3, 4, 5]); + /// # }); + /// ``` + fn collect>(self) -> Collect + where + Self: Sized, + { + assert_future::(Collect::new(self)) + } + + /// Converts a stream of pairs into a future, which + /// resolves to pair of containers. + /// + /// `unzip()` produces a future, which resolves to two + /// collections: one from the left elements of the pairs, + /// and one from the right elements. + /// + /// The returned future will be resolved when the stream terminates. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::StreamExt; + /// use std::thread; + /// + /// let (tx, rx) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// tx.unbounded_send((1, 2)).unwrap(); + /// tx.unbounded_send((3, 4)).unwrap(); + /// tx.unbounded_send((5, 6)).unwrap(); + /// }); + /// + /// let (o1, o2): (Vec<_>, Vec<_>) = rx.unzip().await; + /// assert_eq!(o1, vec![1, 3, 5]); + /// assert_eq!(o2, vec![2, 4, 6]); + /// # }); + /// ``` + fn unzip(self) -> Unzip + where + FromA: Default + Extend, + FromB: Default + Extend, + Self: Sized + Stream, + { + assert_future::<(FromA, FromB), _>(Unzip::new(self)) + } + + /// Concatenate all items of a stream into a single extendable + /// destination, returning a future representing the end result. + /// + /// This combinator will extend the first item with the contents + /// of all the subsequent results of the stream. If the stream is + /// empty, the default value will be returned. + /// + /// Works with all collections that implement the + /// [`Extend`](std::iter::Extend) trait. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::StreamExt; + /// use std::thread; + /// + /// let (tx, rx) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// for i in (0..3).rev() { + /// let n = i * 3; + /// tx.unbounded_send(vec![n + 1, n + 2, n + 3]).unwrap(); + /// } + /// }); + /// + /// let result = rx.concat().await; + /// + /// assert_eq!(result, vec![7, 8, 9, 4, 5, 6, 1, 2, 3]); + /// # }); + /// ``` + fn concat(self) -> Concat + where + Self: Sized, + Self::Item: Extend<<::Item as IntoIterator>::Item> + IntoIterator + Default, + { + assert_future::(Concat::new(self)) + } + + /// Drives the stream to completion, counting the number of items. + /// + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so counting elements of a + /// stream with more than [`usize::MAX`] elements either produces the wrong + /// result or panics. If debug assertions are enabled, a panic is guaranteed. + /// + /// # Panics + /// + /// This function might panic if the iterator has more than [`usize::MAX`] + /// elements. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// let count = stream.count().await; + /// + /// assert_eq!(count, 10); + /// # }); + /// ``` + fn count(self) -> Count + where + Self: Sized, + { + assert_future::(Count::new(self)) + } + + /// Repeats a stream endlessly. + /// + /// The stream never terminates. Note that you likely want to avoid + /// usage of `collect` or such on the returned stream as it will exhaust + /// available memory as it tries to just fill up all RAM. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// let a = [1, 2, 3]; + /// let mut s = stream::iter(a.iter()).cycle(); + /// + /// assert_eq!(s.next().await, Some(&1)); + /// assert_eq!(s.next().await, Some(&2)); + /// assert_eq!(s.next().await, Some(&3)); + /// assert_eq!(s.next().await, Some(&1)); + /// assert_eq!(s.next().await, Some(&2)); + /// assert_eq!(s.next().await, Some(&3)); + /// assert_eq!(s.next().await, Some(&1)); + /// # }); + /// ``` + fn cycle(self) -> Cycle + where + Self: Sized + Clone, + { + assert_stream::(Cycle::new(self)) + } + + /// Execute an accumulating asynchronous computation over a stream, + /// collecting all the values into one final result. + /// + /// This combinator will accumulate all values returned by this stream + /// according to the closure provided. The initial state is also provided to + /// this method and then is returned again by each execution of the closure. + /// Once the entire stream has been exhausted the returned future will + /// resolve to this value. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let number_stream = stream::iter(0..6); + /// let sum = number_stream.fold(0, |acc, x| async move { acc + x }); + /// assert_eq!(sum.await, 15); + /// # }); + /// ``` + fn fold(self, init: T, f: F) -> Fold + where + F: FnMut(T, Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::(Fold::new(self, f, init)) + } + + /// Execute predicate over asynchronous stream, and return `true` if any element in stream satisfied a predicate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let number_stream = stream::iter(0..10); + /// let contain_three = number_stream.any(|i| async move { i == 3 }); + /// assert_eq!(contain_three.await, true); + /// # }); + /// ``` + fn any(self, f: F) -> Any + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::(Any::new(self, f)) + } + + /// Execute predicate over asynchronous stream, and return `true` if all element in stream satisfied a predicate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let number_stream = stream::iter(0..10); + /// let less_then_twenty = number_stream.all(|i| async move { i < 20 }); + /// assert_eq!(less_then_twenty.await, true); + /// # }); + /// ``` + fn all(self, f: F) -> All + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::(All::new(self, f)) + } + + /// Flattens a stream of streams into just one continuous stream. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::StreamExt; + /// use std::thread; + /// + /// let (tx1, rx1) = mpsc::unbounded(); + /// let (tx2, rx2) = mpsc::unbounded(); + /// let (tx3, rx3) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// tx1.unbounded_send(1).unwrap(); + /// tx1.unbounded_send(2).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx2.unbounded_send(3).unwrap(); + /// tx2.unbounded_send(4).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx3.unbounded_send(rx1).unwrap(); + /// tx3.unbounded_send(rx2).unwrap(); + /// }); + /// + /// let output = rx3.flatten().collect::>().await; + /// assert_eq!(output, vec![1, 2, 3, 4]); + /// # }); + /// ``` + fn flatten(self) -> Flatten + where + Self::Item: Stream, + Self: Sized, + { + assert_stream::<::Item, _>(Flatten::new(self)) + } + + /// Flattens a stream of streams into just one continuous stream. Polls + /// inner streams produced by the base stream concurrently. + /// + /// The only argument is an optional limit on the number of concurrently + /// polled streams. If this limit is not `None`, no more than `limit` streams + /// will be polled at the same time. The `limit` argument is of type + /// `Into>`, and so can be provided as either `None`, + /// `Some(10)`, or just `10`. Note: a limit of zero is interpreted as + /// no limit at all, and will have the same result as passing in `None`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::StreamExt; + /// use std::thread; + /// + /// let (tx1, rx1) = mpsc::unbounded(); + /// let (tx2, rx2) = mpsc::unbounded(); + /// let (tx3, rx3) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// tx1.unbounded_send(1).unwrap(); + /// tx1.unbounded_send(2).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx2.unbounded_send(3).unwrap(); + /// tx2.unbounded_send(4).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx3.unbounded_send(rx1).unwrap(); + /// tx3.unbounded_send(rx2).unwrap(); + /// }); + /// + /// let mut output = rx3.flatten_unordered(None).collect::>().await; + /// output.sort(); + /// + /// assert_eq!(output, vec![1, 2, 3, 4]); + /// # }); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn flatten_unordered(self, limit: impl Into>) -> FlattenUnordered + where + Self::Item: Stream + Unpin, + Self: Sized, + { + assert_stream::<::Item, _>(FlattenUnordered::new(self, limit.into())) + } + + /// Maps a stream like [`StreamExt::map`] but flattens nested `Stream`s. + /// + /// [`StreamExt::map`] is very useful, but if it produces a `Stream` instead, + /// you would have to chain combinators like `.map(f).flatten()` while this + /// combinator provides ability to write `.flat_map(f)` instead of chaining. + /// + /// The provided closure which produces inner streams is executed over all elements + /// of stream as last inner stream is terminated and next stream item is available. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `flat_map` methods in the + /// standard library. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=3); + /// let stream = stream.flat_map(|x| stream::iter(vec![x + 3; x])); + /// + /// assert_eq!(vec![4, 5, 5, 6, 6, 6], stream.collect::>().await); + /// # }); + /// ``` + fn flat_map(self, f: F) -> FlatMap + where + F: FnMut(Self::Item) -> U, + U: Stream, + Self: Sized, + { + assert_stream::(FlatMap::new(self, f)) + } + + /// Maps a stream like [`StreamExt::map`] but flattens nested `Stream`s + /// and polls them concurrently, yielding items in any order, as they made + /// available. + /// + /// [`StreamExt::map`] is very useful, but if it produces `Stream`s + /// instead, and you need to poll all of them concurrently, you would + /// have to use something like `for_each_concurrent` and merge values + /// by hand. This combinator provides ability to collect all values + /// from concurrently polled streams into one stream. + /// + /// The first argument is an optional limit on the number of concurrently + /// polled streams. If this limit is not `None`, no more than `limit` streams + /// will be polled at the same time. The `limit` argument is of type + /// `Into>`, and so can be provided as either `None`, + /// `Some(10)`, or just `10`. Note: a limit of zero is interpreted as + /// no limit at all, and will have the same result as passing in `None`. + /// + /// The provided closure which produces inner streams is executed over + /// all elements of stream as next stream item is available and limit + /// of concurrently processed streams isn't exceeded. + /// + /// Note that this function consumes the stream passed into it and + /// returns a wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..5); + /// let stream = stream.flat_map_unordered(1, |x| stream::iter(vec![x; x])); + /// let mut values = stream.collect::>().await; + /// values.sort(); + /// + /// assert_eq!(vec![1usize, 2, 2, 3, 3, 3, 4, 4, 4, 4], values); + /// # }); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn flat_map_unordered( + self, + limit: impl Into>, + f: F, + ) -> FlatMapUnordered + where + U: Stream + Unpin, + F: FnMut(Self::Item) -> U, + Self: Sized, + { + assert_stream::(FlatMapUnordered::new(self, limit.into(), f)) + } + + /// Combinator similar to [`StreamExt::fold`] that holds internal state + /// and produces a new stream. + /// + /// Accepts initial state and closure which will be applied to each element + /// of the stream until provided closure returns `None`. Once `None` is + /// returned, stream will be terminated. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// + /// let stream = stream.scan(0, |state, x| { + /// *state += x; + /// future::ready(if *state < 10 { Some(x) } else { None }) + /// }); + /// + /// assert_eq!(vec![1, 2, 3], stream.collect::>().await); + /// # }); + /// ``` + fn scan(self, initial_state: S, f: F) -> Scan + where + F: FnMut(&mut S, Self::Item) -> Fut, + Fut: Future>, + Self: Sized, + { + assert_stream::(Scan::new(self, initial_state, f)) + } + + /// Skip elements on this stream while the provided asynchronous predicate + /// resolves to `true`. + /// + /// This function, like `Iterator::skip_while`, will skip elements on the + /// stream until the predicate `f` resolves to `false`. Once one element + /// returns `false`, all future elements will be returned from the underlying + /// stream. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// + /// let stream = stream.skip_while(|x| future::ready(*x <= 5)); + /// + /// assert_eq!(vec![6, 7, 8, 9, 10], stream.collect::>().await); + /// # }); + /// ``` + fn skip_while(self, f: F) -> SkipWhile + where + F: FnMut(&Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_stream::(SkipWhile::new(self, f)) + } + + /// Take elements from this stream while the provided asynchronous predicate + /// resolves to `true`. + /// + /// This function, like `Iterator::take_while`, will take elements from the + /// stream until the predicate `f` resolves to `false`. Once one element + /// returns `false`, it will always return that the stream is done. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10); + /// + /// let stream = stream.take_while(|x| future::ready(*x <= 5)); + /// + /// assert_eq!(vec![1, 2, 3, 4, 5], stream.collect::>().await); + /// # }); + /// ``` + fn take_while(self, f: F) -> TakeWhile + where + F: FnMut(&Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_stream::(TakeWhile::new(self, f)) + } + + /// Take elements from this stream until the provided future resolves. + /// + /// This function will take elements from the stream until the provided + /// stopping future `fut` resolves. Once the `fut` future becomes ready, + /// this stream combinator will always return that the stream is done. + /// + /// The stopping future may return any type. Once the stream is stopped + /// the result of the stopping future may be accessed with `TakeUntil::take_result()`. + /// The stream may also be resumed with `TakeUntil::take_future()`. + /// See the documentation of [`TakeUntil`] for more information. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// use futures::task::Poll; + /// + /// let stream = stream::iter(1..=10); + /// + /// let mut i = 0; + /// let stop_fut = future::poll_fn(|_cx| { + /// i += 1; + /// if i <= 5 { + /// Poll::Pending + /// } else { + /// Poll::Ready(()) + /// } + /// }); + /// + /// let stream = stream.take_until(stop_fut); + /// + /// assert_eq!(vec![1, 2, 3, 4, 5], stream.collect::>().await); + /// # }); + /// ``` + fn take_until(self, fut: Fut) -> TakeUntil + where + Fut: Future, + Self: Sized, + { + assert_stream::(TakeUntil::new(self, fut)) + } + + /// Runs this stream to completion, executing the provided asynchronous + /// closure for each element on the stream. + /// + /// The closure provided will be called for each item this stream produces, + /// yielding a future. That future will then be executed to completion + /// before moving on to the next item. + /// + /// The returned value is a `Future` where the `Output` type is `()`; it is + /// executed entirely for its side effects. + /// + /// To process each item in the stream and produce another stream instead + /// of a single future, use `then` instead. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// + /// let mut x = 0; + /// + /// { + /// let fut = stream::repeat(1).take(3).for_each(|item| { + /// x += item; + /// future::ready(()) + /// }); + /// fut.await; + /// } + /// + /// assert_eq!(x, 3); + /// # }); + /// ``` + fn for_each(self, f: F) -> ForEach + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::<(), _>(ForEach::new(self, f)) + } + + /// Runs this stream to completion, executing the provided asynchronous + /// closure for each element on the stream concurrently as elements become + /// available. + /// + /// This is similar to [`StreamExt::for_each`], but the futures + /// produced by the closure are run concurrently (but not in parallel-- + /// this combinator does not introduce any threads). + /// + /// The closure provided will be called for each item this stream produces, + /// yielding a future. That future will then be executed to completion + /// concurrently with the other futures produced by the closure. + /// + /// The first argument is an optional limit on the number of concurrent + /// futures. If this limit is not `None`, no more than `limit` futures + /// will be run concurrently. The `limit` argument is of type + /// `Into>`, and so can be provided as either `None`, + /// `Some(10)`, or just `10`. Note: a limit of zero is interpreted as + /// no limit at all, and will have the same result as passing in `None`. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::oneshot; + /// use futures::stream::{self, StreamExt}; + /// + /// let (tx1, rx1) = oneshot::channel(); + /// let (tx2, rx2) = oneshot::channel(); + /// let (tx3, rx3) = oneshot::channel(); + /// + /// let fut = stream::iter(vec![rx1, rx2, rx3]).for_each_concurrent( + /// /* limit */ 2, + /// |rx| async move { + /// rx.await.unwrap(); + /// } + /// ); + /// tx1.send(()).unwrap(); + /// tx2.send(()).unwrap(); + /// tx3.send(()).unwrap(); + /// fut.await; + /// # }) + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn for_each_concurrent( + self, + limit: impl Into>, + f: F, + ) -> ForEachConcurrent + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::<(), _>(ForEachConcurrent::new(self, limit.into(), f)) + } + + /// Creates a new stream of at most `n` items of the underlying stream. + /// + /// Once `n` items have been yielded from this stream then it will always + /// return that the stream is done. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10).take(3); + /// + /// assert_eq!(vec![1, 2, 3], stream.collect::>().await); + /// # }); + /// ``` + fn take(self, n: usize) -> Take + where + Self: Sized, + { + assert_stream::(Take::new(self, n)) + } + + /// Creates a new stream which skips `n` items of the underlying stream. + /// + /// Once `n` items have been skipped from this stream then it will always + /// return the remaining items on this stream. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(1..=10).skip(5); + /// + /// assert_eq!(vec![6, 7, 8, 9, 10], stream.collect::>().await); + /// # }); + /// ``` + fn skip(self, n: usize) -> Skip + where + Self: Sized, + { + assert_stream::(Skip::new(self, n)) + } + + /// Fuse a stream such that [`poll_next`](Stream::poll_next) will never + /// again be called once it has finished. This method can be used to turn + /// any `Stream` into a `FusedStream`. + /// + /// Normally, once a stream has returned [`None`] from + /// [`poll_next`](Stream::poll_next) any further calls could exhibit bad + /// behavior such as block forever, panic, never return, etc. If it is known + /// that [`poll_next`](Stream::poll_next) may be called after stream + /// has already finished, then this method can be used to ensure that it has + /// defined semantics. + /// + /// The [`poll_next`](Stream::poll_next) method of a `fuse`d stream + /// is guaranteed to return [`None`] after the underlying stream has + /// finished. + /// + /// # Examples + /// + /// ``` + /// use futures::executor::block_on_stream; + /// use futures::stream::{self, StreamExt}; + /// use futures::task::Poll; + /// + /// let mut x = 0; + /// let stream = stream::poll_fn(|_| { + /// x += 1; + /// match x { + /// 0..=2 => Poll::Ready(Some(x)), + /// 3 => Poll::Ready(None), + /// _ => panic!("should not happen") + /// } + /// }).fuse(); + /// + /// let mut iter = block_on_stream(stream); + /// assert_eq!(Some(1), iter.next()); + /// assert_eq!(Some(2), iter.next()); + /// assert_eq!(None, iter.next()); + /// assert_eq!(None, iter.next()); + /// // ... + /// ``` + fn fuse(self) -> Fuse + where + Self: Sized, + { + assert_stream::(Fuse::new(self)) + } + + /// Borrows a stream, rather than consuming it. + /// + /// This is useful to allow applying stream adaptors while still retaining + /// ownership of the original stream. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let mut stream = stream::iter(1..5); + /// + /// let sum = stream.by_ref() + /// .take(2) + /// .fold(0, |a, b| async move { a + b }) + /// .await; + /// assert_eq!(sum, 3); + /// + /// // You can use the stream again + /// let sum = stream.take(2) + /// .fold(0, |a, b| async move { a + b }) + /// .await; + /// assert_eq!(sum, 7); + /// # }); + /// ``` + fn by_ref(&mut self) -> &mut Self { + self + } + + /// Catches unwinding panics while polling the stream. + /// + /// Caught panic (if any) will be the last element of the resulting stream. + /// + /// In general, panics within a stream can propagate all the way out to the + /// task level. This combinator makes it possible to halt unwinding within + /// the stream itself. It's most commonly used within task executors. This + /// method should not be used for error handling. + /// + /// Note that this method requires the `UnwindSafe` bound from the standard + /// library. This isn't always applied automatically, and the standard + /// library provides an `AssertUnwindSafe` wrapper type to apply it + /// after-the fact. To assist using this method, the [`Stream`] trait is + /// also implemented for `AssertUnwindSafe` where `St` implements + /// [`Stream`]. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream = stream::iter(vec![Some(10), None, Some(11)]); + /// // Panic on second element + /// let stream_panicking = stream.map(|o| o.unwrap()); + /// // Collect all the results + /// let stream = stream_panicking.catch_unwind(); + /// + /// let results: Vec> = stream.collect().await; + /// match results[0] { + /// Ok(10) => {} + /// _ => panic!("unexpected result!"), + /// } + /// assert!(results[1].is_err()); + /// assert_eq!(results.len(), 2); + /// # }); + /// ``` + #[cfg(feature = "std")] + fn catch_unwind(self) -> CatchUnwind + where + Self: Sized + std::panic::UnwindSafe, + { + assert_stream(CatchUnwind::new(self)) + } + + /// Wrap the stream in a Box, pinning it. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed<'a>(self) -> BoxStream<'a, Self::Item> + where + Self: Sized + Send + 'a, + { + assert_stream::(Box::pin(self)) + } + + /// Wrap the stream in a Box, pinning it. + /// + /// Similar to `boxed`, but without the `Send` requirement. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed_local<'a>(self) -> LocalBoxStream<'a, Self::Item> + where + Self: Sized + 'a, + { + assert_stream::(Box::pin(self)) + } + + /// An adaptor for creating a buffered list of pending futures. + /// + /// If this stream's item can be converted into a future, then this adaptor + /// will buffer up to at most `n` futures and then return the outputs in the + /// same order as the underlying stream. No more than `n` futures will be + /// buffered at any point in time, and less than `n` may also be buffered + /// depending on the state of each future. + /// + /// The returned stream will be a stream of each future's output. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn buffered(self, n: usize) -> Buffered + where + Self::Item: Future, + Self: Sized, + { + assert_stream::<::Output, _>(Buffered::new(self, n)) + } + + /// An adaptor for creating a buffered list of pending futures (unordered). + /// + /// If this stream's item can be converted into a future, then this adaptor + /// will buffer up to `n` futures and then return the outputs in the order + /// in which they complete. No more than `n` futures will be buffered at + /// any point in time, and less than `n` may also be buffered depending on + /// the state of each future. + /// + /// The returned stream will be a stream of each future's output. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::oneshot; + /// use futures::stream::{self, StreamExt}; + /// + /// let (send_one, recv_one) = oneshot::channel(); + /// let (send_two, recv_two) = oneshot::channel(); + /// + /// let stream_of_futures = stream::iter(vec![recv_one, recv_two]); + /// let mut buffered = stream_of_futures.buffer_unordered(10); + /// + /// send_two.send(2i32)?; + /// assert_eq!(buffered.next().await, Some(Ok(2i32))); + /// + /// send_one.send(1i32)?; + /// assert_eq!(buffered.next().await, Some(Ok(1i32))); + /// + /// assert_eq!(buffered.next().await, None); + /// # Ok::<(), i32>(()) }).unwrap(); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn buffer_unordered(self, n: usize) -> BufferUnordered + where + Self::Item: Future, + Self: Sized, + { + assert_stream::<::Output, _>(BufferUnordered::new(self, n)) + } + + /// An adapter for zipping two streams together. + /// + /// The zipped stream waits for both streams to produce an item, and then + /// returns that pair. If either stream ends then the zipped stream will + /// also end. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream1 = stream::iter(1..=3); + /// let stream2 = stream::iter(5..=10); + /// + /// let vec = stream1.zip(stream2) + /// .collect::>() + /// .await; + /// assert_eq!(vec![(1, 5), (2, 6), (3, 7)], vec); + /// # }); + /// ``` + /// + fn zip(self, other: St) -> Zip + where + St: Stream, + Self: Sized, + { + assert_stream::<(Self::Item, St::Item), _>(Zip::new(self, other)) + } + + /// Adapter for chaining two streams. + /// + /// The resulting stream emits elements from the first stream, and when + /// first stream reaches the end, emits the elements from the second stream. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// + /// let stream1 = stream::iter(vec![Ok(10), Err(false)]); + /// let stream2 = stream::iter(vec![Err(true), Ok(20)]); + /// + /// let stream = stream1.chain(stream2); + /// + /// let result: Vec<_> = stream.collect().await; + /// assert_eq!(result, vec![ + /// Ok(10), + /// Err(false), + /// Err(true), + /// Ok(20), + /// ]); + /// # }); + /// ``` + fn chain(self, other: St) -> Chain + where + St: Stream, + Self: Sized, + { + assert_stream::(Chain::new(self, other)) + } + + /// Creates a new stream which exposes a `peek` method. + /// + /// Calling `peek` returns a reference to the next item in the stream. + fn peekable(self) -> Peekable + where + Self: Sized, + { + assert_stream::(Peekable::new(self)) + } + + /// An adaptor for chunking up items of the stream inside a vector. + /// + /// This combinator will attempt to pull items from this stream and buffer + /// them into a local vector. At most `capacity` items will get buffered + /// before they're yielded from the returned stream. + /// + /// Note that the vectors returned from this iterator may not always have + /// `capacity` elements. If the underlying stream ended and only a partial + /// vector was created, it'll be returned. Additionally if an error happens + /// from the underlying stream then the currently buffered items will be + /// yielded. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Panics + /// + /// This method will panic if `capacity` is zero. + #[cfg(feature = "alloc")] + fn chunks(self, capacity: usize) -> Chunks + where + Self: Sized, + { + assert_stream::, _>(Chunks::new(self, capacity)) + } + + /// An adaptor for chunking up ready items of the stream inside a vector. + /// + /// This combinator will attempt to pull ready items from this stream and + /// buffer them into a local vector. At most `capacity` items will get + /// buffered before they're yielded from the returned stream. If underlying + /// stream returns `Poll::Pending`, and collected chunk is not empty, it will + /// be immediately returned. + /// + /// If the underlying stream ended and only a partial vector was created, + /// it will be returned. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Panics + /// + /// This method will panic if `capacity` is zero. + #[cfg(feature = "alloc")] + fn ready_chunks(self, capacity: usize) -> ReadyChunks + where + Self: Sized, + { + assert_stream::, _>(ReadyChunks::new(self, capacity)) + } + + /// A future that completes after the given stream has been fully processed + /// into the sink and the sink has been flushed and closed. + /// + /// This future will drive the stream to keep producing items until it is + /// exhausted, sending each item to the sink. It will complete once the + /// stream is exhausted, the sink has received and flushed all items, and + /// the sink is closed. Note that neither the original stream nor provided + /// sink will be output by this future. Pass the sink by `Pin<&mut S>` + /// (for example, via `forward(&mut sink)` inside an `async` fn/block) in + /// order to preserve access to the `Sink`. If the stream produces an error, + /// that error will be returned by this future without flushing/closing the sink. + #[cfg(feature = "sink")] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + fn forward(self, sink: S) -> Forward + where + S: Sink, + Self: TryStream + Sized, + // Self: TryStream + Sized + Stream::Ok, ::Error>>, + { + // TODO: type mismatch resolving `::Item == std::result::Result<::Ok, ::Error>` + // assert_future::, _>(Forward::new(self, sink)) + Forward::new(self, sink) + } + + /// Splits this `Stream + Sink` object into separate `Sink` and `Stream` + /// objects. + /// + /// This can be useful when you want to split ownership between tasks, or + /// allow direct interaction between the two objects (e.g. via + /// `Sink::send_all`). + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "sink")] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn split(self) -> (SplitSink, SplitStream) + where + Self: Sink + Sized, + { + let (sink, stream) = split::split(self); + ( + crate::sink::assert_sink::(sink), + assert_stream::(stream), + ) + } + + /// Do something with each item of this stream, afterwards passing it on. + /// + /// This is similar to the `Iterator::inspect` method in the standard + /// library where it allows easily inspecting each value as it passes + /// through the stream, for example to debug what's going on. + fn inspect(self, f: F) -> Inspect + where + F: FnMut(&Self::Item), + Self: Sized, + { + assert_stream::(Inspect::new(self, f)) + } + + /// Wrap this stream in an `Either` stream, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_stream` method to write `if` + /// statements that evaluate to different streams in different branches. + fn left_stream(self) -> Either + where + B: Stream, + Self: Sized, + { + assert_stream::(Either::Left(self)) + } + + /// Wrap this stream in an `Either` stream, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_stream` method to write `if` + /// statements that evaluate to different streams in different branches. + fn right_stream(self) -> Either + where + B: Stream, + Self: Sized, + { + assert_stream::(Either::Right(self)) + } + + /// A convenience method for calling [`Stream::poll_next`] on [`Unpin`] + /// stream types. + fn poll_next_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).poll_next(cx) + } + + /// Returns a [`Future`] that resolves when the next item in this stream is + /// ready. + /// + /// This is similar to the [`next`][StreamExt::next] method, but it won't + /// resolve to [`None`] if used on an empty [`Stream`]. Instead, the + /// returned future type will return `true` from + /// [`FusedFuture::is_terminated`][] when the [`Stream`] is empty, allowing + /// [`select_next_some`][StreamExt::select_next_some] to be easily used with + /// the [`select!`] macro. + /// + /// If the future is polled after this [`Stream`] is empty it will panic. + /// Using the future with a [`FusedFuture`][]-aware primitive like the + /// [`select!`] macro will prevent this. + /// + /// [`FusedFuture`]: futures_core::future::FusedFuture + /// [`FusedFuture::is_terminated`]: futures_core::future::FusedFuture::is_terminated + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::{future, select}; + /// use futures::stream::{StreamExt, FuturesUnordered}; + /// + /// let mut fut = future::ready(1); + /// let mut async_tasks = FuturesUnordered::new(); + /// let mut total = 0; + /// loop { + /// select! { + /// num = fut => { + /// // First, the `ready` future completes. + /// total += num; + /// // Then we spawn a new task onto `async_tasks`, + /// async_tasks.push(async { 5 }); + /// }, + /// // On the next iteration of the loop, the task we spawned + /// // completes. + /// num = async_tasks.select_next_some() => { + /// total += num; + /// } + /// // Finally, both the `ready` future and `async_tasks` have + /// // finished, so we enter the `complete` branch. + /// complete => break, + /// } + /// } + /// assert_eq!(total, 6); + /// # }); + /// ``` + /// + /// [`select!`]: crate::select + fn select_next_some(&mut self) -> SelectNextSome<'_, Self> + where + Self: Unpin + FusedStream, + { + assert_future::(SelectNextSome::new(self)) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/next.rs b/anneal/v2/vendor/futures-util/src/stream/stream/next.rs new file mode 100644 index 0000000000..8d8347aa03 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/next.rs @@ -0,0 +1,34 @@ +use crate::stream::StreamExt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`next`](super::StreamExt::next) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Next<'a, St: ?Sized> { + stream: &'a mut St, +} + +impl Unpin for Next<'_, St> {} + +impl<'a, St: ?Sized + Stream + Unpin> Next<'a, St> { + pub(super) fn new(stream: &'a mut St) -> Self { + Self { stream } + } +} + +impl FusedFuture for Next<'_, St> { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for Next<'_, St> { + type Output = Option; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.stream.poll_next_unpin(cx) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/peek.rs b/anneal/v2/vendor/futures-util/src/stream/stream/peek.rs new file mode 100644 index 0000000000..d696acb5f5 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/peek.rs @@ -0,0 +1,441 @@ +use crate::fns::FnOnce1; +use crate::stream::{Fuse, StreamExt}; +use core::fmt; +use core::marker::PhantomData; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// A `Stream` that implements a `peek` method. + /// + /// The `peek` method can be used to retrieve a reference + /// to the next `Stream::Item` if available. A subsequent + /// call to `poll` will return the owned item. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Peekable { + #[pin] + stream: Fuse, + peeked: Option, + } +} + +impl Peekable { + pub(super) fn new(stream: St) -> Self { + Self { stream: stream.fuse(), peeked: None } + } + + delegate_access_inner!(stream, St, (.)); + + /// Produces a future which retrieves a reference to the next item + /// in the stream, or `None` if the underlying stream terminates. + pub fn peek(self: Pin<&mut Self>) -> Peek<'_, St> { + Peek { inner: Some(self) } + } + + /// Peek retrieves a reference to the next item in the stream. + /// + /// This method polls the underlying stream and return either a reference + /// to the next item if the stream is ready or passes through any errors. + pub fn poll_peek(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if this.peeked.is_some() { + break this.peeked.as_ref(); + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + *this.peeked = Some(item); + } else { + break None; + } + }) + } + + /// Produces a future which retrieves a mutable reference to the next item + /// in the stream, or `None` if the underlying stream terminates. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::stream; + /// use futures::stream::StreamExt; + /// + /// let stream = stream::iter(vec![1, 2, 3]).peekable(); + /// let mut stream = pin!(stream); + /// + /// assert_eq!(stream.as_mut().peek_mut().await, Some(&mut 1)); + /// assert_eq!(stream.as_mut().next().await, Some(1)); + /// + /// // Peek into the stream and modify the value which will be returned next + /// if let Some(p) = stream.as_mut().peek_mut().await { + /// if *p == 2 { + /// *p = 5; + /// } + /// } + /// + /// assert_eq!(stream.collect::>().await, vec![5, 3]); + /// # }); + /// ``` + pub fn peek_mut(self: Pin<&mut Self>) -> PeekMut<'_, St> { + PeekMut { inner: Some(self) } + } + + /// Peek retrieves a mutable reference to the next item in the stream. + pub fn poll_peek_mut( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if this.peeked.is_some() { + break this.peeked.as_mut(); + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + *this.peeked = Some(item); + } else { + break None; + } + }) + } + + /// Creates a future which will consume and return the next value of this + /// stream if a condition is true. + /// + /// If `func` returns `true` for the next value of this stream, consume and + /// return it. Otherwise, return `None`. + /// + /// # Examples + /// + /// Consume a number if it's equal to 0. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::stream; + /// use futures::stream::StreamExt; + /// + /// let stream = stream::iter(0..5).peekable(); + /// let mut stream = pin!(stream); + /// // The first item of the stream is 0; consume it. + /// assert_eq!(stream.as_mut().next_if(|&x| x == 0).await, Some(0)); + /// // The next item returned is now 1, so `consume` will return `false`. + /// assert_eq!(stream.as_mut().next_if(|&x| x == 0).await, None); + /// // `next_if` saves the value of the next item if it was not equal to `expected`. + /// assert_eq!(stream.next().await, Some(1)); + /// # }); + /// ``` + /// + /// Consume any number less than 10. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::stream; + /// use futures::stream::StreamExt; + /// + /// let stream = stream::iter(1..20).peekable(); + /// let mut stream = pin!(stream); + /// // Consume all numbers less than 10 + /// while stream.as_mut().next_if(|&x| x < 10).await.is_some() {} + /// // The next value returned will be 10 + /// assert_eq!(stream.next().await, Some(10)); + /// # }); + /// ``` + pub fn next_if(self: Pin<&mut Self>, func: F) -> NextIf<'_, St, F> + where + F: FnOnce(&St::Item) -> bool, + { + NextIf { inner: Some((self, func)) } + } + + /// Creates a future which will consume and return the next item if it is + /// equal to `expected`. + /// + /// # Example + /// + /// Consume a number if it's equal to 0. + /// + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::stream; + /// use futures::stream::StreamExt; + /// + /// let stream = stream::iter(0..5).peekable(); + /// let mut stream = pin!(stream); + /// // The first item of the stream is 0; consume it. + /// assert_eq!(stream.as_mut().next_if_eq(&0).await, Some(0)); + /// // The next item returned is now 1, so `consume` will return `false`. + /// assert_eq!(stream.as_mut().next_if_eq(&0).await, None); + /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`. + /// assert_eq!(stream.next().await, Some(1)); + /// # }); + /// ``` + pub fn next_if_eq<'a, T>(self: Pin<&'a mut Self>, expected: &'a T) -> NextIfEq<'a, St, T> + where + T: ?Sized, + St::Item: PartialEq, + { + NextIfEq { + inner: NextIf { inner: Some((self, NextIfEqFn { expected, _next: PhantomData })) }, + } + } +} + +impl FusedStream for Peekable { + fn is_terminated(&self) -> bool { + self.peeked.is_none() && self.stream.is_terminated() + } +} + +impl Stream for Peekable { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + if let Some(item) = this.peeked.take() { + return Poll::Ready(Some(item)); + } + this.stream.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + let peek_len = usize::from(self.peeked.is_some()); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(peek_len); + let upper = match upper { + Some(x) => x.checked_add(peek_len), + None => None, + }; + (lower, upper) + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Peekable +where + S: Sink + Stream, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} + +pin_project! { + /// Future for the [`Peekable::peek`](self::Peekable::peek) method. + #[must_use = "futures do nothing unless polled"] + pub struct Peek<'a, St: Stream> { + inner: Option>>, + } +} + +impl fmt::Debug for Peek<'_, St> +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Peek").field("inner", &self.inner).finish() + } +} + +impl FusedFuture for Peek<'_, St> { + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl<'a, St> Future for Peek<'a, St> +where + St: Stream, +{ + type Output = Option<&'a St::Item>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let inner = self.project().inner; + if let Some(peekable) = inner { + ready!(peekable.as_mut().poll_peek(cx)); + + inner.take().unwrap().poll_peek(cx) + } else { + panic!("Peek polled after completion") + } + } +} + +pin_project! { + /// Future for the [`Peekable::peek_mut`](self::Peekable::peek_mut) method. + #[must_use = "futures do nothing unless polled"] + pub struct PeekMut<'a, St: Stream> { + inner: Option>>, + } +} + +impl fmt::Debug for PeekMut<'_, St> +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PeekMut").field("inner", &self.inner).finish() + } +} + +impl FusedFuture for PeekMut<'_, St> { + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl<'a, St> Future for PeekMut<'a, St> +where + St: Stream, +{ + type Output = Option<&'a mut St::Item>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let inner = self.project().inner; + if let Some(peekable) = inner { + ready!(peekable.as_mut().poll_peek_mut(cx)); + + inner.take().unwrap().poll_peek_mut(cx) + } else { + panic!("PeekMut polled after completion") + } + } +} + +pin_project! { + /// Future for the [`Peekable::next_if`](self::Peekable::next_if) method. + #[must_use = "futures do nothing unless polled"] + pub struct NextIf<'a, St: Stream, F> { + inner: Option<(Pin<&'a mut Peekable>, F)>, + } +} + +impl fmt::Debug for NextIf<'_, St, F> +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("NextIf").field("inner", &self.inner.as_ref().map(|(s, _f)| s)).finish() + } +} + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl FusedFuture for NextIf<'_, St, F> +where + St: Stream, + F: for<'a> FnOnce1<&'a St::Item, Output = bool>, +{ + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 +impl Future for NextIf<'_, St, F> +where + St: Stream, + F: for<'a> FnOnce1<&'a St::Item, Output = bool>, +{ + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let inner = self.project().inner; + if let Some((peekable, _)) = inner { + let res = ready!(peekable.as_mut().poll_next(cx)); + + let (peekable, func) = inner.take().unwrap(); + match res { + Some(ref matched) if func.call_once(matched) => Poll::Ready(res), + other => { + let peekable = peekable.project(); + // Since we called `self.next()`, we consumed `self.peeked`. + assert!(peekable.peeked.is_none()); + *peekable.peeked = other; + Poll::Ready(None) + } + } + } else { + panic!("NextIf polled after completion") + } + } +} + +pin_project! { + /// Future for the [`Peekable::next_if_eq`](self::Peekable::next_if_eq) method. + #[must_use = "futures do nothing unless polled"] + pub struct NextIfEq<'a, St: Stream, T: ?Sized> { + #[pin] + inner: NextIf<'a, St, NextIfEqFn<'a, T, St::Item>>, + } +} + +impl fmt::Debug for NextIfEq<'_, St, T> +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + T: ?Sized, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("NextIfEq") + .field("inner", &self.inner.inner.as_ref().map(|(s, _f)| s)) + .finish() + } +} + +impl FusedFuture for NextIfEq<'_, St, T> +where + St: Stream, + T: ?Sized, + St::Item: PartialEq, +{ + fn is_terminated(&self) -> bool { + self.inner.is_terminated() + } +} + +impl Future for NextIfEq<'_, St, T> +where + St: Stream, + T: ?Sized, + St::Item: PartialEq, +{ + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.project().inner.poll(cx) + } +} + +struct NextIfEqFn<'a, T: ?Sized, Item> { + expected: &'a T, + _next: PhantomData, +} + +impl FnOnce1<&Item> for NextIfEqFn<'_, T, Item> +where + T: ?Sized, + Item: PartialEq, +{ + type Output = bool; + + fn call_once(self, next: &Item) -> Self::Output { + next == self.expected + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/ready_chunks.rs b/anneal/v2/vendor/futures-util/src/stream/stream/ready_chunks.rs new file mode 100644 index 0000000000..192054c4ae --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/ready_chunks.rs @@ -0,0 +1,93 @@ +use crate::stream::{Fuse, StreamExt}; +use alloc::vec::Vec; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`ready_chunks`](super::StreamExt::ready_chunks) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct ReadyChunks { + #[pin] + stream: Fuse, + cap: usize, // https://github.com/rust-lang/futures-rs/issues/1475 + } +} + +impl ReadyChunks { + pub(super) fn new(stream: St, capacity: usize) -> Self { + assert!(capacity > 0); + + Self { stream: stream.fuse(), cap: capacity } + } + + delegate_access_inner!(stream, St, (.)); +} + +impl Stream for ReadyChunks { + type Item = Vec; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + let mut items: Vec = Vec::new(); + + loop { + match this.stream.as_mut().poll_next(cx) { + // Flush all collected data if underlying stream doesn't contain + // more ready values + Poll::Pending => { + return if items.is_empty() { Poll::Pending } else { Poll::Ready(Some(items)) } + } + + // Push the ready item into the buffer and check whether it is full. + // If so, replace our buffer with a new and empty one and return + // the full one. + Poll::Ready(Some(item)) => { + if items.is_empty() { + items.reserve(*this.cap); + } + items.push(item); + if items.len() >= *this.cap { + return Poll::Ready(Some(items)); + } + } + + // Since the underlying stream ran out of values, return what we + // have buffered, if we have anything. + Poll::Ready(None) => { + let last = if items.is_empty() { None } else { Some(items) }; + + return Poll::Ready(last); + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.stream.size_hint(); + let lower = lower / self.cap; + (lower, upper) + } +} + +impl FusedStream for ReadyChunks { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for ReadyChunks +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/scan.rs b/anneal/v2/vendor/futures-util/src/stream/stream/scan.rs new file mode 100644 index 0000000000..f5cfde9c36 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/scan.rs @@ -0,0 +1,128 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +struct StateFn { + state: S, + f: F, +} + +pin_project! { + /// Stream for the [`scan`](super::StreamExt::scan) method. + #[must_use = "streams do nothing unless polled"] + pub struct Scan { + #[pin] + stream: St, + state_f: Option>, + #[pin] + future: Option, + } +} + +impl fmt::Debug for Scan +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + S: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Scan") + .field("stream", &self.stream) + .field("state", &self.state_f.as_ref().map(|s| &s.state)) + .field("future", &self.future) + .field("done_taking", &self.is_done_taking()) + .finish() + } +} + +impl Scan { + /// Checks if internal state is `None`. + fn is_done_taking(&self) -> bool { + self.state_f.is_none() + } +} + +impl Scan +where + St: Stream, + F: FnMut(&mut S, St::Item) -> Fut, + Fut: Future>, +{ + pub(super) fn new(stream: St, initial_state: S, f: F) -> Self { + Self { stream, state_f: Some(StateFn { state: initial_state, f }), future: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for Scan +where + St: Stream, + F: FnMut(&mut S, St::Item) -> Fut, + Fut: Future>, +{ + type Item = B; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.is_done_taking() { + return Poll::Ready(None); + } + + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + let item = ready!(fut.poll(cx)); + this.future.set(None); + + if item.is_none() { + *this.state_f = None; + } + + break item; + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + let state_f = this.state_f.as_mut().unwrap(); + this.future.set(Some((state_f.f)(&mut state_f.state, item))) + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + if self.is_done_taking() { + (0, Some(0)) + } else { + self.stream.size_hint() // can't know a lower bound, due to the predicate + } + } +} + +impl FusedStream for Scan +where + St: FusedStream, + F: FnMut(&mut S, St::Item) -> Fut, + Fut: Future>, +{ + fn is_terminated(&self) -> bool { + self.is_done_taking() || self.future.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Scan +where + St: Stream + Sink, +{ + type Error = St::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/select_next_some.rs b/anneal/v2/vendor/futures-util/src/stream/stream/select_next_some.rs new file mode 100644 index 0000000000..3115e14d9a --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/select_next_some.rs @@ -0,0 +1,42 @@ +use crate::stream::StreamExt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::FusedStream; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select_next_some`](super::StreamExt::select_next_some) +/// method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SelectNextSome<'a, St: ?Sized> { + stream: &'a mut St, +} + +impl<'a, St: ?Sized> SelectNextSome<'a, St> { + pub(super) fn new(stream: &'a mut St) -> Self { + Self { stream } + } +} + +impl FusedFuture for SelectNextSome<'_, St> { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for SelectNextSome<'_, St> { + type Output = St::Item; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + assert!(!self.stream.is_terminated(), "SelectNextSome polled after terminated"); + + if let Some(item) = ready!(self.stream.poll_next_unpin(cx)) { + Poll::Ready(item) + } else { + debug_assert!(self.stream.is_terminated()); + cx.waker().wake_by_ref(); + Poll::Pending + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/skip.rs b/anneal/v2/vendor/futures-util/src/stream/stream/skip.rs new file mode 100644 index 0000000000..f495779521 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/skip.rs @@ -0,0 +1,70 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`skip`](super::StreamExt::skip) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Skip { + #[pin] + stream: St, + remaining: usize, + } +} + +impl Skip { + pub(super) fn new(stream: St, n: usize) -> Self { + Self { stream, remaining: n } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Skip { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Stream for Skip { + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + while *this.remaining > 0 { + if ready!(this.stream.as_mut().poll_next(cx)).is_some() { + *this.remaining -= 1; + } else { + return Poll::Ready(None); + } + } + + this.stream.poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.stream.size_hint(); + + let lower = lower.saturating_sub(self.remaining); + let upper = upper.map(|x| x.saturating_sub(self.remaining)); + + (lower, upper) + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Skip +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/skip_while.rs b/anneal/v2/vendor/futures-util/src/stream/stream/skip_while.rs new file mode 100644 index 0000000000..dabd5eefae --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/skip_while.rs @@ -0,0 +1,124 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`skip_while`](super::StreamExt::skip_while) method. + #[must_use = "streams do nothing unless polled"] + pub struct SkipWhile where St: Stream { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + done_skipping: bool, + } +} + +impl fmt::Debug for SkipWhile +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SkipWhile") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .field("done_skipping", &self.done_skipping) + .finish() + } +} + +impl SkipWhile +where + St: Stream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None, done_skipping: false } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for SkipWhile +where + St: FusedStream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.pending_item.is_none() && self.stream.is_terminated() + } +} + +impl Stream for SkipWhile +where + St: Stream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if *this.done_skipping { + return this.stream.poll_next(cx); + } + + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let skipped = ready!(fut.poll(cx)); + let item = this.pending_item.take(); + this.pending_fut.set(None); + if !skipped { + *this.done_skipping = true; + break item; + } + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + this.pending_fut.set(Some((this.f)(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + if self.done_skipping { + self.stream.size_hint() + } else { + let pending_len = usize::from(self.pending_item.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for SkipWhile +where + S: Stream + Sink, + F: FnMut(&S::Item) -> Fut, + Fut: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/split.rs b/anneal/v2/vendor/futures-util/src/stream/stream/split.rs new file mode 100644 index 0000000000..e192f8a92d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/split.rs @@ -0,0 +1,224 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use futures_sink::Sink; + +use crate::lock::BiLock; + +/// A `Stream` part of the split pair +#[derive(Debug)] +#[must_use = "streams do nothing unless polled"] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub struct SplitStream(BiLock); + +impl Unpin for SplitStream {} + +impl SplitStream { + /// Returns `true` if the `SplitStream` and `SplitSink` originate from the same call to `StreamExt::split`. + pub fn is_pair_of(&self, other: &SplitSink) -> bool { + other.is_pair_of(&self) + } +} + +impl SplitStream { + /// Attempts to put the two "halves" of a split `Stream + Sink` back + /// together. Succeeds only if the `SplitStream` and `SplitSink` are + /// a matching pair originating from the same call to `StreamExt::split`. + pub fn reunite(self, other: SplitSink) -> Result> + where + S: Sink, + { + other.reunite(self) + } +} + +impl Stream for SplitStream { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.0.poll_lock(cx)).as_pin_mut().poll_next(cx) + } +} + +#[allow(non_snake_case)] +fn SplitSink, Item>(lock: BiLock) -> SplitSink { + SplitSink { lock, slot: None } +} + +/// A `Sink` part of the split pair +#[derive(Debug)] +#[must_use = "sinks do nothing unless polled"] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub struct SplitSink { + lock: BiLock, + slot: Option, +} + +impl Unpin for SplitSink {} + +impl + Unpin, Item> SplitSink { + /// Attempts to put the two "halves" of a split `Stream + Sink` back + /// together. Succeeds only if the `SplitStream` and `SplitSink` are + /// a matching pair originating from the same call to `StreamExt::split`. + pub fn reunite(self, other: SplitStream) -> Result> { + self.lock.reunite(other.0).map_err(|err| ReuniteError(SplitSink(err.0), SplitStream(err.1))) + } +} + +impl SplitSink { + /// Returns `true` if the `SplitStream` and `SplitSink` originate from the same call to `StreamExt::split`. + pub fn is_pair_of(&self, other: &SplitStream) -> bool { + self.lock.is_pair_of(&other.0) + } +} + +impl, Item> SplitSink { + fn poll_flush_slot( + mut inner: Pin<&mut S>, + slot: &mut Option, + cx: &mut Context<'_>, + ) -> Poll> { + if slot.is_some() { + ready!(inner.as_mut().poll_ready(cx))?; + Poll::Ready(inner.start_send(slot.take().unwrap())) + } else { + Poll::Ready(Ok(())) + } + } + + fn poll_lock_and_flush_slot( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let this = &mut *self; + let mut inner = ready!(this.lock.poll_lock(cx)); + Self::poll_flush_slot(inner.as_pin_mut(), &mut this.slot, cx) + } +} + +impl, Item> Sink for SplitSink { + type Error = S::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + loop { + if self.slot.is_none() { + return Poll::Ready(Ok(())); + } + ready!(self.as_mut().poll_lock_and_flush_slot(cx))?; + } + } + + fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), S::Error> { + self.slot = Some(item); + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = &mut *self; + let mut inner = ready!(this.lock.poll_lock(cx)); + ready!(Self::poll_flush_slot(inner.as_pin_mut(), &mut this.slot, cx))?; + inner.as_pin_mut().poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = &mut *self; + let mut inner = ready!(this.lock.poll_lock(cx)); + ready!(Self::poll_flush_slot(inner.as_pin_mut(), &mut this.slot, cx))?; + inner.as_pin_mut().poll_close(cx) + } +} + +pub(super) fn split, Item>(s: S) -> (SplitSink, SplitStream) { + let (a, b) = BiLock::new(s); + let read = SplitStream(a); + let write = SplitSink(b); + (write, read) +} + +/// Error indicating a `SplitSink` and `SplitStream` were not two halves +/// of a `Stream + Split`, and thus could not be `reunite`d. +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub struct ReuniteError(pub SplitSink, pub SplitStream); + +impl fmt::Debug for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ReuniteError").field(&"...").finish() + } +} + +impl fmt::Display for ReuniteError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "tried to reunite a SplitStream and SplitSink that don't form a pair") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ReuniteError {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::stream::StreamExt; + use core::marker::PhantomData; + + struct NopStream { + phantom: PhantomData, + } + + impl Stream for NopStream { + type Item = Item; + + fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + todo!() + } + } + + impl Sink for NopStream { + type Error = (); + + fn poll_ready( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + todo!() + } + + fn start_send(self: Pin<&mut Self>, _item: Item) -> Result<(), Self::Error> { + todo!() + } + + fn poll_flush( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + todo!() + } + + fn poll_close( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + todo!() + } + } + + #[test] + fn test_pairing() { + let s1 = NopStream::<()> { phantom: PhantomData }; + let (sink1, stream1) = s1.split(); + assert!(sink1.is_pair_of(&stream1)); + assert!(stream1.is_pair_of(&sink1)); + + let s2 = NopStream::<()> { phantom: PhantomData }; + let (sink2, stream2) = s2.split(); + assert!(sink2.is_pair_of(&stream2)); + assert!(stream2.is_pair_of(&sink2)); + + assert!(!sink1.is_pair_of(&stream2)); + assert!(!stream1.is_pair_of(&sink2)); + assert!(!sink2.is_pair_of(&stream1)); + assert!(!stream2.is_pair_of(&sink1)); + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/take.rs b/anneal/v2/vendor/futures-util/src/stream/stream/take.rs new file mode 100644 index 0000000000..29d6c39ee3 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/take.rs @@ -0,0 +1,86 @@ +use core::cmp; +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`take`](super::StreamExt::take) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Take { + #[pin] + stream: St, + remaining: usize, + } +} + +impl Take { + pub(super) fn new(stream: St, n: usize) -> Self { + Self { stream, remaining: n } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for Take +where + St: Stream, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.remaining == 0 { + Poll::Ready(None) + } else { + let this = self.project(); + let next = ready!(this.stream.poll_next(cx)); + if next.is_some() { + *this.remaining -= 1; + } else { + *this.remaining = 0; + } + Poll::Ready(next) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.remaining == 0 { + return (0, Some(0)); + } + + let (lower, upper) = self.stream.size_hint(); + + let lower = cmp::min(lower, self.remaining); + + let upper = match upper { + Some(x) if x < self.remaining => Some(x), + _ => Some(self.remaining), + }; + + (lower, upper) + } +} + +impl FusedStream for Take +where + St: FusedStream, +{ + fn is_terminated(&self) -> bool { + self.remaining == 0 || self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Take +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/take_until.rs b/anneal/v2/vendor/futures-util/src/stream/stream/take_until.rs new file mode 100644 index 0000000000..d14f9ce100 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/take_until.rs @@ -0,0 +1,170 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +// FIXME: docs, tests + +pin_project! { + /// Stream for the [`take_until`](super::StreamExt::take_until) method. + #[must_use = "streams do nothing unless polled"] + pub struct TakeUntil { + #[pin] + stream: St, + // Contains the inner Future on start and None once the inner Future is resolved + // or taken out by the user. + #[pin] + fut: Option, + // Contains fut's return value once fut is resolved + fut_result: Option, + // Whether the future was taken out by the user. + free: bool, + } +} + +impl fmt::Debug for TakeUntil +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + Fut: Future + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TakeUntil").field("stream", &self.stream).field("fut", &self.fut).finish() + } +} + +impl TakeUntil +where + St: Stream, + Fut: Future, +{ + pub(super) fn new(stream: St, fut: Fut) -> Self { + Self { stream, fut: Some(fut), fut_result: None, free: false } + } + + delegate_access_inner!(stream, St, ()); + + /// Extract the stopping future out of the combinator. + /// The future is returned only if it isn't resolved yet, ie. if the stream isn't stopped yet. + /// Taking out the future means the combinator will be yielding + /// elements from the wrapped stream without ever stopping it. + pub fn take_future(&mut self) -> Option { + if self.fut.is_some() { + self.free = true; + } + + self.fut.take() + } + + /// Once the stopping future is resolved, this method can be used + /// to extract the value returned by the stopping future. + /// + /// This may be used to retrieve arbitrary data from the stopping + /// future, for example a reason why the stream was stopped. + /// + /// This method will return `None` if the future isn't resolved yet, + /// or if the result was already taken out. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt}; + /// use futures::task::Poll; + /// + /// let stream = stream::iter(1..=10); + /// + /// let mut i = 0; + /// let stop_fut = future::poll_fn(|_cx| { + /// i += 1; + /// if i <= 5 { + /// Poll::Pending + /// } else { + /// Poll::Ready("reason") + /// } + /// }); + /// + /// let mut stream = stream.take_until(stop_fut); + /// let _ = stream.by_ref().collect::>().await; + /// + /// let result = stream.take_result().unwrap(); + /// assert_eq!(result, "reason"); + /// # }); + /// ``` + pub fn take_result(&mut self) -> Option { + self.fut_result.take() + } + + /// Whether the stream was stopped yet by the stopping future + /// being resolved. + pub fn is_stopped(&self) -> bool { + !self.free && self.fut.is_none() + } +} + +impl Stream for TakeUntil +where + St: Stream, + Fut: Future, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if let Some(f) = this.fut.as_mut().as_pin_mut() { + if let Poll::Ready(result) = f.poll(cx) { + this.fut.set(None); + *this.fut_result = Some(result); + } + } + + if !*this.free && this.fut.is_none() { + // Future resolved, inner stream stopped + Poll::Ready(None) + } else { + // Future either not resolved yet or taken out by the user + let item = ready!(this.stream.poll_next(cx)); + if item.is_none() { + this.fut.set(None); + } + Poll::Ready(item) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.is_stopped() { + return (0, Some(0)); + } + + self.stream.size_hint() + } +} + +impl FusedStream for TakeUntil +where + St: Stream, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.is_stopped() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TakeUntil +where + S: Stream + Sink, + Fut: Future, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/take_while.rs b/anneal/v2/vendor/futures-util/src/stream/stream/take_while.rs new file mode 100644 index 0000000000..9256943010 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/take_while.rs @@ -0,0 +1,124 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`take_while`](super::StreamExt::take_while) method. + #[must_use = "streams do nothing unless polled"] + pub struct TakeWhile { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + done_taking: bool, + } +} + +impl fmt::Debug for TakeWhile +where + St: Stream + fmt::Debug, + St::Item: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TakeWhile") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .field("done_taking", &self.done_taking) + .finish() + } +} + +impl TakeWhile +where + St: Stream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None, done_taking: false } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for TakeWhile +where + St: Stream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + type Item = St::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.done_taking { + return Poll::Ready(None); + } + + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let take = ready!(fut.poll(cx)); + let item = this.pending_item.take(); + this.pending_fut.set(None); + if take { + break item; + } else { + *this.done_taking = true; + break None; + } + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + this.pending_fut.set(Some((this.f)(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + if self.done_taking { + return (0, Some(0)); + } + + let pending_len = usize::from(self.pending_item.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl FusedStream for TakeWhile +where + St: FusedStream, + F: FnMut(&St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.done_taking || self.pending_item.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TakeWhile +where + S: Stream + Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/then.rs b/anneal/v2/vendor/futures-util/src/stream/stream/then.rs new file mode 100644 index 0000000000..9192c0b0cf --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/then.rs @@ -0,0 +1,101 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`then`](super::StreamExt::then) method. + #[must_use = "streams do nothing unless polled"] + pub struct Then { + #[pin] + stream: St, + #[pin] + future: Option, + f: F, + } +} + +impl fmt::Debug for Then +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Then").field("stream", &self.stream).field("future", &self.future).finish() + } +} + +impl Then +where + St: Stream, + F: FnMut(St::Item) -> Fut, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, future: None, f } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for Then +where + St: FusedStream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.future.is_none() && self.stream.is_terminated() + } +} + +impl Stream for Then +where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, +{ + type Item = Fut::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + let item = ready!(fut.poll(cx)); + this.future.set(None); + break Some(item); + } else if let Some(item) = ready!(this.stream.as_mut().poll_next(cx)) { + this.future.set(Some((this.f)(item))); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let future_len = usize::from(self.future.is_some()); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(future_len); + let upper = match upper { + Some(x) => x.checked_add(future_len), + None => None, + }; + (lower, upper) + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for Then +where + S: Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/unzip.rs b/anneal/v2/vendor/futures-util/src/stream/stream/unzip.rs new file mode 100644 index 0000000000..a88cf03266 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/unzip.rs @@ -0,0 +1,63 @@ +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`unzip`](super::StreamExt::unzip) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Unzip { + #[pin] + stream: St, + left: FromA, + right: FromB, + } +} + +impl Unzip { + fn finish(self: Pin<&mut Self>) -> (FromA, FromB) { + let this = self.project(); + (mem::take(this.left), mem::take(this.right)) + } + + pub(super) fn new(stream: St) -> Self { + Self { stream, left: Default::default(), right: Default::default() } + } +} + +impl FusedFuture for Unzip +where + St: FusedStream, + FromA: Default + Extend, + FromB: Default + Extend, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for Unzip +where + St: Stream, + FromA: Default + Extend, + FromB: Default + Extend, +{ + type Output = (FromA, FromB); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<(FromA, FromB)> { + let mut this = self.as_mut().project(); + loop { + match ready!(this.stream.as_mut().poll_next(cx)) { + Some(e) => { + this.left.extend(Some(e.0)); + this.right.extend(Some(e.1)); + } + None => return Poll::Ready(self.finish()), + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/stream/zip.rs b/anneal/v2/vendor/futures-util/src/stream/stream/zip.rs new file mode 100644 index 0000000000..25a47e96be --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/stream/zip.rs @@ -0,0 +1,128 @@ +use crate::stream::{Fuse, StreamExt}; +use core::cmp; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`zip`](super::StreamExt::zip) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct Zip { + #[pin] + stream1: Fuse, + #[pin] + stream2: Fuse, + queued1: Option, + queued2: Option, + } +} + +impl Zip { + pub(super) fn new(stream1: St1, stream2: St2) -> Self { + Self { stream1: stream1.fuse(), stream2: stream2.fuse(), queued1: None, queued2: None } + } + + /// Acquires a reference to the underlying streams that this combinator is + /// pulling from. + pub fn get_ref(&self) -> (&St1, &St2) { + (self.stream1.get_ref(), self.stream2.get_ref()) + } + + /// Acquires a mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_mut(&mut self) -> (&mut St1, &mut St2) { + (self.stream1.get_mut(), self.stream2.get_mut()) + } + + /// Acquires a pinned mutable reference to the underlying streams that this + /// combinator is pulling from. + /// + /// Note that care must be taken to avoid tampering with the state of the + /// stream which may otherwise confuse this combinator. + pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut St1>, Pin<&mut St2>) { + let this = self.project(); + (this.stream1.get_pin_mut(), this.stream2.get_pin_mut()) + } + + /// Consumes this combinator, returning the underlying streams. + /// + /// Note that this may discard intermediate state of this combinator, so + /// care should be taken to avoid losing resources when this is called. + pub fn into_inner(self) -> (St1, St2) { + (self.stream1.into_inner(), self.stream2.into_inner()) + } +} + +impl FusedStream for Zip +where + St1: Stream, + St2: Stream, +{ + fn is_terminated(&self) -> bool { + self.stream1.is_terminated() && self.stream2.is_terminated() + } +} + +impl Stream for Zip +where + St1: Stream, + St2: Stream, +{ + type Item = (St1::Item, St2::Item); + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if this.queued1.is_none() { + match this.stream1.as_mut().poll_next(cx) { + Poll::Ready(Some(item1)) => *this.queued1 = Some(item1), + Poll::Ready(None) | Poll::Pending => {} + } + } + if this.queued2.is_none() { + match this.stream2.as_mut().poll_next(cx) { + Poll::Ready(Some(item2)) => *this.queued2 = Some(item2), + Poll::Ready(None) | Poll::Pending => {} + } + } + + if this.queued1.is_some() && this.queued2.is_some() { + let pair = (this.queued1.take().unwrap(), this.queued2.take().unwrap()); + Poll::Ready(Some(pair)) + } else if this.stream1.is_done() || this.stream2.is_done() { + Poll::Ready(None) + } else { + Poll::Pending + } + } + + fn size_hint(&self) -> (usize, Option) { + let queued1_len = usize::from(self.queued1.is_some()); + let queued2_len = usize::from(self.queued2.is_some()); + let (stream1_lower, stream1_upper) = self.stream1.size_hint(); + let (stream2_lower, stream2_upper) = self.stream2.size_hint(); + + let stream1_lower = stream1_lower.saturating_add(queued1_len); + let stream2_lower = stream2_lower.saturating_add(queued2_len); + + let lower = cmp::min(stream1_lower, stream2_lower); + + let upper = match (stream1_upper, stream2_upper) { + (Some(x), Some(y)) => { + let x = x.saturating_add(queued1_len); + let y = y.saturating_add(queued2_len); + Some(cmp::min(x, y)) + } + (Some(x), None) => x.checked_add(queued1_len), + (None, Some(y)) => y.checked_add(queued2_len), + (None, None) => None, + }; + + (lower, upper) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/and_then.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/and_then.rs new file mode 100644 index 0000000000..2f8b6f2589 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/and_then.rs @@ -0,0 +1,105 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`and_then`](super::TryStreamExt::and_then) method. + #[must_use = "streams do nothing unless polled"] + pub struct AndThen { + #[pin] + stream: St, + #[pin] + future: Option, + f: F, + } +} + +impl fmt::Debug for AndThen +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AndThen") + .field("stream", &self.stream) + .field("future", &self.future) + .finish() + } +} + +impl AndThen +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, future: None, f } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for AndThen +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: TryFuture, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + let item = ready!(fut.try_poll(cx)); + this.future.set(None); + break Some(item); + } else if let Some(item) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + this.future.set(Some((this.f)(item))); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let future_len = usize::from(self.future.is_some()); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(future_len); + let upper = match upper { + Some(x) => x.checked_add(future_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for AndThen +where + St: TryStream + FusedStream, + F: FnMut(St::Ok) -> Fut, + Fut: TryFuture, +{ + fn is_terminated(&self) -> bool { + self.future.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for AndThen +where + S: Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/into_async_read.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/into_async_read.rs new file mode 100644 index 0000000000..ffbfc7eae9 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/into_async_read.rs @@ -0,0 +1,166 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use futures_io::{AsyncBufRead, AsyncRead, AsyncWrite}; +use pin_project_lite::pin_project; +use std::cmp; +use std::io::{Error, Result}; + +pin_project! { + /// Reader for the [`into_async_read`](super::TryStreamExt::into_async_read) method. + #[derive(Debug)] + #[must_use = "readers do nothing unless polled"] + #[cfg_attr(docsrs, doc(cfg(feature = "io")))] + pub struct IntoAsyncRead + where + St: TryStream, + St::Ok: AsRef<[u8]>, + { + #[pin] + stream: St, + state: ReadState, + } +} + +#[derive(Debug)] +enum ReadState> { + Ready { chunk: T, chunk_start: usize }, + PendingChunk, + Eof, +} + +impl IntoAsyncRead +where + St: TryStream, + St::Ok: AsRef<[u8]>, +{ + pub(super) fn new(stream: St) -> Self { + Self { stream, state: ReadState::PendingChunk } + } +} + +impl AsyncRead for IntoAsyncRead +where + St: TryStream, + St::Ok: AsRef<[u8]>, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let mut this = self.project(); + + loop { + match this.state { + ReadState::Ready { chunk, chunk_start } => { + let chunk = chunk.as_ref(); + let len = cmp::min(buf.len(), chunk.len() - *chunk_start); + + buf[..len].copy_from_slice(&chunk[*chunk_start..*chunk_start + len]); + *chunk_start += len; + + if chunk.len() == *chunk_start { + *this.state = ReadState::PendingChunk; + } + + return Poll::Ready(Ok(len)); + } + ReadState::PendingChunk => match ready!(this.stream.as_mut().try_poll_next(cx)) { + Some(Ok(chunk)) => { + if !chunk.as_ref().is_empty() { + *this.state = ReadState::Ready { chunk, chunk_start: 0 }; + } + } + Some(Err(err)) => { + *this.state = ReadState::Eof; + return Poll::Ready(Err(err)); + } + None => { + *this.state = ReadState::Eof; + return Poll::Ready(Ok(0)); + } + }, + ReadState::Eof => { + return Poll::Ready(Ok(0)); + } + } + } + } +} + +impl AsyncWrite for IntoAsyncRead +where + St: TryStream + AsyncWrite, + St::Ok: AsRef<[u8]>, +{ + fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { + let this = self.project(); + this.stream.poll_write(cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + this.stream.poll_flush(cx) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + this.stream.poll_close(cx) + } +} + +impl AsyncBufRead for IntoAsyncRead +where + St: TryStream, + St::Ok: AsRef<[u8]>, +{ + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + while let ReadState::PendingChunk = this.state { + match ready!(this.stream.as_mut().try_poll_next(cx)) { + Some(Ok(chunk)) => { + if !chunk.as_ref().is_empty() { + *this.state = ReadState::Ready { chunk, chunk_start: 0 }; + } + } + Some(Err(err)) => { + *this.state = ReadState::Eof; + return Poll::Ready(Err(err)); + } + None => { + *this.state = ReadState::Eof; + return Poll::Ready(Ok(&[])); + } + } + } + + if let &mut ReadState::Ready { ref chunk, chunk_start } = this.state { + let chunk = chunk.as_ref(); + return Poll::Ready(Ok(&chunk[chunk_start..])); + } + + // To get to this point we must be in ReadState::Eof + Poll::Ready(Ok(&[])) + } + + fn consume(self: Pin<&mut Self>, amount: usize) { + let this = self.project(); + + // https://github.com/rust-lang/futures-rs/pull/1556#discussion_r281644295 + if amount == 0 { + return; + } + if let ReadState::Ready { chunk, chunk_start } = this.state { + *chunk_start += amount; + debug_assert!(*chunk_start <= chunk.as_ref().len()); + if *chunk_start >= chunk.as_ref().len() { + *this.state = ReadState::PendingChunk; + } + } else { + debug_assert!(false, "Attempted to consume from IntoAsyncRead without chunk"); + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/into_stream.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/into_stream.rs new file mode 100644 index 0000000000..2126258af7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/into_stream.rs @@ -0,0 +1,52 @@ +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`into_stream`](super::TryStreamExt::into_stream) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct IntoStream { + #[pin] + stream: St, + } +} + +impl IntoStream { + #[inline] + pub(super) fn new(stream: St) -> Self { + Self { stream } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for IntoStream { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Stream for IntoStream { + type Item = Result; + + #[inline] + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.project().stream.try_poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + self.stream.size_hint() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl, Item> Sink for IntoStream { + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/mod.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/mod.rs new file mode 100644 index 0000000000..311bfb33d0 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/mod.rs @@ -0,0 +1,1254 @@ +//! Streams +//! +//! This module contains a number of functions for working with `Streams`s +//! that return `Result`s, allowing for short-circuiting computations. + +#[cfg(feature = "compat")] +use crate::compat::Compat; +use crate::fns::{ + inspect_err_fn, inspect_ok_fn, into_fn, map_err_fn, map_ok_fn, InspectErrFn, InspectOkFn, + IntoFn, MapErrFn, MapOkFn, +}; +use crate::future::assert_future; +use crate::stream::assert_stream; +use crate::stream::{Inspect, Map}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::pin::Pin; + +use futures_core::{ + future::{Future, TryFuture}, + stream::TryStream, + task::{Context, Poll}, +}; + +mod and_then; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::and_then::AndThen; + +delegate_all!( + /// Stream for the [`err_into`](super::TryStreamExt::err_into) method. + ErrInto( + MapErr> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (.)] + New[|x: St| MapErr::new(x, into_fn())] +); + +delegate_all!( + /// Stream for the [`inspect_ok`](super::TryStreamExt::inspect_ok) method. + InspectOk( + Inspect, InspectOkFn> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, f: F| Inspect::new(IntoStream::new(x), inspect_ok_fn(f))] +); + +delegate_all!( + /// Stream for the [`inspect_err`](super::TryStreamExt::inspect_err) method. + InspectErr( + Inspect, InspectErrFn> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, f: F| Inspect::new(IntoStream::new(x), inspect_err_fn(f))] +); + +mod into_stream; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::into_stream::IntoStream; + +delegate_all!( + /// Stream for the [`map_ok`](super::TryStreamExt::map_ok) method. + MapOk( + Map, MapOkFn> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, f: F| Map::new(IntoStream::new(x), map_ok_fn(f))] +); + +delegate_all!( + /// Stream for the [`map_err`](super::TryStreamExt::map_err) method. + MapErr( + Map, MapErrFn> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + New[|x: St, f: F| Map::new(IntoStream::new(x), map_err_fn(f))] +); + +mod or_else; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::or_else::OrElse; + +mod try_next; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_next::TryNext; + +mod try_for_each; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_for_each::TryForEach; + +mod try_filter; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_filter::TryFilter; + +mod try_filter_map; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_filter_map::TryFilterMap; + +mod try_flatten; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_flatten::TryFlatten; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod try_flatten_unordered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_flatten_unordered::TryFlattenUnordered; + +mod try_collect; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_collect::TryCollect; + +mod try_concat; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_concat::TryConcat; + +#[cfg(feature = "alloc")] +mod try_chunks; +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_chunks::{TryChunks, TryChunksError}; + +#[cfg(feature = "alloc")] +mod try_ready_chunks; +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_ready_chunks::{TryReadyChunks, TryReadyChunksError}; + +mod try_fold; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_fold::TryFold; + +mod try_unfold; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_unfold::{try_unfold, TryUnfold}; + +mod try_skip_while; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_skip_while::TrySkipWhile; + +mod try_take_while; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_take_while::TryTakeWhile; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod try_buffer_unordered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_buffer_unordered::TryBufferUnordered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod try_buffered; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_buffered::TryBuffered; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +mod try_for_each_concurrent; +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_for_each_concurrent::TryForEachConcurrent; + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +mod into_async_read; +#[cfg(feature = "io")] +#[cfg_attr(docsrs, doc(cfg(feature = "io")))] +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::into_async_read::IntoAsyncRead; + +mod try_all; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_all::TryAll; + +mod try_any; +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::try_any::TryAny; + +impl TryStreamExt for S {} + +/// Adapters specific to `Result`-returning streams +pub trait TryStreamExt: TryStream { + /// Wraps the current stream in a new stream which converts the error type + /// into the one provided. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// + /// let mut stream = + /// stream::iter(vec![Ok(()), Err(5i32)]) + /// .err_into::(); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(()))); + /// assert_eq!(stream.try_next().await, Err(5i64)); + /// # }) + /// ``` + fn err_into(self) -> ErrInto + where + Self: Sized, + Self::Error: Into, + { + assert_stream::, _>(ErrInto::new(self)) + } + + /// Wraps the current stream in a new stream which maps the success value + /// using the provided closure. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// + /// let mut stream = + /// stream::iter(vec![Ok(5), Err(0)]) + /// .map_ok(|x| x + 2); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(7))); + /// assert_eq!(stream.try_next().await, Err(0)); + /// # }) + /// ``` + fn map_ok(self, f: F) -> MapOk + where + Self: Sized, + F: FnMut(Self::Ok) -> T, + { + assert_stream::, _>(MapOk::new(self, f)) + } + + /// Wraps the current stream in a new stream which maps the error value + /// using the provided closure. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// + /// let mut stream = + /// stream::iter(vec![Ok(5), Err(0)]) + /// .map_err(|x| x + 2); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(5))); + /// assert_eq!(stream.try_next().await, Err(2)); + /// # }) + /// ``` + fn map_err(self, f: F) -> MapErr + where + Self: Sized, + F: FnMut(Self::Error) -> E, + { + assert_stream::, _>(MapErr::new(self, f)) + } + + /// Chain on a computation for when a value is ready, passing the successful + /// results to the provided closure `f`. + /// + /// This function can be used to run a unit of work when the next successful + /// value on a stream is ready. The closure provided will be yielded a value + /// when ready, and the returned future will then be run to completion to + /// produce the next value on this stream. + /// + /// Any errors produced by this stream will not be passed to the closure, + /// and will be passed through. + /// + /// The returned value of the closure must implement the `TryFuture` trait + /// and can represent some more work to be done before the composed stream + /// is finished. + /// + /// Note that this function consumes the receiving stream and returns a + /// wrapped version of it. + /// + /// To process the entire stream and return a single future representing + /// success or error, use `try_for_each` instead. + /// + /// # Examples + /// + /// ``` + /// use futures::channel::mpsc; + /// use futures::future; + /// use futures::stream::TryStreamExt; + /// + /// let (_tx, rx) = mpsc::channel::>(1); + /// + /// let rx = rx.and_then(|result| { + /// future::ok(if result % 2 == 0 { + /// Some(result) + /// } else { + /// None + /// }) + /// }); + /// ``` + fn and_then(self, f: F) -> AndThen + where + F: FnMut(Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_stream::, _>(AndThen::new(self, f)) + } + + /// Chain on a computation for when an error happens, passing the + /// erroneous result to the provided closure `f`. + /// + /// This function can be used to run a unit of work and attempt to recover from + /// an error if one happens. The closure provided will be yielded an error + /// when one appears, and the returned future will then be run to completion + /// to produce the next value on this stream. + /// + /// Any successful values produced by this stream will not be passed to the + /// closure, and will be passed through. + /// + /// The returned value of the closure must implement the [`TryFuture`](futures_core::future::TryFuture) trait + /// and can represent some more work to be done before the composed stream + /// is finished. + /// + /// Note that this function consumes the receiving stream and returns a + /// wrapped version of it. + fn or_else(self, f: F) -> OrElse + where + F: FnMut(Self::Error) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_stream::, _>(OrElse::new(self, f)) + } + + /// Do something with the success value of this stream, afterwards passing + /// it on. + /// + /// This is similar to the `StreamExt::inspect` method where it allows + /// easily inspecting the success value as it passes through the stream, for + /// example to debug what's going on. + fn inspect_ok(self, f: F) -> InspectOk + where + F: FnMut(&Self::Ok), + Self: Sized, + { + assert_stream::, _>(InspectOk::new(self, f)) + } + + /// Do something with the error value of this stream, afterwards passing it on. + /// + /// This is similar to the `StreamExt::inspect` method where it allows + /// easily inspecting the error value as it passes through the stream, for + /// example to debug what's going on. + fn inspect_err(self, f: F) -> InspectErr + where + F: FnMut(&Self::Error), + Self: Sized, + { + assert_stream::, _>(InspectErr::new(self, f)) + } + + /// Wraps a [`TryStream`] into a type that implements + /// [`Stream`](futures_core::stream::Stream) + /// + /// [`TryStream`]s currently do not implement the + /// [`Stream`](futures_core::stream::Stream) trait because of limitations + /// of the compiler. + /// + /// # Examples + /// + /// ``` + /// use futures::stream::{Stream, TryStream, TryStreamExt}; + /// + /// # type T = i32; + /// # type E = (); + /// fn make_try_stream() -> impl TryStream { // ... } + /// # futures::stream::empty() + /// # } + /// fn take_stream(stream: impl Stream>) { /* ... */ } + /// + /// take_stream(make_try_stream().into_stream()); + /// ``` + fn into_stream(self) -> IntoStream + where + Self: Sized, + { + assert_stream::, _>(IntoStream::new(self)) + } + + /// Creates a future that attempts to resolve the next item in the stream. + /// If an error is encountered before the next item, the error is returned + /// instead. + /// + /// This is similar to the `Stream::next` combinator, but returns a + /// `Result, E>` rather than an `Option>`, making + /// for easy use with the `?` operator. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// + /// let mut stream = stream::iter(vec![Ok(()), Err(())]); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(()))); + /// assert_eq!(stream.try_next().await, Err(())); + /// # }) + /// ``` + fn try_next(&mut self) -> TryNext<'_, Self> + where + Self: Unpin, + { + assert_future::, Self::Error>, _>(TryNext::new(self)) + } + + /// Attempts to run this stream to completion, executing the provided + /// asynchronous closure for each element on the stream. + /// + /// The provided closure will be called for each item this stream produces, + /// yielding a future. That future will then be executed to completion + /// before moving on to the next item. + /// + /// The returned value is a [`Future`](futures_core::future::Future) where the + /// [`Output`](futures_core::future::Future::Output) type is + /// `Result<(), Self::Error>`. If any of the intermediate + /// futures or the stream returns an error, this future will return + /// immediately with an error. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, TryStreamExt}; + /// + /// let mut x = 0i32; + /// + /// { + /// let fut = stream::repeat(Ok(1)).try_for_each(|item| { + /// x += item; + /// future::ready(if x == 3 { Err(()) } else { Ok(()) }) + /// }); + /// assert_eq!(fut.await, Err(())); + /// } + /// + /// assert_eq!(x, 3); + /// # }) + /// ``` + fn try_for_each(self, f: F) -> TryForEach + where + F: FnMut(Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(TryForEach::new(self, f)) + } + + /// Skip elements on this stream while the provided asynchronous predicate + /// resolves to `true`. + /// + /// This function is similar to + /// [`StreamExt::skip_while`](crate::stream::StreamExt::skip_while) but exits + /// early if an error occurs. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, TryStreamExt}; + /// + /// let stream = stream::iter(vec![Ok::(1), Ok(3), Ok(2)]); + /// let stream = stream.try_skip_while(|x| future::ready(Ok(*x < 3))); + /// + /// let output: Result, i32> = stream.try_collect().await; + /// assert_eq!(output, Ok(vec![3, 2])); + /// # }) + /// ``` + fn try_skip_while(self, f: F) -> TrySkipWhile + where + F: FnMut(&Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_stream::, _>(TrySkipWhile::new(self, f)) + } + + /// Take elements on this stream while the provided asynchronous predicate + /// resolves to `true`. + /// + /// This function is similar to + /// [`StreamExt::take_while`](crate::stream::StreamExt::take_while) but exits + /// early if an error occurs. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, TryStreamExt}; + /// + /// let stream = stream::iter(vec![Ok::(1), Ok(2), Ok(3), Ok(2)]); + /// let stream = stream.try_take_while(|x| future::ready(Ok(*x < 3))); + /// + /// let output: Result, i32> = stream.try_collect().await; + /// assert_eq!(output, Ok(vec![1, 2])); + /// # }) + /// ``` + fn try_take_while(self, f: F) -> TryTakeWhile + where + F: FnMut(&Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_stream::, _>(TryTakeWhile::new(self, f)) + } + + /// Attempts to run this stream to completion, executing the provided asynchronous + /// closure for each element on the stream concurrently as elements become + /// available, exiting as soon as an error occurs. + /// + /// This is similar to + /// [`StreamExt::for_each_concurrent`](crate::stream::StreamExt::for_each_concurrent), + /// but will resolve to an error immediately if the underlying stream or the provided + /// closure return an error. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::oneshot; + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// + /// let (tx1, rx1) = oneshot::channel(); + /// let (tx2, rx2) = oneshot::channel(); + /// let (_tx3, rx3) = oneshot::channel(); + /// + /// let stream = stream::iter(vec![rx1, rx2, rx3]); + /// let fut = stream.map(Ok).try_for_each_concurrent( + /// /* limit */ 2, + /// |rx| async move { + /// let res: Result<(), oneshot::Canceled> = rx.await; + /// res + /// } + /// ); + /// + /// tx1.send(()).unwrap(); + /// // Drop the second sender so that `rx2` resolves to `Canceled`. + /// drop(tx2); + /// + /// // The final result is an error because the second future + /// // resulted in an error. + /// assert_eq!(Err(oneshot::Canceled), fut.await); + /// # }) + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn try_for_each_concurrent( + self, + limit: impl Into>, + f: F, + ) -> TryForEachConcurrent + where + F: FnMut(Self::Ok) -> Fut, + Fut: Future>, + Self: Sized, + { + assert_future::, _>(TryForEachConcurrent::new( + self, + limit.into(), + f, + )) + } + + /// Attempt to transform a stream into a collection, + /// returning a future representing the result of that computation. + /// + /// This combinator will collect all successful results of this stream and + /// collect them into the specified collection type. If an error happens then all + /// collected elements will be dropped and the error will be returned. + /// + /// The returned future will be resolved when the stream terminates. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::TryStreamExt; + /// use std::thread; + /// + /// let (tx, rx) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// for i in 1..=5 { + /// tx.unbounded_send(Ok(i)).unwrap(); + /// } + /// tx.unbounded_send(Err(6)).unwrap(); + /// }); + /// + /// let output: Result, i32> = rx.try_collect().await; + /// assert_eq!(output, Err(6)); + /// # }) + /// ``` + fn try_collect>(self) -> TryCollect + where + Self: Sized, + { + assert_future::, _>(TryCollect::new(self)) + } + + /// An adaptor for chunking up successful items of the stream inside a vector. + /// + /// This combinator will attempt to pull successful items from this stream and buffer + /// them into a local vector. At most `capacity` items will get buffered + /// before they're yielded from the returned stream. + /// + /// Note that the vectors returned from this iterator may not always have + /// `capacity` elements. If the underlying stream ended and only a partial + /// vector was created, it'll be returned. Additionally if an error happens + /// from the underlying stream then the currently buffered items will be + /// yielded. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// This function is similar to + /// [`StreamExt::chunks`](crate::stream::StreamExt::chunks) but exits + /// early if an error occurs. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryChunksError, TryStreamExt}; + /// + /// let stream = stream::iter(vec![Ok::(1), Ok(2), Ok(3), Err(4), Ok(5), Ok(6)]); + /// let mut stream = stream.try_chunks(2); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(vec![1, 2]))); + /// assert_eq!(stream.try_next().await, Err(TryChunksError(vec![3], 4))); + /// assert_eq!(stream.try_next().await, Ok(Some(vec![5, 6]))); + /// # }) + /// ``` + /// + /// # Panics + /// + /// This method will panic if `capacity` is zero. + #[cfg(feature = "alloc")] + fn try_chunks(self, capacity: usize) -> TryChunks + where + Self: Sized, + { + assert_stream::, TryChunksError>, _>( + TryChunks::new(self, capacity), + ) + } + + /// An adaptor for chunking up successful, ready items of the stream inside a vector. + /// + /// This combinator will attempt to pull successful items from this stream and buffer + /// them into a local vector. At most `capacity` items will get buffered + /// before they're yielded from the returned stream. If the underlying stream + /// returns `Poll::Pending`, and the collected chunk is not empty, it will + /// be immediately returned. + /// + /// Note that the vectors returned from this iterator may not always have + /// `capacity` elements. If the underlying stream ended and only a partial + /// vector was created, it'll be returned. Additionally if an error happens + /// from the underlying stream then the currently buffered items will be + /// yielded. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// This function is similar to + /// [`StreamExt::ready_chunks`](crate::stream::StreamExt::ready_chunks) but exits + /// early if an error occurs. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryReadyChunksError, TryStreamExt}; + /// + /// let stream = stream::iter(vec![Ok::(1), Ok(2), Ok(3), Err(4), Ok(5), Ok(6)]); + /// let mut stream = stream.try_ready_chunks(2); + /// + /// assert_eq!(stream.try_next().await, Ok(Some(vec![1, 2]))); + /// assert_eq!(stream.try_next().await, Err(TryReadyChunksError(vec![3], 4))); + /// assert_eq!(stream.try_next().await, Ok(Some(vec![5, 6]))); + /// # }) + /// ``` + /// + /// # Panics + /// + /// This method will panic if `capacity` is zero. + #[cfg(feature = "alloc")] + fn try_ready_chunks(self, capacity: usize) -> TryReadyChunks + where + Self: Sized, + { + assert_stream::, TryReadyChunksError>, _>( + TryReadyChunks::new(self, capacity), + ) + } + + /// Attempt to filter the values produced by this stream according to the + /// provided asynchronous closure. + /// + /// As values of this stream are made available, the provided predicate `f` + /// will be run on them. If the predicate returns a `Future` which resolves + /// to `true`, then the stream will yield the value, but if the predicate + /// return a `Future` which resolves to `false`, then the value will be + /// discarded and the next value will be produced. + /// + /// All errors are passed through without filtering in this combinator. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `filter` methods in + /// the standard library. + /// + /// # Examples + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future; + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// + /// let stream = stream::iter(vec![Ok(1i32), Ok(2i32), Ok(3i32), Err("error")]); + /// let mut evens = stream.try_filter(|x| { + /// future::ready(x % 2 == 0) + /// }); + /// + /// assert_eq!(evens.next().await, Some(Ok(2))); + /// assert_eq!(evens.next().await, Some(Err("error"))); + /// # }) + /// ``` + fn try_filter(self, f: F) -> TryFilter + where + Fut: Future, + F: FnMut(&Self::Ok) -> Fut, + Self: Sized, + { + assert_stream::, _>(TryFilter::new(self, f)) + } + + /// Attempt to filter the values produced by this stream while + /// simultaneously mapping them to a different type according to the + /// provided asynchronous closure. + /// + /// As values of this stream are made available, the provided function will + /// be run on them. If the future returned by the predicate `f` resolves to + /// [`Some(item)`](Some) then the stream will yield the value `item`, but if + /// it resolves to [`None`] then the next value will be produced. + /// + /// All errors are passed through without filtering in this combinator. + /// + /// Note that this function consumes the stream passed into it and returns a + /// wrapped version of it, similar to the existing `filter_map` methods in + /// the standard library. + /// + /// # Examples + /// ``` + /// # futures::executor::block_on(async { + /// use core::pin::pin; + /// + /// use futures::stream; + /// use futures::stream::StreamExt; + /// use futures::stream::TryStreamExt; + /// + /// let stream = stream::iter(vec![Ok(1i32), Ok(6i32), Err("error")]); + /// let halves = stream.try_filter_map(|x| async move { + /// let ret = if x % 2 == 0 { Some(x / 2) } else { None }; + /// Ok(ret) + /// }); + /// + /// let mut halves = pin!(halves); + /// assert_eq!(halves.next().await, Some(Ok(3))); + /// assert_eq!(halves.next().await, Some(Err("error"))); + /// # }) + /// ``` + fn try_filter_map(self, f: F) -> TryFilterMap + where + Fut: TryFuture, Error = Self::Error>, + F: FnMut(Self::Ok) -> Fut, + Self: Sized, + { + assert_stream::, _>(TryFilterMap::new(self, f)) + } + + /// Flattens a stream of streams into just one continuous stream. Produced streams + /// will be polled concurrently and any errors will be passed through without looking at them. + /// If the underlying base stream returns an error, it will be **immediately** propagated. + /// + /// The only argument is an optional limit on the number of concurrently + /// polled streams. If this limit is not `None`, no more than `limit` streams + /// will be polled at the same time. The `limit` argument is of type + /// `Into>`, and so can be provided as either `None`, + /// `Some(10)`, or just `10`. Note: a limit of zero is interpreted as + /// no limit at all, and will have the same result as passing in `None`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::{StreamExt, TryStreamExt}; + /// use std::thread; + /// + /// let (tx1, rx1) = mpsc::unbounded(); + /// let (tx2, rx2) = mpsc::unbounded(); + /// let (tx3, rx3) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// tx1.unbounded_send(Ok(1)).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx2.unbounded_send(Ok(2)).unwrap(); + /// tx2.unbounded_send(Err(3)).unwrap(); + /// tx2.unbounded_send(Ok(4)).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx3.unbounded_send(Ok(rx1)).unwrap(); + /// tx3.unbounded_send(Ok(rx2)).unwrap(); + /// tx3.unbounded_send(Err(5)).unwrap(); + /// }); + /// + /// let stream = rx3.try_flatten_unordered(None); + /// let mut values: Vec<_> = stream.collect().await; + /// values.sort(); + /// + /// assert_eq!(values, vec![Ok(1), Ok(2), Ok(4), Err(3), Err(5)]); + /// # }); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn try_flatten_unordered(self, limit: impl Into>) -> TryFlattenUnordered + where + Self::Ok: TryStream + Unpin, + ::Error: From, + Self: Sized, + { + assert_stream::::Ok, ::Error>, _>( + TryFlattenUnordered::new(self, limit), + ) + } + + /// Flattens a stream of streams into just one continuous stream. + /// + /// If this stream's elements are themselves streams then this combinator + /// will flatten out the entire stream to one long chain of elements. Any + /// errors are passed through without looking at them, but otherwise each + /// individual stream will get exhausted before moving on to the next. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::{StreamExt, TryStreamExt}; + /// use std::thread; + /// + /// let (tx1, rx1) = mpsc::unbounded(); + /// let (tx2, rx2) = mpsc::unbounded(); + /// let (tx3, rx3) = mpsc::unbounded(); + /// + /// thread::spawn(move || { + /// tx1.unbounded_send(Ok(1)).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx2.unbounded_send(Ok(2)).unwrap(); + /// tx2.unbounded_send(Err(3)).unwrap(); + /// tx2.unbounded_send(Ok(4)).unwrap(); + /// }); + /// thread::spawn(move || { + /// tx3.unbounded_send(Ok(rx1)).unwrap(); + /// tx3.unbounded_send(Ok(rx2)).unwrap(); + /// tx3.unbounded_send(Err(5)).unwrap(); + /// }); + /// + /// let mut stream = rx3.try_flatten(); + /// assert_eq!(stream.next().await, Some(Ok(1))); + /// assert_eq!(stream.next().await, Some(Ok(2))); + /// assert_eq!(stream.next().await, Some(Err(3))); + /// assert_eq!(stream.next().await, Some(Ok(4))); + /// assert_eq!(stream.next().await, Some(Err(5))); + /// assert_eq!(stream.next().await, None); + /// # }); + /// ``` + fn try_flatten(self) -> TryFlatten + where + Self::Ok: TryStream, + ::Error: From, + Self: Sized, + { + assert_stream::::Ok, ::Error>, _>( + TryFlatten::new(self), + ) + } + + /// Attempt to execute an accumulating asynchronous computation over a + /// stream, collecting all the values into one final result. + /// + /// This combinator will accumulate all values returned by this stream + /// according to the closure provided. The initial state is also provided to + /// this method and then is returned again by each execution of the closure. + /// Once the entire stream has been exhausted the returned future will + /// resolve to this value. + /// + /// This method is similar to [`fold`](crate::stream::StreamExt::fold), but will + /// exit early if an error is encountered in either the stream or the + /// provided closure. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// + /// let number_stream = stream::iter(vec![Ok::(1), Ok(2)]); + /// let sum = number_stream.try_fold(0, |acc, x| async move { Ok(acc + x) }); + /// assert_eq!(sum.await, Ok(3)); + /// + /// let number_stream_with_err = stream::iter(vec![Ok::(1), Err(2), Ok(1)]); + /// let sum = number_stream_with_err.try_fold(0, |acc, x| async move { Ok(acc + x) }); + /// assert_eq!(sum.await, Err(2)); + /// # }) + /// ``` + fn try_fold(self, init: T, f: F) -> TryFold + where + F: FnMut(T, Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(TryFold::new(self, f, init)) + } + + /// Attempt to concatenate all items of a stream into a single + /// extendable destination, returning a future representing the end result. + /// + /// This combinator will extend the first item with the contents of all + /// the subsequent successful results of the stream. If the stream is empty, + /// the default value will be returned. + /// + /// Works with all collections that implement the [`Extend`](std::iter::Extend) trait. + /// + /// This method is similar to [`concat`](crate::stream::StreamExt::concat), but will + /// exit early if an error is encountered in the stream. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::TryStreamExt; + /// use std::thread; + /// + /// let (tx, rx) = mpsc::unbounded::, ()>>(); + /// + /// thread::spawn(move || { + /// for i in (0..3).rev() { + /// let n = i * 3; + /// tx.unbounded_send(Ok(vec![n + 1, n + 2, n + 3])).unwrap(); + /// } + /// }); + /// + /// let result = rx.try_concat().await; + /// + /// assert_eq!(result, Ok(vec![7, 8, 9, 4, 5, 6, 1, 2, 3])); + /// # }); + /// ``` + fn try_concat(self) -> TryConcat + where + Self: Sized, + Self::Ok: Extend<<::Ok as IntoIterator>::Item> + IntoIterator + Default, + { + assert_future::, _>(TryConcat::new(self)) + } + + /// Attempt to execute several futures from a stream concurrently (unordered). + /// + /// This stream's `Ok` type must be a [`TryFuture`](futures_core::future::TryFuture) with an `Error` type + /// that matches the stream's `Error` type. + /// + /// This adaptor will buffer up to `n` futures and then return their + /// outputs in the order in which they complete. If the underlying stream + /// returns an error, it will be immediately propagated. + /// + /// The returned stream will be a stream of results, each containing either + /// an error or a future's output. An error can be produced either by the + /// underlying stream itself or by one of the futures it yielded. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// Results are returned in the order of completion: + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::oneshot; + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// + /// let (send_one, recv_one) = oneshot::channel(); + /// let (send_two, recv_two) = oneshot::channel(); + /// + /// let stream_of_futures = stream::iter(vec![Ok(recv_one), Ok(recv_two)]); + /// + /// let mut buffered = stream_of_futures.try_buffer_unordered(10); + /// + /// send_two.send(2i32)?; + /// assert_eq!(buffered.next().await, Some(Ok(2i32))); + /// + /// send_one.send(1i32)?; + /// assert_eq!(buffered.next().await, Some(Ok(1i32))); + /// + /// assert_eq!(buffered.next().await, None); + /// # Ok::<(), i32>(()) }).unwrap(); + /// ``` + /// + /// Errors from the underlying stream itself are propagated: + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::{StreamExt, TryStreamExt}; + /// + /// let (sink, stream_of_futures) = mpsc::unbounded(); + /// let mut buffered = stream_of_futures.try_buffer_unordered(10); + /// + /// sink.unbounded_send(Ok(async { Ok(7i32) }))?; + /// assert_eq!(buffered.next().await, Some(Ok(7i32))); + /// + /// sink.unbounded_send(Err("error in the stream"))?; + /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered + where + Self::Ok: TryFuture, + Self: Sized, + { + assert_stream::::Ok, Self::Error>, _>( + TryBufferUnordered::new(self, n), + ) + } + + /// Attempt to execute several futures from a stream concurrently. + /// + /// This stream's `Ok` type must be a [`TryFuture`](futures_core::future::TryFuture) with an `Error` type + /// that matches the stream's `Error` type. + /// + /// This adaptor will buffer up to `n` futures and then return their + /// outputs in the same order as the underlying stream. If the underlying stream returns an error, it will + /// be immediately propagated. + /// + /// The returned stream will be a stream of results, each containing either + /// an error or a future's output. An error can be produced either by the + /// underlying stream itself or by one of the futures it yielded. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// Results are returned in the order of addition: + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::oneshot; + /// use futures::future::lazy; + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// + /// let (send_one, recv_one) = oneshot::channel(); + /// let (send_two, recv_two) = oneshot::channel(); + /// + /// let mut buffered = lazy(move |cx| { + /// let stream_of_futures = stream::iter(vec![Ok(recv_one), Ok(recv_two)]); + /// + /// let mut buffered = stream_of_futures.try_buffered(10); + /// + /// assert!(buffered.try_poll_next_unpin(cx).is_pending()); + /// + /// send_two.send(2i32)?; + /// assert!(buffered.try_poll_next_unpin(cx).is_pending()); + /// Ok::<_, i32>(buffered) + /// }).await?; + /// + /// send_one.send(1i32)?; + /// assert_eq!(buffered.next().await, Some(Ok(1i32))); + /// assert_eq!(buffered.next().await, Some(Ok(2i32))); + /// + /// assert_eq!(buffered.next().await, None); + /// # Ok::<(), i32>(()) }).unwrap(); + /// ``` + /// + /// Errors from the underlying stream itself are propagated: + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::stream::{StreamExt, TryStreamExt}; + /// + /// let (sink, stream_of_futures) = mpsc::unbounded(); + /// let mut buffered = stream_of_futures.try_buffered(10); + /// + /// sink.unbounded_send(Ok(async { Ok(7i32) }))?; + /// assert_eq!(buffered.next().await, Some(Ok(7i32))); + /// + /// sink.unbounded_send(Err("error in the stream"))?; + /// assert_eq!(buffered.next().await, Some(Err("error in the stream"))); + /// # Ok::<(), Box>(()) }).unwrap(); + /// ``` + #[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] + #[cfg(feature = "alloc")] + fn try_buffered(self, n: usize) -> TryBuffered + where + Self::Ok: TryFuture, + Self: Sized, + { + assert_stream::::Ok, Self::Error>, _>(TryBuffered::new( + self, n, + )) + } + + // TODO: false positive warning from rustdoc. Verify once #43466 settles + // + /// A convenience method for calling [`TryStream::try_poll_next`] on [`Unpin`] + /// stream types. + fn try_poll_next_unpin( + &mut self, + cx: &mut Context<'_>, + ) -> Poll>> + where + Self: Unpin, + { + Pin::new(self).try_poll_next(cx) + } + + /// Wraps a [`TryStream`] into a stream compatible with libraries using + /// futures 0.1 `Stream`. Requires the `compat` feature to be enabled. + /// ``` + /// # if cfg!(miri) { return; } // Miri does not support epoll + /// use futures::future::{FutureExt, TryFutureExt}; + /// # let (tx, rx) = futures::channel::oneshot::channel(); + /// + /// let future03 = async { + /// println!("Running on the pool"); + /// tx.send(42).unwrap(); + /// }; + /// + /// let future01 = future03 + /// .unit_error() // Make it a TryFuture + /// .boxed() // Make it Unpin + /// .compat(); + /// + /// tokio::run(future01); + /// # assert_eq!(42, futures::executor::block_on(rx).unwrap()); + /// ``` + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> Compat + where + Self: Sized + Unpin, + { + Compat::new(self) + } + + /// Adapter that converts this stream into an [`AsyncBufRead`](crate::io::AsyncBufRead). + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, TryStreamExt}; + /// use futures::io::AsyncReadExt; + /// + /// let stream = stream::iter([Ok(vec![1, 2, 3]), Ok(vec![4, 5])]); + /// let mut reader = stream.into_async_read(); + /// + /// let mut buf = Vec::new(); + /// reader.read_to_end(&mut buf).await.unwrap(); + /// assert_eq!(buf, [1, 2, 3, 4, 5]); + /// # }) + /// ``` + #[cfg(feature = "io")] + #[cfg_attr(docsrs, doc(cfg(feature = "io")))] + #[cfg(feature = "std")] + fn into_async_read(self) -> IntoAsyncRead + where + Self: Sized + TryStreamExt, + Self::Ok: AsRef<[u8]>, + { + crate::io::assert_read(IntoAsyncRead::new(self)) + } + + /// Attempt to execute a predicate over an asynchronous stream and evaluate if all items + /// satisfy the predicate. Exits early if an `Err` is encountered or if an `Ok` item is found + /// that does not satisfy the predicate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// use std::convert::Infallible; + /// + /// let number_stream = stream::iter(1..10).map(Ok::<_, Infallible>); + /// let positive = number_stream.try_all(|i| async move { i > 0 }); + /// assert_eq!(positive.await, Ok(true)); + /// + /// let stream_with_errors = stream::iter([Ok(1), Err("err"), Ok(3)]); + /// let positive = stream_with_errors.try_all(|i| async move { i > 0 }); + /// assert_eq!(positive.await, Err("err")); + /// # }); + /// ``` + fn try_all(self, f: F) -> TryAll + where + Self: Sized, + F: FnMut(Self::Ok) -> Fut, + Fut: Future, + { + assert_future::, _>(TryAll::new(self, f)) + } + + /// Attempt to execute a predicate over an asynchronous stream and evaluate if any items + /// satisfy the predicate. Exits early if an `Err` is encountered or if an `Ok` item is found + /// that satisfies the predicate. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt, TryStreamExt}; + /// use std::convert::Infallible; + /// + /// let number_stream = stream::iter(0..10).map(Ok::<_, Infallible>); + /// let contain_three = number_stream.try_any(|i| async move { i == 3 }); + /// assert_eq!(contain_three.await, Ok(true)); + /// + /// let stream_with_errors = stream::iter([Ok(1), Err("err"), Ok(3)]); + /// let contain_three = stream_with_errors.try_any(|i| async move { i == 3 }); + /// assert_eq!(contain_three.await, Err("err")); + /// # }); + /// ``` + fn try_any(self, f: F) -> TryAny + where + Self: Sized, + F: FnMut(Self::Ok) -> Fut, + Fut: Future, + { + assert_future::, _>(TryAny::new(self, f)) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/or_else.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/or_else.rs new file mode 100644 index 0000000000..53aceb8e64 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/or_else.rs @@ -0,0 +1,109 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`or_else`](super::TryStreamExt::or_else) method. + #[must_use = "streams do nothing unless polled"] + pub struct OrElse { + #[pin] + stream: St, + #[pin] + future: Option, + f: F, + } +} + +impl fmt::Debug for OrElse +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OrElse") + .field("stream", &self.stream) + .field("future", &self.future) + .finish() + } +} + +impl OrElse +where + St: TryStream, + F: FnMut(St::Error) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, future: None, f } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for OrElse +where + St: TryStream, + F: FnMut(St::Error) -> Fut, + Fut: TryFuture, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + let item = ready!(fut.try_poll(cx)); + this.future.set(None); + break Some(item); + } else { + match ready!(this.stream.as_mut().try_poll_next(cx)) { + Some(Ok(item)) => break Some(Ok(item)), + Some(Err(e)) => { + this.future.set(Some((this.f)(e))); + } + None => break None, + } + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let future_len = usize::from(self.future.is_some()); + let (lower, upper) = self.stream.size_hint(); + let lower = lower.saturating_add(future_len); + let upper = match upper { + Some(x) => x.checked_add(future_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for OrElse +where + St: TryStream + FusedStream, + F: FnMut(St::Error) -> Fut, + Fut: TryFuture, +{ + fn is_terminated(&self) -> bool { + self.future.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for OrElse +where + S: Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_all.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_all.rs new file mode 100644 index 0000000000..8179f86afc --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_all.rs @@ -0,0 +1,98 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_all`](super::TryStreamExt::try_all) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryAll { + #[pin] + stream: St, + f: F, + done: bool, + #[pin] + future: Option, + } +} + +impl fmt::Debug for TryAll +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryAll") + .field("stream", &self.stream) + .field("done", &self.done) + .field("future", &self.future) + .finish() + } +} + +impl TryAll +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, done: false, future: None } + } +} + +impl FusedFuture for TryAll +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.done && self.future.is_none() + } +} + +impl Future for TryAll +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new value + let acc = ready!(fut.poll(cx)); + this.future.set(None); + if !acc { + *this.done = true; + break Ok(false); + } // early exit + } else if !*this.done { + // we're waiting on a new item from the stream + match ready!(this.stream.as_mut().try_poll_next(cx)) { + Some(Ok(item)) => { + this.future.set(Some((this.f)(item))); + } + Some(Err(err)) => { + *this.done = true; + break Err(err); + } + None => { + *this.done = true; + break Ok(true); + } + } + } else { + panic!("TryAll polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_any.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_any.rs new file mode 100644 index 0000000000..55e876be05 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_any.rs @@ -0,0 +1,98 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_any`](super::TryStreamExt::try_any) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryAny { + #[pin] + stream: St, + f: F, + done: bool, + #[pin] + future: Option, + } +} + +impl fmt::Debug for TryAny +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryAny") + .field("stream", &self.stream) + .field("done", &self.done) + .field("future", &self.future) + .finish() + } +} + +impl TryAny +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, done: false, future: None } + } +} + +impl FusedFuture for TryAny +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.done && self.future.is_none() + } +} + +impl Future for TryAny +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new value + let acc = ready!(fut.poll(cx)); + this.future.set(None); + if acc { + *this.done = true; + break Ok(true); + } // early exit + } else if !*this.done { + // we're waiting on a new item from the stream + match ready!(this.stream.as_mut().try_poll_next(cx)) { + Some(Ok(item)) => { + this.future.set(Some((this.f)(item))); + } + Some(Err(err)) => { + *this.done = true; + break Err(err); + } + None => { + *this.done = true; + break Ok(false); + } + } + } else { + panic!("TryAny polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffer_unordered.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffer_unordered.rs new file mode 100644 index 0000000000..9a899d4ea6 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffer_unordered.rs @@ -0,0 +1,86 @@ +use crate::future::{IntoFuture, TryFutureExt}; +use crate::stream::{Fuse, FuturesUnordered, IntoStream, StreamExt}; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::stream::{Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the + /// [`try_buffer_unordered`](super::TryStreamExt::try_buffer_unordered) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct TryBufferUnordered + where St: TryStream + { + #[pin] + stream: Fuse>, + in_progress_queue: FuturesUnordered>, + max: usize, + } +} + +impl TryBufferUnordered +where + St: TryStream, + St::Ok: TryFuture, +{ + pub(super) fn new(stream: St, n: usize) -> Self { + Self { + stream: IntoStream::new(stream).fuse(), + in_progress_queue: FuturesUnordered::new(), + max: n, + } + } + + delegate_access_inner!(stream, St, (. .)); +} + +impl Stream for TryBufferUnordered +where + St: TryStream, + St::Ok: TryFuture, +{ + type Item = Result<::Ok, St::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + // First up, try to spawn off as many futures as possible by filling up + // our queue of futures. Propagate errors from the stream immediately. + while this.in_progress_queue.len() < *this.max { + match this.stream.as_mut().poll_next(cx)? { + Poll::Ready(Some(fut)) => this.in_progress_queue.push(fut.into_future()), + Poll::Ready(None) | Poll::Pending => break, + } + } + + // Attempt to pull the next value from the in_progress_queue + match this.in_progress_queue.poll_next_unpin(cx) { + x @ Poll::Pending | x @ Poll::Ready(Some(_)) => return x, + Poll::Ready(None) => {} + } + + // If more values are still coming from the stream, we're not done yet + if this.stream.is_done() { + Poll::Ready(None) + } else { + Poll::Pending + } + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryBufferUnordered +where + S: TryStream + Sink, + S::Ok: TryFuture, +{ + type Error = E; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffered.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffered.rs new file mode 100644 index 0000000000..9f48e5c0a7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_buffered.rs @@ -0,0 +1,87 @@ +use crate::future::{IntoFuture, TryFutureExt}; +use crate::stream::{Fuse, FuturesOrdered, IntoStream, StreamExt}; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::stream::{Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_buffered`](super::TryStreamExt::try_buffered) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct TryBuffered + where + St: TryStream, + St::Ok: TryFuture, + { + #[pin] + stream: Fuse>, + in_progress_queue: FuturesOrdered>, + max: usize, + } +} + +impl TryBuffered +where + St: TryStream, + St::Ok: TryFuture, +{ + pub(super) fn new(stream: St, n: usize) -> Self { + Self { + stream: IntoStream::new(stream).fuse(), + in_progress_queue: FuturesOrdered::new(), + max: n, + } + } + + delegate_access_inner!(stream, St, (. .)); +} + +impl Stream for TryBuffered +where + St: TryStream, + St::Ok: TryFuture, +{ + type Item = Result<::Ok, St::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + // First up, try to spawn off as many futures as possible by filling up + // our queue of futures. Propagate errors from the stream immediately. + while this.in_progress_queue.len() < *this.max { + match this.stream.as_mut().poll_next(cx)? { + Poll::Ready(Some(fut)) => this.in_progress_queue.push_back(fut.into_future()), + Poll::Ready(None) | Poll::Pending => break, + } + } + + // Attempt to pull the next value from the in_progress_queue + match this.in_progress_queue.poll_next_unpin(cx) { + x @ Poll::Pending | x @ Poll::Ready(Some(_)) => return x, + Poll::Ready(None) => {} + } + + // If more values are still coming from the stream, we're not done yet + if this.stream.is_done() { + Poll::Ready(None) + } else { + Poll::Pending + } + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryBuffered +where + S: TryStream + Sink, + S::Ok: TryFuture, +{ + type Error = E; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_chunks.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_chunks.rs new file mode 100644 index 0000000000..ec53f4bd11 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_chunks.rs @@ -0,0 +1,132 @@ +use crate::stream::{Fuse, IntoStream, StreamExt}; + +use alloc::vec::Vec; +use core::pin::Pin; +use core::{fmt, mem}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_chunks`](super::TryStreamExt::try_chunks) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct TryChunks { + #[pin] + stream: Fuse>, + items: Vec, + cap: usize, // https://github.com/rust-lang/futures-rs/issues/1475 + } +} + +impl TryChunks { + pub(super) fn new(stream: St, capacity: usize) -> Self { + assert!(capacity > 0); + + Self { + stream: IntoStream::new(stream).fuse(), + items: Vec::with_capacity(capacity), + cap: capacity, + } + } + + fn take(self: Pin<&mut Self>) -> Vec { + let cap = self.cap; + mem::replace(self.project().items, Vec::with_capacity(cap)) + } + + delegate_access_inner!(stream, St, (. .)); +} + +type TryChunksStreamError = TryChunksError<::Ok, ::Error>; + +impl Stream for TryChunks { + type Item = Result, TryChunksStreamError>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.as_mut().project(); + loop { + match ready!(this.stream.as_mut().try_poll_next(cx)) { + // Push the item into the buffer and check whether it is full. + // If so, replace our buffer with a new and empty one and return + // the full one. + Some(item) => match item { + Ok(item) => { + this.items.push(item); + if this.items.len() >= *this.cap { + return Poll::Ready(Some(Ok(self.take()))); + } + } + Err(e) => { + return Poll::Ready(Some(Err(TryChunksError(self.take(), e)))); + } + }, + + // Since the underlying stream ran out of values, return what we + // have buffered, if we have anything. + None => { + let last = if this.items.is_empty() { + None + } else { + let full_buf = mem::take(this.items); + Some(full_buf) + }; + + return Poll::Ready(last.map(Ok)); + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let chunk_len = usize::from(!self.items.is_empty()); + let (lower, upper) = self.stream.size_hint(); + let lower = (lower / self.cap).saturating_add(chunk_len); + let upper = match upper { + Some(x) => x.checked_add(chunk_len), + None => None, + }; + (lower, upper) + } +} + +impl FusedStream for TryChunks { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() && self.items.is_empty() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryChunks +where + S: TryStream + Sink, +{ + type Error = >::Error; + + delegate_sink!(stream, Item); +} + +/// Error indicating, that while chunk was collected inner stream produced an error. +/// +/// Contains all items that were collected before an error occurred, and the stream error itself. +#[derive(PartialEq, Eq)] +pub struct TryChunksError(pub Vec, pub E); + +impl fmt::Debug for TryChunksError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.1.fmt(f) + } +} + +impl fmt::Display for TryChunksError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.1.fmt(f) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryChunksError {} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_collect.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_collect.rs new file mode 100644 index 0000000000..3e5963f033 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_collect.rs @@ -0,0 +1,52 @@ +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, TryStream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_collect`](super::TryStreamExt::try_collect) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryCollect { + #[pin] + stream: St, + items: C, + } +} + +impl TryCollect { + pub(super) fn new(s: St) -> Self { + Self { stream: s, items: Default::default() } + } +} + +impl FusedFuture for TryCollect +where + St: TryStream + FusedStream, + C: Default + Extend, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for TryCollect +where + St: TryStream, + C: Default + Extend, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + Poll::Ready(Ok(loop { + match ready!(this.stream.as_mut().try_poll_next(cx)?) { + Some(x) => this.items.extend(Some(x)), + None => break mem::take(this.items), + } + })) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_concat.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_concat.rs new file mode 100644 index 0000000000..58fb6a5413 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_concat.rs @@ -0,0 +1,51 @@ +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_concat`](super::TryStreamExt::try_concat) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryConcat { + #[pin] + stream: St, + accum: Option, + } +} + +impl TryConcat +where + St: TryStream, + St::Ok: Extend<::Item> + IntoIterator + Default, +{ + pub(super) fn new(stream: St) -> Self { + Self { stream, accum: None } + } +} + +impl Future for TryConcat +where + St: TryStream, + St::Ok: Extend<::Item> + IntoIterator + Default, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + + Poll::Ready(Ok(loop { + if let Some(x) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + if let Some(a) = this.accum { + a.extend(x) + } else { + *this.accum = Some(x) + } + } else { + break this.accum.take().unwrap_or_default(); + } + })) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter.rs new file mode 100644 index 0000000000..11d58243fd --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter.rs @@ -0,0 +1,112 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_filter`](super::TryStreamExt::try_filter) + /// method. + #[must_use = "streams do nothing unless polled"] + pub struct TryFilter + where St: TryStream + { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + } +} + +impl fmt::Debug for TryFilter +where + St: TryStream + fmt::Debug, + St::Ok: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryFilter") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .finish() + } +} + +impl TryFilter +where + St: TryStream, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for TryFilter +where + St: TryStream + FusedStream, + F: FnMut(&St::Ok) -> Fut, + Fut: Future, +{ + fn is_terminated(&self) -> bool { + self.pending_fut.is_none() && self.stream.is_terminated() + } +} + +impl Stream for TryFilter +where + St: TryStream, + Fut: Future, + F: FnMut(&St::Ok) -> Fut, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let res = ready!(fut.poll(cx)); + this.pending_fut.set(None); + if res { + break this.pending_item.take().map(Ok); + } + *this.pending_item = None; + } else if let Some(item) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + this.pending_fut.set(Some((this.f)(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let pending_len = usize::from(self.pending_fut.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryFilter +where + S: TryStream + Sink, +{ + type Error = E; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter_map.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter_map.rs new file mode 100644 index 0000000000..ed1201732b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_filter_map.rs @@ -0,0 +1,106 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_filter_map`](super::TryStreamExt::try_filter_map) + /// method. + #[must_use = "streams do nothing unless polled"] + pub struct TryFilterMap { + #[pin] + stream: St, + f: F, + #[pin] + pending: Option, + } +} + +impl fmt::Debug for TryFilterMap +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryFilterMap") + .field("stream", &self.stream) + .field("pending", &self.pending) + .finish() + } +} + +impl TryFilterMap { + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for TryFilterMap +where + St: TryStream + FusedStream, + Fut: TryFuture, Error = St::Error>, + F: FnMut(St::Ok) -> Fut, +{ + fn is_terminated(&self) -> bool { + self.pending.is_none() && self.stream.is_terminated() + } +} + +impl Stream for TryFilterMap +where + St: TryStream, + Fut: TryFuture, Error = St::Error>, + F: FnMut(St::Ok) -> Fut, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(p) = this.pending.as_mut().as_pin_mut() { + // We have an item in progress, poll that until it's done + let res = ready!(p.try_poll(cx)); + this.pending.set(None); + let item = res?; + if item.is_some() { + break item.map(Ok); + } + } else if let Some(item) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + // No item in progress, but the stream is still going + this.pending.set(Some((this.f)(item))); + } else { + // The stream is done + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let pending_len = usize::from(self.pending.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryFilterMap +where + S: Sink, +{ + type Error = S::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten.rs new file mode 100644 index 0000000000..4fc04a07bb --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten.rs @@ -0,0 +1,84 @@ +use core::pin::Pin; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_flatten`](super::TryStreamExt::try_flatten) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct TryFlatten + where + St: TryStream, + { + #[pin] + stream: St, + #[pin] + next: Option, + } +} + +impl TryFlatten +where + St: TryStream, + St::Ok: TryStream, + ::Error: From, +{ + pub(super) fn new(stream: St) -> Self { + Self { stream, next: None } + } + + delegate_access_inner!(stream, St, ()); +} + +impl FusedStream for TryFlatten +where + St: TryStream + FusedStream, + St::Ok: TryStream, + ::Error: From, +{ + fn is_terminated(&self) -> bool { + self.next.is_none() && self.stream.is_terminated() + } +} + +impl Stream for TryFlatten +where + St: TryStream, + St::Ok: TryStream, + ::Error: From, +{ + type Item = Result<::Ok, ::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(s) = this.next.as_mut().as_pin_mut() { + if let Some(item) = ready!(s.try_poll_next(cx)?) { + break Some(Ok(item)); + } else { + this.next.set(None); + } + } else if let Some(s) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + this.next.set(Some(s)); + } else { + break None; + } + }) + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryFlatten +where + S: TryStream + Sink, +{ + type Error = >::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten_unordered.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten_unordered.rs new file mode 100644 index 0000000000..a74dfc451d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_flatten_unordered.rs @@ -0,0 +1,176 @@ +use core::marker::PhantomData; +use core::pin::Pin; + +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +use pin_project_lite::pin_project; + +use crate::future::Either; +use crate::stream::stream::flatten_unordered::{ + FlattenUnorderedWithFlowController, FlowController, FlowStep, +}; +use crate::stream::IntoStream; +use crate::TryStreamExt; + +delegate_all!( + /// Stream for the [`try_flatten_unordered`](super::TryStreamExt::try_flatten_unordered) method. + TryFlattenUnordered( + FlattenUnorderedWithFlowController, PropagateBaseStreamError> + ): Debug + Sink + Stream + FusedStream + AccessInner[St, (. .)] + + New[ + |stream: St, limit: impl Into>| + FlattenUnorderedWithFlowController::new( + NestedTryStreamIntoEitherTryStream::new(stream), + limit.into() + ) + ] + where + St: TryStream, + St::Ok: TryStream, + St::Ok: Unpin, + ::Error: From +); + +pin_project! { + /// Emits either successful streams or single-item streams containing the underlying errors. + /// This's a wrapper for `FlattenUnordered` to reuse its logic over `TryStream`. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct NestedTryStreamIntoEitherTryStream + where + St: TryStream, + St::Ok: TryStream, + St::Ok: Unpin, + ::Error: From + { + #[pin] + stream: St + } +} + +impl NestedTryStreamIntoEitherTryStream +where + St: TryStream, + St::Ok: TryStream + Unpin, + ::Error: From, +{ + fn new(stream: St) -> Self { + Self { stream } + } + + delegate_access_inner!(stream, St, ()); +} + +/// Emits a single item immediately, then stream will be terminated. +#[derive(Debug, Clone)] +pub struct Single(Option); + +impl Single { + /// Constructs new `Single` with the given value. + fn new(val: T) -> Self { + Self(Some(val)) + } + + /// Attempts to take inner item immediately. Will always succeed if the stream isn't terminated. + fn next_immediate(&mut self) -> Option { + self.0.take() + } +} + +impl Unpin for Single {} + +impl Stream for Single { + type Item = T; + + fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(self.0.take()) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.as_ref().map_or((0, Some(0)), |_| (1, Some(1))) + } +} + +/// Immediately propagates errors occurred in the base stream. +#[derive(Debug, Clone, Copy)] +pub struct PropagateBaseStreamError(PhantomData); + +type BaseStreamItem = as Stream>::Item; +type InnerStreamItem = as Stream>::Item; + +impl FlowController, InnerStreamItem> for PropagateBaseStreamError +where + St: TryStream, + St::Ok: TryStream + Unpin, + ::Error: From, +{ + fn next_step(item: BaseStreamItem) -> FlowStep, InnerStreamItem> { + match item { + // A new successful inner stream received + st @ Either::Left(_) => FlowStep::Continue(st), + // An error encountered + Either::Right(mut err) => FlowStep::Return(err.next_immediate().unwrap()), + } + } +} + +type SingleStreamResult = Single::Ok, ::Error>>; + +impl Stream for NestedTryStreamIntoEitherTryStream +where + St: TryStream, + St::Ok: TryStream + Unpin, + ::Error: From, +{ + // Item is either an inner stream or a stream containing a single error. + // This will allow using `Either`'s `Stream` implementation as both branches are actually streams of `Result`'s. + type Item = Either, SingleStreamResult>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let item = ready!(self.project().stream.try_poll_next(cx)); + + let out = match item { + Some(res) => match res { + // Emit successful inner stream as is + Ok(stream) => Either::Left(stream.into_stream()), + // Wrap an error into a stream containing a single item + err @ Err(_) => { + let res = err.map(|_: St::Ok| unreachable!()).map_err(Into::into); + + Either::Right(Single::new(res)) + } + }, + None => return Poll::Ready(None), + }; + + Poll::Ready(Some(out)) + } +} + +impl FusedStream for NestedTryStreamIntoEitherTryStream +where + St: TryStream + FusedStream, + St::Ok: TryStream + Unpin, + ::Error: From, +{ + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for NestedTryStreamIntoEitherTryStream +where + St: TryStream + Sink, + St::Ok: TryStream + Unpin, + ::Error: From<::Error>, +{ + type Error = >::Error; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_fold.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_fold.rs new file mode 100644 index 0000000000..d344d96e7d --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_fold.rs @@ -0,0 +1,93 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_fold`](super::TryStreamExt::try_fold) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryFold { + #[pin] + stream: St, + f: F, + accum: Option, + #[pin] + future: Option, + } +} + +impl fmt::Debug for TryFold +where + St: fmt::Debug, + Fut: fmt::Debug, + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryFold") + .field("stream", &self.stream) + .field("accum", &self.accum) + .field("future", &self.future) + .finish() + } +} + +impl TryFold +where + St: TryStream, + F: FnMut(T, St::Ok) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F, t: T) -> Self { + Self { stream, f, accum: Some(t), future: None } + } +} + +impl FusedFuture for TryFold +where + St: TryStream, + F: FnMut(T, St::Ok) -> Fut, + Fut: TryFuture, +{ + fn is_terminated(&self) -> bool { + self.accum.is_none() && self.future.is_none() + } +} + +impl Future for TryFold +where + St: TryStream, + F: FnMut(T, St::Ok) -> Fut, + Fut: TryFuture, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + + Poll::Ready(loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + // we're currently processing a future to produce a new accum value + let res = ready!(fut.try_poll(cx)); + this.future.set(None); + match res { + Ok(a) => *this.accum = Some(a), + Err(e) => break Err(e), + } + } else if this.accum.is_some() { + // we're waiting on a new item from the stream + let res = ready!(this.stream.as_mut().try_poll_next(cx)); + let a = this.accum.take().unwrap(); + match res { + Some(Ok(item)) => this.future.set(Some((this.f)(a, item))), + Some(Err(e)) => break Err(e), + None => break Ok(a), + } + } else { + panic!("Fold polled after completion") + } + }) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each.rs new file mode 100644 index 0000000000..6a081d84e7 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each.rs @@ -0,0 +1,68 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::ready; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`try_for_each`](super::TryStreamExt::try_for_each) method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryForEach { + #[pin] + stream: St, + f: F, + #[pin] + future: Option, + } +} + +impl fmt::Debug for TryForEach +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryForEach") + .field("stream", &self.stream) + .field("future", &self.future) + .finish() + } +} + +impl TryForEach +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, future: None } + } +} + +impl Future for TryForEach +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: TryFuture, +{ + type Output = Result<(), St::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + loop { + if let Some(fut) = this.future.as_mut().as_pin_mut() { + ready!(fut.try_poll(cx))?; + this.future.set(None); + } else { + match ready!(this.stream.as_mut().try_poll_next(cx)?) { + Some(e) => this.future.set(Some((this.f)(e))), + None => break, + } + } + } + Poll::Ready(Ok(())) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each_concurrent.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each_concurrent.rs new file mode 100644 index 0000000000..271e03c2ba --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_for_each_concurrent.rs @@ -0,0 +1,132 @@ +use crate::stream::{FuturesUnordered, StreamExt}; +use core::fmt; +use core::num::NonZeroUsize; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::TryStream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the + /// [`try_for_each_concurrent`](super::TryStreamExt::try_for_each_concurrent) + /// method. + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct TryForEachConcurrent { + #[pin] + stream: Option, + f: F, + futures: FuturesUnordered, + limit: Option, + } +} + +impl fmt::Debug for TryForEachConcurrent +where + St: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryForEachConcurrent") + .field("stream", &self.stream) + .field("futures", &self.futures) + .field("limit", &self.limit) + .finish() + } +} + +impl FusedFuture for TryForEachConcurrent +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future>, +{ + fn is_terminated(&self) -> bool { + self.stream.is_none() && self.futures.is_empty() + } +} + +impl TryForEachConcurrent +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future>, +{ + pub(super) fn new(stream: St, limit: Option, f: F) -> Self { + Self { + stream: Some(stream), + // Note: `limit` = 0 gets ignored. + limit: limit.and_then(NonZeroUsize::new), + f, + futures: FuturesUnordered::new(), + } + } +} + +impl Future for TryForEachConcurrent +where + St: TryStream, + F: FnMut(St::Ok) -> Fut, + Fut: Future>, +{ + type Output = Result<(), St::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + loop { + let mut made_progress_this_iter = false; + + // Check if we've already created a number of futures greater than `limit` + if this.limit.map(|limit| limit.get() > this.futures.len()).unwrap_or(true) { + let poll_res = match this.stream.as_mut().as_pin_mut() { + Some(stream) => stream.try_poll_next(cx), + None => Poll::Ready(None), + }; + + let elem = match poll_res { + Poll::Ready(Some(Ok(elem))) => { + made_progress_this_iter = true; + Some(elem) + } + Poll::Ready(None) => { + this.stream.set(None); + None + } + Poll::Pending => None, + Poll::Ready(Some(Err(e))) => { + // Empty the stream and futures so that we know + // the future has completed. + this.stream.set(None); + drop(core::mem::take(this.futures)); + return Poll::Ready(Err(e)); + } + }; + + if let Some(elem) = elem { + this.futures.push((this.f)(elem)); + } + } + + match this.futures.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(()))) => made_progress_this_iter = true, + Poll::Ready(None) => { + if this.stream.is_none() { + return Poll::Ready(Ok(())); + } + } + Poll::Pending => {} + Poll::Ready(Some(Err(e))) => { + // Empty the stream and futures so that we know + // the future has completed. + this.stream.set(None); + drop(core::mem::take(this.futures)); + return Poll::Ready(Err(e)); + } + } + + if !made_progress_this_iter { + return Poll::Pending; + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_next.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_next.rs new file mode 100644 index 0000000000..13fcf80cae --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_next.rs @@ -0,0 +1,34 @@ +use crate::stream::TryStreamExt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::{FusedStream, TryStream}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`try_next`](super::TryStreamExt::try_next) method. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct TryNext<'a, St: ?Sized> { + stream: &'a mut St, +} + +impl Unpin for TryNext<'_, St> {} + +impl<'a, St: ?Sized + TryStream + Unpin> TryNext<'a, St> { + pub(super) fn new(stream: &'a mut St) -> Self { + Self { stream } + } +} + +impl FusedFuture for TryNext<'_, St> { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +impl Future for TryNext<'_, St> { + type Output = Result, St::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.stream.try_poll_next_unpin(cx)?.map(Ok) + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_ready_chunks.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_ready_chunks.rs new file mode 100644 index 0000000000..8b1470ea26 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_ready_chunks.rs @@ -0,0 +1,126 @@ +use crate::stream::{Fuse, IntoStream, StreamExt}; + +use alloc::vec::Vec; +use core::fmt; +use core::pin::Pin; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_ready_chunks`](super::TryStreamExt::try_ready_chunks) method. + #[derive(Debug)] + #[must_use = "streams do nothing unless polled"] + pub struct TryReadyChunks { + #[pin] + stream: Fuse>, + cap: usize, // https://github.com/rust-lang/futures-rs/issues/1475 + } +} + +impl TryReadyChunks { + pub(super) fn new(stream: St, capacity: usize) -> Self { + assert!(capacity > 0); + + Self { stream: IntoStream::new(stream).fuse(), cap: capacity } + } + + delegate_access_inner!(stream, St, (. .)); +} + +type TryReadyChunksStreamError = + TryReadyChunksError<::Ok, ::Error>; + +impl Stream for TryReadyChunks { + type Item = Result, TryReadyChunksStreamError>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.as_mut().project(); + + let mut items: Vec = Vec::new(); + + loop { + match this.stream.as_mut().poll_next(cx) { + // Flush all the collected data if the underlying stream doesn't + // contain more ready values + Poll::Pending => { + return if items.is_empty() { + Poll::Pending + } else { + Poll::Ready(Some(Ok(items))) + } + } + + // Push the ready item into the buffer and check whether it is full. + // If so, return the buffer. + Poll::Ready(Some(Ok(item))) => { + if items.is_empty() { + items.reserve_exact(*this.cap); + } + items.push(item); + if items.len() >= *this.cap { + return Poll::Ready(Some(Ok(items))); + } + } + + // Return the already collected items and the error. + Poll::Ready(Some(Err(e))) => { + return Poll::Ready(Some(Err(TryReadyChunksError(items, e)))); + } + + // Since the underlying stream ran out of values, return what we + // have buffered, if we have anything. + Poll::Ready(None) => { + let last = if items.is_empty() { None } else { Some(Ok(items)) }; + return Poll::Ready(last); + } + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.stream.size_hint(); + let lower = lower / self.cap; + (lower, upper) + } +} + +impl FusedStream for TryReadyChunks { + fn is_terminated(&self) -> bool { + self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryReadyChunks +where + S: TryStream + Sink, +{ + type Error = >::Error; + + delegate_sink!(stream, Item); +} + +/// Error indicating, that while chunk was collected inner stream produced an error. +/// +/// Contains all items that were collected before an error occurred, and the stream error itself. +#[derive(PartialEq, Eq)] +pub struct TryReadyChunksError(pub Vec, pub E); + +impl fmt::Debug for TryReadyChunksError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.1.fmt(f) + } +} + +impl fmt::Display for TryReadyChunksError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.1.fmt(f) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryReadyChunksError {} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_skip_while.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_skip_while.rs new file mode 100644 index 0000000000..52aa2d478b --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_skip_while.rs @@ -0,0 +1,120 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_skip_while`](super::TryStreamExt::try_skip_while) + /// method. + #[must_use = "streams do nothing unless polled"] + pub struct TrySkipWhile where St: TryStream { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + done_skipping: bool, + } +} + +impl fmt::Debug for TrySkipWhile +where + St: TryStream + fmt::Debug, + St::Ok: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TrySkipWhile") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .field("done_skipping", &self.done_skipping) + .finish() + } +} + +impl TrySkipWhile +where + St: TryStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None, done_skipping: false } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for TrySkipWhile +where + St: TryStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if *this.done_skipping { + return this.stream.try_poll_next(cx); + } + + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let res = ready!(fut.try_poll(cx)); + this.pending_fut.set(None); + let skipped = res?; + let item = this.pending_item.take(); + if !skipped { + *this.done_skipping = true; + break item.map(Ok); + } + } else if let Some(item) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + this.pending_fut.set(Some((this.f)(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + let pending_len = usize::from(self.pending_item.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl FusedStream for TrySkipWhile +where + St: TryStream + FusedStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + fn is_terminated(&self) -> bool { + self.pending_item.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TrySkipWhile +where + S: TryStream + Sink, +{ + type Error = E; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_take_while.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_take_while.rs new file mode 100644 index 0000000000..4b5ff1ad38 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_take_while.rs @@ -0,0 +1,129 @@ +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + /// Stream for the [`try_take_while`](super::TryStreamExt::try_take_while) + /// method. + #[must_use = "streams do nothing unless polled"] + pub struct TryTakeWhile + where + St: TryStream, + { + #[pin] + stream: St, + f: F, + #[pin] + pending_fut: Option, + pending_item: Option, + done_taking: bool, + } +} + +impl fmt::Debug for TryTakeWhile +where + St: TryStream + fmt::Debug, + St::Ok: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryTakeWhile") + .field("stream", &self.stream) + .field("pending_fut", &self.pending_fut) + .field("pending_item", &self.pending_item) + .field("done_taking", &self.done_taking) + .finish() + } +} + +impl TryTakeWhile +where + St: TryStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + pub(super) fn new(stream: St, f: F) -> Self { + Self { stream, f, pending_fut: None, pending_item: None, done_taking: false } + } + + delegate_access_inner!(stream, St, ()); +} + +impl Stream for TryTakeWhile +where + St: TryStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if *this.done_taking { + return Poll::Ready(None); + } + + Poll::Ready(loop { + if let Some(fut) = this.pending_fut.as_mut().as_pin_mut() { + let res = ready!(fut.try_poll(cx)); + this.pending_fut.set(None); + let take = res?; + let item = this.pending_item.take(); + if take { + break item.map(Ok); + } else { + *this.done_taking = true; + break None; + } + } else if let Some(item) = ready!(this.stream.as_mut().try_poll_next(cx)?) { + this.pending_fut.set(Some((this.f)(&item))); + *this.pending_item = Some(item); + } else { + break None; + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + if self.done_taking { + return (0, Some(0)); + } + + let pending_len = usize::from(self.pending_item.is_some()); + let (_, upper) = self.stream.size_hint(); + let upper = match upper { + Some(x) => x.checked_add(pending_len), + None => None, + }; + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl FusedStream for TryTakeWhile +where + St: TryStream + FusedStream, + F: FnMut(&St::Ok) -> Fut, + Fut: TryFuture, +{ + fn is_terminated(&self) -> bool { + self.done_taking || self.pending_item.is_none() && self.stream.is_terminated() + } +} + +// Forwarding impl of Sink from the underlying stream +#[cfg(feature = "sink")] +impl Sink for TryTakeWhile +where + S: TryStream + Sink, +{ + type Error = E; + + delegate_sink!(stream, Item); +} diff --git a/anneal/v2/vendor/futures-util/src/stream/try_stream/try_unfold.rs b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_unfold.rs new file mode 100644 index 0000000000..fd9cdf1d8c --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/try_stream/try_unfold.rs @@ -0,0 +1,122 @@ +use super::assert_stream; +use core::fmt; +use core::pin::Pin; +use futures_core::future::TryFuture; +use futures_core::ready; +use futures_core::stream::Stream; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +/// Creates a `TryStream` from a seed and a closure returning a `TryFuture`. +/// +/// This function is the dual for the `TryStream::try_fold()` adapter: while +/// `TryStream::try_fold()` reduces a `TryStream` to one single value, +/// `try_unfold()` creates a `TryStream` from a seed value. +/// +/// `try_unfold()` will call the provided closure with the provided seed, then +/// wait for the returned `TryFuture` to complete with `(a, b)`. It will then +/// yield the value `a`, and use `b` as the next internal state. +/// +/// If the closure returns `None` instead of `Some(TryFuture)`, then the +/// `try_unfold()` will stop producing items and return `Poll::Ready(None)` in +/// future calls to `poll()`. +/// +/// In case of error generated by the returned `TryFuture`, the error will be +/// returned by the `TryStream`. The `TryStream` will then yield +/// `Poll::Ready(None)` in future calls to `poll()`. +/// +/// This function can typically be used when wanting to go from the "world of +/// futures" to the "world of streams": the provided closure can build a +/// `TryFuture` using other library functions working on futures, and +/// `try_unfold()` will turn it into a `TryStream` by repeating the operation. +/// +/// # Example +/// +/// ``` +/// # #[derive(Debug, PartialEq)] +/// # struct SomeError; +/// # futures::executor::block_on(async { +/// use futures::stream::{self, TryStreamExt}; +/// +/// let stream = stream::try_unfold(0, |state| async move { +/// if state < 0 { +/// return Err(SomeError); +/// } +/// +/// if state <= 2 { +/// let next_state = state + 1; +/// let yielded = state * 2; +/// Ok(Some((yielded, next_state))) +/// } else { +/// Ok(None) +/// } +/// }); +/// +/// let result: Result, _> = stream.try_collect().await; +/// assert_eq!(result, Ok(vec![0, 2, 4])); +/// # }); +/// ``` +pub fn try_unfold(init: T, f: F) -> TryUnfold +where + F: FnMut(T) -> Fut, + Fut: TryFuture>, +{ + assert_stream::, _>(TryUnfold { f, state: Some(init), fut: None }) +} + +pin_project! { + /// Stream for the [`try_unfold`] function. + #[must_use = "streams do nothing unless polled"] + pub struct TryUnfold { + f: F, + state: Option, + #[pin] + fut: Option, + } +} + +impl fmt::Debug for TryUnfold +where + T: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TryUnfold").field("state", &self.state).field("fut", &self.fut).finish() + } +} + +impl Stream for TryUnfold +where + F: FnMut(T) -> Fut, + Fut: TryFuture>, +{ + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if let Some(state) = this.state.take() { + this.fut.set(Some((this.f)(state))); + } + + match this.fut.as_mut().as_pin_mut() { + None => { + // The future previously errored + Poll::Ready(None) + } + Some(future) => { + let step = ready!(future.try_poll(cx)); + this.fut.set(None); + + match step { + Ok(Some((item, next_state))) => { + *this.state = Some(next_state); + Poll::Ready(Some(Ok(item))) + } + Ok(None) => Poll::Ready(None), + Err(e) => Poll::Ready(Some(Err(e))), + } + } + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/stream/unfold.rs b/anneal/v2/vendor/futures-util/src/stream/unfold.rs new file mode 100644 index 0000000000..2f48cccb44 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/stream/unfold.rs @@ -0,0 +1,119 @@ +use super::assert_stream; +use crate::unfold_state::UnfoldState; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +/// Creates a `Stream` from a seed and a closure returning a `Future`. +/// +/// This function is the dual for the `Stream::fold()` adapter: while +/// `Stream::fold()` reduces a `Stream` to one single value, `unfold()` creates a +/// `Stream` from a seed value. +/// +/// `unfold()` will call the provided closure with the provided seed, then wait +/// for the returned `Future` to complete with `(a, b)`. It will then yield the +/// value `a`, and use `b` as the next internal state. +/// +/// If the closure returns `None` instead of `Some(Future)`, then the `unfold()` +/// will stop producing items and return `Poll::Ready(None)` in future +/// calls to `poll()`. +/// +/// This function can typically be used when wanting to go from the "world of +/// futures" to the "world of streams": the provided closure can build a +/// `Future` using other library functions working on futures, and `unfold()` +/// will turn it into a `Stream` by repeating the operation. +/// +/// # Example +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::stream::{self, StreamExt}; +/// +/// let stream = stream::unfold(0, |state| async move { +/// if state <= 2 { +/// let next_state = state + 1; +/// let yielded = state * 2; +/// Some((yielded, next_state)) +/// } else { +/// None +/// } +/// }); +/// +/// let result = stream.collect::>().await; +/// assert_eq!(result, vec![0, 2, 4]); +/// # }); +/// ``` +pub fn unfold(init: T, f: F) -> Unfold +where + F: FnMut(T) -> Fut, + Fut: Future>, +{ + assert_stream::(Unfold { f, state: UnfoldState::Value { value: init } }) +} + +pin_project! { + /// Stream for the [`unfold`] function. + #[must_use = "streams do nothing unless polled"] + pub struct Unfold { + f: F, + #[pin] + state: UnfoldState, + } +} + +impl fmt::Debug for Unfold +where + T: fmt::Debug, + Fut: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Unfold").field("state", &self.state).finish() + } +} + +impl FusedStream for Unfold +where + F: FnMut(T) -> Fut, + Fut: Future>, +{ + fn is_terminated(&self) -> bool { + if let UnfoldState::Empty = self.state { + true + } else { + false + } + } +} + +impl Stream for Unfold +where + F: FnMut(T) -> Fut, + Fut: Future>, +{ + type Item = Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + + if let Some(state) = this.state.as_mut().take_value() { + this.state.set(UnfoldState::Future { future: (this.f)(state) }); + } + + let step = match this.state.as_mut().project_future() { + Some(fut) => ready!(fut.poll(cx)), + None => panic!("Unfold must not be polled after it returned `Poll::Ready(None)`"), + }; + + if let Some((item, next_state)) = step { + this.state.set(UnfoldState::Value { value: next_state }); + Poll::Ready(Some(item)) + } else { + this.state.set(UnfoldState::Empty); + Poll::Ready(None) + } + } +} diff --git a/anneal/v2/vendor/futures-util/src/task/mod.rs b/anneal/v2/vendor/futures-util/src/task/mod.rs new file mode 100644 index 0000000000..7a9e993e5e --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/task/mod.rs @@ -0,0 +1,40 @@ +//! Tools for working with tasks. +//! +//! This module contains: +//! +//! - [`Spawn`], a trait for spawning new tasks. +//! - [`Context`], a context of an asynchronous task, +//! including a handle for waking up the task. +//! - [`Waker`], a handle for waking up a task. +//! +//! The remaining types and traits in the module are used for implementing +//! executors or dealing with synchronization issues around task wakeup. + +#[doc(no_inline)] +pub use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; + +pub use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError, UnsafeFutureObj}; + +pub use futures_task::noop_waker; +pub use futures_task::noop_waker_ref; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use futures_task::ArcWake; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use futures_task::waker; + +#[cfg_attr(target_os = "none", cfg(target_has_atomic = "ptr"))] +#[cfg(feature = "alloc")] +pub use futures_task::{waker_ref, WakerRef}; + +#[cfg_attr( + target_os = "none", + cfg(any(target_has_atomic = "ptr", feature = "portable-atomic")) +)] +pub use futures_core::task::__internal::AtomicWaker; + +mod spawn; +pub use self::spawn::{LocalSpawnExt, SpawnExt}; diff --git a/anneal/v2/vendor/futures-util/src/task/spawn.rs b/anneal/v2/vendor/futures-util/src/task/spawn.rs new file mode 100644 index 0000000000..d9e9985309 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/task/spawn.rs @@ -0,0 +1,169 @@ +use futures_task::{LocalSpawn, Spawn}; + +#[cfg(feature = "compat")] +use crate::compat::Compat; + +#[cfg(feature = "channel")] +#[cfg(feature = "std")] +use crate::future::{FutureExt, RemoteHandle}; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use futures_core::future::Future; +#[cfg(feature = "alloc")] +use futures_task::{FutureObj, LocalFutureObj, SpawnError}; + +impl SpawnExt for Sp where Sp: Spawn {} +impl LocalSpawnExt for Sp where Sp: LocalSpawn {} + +/// Extension trait for `Spawn`. +pub trait SpawnExt: Spawn { + /// Spawns a task that polls the given future with output `()` to + /// completion. + /// + /// This method returns a [`Result`] that contains a [`SpawnError`] if + /// spawning fails. + /// + /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if + /// you want to spawn a future with output other than `()` or if you want + /// to be able to await its completion. + /// + /// Note this method will eventually be replaced with the upcoming + /// `Spawn::spawn` method which will take a `dyn Future` as input. + /// Technical limitations prevent `Spawn::spawn` from being implemented + /// today. Feel free to use this method in the meantime. + /// + /// ``` + /// # { + /// use futures::executor::ThreadPool; + /// use futures::task::SpawnExt; + /// + /// let executor = ThreadPool::new().unwrap(); + /// + /// let future = async { /* ... */ }; + /// executor.spawn(future).unwrap(); + /// # } + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + #[cfg(feature = "alloc")] + fn spawn(&self, future: Fut) -> Result<(), SpawnError> + where + Fut: Future + Send + 'static, + { + self.spawn_obj(FutureObj::new(Box::new(future))) + } + + /// Spawns a task that polls the given future to completion and returns a + /// future that resolves to the spawned future's output. + /// + /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if + /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that + /// resolves to the output of the spawned future. + /// + /// ``` + /// # { + /// use futures::executor::{block_on, ThreadPool}; + /// use futures::future; + /// use futures::task::SpawnExt; + /// + /// let executor = ThreadPool::new().unwrap(); + /// + /// let future = future::ready(1); + /// let join_handle_fut = executor.spawn_with_handle(future).unwrap(); + /// assert_eq!(block_on(join_handle_fut), 1); + /// # } + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn spawn_with_handle(&self, future: Fut) -> Result, SpawnError> + where + Fut: Future + Send + 'static, + Fut::Output: Send, + { + let (future, handle) = future.remote_handle(); + self.spawn(future)?; + Ok(handle) + } + + /// Wraps a [`Spawn`] and makes it usable as a futures 0.1 `Executor`. + /// Requires the `compat` feature to enable. + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> Compat + where + Self: Sized, + { + Compat::new(self) + } +} + +/// Extension trait for `LocalSpawn`. +pub trait LocalSpawnExt: LocalSpawn { + /// Spawns a task that polls the given future with output `()` to + /// completion. + /// + /// This method returns a [`Result`] that contains a [`SpawnError`] if + /// spawning fails. + /// + /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if + /// you want to spawn a future with output other than `()` or if you want + /// to be able to await its completion. + /// + /// Note this method will eventually be replaced with the upcoming + /// `Spawn::spawn` method which will take a `dyn Future` as input. + /// Technical limitations prevent `Spawn::spawn` from being implemented + /// today. Feel free to use this method in the meantime. + /// + /// ``` + /// use futures::executor::LocalPool; + /// use futures::task::LocalSpawnExt; + /// + /// let executor = LocalPool::new(); + /// let spawner = executor.spawner(); + /// + /// let future = async { /* ... */ }; + /// spawner.spawn_local(future).unwrap(); + /// ``` + #[cfg(feature = "alloc")] + fn spawn_local(&self, future: Fut) -> Result<(), SpawnError> + where + Fut: Future + 'static, + { + self.spawn_local_obj(LocalFutureObj::new(Box::new(future))) + } + + /// Spawns a task that polls the given future to completion and returns a + /// future that resolves to the spawned future's output. + /// + /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if + /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that + /// resolves to the output of the spawned future. + /// + /// ``` + /// use futures::executor::LocalPool; + /// use futures::task::LocalSpawnExt; + /// + /// let mut executor = LocalPool::new(); + /// let spawner = executor.spawner(); + /// + /// let future = async { 1 }; + /// let join_handle_fut = spawner.spawn_local_with_handle(future).unwrap(); + /// assert_eq!(executor.run_until(join_handle_fut), 1); + /// ``` + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn spawn_local_with_handle( + &self, + future: Fut, + ) -> Result, SpawnError> + where + Fut: Future + 'static, + { + let (future, handle) = future.remote_handle(); + self.spawn_local(future)?; + Ok(handle) + } +} diff --git a/anneal/v2/vendor/futures-util/src/unfold_state.rs b/anneal/v2/vendor/futures-util/src/unfold_state.rs new file mode 100644 index 0000000000..b66956bbd8 --- /dev/null +++ b/anneal/v2/vendor/futures-util/src/unfold_state.rs @@ -0,0 +1,39 @@ +use core::pin::Pin; + +use pin_project_lite::pin_project; + +pin_project! { + /// UnfoldState used for stream and sink unfolds + #[project = UnfoldStateProj] + #[project_replace = UnfoldStateProjReplace] + #[derive(Debug)] + pub(crate) enum UnfoldState { + Value { + value: T, + }, + Future { + #[pin] + future: R, + }, + Empty, + } +} + +impl UnfoldState { + pub(crate) fn project_future(self: Pin<&mut Self>) -> Option> { + match self.project() { + UnfoldStateProj::Future { future } => Some(future), + _ => None, + } + } + + pub(crate) fn take_value(self: Pin<&mut Self>) -> Option { + match &*self { + Self::Value { .. } => match self.project_replace(Self::Empty) { + UnfoldStateProjReplace::Value { value } => Some(value), + _ => unreachable!(), + }, + _ => None, + } + } +} diff --git a/anneal/v2/vendor/generic-array/.cargo-checksum.json b/anneal/v2/vendor/generic-array/.cargo-checksum.json new file mode 100644 index 0000000000..ccd0b192f4 --- /dev/null +++ b/anneal/v2/vendor/generic-array/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"4ffa26adbb029ef507f165ca47fb9699af8b49e642d1e60942666273c5a521a9","CHANGELOG.md":"478d33deb9d0c943c20671eed67bc393891aad1679e61f74412f98c9a5017f84","Cargo.toml":"4b5daed75505275d11f4854dd9172f910da61d9856ca2936d95e2e6e0c9040e4","Cargo.toml.orig":"12c6e718e7f54564e81ca6e5f5e3d0fef220a86e8dab77215e6ff38b6f6c2081","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","src/arr.rs":"c115d6926deb769ced772e9c4e1c84baf1bdea4fe4b9eb2061658a63869eab62","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impl_zeroize.rs":"dd1af63ef2cba2120c6f775350c98eb12bb1be6ba784d5350d07d4ae5419c292","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"4f50253f4130caa0780984b64467ca1916a881410f631f7eb85a1724b3ab4ced","src/lib.rs":"20b64b4359b0e82a3523fd536ad06de25e174cead734cffd3fa5f7c48f659247","src/sequence.rs":"26679cfec035bae7298f067f37e8d42a1eda8fe241e9cf2c2977ba4bddddab1d"},"package":"85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"} \ No newline at end of file diff --git a/anneal/v2/vendor/generic-array/.cargo_vcs_info.json b/anneal/v2/vendor/generic-array/.cargo_vcs_info.json new file mode 100644 index 0000000000..5d0288db36 --- /dev/null +++ b/anneal/v2/vendor/generic-array/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "1397d2bb40c406901b7827161b73b34b056cbe3a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/generic-array/CHANGELOG.md b/anneal/v2/vendor/generic-array/CHANGELOG.md new file mode 100644 index 0000000000..0c8a9361d1 --- /dev/null +++ b/anneal/v2/vendor/generic-array/CHANGELOG.md @@ -0,0 +1,101 @@ +* **`0.14.7`** + * Backport [#133](https://github.com/fizyk20/generic-array/pull/133) and [#134](https://github.com/fizyk20/generic-array/pull/134) + +* **`0.14.6`** + * Add an optional `Zeroize` impl for `GenericArray` ([#126](https://github.com/fizyk20/generic-array/pull/126) and [#112](https://github.com/fizyk20/generic-array/pull/112)) + * Cleanup some unsafe ([#125](https://github.com/fizyk20/generic-array/pull/125)) and typos ([#114](https://github.com/fizyk20/generic-array/pull/114)) + * Use `include` in `Cargo.toml` to reduce package size + +* **`0.14.5`** + * Fix unsoundness behavior in `GenericArrayIter::clone` ([#120](https://github.com/fizyk20/generic-array/pull/120)) + +* **`0.14.4`** + * Update `typenum` to `1.12.0` + * Make `Drop` a no-op when the inner type does not require `Drop` (using `core::mem::needs_drop`) + +* **`0.14.3`** + * Improve behavior of `GenericArray::from_exact_iter` to assume `ExactIterator`s can lie. + * Fix alignment of zero-length `GenericArray`s + * Implement `From<&[T; N]> for &GenericArray` and its mutable variant + +* **`0.14.2`** + * Lower MSRV to `1.36.0` without `From<[T; N]>` implementations. + +* **`0.14.1`** + * Fix element conversions in `arr!` macro. + +* **`0.14.0`** + * Replace `Into` implementations with the more general `From`. + * Requires minumum Rust version of 1.41.0 + * Fix unsoundness in `arr!` macro. + * Fix meta variable misuse + * Fix Undefined Behavior across the crate by switching to `MaybeUninit` + * Improve some documentation and doctests + * Add `AsRef<[T; N]>` and `AsMut<[T; N]>` impls to `GenericArray` + * Add `Split` impl for `&GenericArray` and `&mut GenericArray` + +* **`0.13.2`** + * Add feature `more_lengths`, which adds more `From`/`Into` implementations for arrays of various lengths. + +* **`0.13.1`** + * Mark `GenericArray` as `#[repr(transparent)]` + * Implement `Into<[T; N]>` for `GenericArray` up to N=32 + +* **`0.13.0`** + * Allow `arr!` to be imported with use syntax. + * Requires minumum Rust version of 1.30.1 + +* **`0.12.2`** + * Implement `FusedIterator` for `GenericArrayIter` + +* **`0.12.1`** + * Use internal iteration where possible and provide more efficient internal iteration methods. + +* **`0.12.0`** + * Allow trailing commas in `arr!` macro. + * **BREAKING**: Serialize `GenericArray` using `serde` tuples, instead of variable-length sequences. This may not be compatible with old serialized data. + +* **`0.11.0`** + * **BREAKING** Redesign `GenericSequence` with an emphasis on use in generic type parameters. + * Add `MappedGenericSequence` and `FunctionalSequence` + * Implements optimized `map`, `zip` and `fold` for `GenericArray`, `&GenericArray` and `&mut GenericArray` + * **BREAKING** Remove `map_ref`, `zip_ref` and `map_slice` + * `map_slice` is now equivalent to `GenericArray::from_iter(slice.iter().map(...))` +* **`0.10.0`** + * Add `GenericSequence`, `Lengthen`, `Shorten`, `Split` and `Concat` traits. + * Redefine `transmute` to avert errors. +* **`0.9.0`** + * Rewrite construction methods to be well-defined in panic situations, correctly dropping elements. + * `NoDrop` crate replaced by `ManuallyDrop` as it became stable in Rust core. + * Add optimized `map`/`map_ref` and `zip`/`zip_ref` methods to `GenericArray` +* **`0.8.0`** + * Implement `AsRef`, `AsMut`, `Borrow`, `BorrowMut`, `Hash` for `GenericArray` + * Update `serde` to `1.0` + * Update `typenum` + * Make macro `arr!` non-cloning + * Implement `From<[T; N]>` up to `N=32` + * Fix #45 +* **`0.7.0`** + * Upgrade `serde` to `0.9` + * Make `serde` with `no_std` + * Implement `PartialOrd`/`Ord` for `GenericArray` +* **`0.6.0`** + * Fixed #30 + * Implement `Default` for `GenericArray` + * Implement `LowerHex` and `UpperHex` for `GenericArray` + * Use `precision` formatting field in hex representation + * Add `as_slice`, `as_mut_slice` + * Remove `GenericArray::new` in favor of `Default` trait + * Add `from_slice` and `from_mut_slice` + * `no_std` and `core` for crate. +* **`0.5.0`** + * Update `serde` + * remove `no_std` feature, fixed #19 +* **`0.4.0`** + * Re-export `typenum` +* **`0.3.0`** + * Implement `IntoIter` for `GenericArray` + * Add `map` method + * Add optional `serde` (de)serialization support feature. +* **`< 0.3.0`** + * Initial implementation in late 2015 diff --git a/anneal/v2/vendor/generic-array/Cargo.toml b/anneal/v2/vendor/generic-array/Cargo.toml new file mode 100644 index 0000000000..a301cebfbb --- /dev/null +++ b/anneal/v2/vendor/generic-array/Cargo.toml @@ -0,0 +1,75 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "generic-array" +version = "0.14.7" +authors = [ + "Bartłomiej Kamiński ", + "Aaron Trent ", +] +include = [ + "src/**/*", + "LICENSE", + "README.md", + "CHANGELOG.md", + "build.rs", +] +description = "Generic types implementing functionality of arrays" +documentation = "http://fizyk20.github.io/generic-array/generic_array/" +readme = "README.md" +keywords = [ + "generic", + "array", +] +categories = [ + "data-structures", + "no-std", +] +license = "MIT" +repository = "https://github.com/fizyk20/generic-array.git" + +[package.metadata.docs.rs] +features = [ + "serde", + "zeroize", +] + +[lib] +name = "generic_array" + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.typenum] +version = "1.12" + +[dependencies.zeroize] +version = "1" +optional = true +default-features = false + +[dev-dependencies.bincode] +version = "1.0" + +[dev-dependencies.serde_json] +version = "1.0" + +[build-dependencies.version_check] +version = "0.9" + +[features] +more_lengths = [] + +[badges.travis-ci] +repository = "fizyk20/generic-array" diff --git a/anneal/v2/vendor/generic-array/Cargo.toml.orig b/anneal/v2/vendor/generic-array/Cargo.toml.orig new file mode 100644 index 0000000000..b518422205 --- /dev/null +++ b/anneal/v2/vendor/generic-array/Cargo.toml.orig @@ -0,0 +1,43 @@ +[package] + +name = "generic-array" +version = "0.14.7" +authors = [ "Bartłomiej Kamiński ", "Aaron Trent " ] + +description = "Generic types implementing functionality of arrays" +readme = "README.md" + +license = "MIT" + +documentation = "http://fizyk20.github.io/generic-array/generic_array/" +repository = "https://github.com/fizyk20/generic-array.git" + +keywords = ["generic", "array"] +categories = ["data-structures", "no-std"] + +include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md", "build.rs"] + +[badges] +travis-ci = { repository = "fizyk20/generic-array" } + +[lib] +name = "generic_array" + +[features] +more_lengths = [] + +[dependencies] +typenum = "1.12" +serde = { version = "1.0", optional = true, default-features = false } +zeroize = { version = "1", optional = true, default-features = false } + +[dev_dependencies] +# this can't yet be made optional, see https://github.com/rust-lang/cargo/issues/1596 +serde_json = "1.0" +bincode = "1.0" + +[build_dependencies] +version_check = "0.9" + +[package.metadata.docs.rs] +features = ["serde", "zeroize"] \ No newline at end of file diff --git a/anneal/v2/vendor/generic-array/LICENSE b/anneal/v2/vendor/generic-array/LICENSE new file mode 100644 index 0000000000..6d318946df --- /dev/null +++ b/anneal/v2/vendor/generic-array/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Bartłomiej Kamiński + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/anneal/v2/vendor/generic-array/README.md b/anneal/v2/vendor/generic-array/README.md new file mode 100644 index 0000000000..cf54f40550 --- /dev/null +++ b/anneal/v2/vendor/generic-array/README.md @@ -0,0 +1,62 @@ +[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array) +[![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array) +# generic-array + +This crate implements generic array types for Rust. + +**Requires minumum Rust version of 1.36.0, or 1.41.0 for `From<[T; N]>` implementations** + +[Documentation](http://fizyk20.github.io/generic-array/generic_array/) + +## Usage + +The Rust arrays `[T; N]` are problematic in that they can't be used generically with respect to `N`, so for example this won't work: + +```rust +struct Foo { + data: [i32; N] +} +``` + +**generic-array** defines a new trait `ArrayLength` and a struct `GenericArray>`, which let the above be implemented as: + +```rust +struct Foo> { + data: GenericArray +} +``` + +The `ArrayLength` trait is implemented by default for [unsigned integer types](http://fizyk20.github.io/generic-array/typenum/uint/index.html) from [typenum](http://fizyk20.github.io/generic-array/typenum/index.html) crate: + +```rust +use generic_array::typenum::U5; + +struct Foo> { + data: GenericArray +} + +fn main() { + let foo = Foo::{data: GenericArray::default()}; +} +``` + +For example, `GenericArray` would work almost like `[T; 5]`: + +```rust +use generic_array::typenum::U5; + +struct Foo> { + data: GenericArray +} + +fn main() { + let foo = Foo::{data: GenericArray::default()}; +} +``` + +In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below: + +```rust +let array = arr![u32; 1, 2, 3]; +assert_eq!(array[2], 3); +``` diff --git a/anneal/v2/vendor/generic-array/build.rs b/anneal/v2/vendor/generic-array/build.rs new file mode 100644 index 0000000000..c27c7e3fa9 --- /dev/null +++ b/anneal/v2/vendor/generic-array/build.rs @@ -0,0 +1,5 @@ +fn main() { + if version_check::is_min_version("1.41.0").unwrap_or(false) { + println!("cargo:rustc-cfg=relaxed_coherence"); + } +} diff --git a/anneal/v2/vendor/generic-array/src/arr.rs b/anneal/v2/vendor/generic-array/src/arr.rs new file mode 100644 index 0000000000..cdcc038a3d --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/arr.rs @@ -0,0 +1,125 @@ +//! Implementation for `arr!` macro. + +use super::ArrayLength; +use core::ops::Add; +use typenum::U1; + +/// Helper trait for `arr!` macro +pub trait AddLength>: ArrayLength { + /// Resulting length + type Output: ArrayLength; +} + +impl AddLength for N1 +where + N1: ArrayLength + Add, + N2: ArrayLength, + >::Output: ArrayLength, +{ + type Output = >::Output; +} + +/// Helper type for `arr!` macro +pub type Inc = >::Output; + +#[doc(hidden)] +#[macro_export] +macro_rules! arr_impl { + (@replace_expr $e:expr) => { 1 }; + ($T:ty; $N:ty, [$($x:expr),*], []) => ({ + const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*; + + #[inline(always)] + fn __do_transmute>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray { + unsafe { $crate::transmute(arr) } + } + + let _: [(); <$N as $crate::typenum::Unsigned>::USIZE] = [(); __ARR_LENGTH]; + + __do_transmute::<$T, $N>([$($x as $T),*]) + }); + ($T:ty; $N:ty, [], [$x1:expr]) => ( + $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], []) + ); + ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => ( + $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+]) + ); + ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => ( + $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], []) + ); + ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => ( + $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+]) + ); +} + +/// Macro allowing for easy generation of Generic Arrays. +/// Example: `let test = arr![u32; 1, 2, 3];` +#[macro_export] +macro_rules! arr { + ($T:ty; $(,)*) => ({ + unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) } + }); + ($T:ty; $($x:expr),* $(,)*) => ( + $crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*]) + ); + ($($x:expr,)+) => (arr![$($x),+]); + () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`") +} + +mod doctests_only { + /// + /// # With ellision + /// + /// Testing that lifetimes aren't transmuted when they're ellided. + /// + /// ```compile_fail + /// #[macro_use] extern crate generic_array; + /// fn main() { + /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { + /// arr![&A; a][0] + /// } + /// } + /// ``` + /// + /// ```rust + /// #[macro_use] extern crate generic_array; + /// fn main() { + /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A { + /// arr![&A; a][0] + /// } + /// } + /// ``` + /// + /// # Without ellision + /// + /// Testing that lifetimes aren't transmuted when they're specified explicitly. + /// + /// ```compile_fail + /// #[macro_use] extern crate generic_array; + /// fn main() { + /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { + /// arr![&'a A; a][0] + /// } + /// } + /// ``` + /// + /// ```compile_fail + /// #[macro_use] extern crate generic_array; + /// fn main() { + /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { + /// arr![&'static A; a][0] + /// } + /// } + /// ``` + /// + /// ```rust + /// #[macro_use] extern crate generic_array; + /// fn main() { + /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A { + /// arr![&'a A; a][0] + /// } + /// } + /// ``` + #[allow(dead_code)] + pub enum DocTests {} +} diff --git a/anneal/v2/vendor/generic-array/src/functional.rs b/anneal/v2/vendor/generic-array/src/functional.rs new file mode 100644 index 0000000000..2ddcc5c4c4 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/functional.rs @@ -0,0 +1,95 @@ +//! Functional programming with generic sequences +//! +//! Please see `tests/generics.rs` for examples of how to best use these in your generic functions. + +use super::ArrayLength; +use core::iter::FromIterator; + +use crate::sequence::*; + +/// Defines the relationship between one generic sequence and another, +/// for operations such as `map` and `zip`. +pub unsafe trait MappedGenericSequence: GenericSequence +where + Self::Length: ArrayLength, +{ + /// Mapped sequence type + type Mapped: GenericSequence; +} + +unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a S +where + &'a S: GenericSequence, + S: GenericSequence>::Length>, + >::Length: ArrayLength, +{ + type Mapped = >::Mapped; +} + +unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a mut S +where + &'a mut S: GenericSequence, + S: GenericSequence>::Length>, + >::Length: ArrayLength, +{ + type Mapped = >::Mapped; +} + +/// Accessor type for a mapped generic sequence +pub type MappedSequence = + <>::Mapped as GenericSequence>::Sequence; + +/// Defines functional programming methods for generic sequences +pub unsafe trait FunctionalSequence: GenericSequence { + /// Maps a `GenericSequence` to another `GenericSequence`. + /// + /// If the mapping function panics, any already initialized elements in the new sequence + /// will be dropped, AND any unused elements in the source sequence will also be dropped. + fn map(self, f: F) -> MappedSequence + where + Self: MappedGenericSequence, + Self::Length: ArrayLength, + F: FnMut(Self::Item) -> U, + { + FromIterator::from_iter(self.into_iter().map(f)) + } + + /// Combines two `GenericSequence` instances and iterates through both of them, + /// initializing a new `GenericSequence` with the result of the zipped mapping function. + /// + /// If the mapping function panics, any already initialized elements in the new sequence + /// will be dropped, AND any unused elements in the source sequences will also be dropped. + #[inline] + fn zip(self, rhs: Rhs, f: F) -> MappedSequence + where + Self: MappedGenericSequence, + Rhs: MappedGenericSequence>, + Self::Length: ArrayLength + ArrayLength, + Rhs: GenericSequence, + F: FnMut(Self::Item, Rhs::Item) -> U, + { + rhs.inverted_zip2(self, f) + } + + /// Folds (or reduces) a sequence of data into a single value. + /// + /// If the fold function panics, any unused elements will be dropped. + fn fold(self, init: U, f: F) -> U + where + F: FnMut(U, Self::Item) -> U, + { + self.into_iter().fold(init, f) + } +} + +unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a S +where + &'a S: GenericSequence, +{ +} + +unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a mut S +where + &'a mut S: GenericSequence, +{ +} diff --git a/anneal/v2/vendor/generic-array/src/hex.rs b/anneal/v2/vendor/generic-array/src/hex.rs new file mode 100644 index 0000000000..33c796f3c9 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/hex.rs @@ -0,0 +1,105 @@ +//! Generic array are commonly used as a return value for hash digests, so +//! it's a good idea to allow to hexlify them easily. This module implements +//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits. +//! +//! Example: +//! +//! ```rust +//! # #[macro_use] +//! # extern crate generic_array; +//! # extern crate typenum; +//! # fn main() { +//! let array = arr![u8; 10, 20, 30]; +//! assert_eq!(format!("{:x}", array), "0a141e"); +//! # } +//! ``` +//! + +use core::{fmt, str, ops::Add, cmp::min}; + +use typenum::*; + +use crate::{ArrayLength, GenericArray}; + +static LOWER_CHARS: &'static [u8] = b"0123456789abcdef"; +static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF"; + +impl> fmt::LowerHex for GenericArray +where + T: Add, + >::Output: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); + let max_hex = (max_digits >> 1) + (max_digits & 1); + + if T::USIZE < 1024 { + // For small arrays use a stack allocated + // buffer of 2x number of bytes + let mut res = GenericArray::>::default(); + + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { + res[i * 2] = LOWER_CHARS[(c >> 4) as usize]; + res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; + }); + + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; + } else { + // For large array use chunks of up to 1024 bytes (2048 hex chars) + let mut buf = [0u8; 2048]; + let mut digits_left = max_digits; + + for chunk in self[..max_hex].chunks(1024) { + chunk.iter().enumerate().for_each(|(i, c)| { + buf[i * 2] = LOWER_CHARS[(c >> 4) as usize]; + buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; + }); + + let n = min(chunk.len() * 2, digits_left); + f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; + digits_left -= n; + } + } + Ok(()) + } +} + +impl> fmt::UpperHex for GenericArray +where + T: Add, + >::Output: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); + let max_hex = (max_digits >> 1) + (max_digits & 1); + + if T::USIZE < 1024 { + // For small arrays use a stack allocated + // buffer of 2x number of bytes + let mut res = GenericArray::>::default(); + + self.iter().take(max_hex).enumerate().for_each(|(i, c)| { + res[i * 2] = UPPER_CHARS[(c >> 4) as usize]; + res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; + }); + + f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; + } else { + // For large array use chunks of up to 1024 bytes (2048 hex chars) + let mut buf = [0u8; 2048]; + let mut digits_left = max_digits; + + for chunk in self[..max_hex].chunks(1024) { + chunk.iter().enumerate().for_each(|(i, c)| { + buf[i * 2] = UPPER_CHARS[(c >> 4) as usize]; + buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; + }); + + let n = min(chunk.len() * 2, digits_left); + f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; + digits_left -= n; + } + } + Ok(()) + } +} diff --git a/anneal/v2/vendor/generic-array/src/impl_serde.rs b/anneal/v2/vendor/generic-array/src/impl_serde.rs new file mode 100644 index 0000000000..49c095a5de --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/impl_serde.rs @@ -0,0 +1,108 @@ +//! Serde serialization/deserialization implementation + +use core::fmt; +use core::marker::PhantomData; +use serde::de::{self, SeqAccess, Visitor}; +use serde::{ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer}; +use {ArrayLength, GenericArray}; + +impl Serialize for GenericArray +where + T: Serialize, + N: ArrayLength, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut tup = serializer.serialize_tuple(N::USIZE)?; + for el in self { + tup.serialize_element(el)?; + } + + tup.end() + } +} + +struct GAVisitor { + _t: PhantomData, + _n: PhantomData, +} + +impl<'de, T, N> Visitor<'de> for GAVisitor +where + T: Deserialize<'de> + Default, + N: ArrayLength, +{ + type Value = GenericArray; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct GenericArray") + } + + fn visit_seq(self, mut seq: A) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + let mut result = GenericArray::default(); + for i in 0..N::USIZE { + result[i] = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(i, &self))?; + } + Ok(result) + } +} + +impl<'de, T, N> Deserialize<'de> for GenericArray +where + T: Deserialize<'de> + Default, + N: ArrayLength, +{ + fn deserialize(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let visitor = GAVisitor { + _t: PhantomData, + _n: PhantomData, + }; + deserializer.deserialize_tuple(N::USIZE, visitor) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bincode; + use typenum; + + #[test] + fn test_serialize() { + let array = GenericArray::::default(); + let serialized = bincode::serialize(&array); + assert!(serialized.is_ok()); + } + + #[test] + fn test_deserialize() { + let mut array = GenericArray::::default(); + array[0] = 1; + array[1] = 2; + let serialized = bincode::serialize(&array).unwrap(); + let deserialized = bincode::deserialize::>(&serialized); + assert!(deserialized.is_ok()); + let array = deserialized.unwrap(); + assert_eq!(array[0], 1); + assert_eq!(array[1], 2); + } + + #[test] + fn test_serialized_size() { + let array = GenericArray::::default(); + let size = bincode::serialized_size(&array).unwrap(); + assert_eq!(size, 1); + } + +} diff --git a/anneal/v2/vendor/generic-array/src/impl_zeroize.rs b/anneal/v2/vendor/generic-array/src/impl_zeroize.rs new file mode 100644 index 0000000000..4edf558fc6 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/impl_zeroize.rs @@ -0,0 +1,24 @@ +use crate::{ArrayLength, GenericArray}; + +use zeroize::Zeroize; + +impl> Zeroize for GenericArray { + fn zeroize(&mut self) { + self.as_mut_slice().iter_mut().zeroize() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_zeroize() { + let mut array = GenericArray::::default(); + array[0] = 4; + array[1] = 9; + array.zeroize(); + assert_eq!(array[0], 0); + assert_eq!(array[1], 0); + } +} diff --git a/anneal/v2/vendor/generic-array/src/impls.rs b/anneal/v2/vendor/generic-array/src/impls.rs new file mode 100644 index 0000000000..47ecc1d31d --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/impls.rs @@ -0,0 +1,269 @@ +use core::borrow::{Borrow, BorrowMut}; +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; + +use super::{ArrayLength, GenericArray}; + +use crate::functional::*; +use crate::sequence::*; + +impl Default for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn default() -> Self { + Self::generate(|_| T::default()) + } +} + +impl Clone for GenericArray +where + N: ArrayLength, +{ + fn clone(&self) -> GenericArray { + self.map(Clone::clone) + } +} + +impl Copy for GenericArray +where + N: ArrayLength, + N::ArrayType: Copy, +{ +} + +impl PartialEq for GenericArray +where + N: ArrayLength, +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} +impl Eq for GenericArray where N: ArrayLength {} + +impl PartialOrd for GenericArray +where + N: ArrayLength, +{ + fn partial_cmp(&self, other: &GenericArray) -> Option { + PartialOrd::partial_cmp(self.as_slice(), other.as_slice()) + } +} + +impl Ord for GenericArray +where + N: ArrayLength, +{ + fn cmp(&self, other: &GenericArray) -> Ordering { + Ord::cmp(self.as_slice(), other.as_slice()) + } +} + +impl Debug for GenericArray +where + N: ArrayLength, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + self[..].fmt(fmt) + } +} + +impl Borrow<[T]> for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn borrow(&self) -> &[T] { + &self[..] + } +} + +impl BorrowMut<[T]> for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn borrow_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +impl AsRef<[T]> for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn as_ref(&self) -> &[T] { + &self[..] + } +} + +impl AsMut<[T]> for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn as_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +impl Hash for GenericArray +where + N: ArrayLength, +{ + fn hash(&self, state: &mut H) + where + H: Hasher, + { + Hash::hash(&self[..], state) + } +} + +macro_rules! impl_from { + ($($n: expr => $ty: ty),*) => { + $( + impl From<[T; $n]> for GenericArray { + #[inline(always)] + fn from(arr: [T; $n]) -> Self { + unsafe { $crate::transmute(arr) } + } + } + + #[cfg(relaxed_coherence)] + impl From> for [T; $n] { + #[inline(always)] + fn from(sel: GenericArray) -> [T; $n] { + unsafe { $crate::transmute(sel) } + } + } + + impl<'a, T> From<&'a [T; $n]> for &'a GenericArray { + #[inline] + fn from(slice: &[T; $n]) -> &GenericArray { + unsafe { &*(slice.as_ptr() as *const GenericArray) } + } + } + + impl<'a, T> From<&'a mut [T; $n]> for &'a mut GenericArray { + #[inline] + fn from(slice: &mut [T; $n]) -> &mut GenericArray { + unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray) } + } + } + + #[cfg(not(relaxed_coherence))] + impl Into<[T; $n]> for GenericArray { + #[inline(always)] + fn into(self) -> [T; $n] { + unsafe { $crate::transmute(self) } + } + } + + impl AsRef<[T; $n]> for GenericArray { + #[inline] + fn as_ref(&self) -> &[T; $n] { + unsafe { $crate::transmute(self) } + } + } + + impl AsMut<[T; $n]> for GenericArray { + #[inline] + fn as_mut(&mut self) -> &mut [T; $n] { + unsafe { $crate::transmute(self) } + } + } + )* + } +} + +impl_from! { + 1 => ::typenum::U1, + 2 => ::typenum::U2, + 3 => ::typenum::U3, + 4 => ::typenum::U4, + 5 => ::typenum::U5, + 6 => ::typenum::U6, + 7 => ::typenum::U7, + 8 => ::typenum::U8, + 9 => ::typenum::U9, + 10 => ::typenum::U10, + 11 => ::typenum::U11, + 12 => ::typenum::U12, + 13 => ::typenum::U13, + 14 => ::typenum::U14, + 15 => ::typenum::U15, + 16 => ::typenum::U16, + 17 => ::typenum::U17, + 18 => ::typenum::U18, + 19 => ::typenum::U19, + 20 => ::typenum::U20, + 21 => ::typenum::U21, + 22 => ::typenum::U22, + 23 => ::typenum::U23, + 24 => ::typenum::U24, + 25 => ::typenum::U25, + 26 => ::typenum::U26, + 27 => ::typenum::U27, + 28 => ::typenum::U28, + 29 => ::typenum::U29, + 30 => ::typenum::U30, + 31 => ::typenum::U31, + 32 => ::typenum::U32 +} + +#[cfg(feature = "more_lengths")] +impl_from! { + 33 => ::typenum::U33, + 34 => ::typenum::U34, + 35 => ::typenum::U35, + 36 => ::typenum::U36, + 37 => ::typenum::U37, + 38 => ::typenum::U38, + 39 => ::typenum::U39, + 40 => ::typenum::U40, + 41 => ::typenum::U41, + 42 => ::typenum::U42, + 43 => ::typenum::U43, + 44 => ::typenum::U44, + 45 => ::typenum::U45, + 46 => ::typenum::U46, + 47 => ::typenum::U47, + 48 => ::typenum::U48, + 49 => ::typenum::U49, + 50 => ::typenum::U50, + 51 => ::typenum::U51, + 52 => ::typenum::U52, + 53 => ::typenum::U53, + 54 => ::typenum::U54, + 55 => ::typenum::U55, + 56 => ::typenum::U56, + 57 => ::typenum::U57, + 58 => ::typenum::U58, + 59 => ::typenum::U59, + 60 => ::typenum::U60, + 61 => ::typenum::U61, + 62 => ::typenum::U62, + 63 => ::typenum::U63, + 64 => ::typenum::U64, + + 70 => ::typenum::U70, + 80 => ::typenum::U80, + 90 => ::typenum::U90, + + 100 => ::typenum::U100, + 200 => ::typenum::U200, + 300 => ::typenum::U300, + 400 => ::typenum::U400, + 500 => ::typenum::U500, + + 128 => ::typenum::U128, + 256 => ::typenum::U256, + 512 => ::typenum::U512, + + 1000 => ::typenum::U1000, + 1024 => ::typenum::U1024 +} diff --git a/anneal/v2/vendor/generic-array/src/iter.rs b/anneal/v2/vendor/generic-array/src/iter.rs new file mode 100644 index 0000000000..784ffa9068 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/iter.rs @@ -0,0 +1,251 @@ +//! `GenericArray` iterator implementation. + +use super::{ArrayLength, GenericArray}; +use core::iter::FusedIterator; +use core::mem::ManuallyDrop; +use core::{cmp, fmt, mem, ptr}; + +/// An iterator that moves out of a `GenericArray` +pub struct GenericArrayIter> { + // Invariants: index <= index_back <= N + // Only values in array[index..index_back] are alive at any given time. + // Values from array[..index] and array[index_back..] are already moved/dropped. + array: ManuallyDrop>, + index: usize, + index_back: usize, +} + +#[cfg(test)] +mod test { + use super::*; + + fn send(_iter: I) {} + + #[test] + fn test_send_iter() { + send(GenericArray::from([1, 2, 3, 4]).into_iter()); + } +} + +impl GenericArrayIter +where + N: ArrayLength, +{ + /// Returns the remaining items of this iterator as a slice + #[inline] + pub fn as_slice(&self) -> &[T] { + &self.array.as_slice()[self.index..self.index_back] + } + + /// Returns the remaining items of this iterator as a mutable slice + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + &mut self.array.as_mut_slice()[self.index..self.index_back] + } +} + +impl IntoIterator for GenericArray +where + N: ArrayLength, +{ + type Item = T; + type IntoIter = GenericArrayIter; + + fn into_iter(self) -> Self::IntoIter { + GenericArrayIter { + array: ManuallyDrop::new(self), + index: 0, + index_back: N::USIZE, + } + } +} + +// Based on work in rust-lang/rust#49000 +impl fmt::Debug for GenericArrayIter +where + N: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("GenericArrayIter") + .field(&self.as_slice()) + .finish() + } +} + +impl Drop for GenericArrayIter +where + N: ArrayLength, +{ + #[inline] + fn drop(&mut self) { + if mem::needs_drop::() { + // Drop values that are still alive. + for p in self.as_mut_slice() { + unsafe { + ptr::drop_in_place(p); + } + } + } + } +} + +// Based on work in rust-lang/rust#49000 +impl Clone for GenericArrayIter +where + N: ArrayLength, +{ + fn clone(&self) -> Self { + // This places all cloned elements at the start of the new array iterator, + // not at their original indices. + + let mut array = unsafe { ptr::read(&self.array) }; + let mut index_back = 0; + + for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) { + unsafe { ptr::write(dst, src.clone()) }; + index_back += 1; + } + + GenericArrayIter { + array, + index: 0, + index_back, + } + } +} + +impl Iterator for GenericArrayIter +where + N: ArrayLength, +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.index < self.index_back { + let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) }; + + self.index += 1; + + p + } else { + None + } + } + + fn fold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + ref mut index, + index_back, + } = self; + + let remaining = &array[*index..index_back]; + + remaining.iter().fold(init, |acc, src| { + let value = ptr::read(src); + + *index += 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + fn nth(&mut self, n: usize) -> Option { + // First consume values prior to the nth. + let ndrop = cmp::min(n, self.len()); + + for p in &mut self.array[self.index..self.index + ndrop] { + self.index += 1; + + unsafe { + ptr::drop_in_place(p); + } + } + + self.next() + } + + #[inline] + fn last(mut self) -> Option { + // Note, everything else will correctly drop first as `self` leaves scope. + self.next_back() + } +} + +impl DoubleEndedIterator for GenericArrayIter +where + N: ArrayLength, +{ + fn next_back(&mut self) -> Option { + if self.index < self.index_back { + self.index_back -= 1; + + unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) } + } else { + None + } + } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + index, + ref mut index_back, + } = self; + + let remaining = &array[index..*index_back]; + + remaining.iter().rfold(init, |acc, src| { + let value = ptr::read(src); + + *index_back -= 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } +} + +impl ExactSizeIterator for GenericArrayIter +where + N: ArrayLength, +{ + fn len(&self) -> usize { + self.index_back - self.index + } +} + +impl FusedIterator for GenericArrayIter where N: ArrayLength {} + +// TODO: Implement `TrustedLen` when stabilized diff --git a/anneal/v2/vendor/generic-array/src/lib.rs b/anneal/v2/vendor/generic-array/src/lib.rs new file mode 100644 index 0000000000..14a2797f87 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/lib.rs @@ -0,0 +1,690 @@ +//! This crate implements a structure that can be used as a generic array type. +//! Core Rust array types `[T; N]` can't be used generically with +//! respect to `N`, so for example this: +//! +//! ```rust{compile_fail} +//! struct Foo { +//! data: [T; N] +//! } +//! ``` +//! +//! won't work. +//! +//! **generic-array** exports a `GenericArray` type, which lets +//! the above be implemented as: +//! +//! ```rust +//! use generic_array::{ArrayLength, GenericArray}; +//! +//! struct Foo> { +//! data: GenericArray +//! } +//! ``` +//! +//! The `ArrayLength` trait is implemented by default for +//! [unsigned integer types](../typenum/uint/index.html) from +//! [typenum](../typenum/index.html): +//! +//! ```rust +//! # use generic_array::{ArrayLength, GenericArray}; +//! use generic_array::typenum::U5; +//! +//! struct Foo> { +//! data: GenericArray +//! } +//! +//! # fn main() { +//! let foo = Foo::{data: GenericArray::default()}; +//! # } +//! ``` +//! +//! For example, `GenericArray` would work almost like `[T; 5]`: +//! +//! ```rust +//! # use generic_array::{ArrayLength, GenericArray}; +//! use generic_array::typenum::U5; +//! +//! struct Foo> { +//! data: GenericArray +//! } +//! +//! # fn main() { +//! let foo = Foo::{data: GenericArray::default()}; +//! # } +//! ``` +//! +//! For ease of use, an `arr!` macro is provided - example below: +//! +//! ``` +//! # #[macro_use] +//! # extern crate generic_array; +//! # extern crate typenum; +//! # fn main() { +//! let array = arr![u32; 1, 2, 3]; +//! assert_eq!(array[2], 3); +//! # } +//! ``` + +#![deny(missing_docs)] +#![deny(meta_variable_misuse)] +#![no_std] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +#[cfg(feature = "serde")] +extern crate serde; + +#[cfg(feature = "zeroize")] +extern crate zeroize; + +#[cfg(test)] +extern crate bincode; + +pub extern crate typenum; + +mod hex; +mod impls; + +#[cfg(feature = "serde")] +mod impl_serde; + +#[cfg(feature = "zeroize")] +mod impl_zeroize; + +use core::iter::FromIterator; +use core::marker::PhantomData; +use core::mem::{MaybeUninit, ManuallyDrop}; +use core::ops::{Deref, DerefMut}; +use core::{mem, ptr, slice}; +use typenum::bit::{B0, B1}; +use typenum::uint::{UInt, UTerm, Unsigned}; + +#[cfg_attr(test, macro_use)] +pub mod arr; +pub mod functional; +pub mod iter; +pub mod sequence; + +use self::functional::*; +pub use self::iter::GenericArrayIter; +use self::sequence::*; + +/// Trait making `GenericArray` work, marking types to be used as length of an array +pub unsafe trait ArrayLength: Unsigned { + /// Associated type representing the array type for the number + type ArrayType; +} + +unsafe impl ArrayLength for UTerm { + #[doc(hidden)] + type ArrayType = [T; 0]; +} + +/// Internal type used to generate a struct of appropriate size +#[allow(dead_code)] +#[repr(C)] +#[doc(hidden)] +pub struct GenericArrayImplEven { + parent1: U, + parent2: U, + _marker: PhantomData, +} + +impl Clone for GenericArrayImplEven { + fn clone(&self) -> GenericArrayImplEven { + GenericArrayImplEven { + parent1: self.parent1.clone(), + parent2: self.parent2.clone(), + _marker: PhantomData, + } + } +} + +impl Copy for GenericArrayImplEven {} + +/// Internal type used to generate a struct of appropriate size +#[allow(dead_code)] +#[repr(C)] +#[doc(hidden)] +pub struct GenericArrayImplOdd { + parent1: U, + parent2: U, + data: T, +} + +impl Clone for GenericArrayImplOdd { + fn clone(&self) -> GenericArrayImplOdd { + GenericArrayImplOdd { + parent1: self.parent1.clone(), + parent2: self.parent2.clone(), + data: self.data.clone(), + } + } +} + +impl Copy for GenericArrayImplOdd {} + +unsafe impl> ArrayLength for UInt { + #[doc(hidden)] + type ArrayType = GenericArrayImplEven; +} + +unsafe impl> ArrayLength for UInt { + #[doc(hidden)] + type ArrayType = GenericArrayImplOdd; +} + +/// Struct representing a generic array - `GenericArray` works like [T; N] +#[allow(dead_code)] +#[repr(transparent)] +pub struct GenericArray> { + data: U::ArrayType, +} + +unsafe impl> Send for GenericArray {} +unsafe impl> Sync for GenericArray {} + +impl Deref for GenericArray +where + N: ArrayLength, +{ + type Target = [T]; + + #[inline(always)] + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) } + } +} + +impl DerefMut for GenericArray +where + N: ArrayLength, +{ + #[inline(always)] + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) } + } +} + +/// Creates an array one element at a time using a mutable iterator +/// you can write to with `ptr::write`. +/// +/// Increment the position while iterating to mark off created elements, +/// which will be dropped if `into_inner` is not called. +#[doc(hidden)] +pub struct ArrayBuilder> { + array: MaybeUninit>, + position: usize, +} + +impl> ArrayBuilder { + #[doc(hidden)] + #[inline] + pub unsafe fn new() -> ArrayBuilder { + ArrayBuilder { + array: MaybeUninit::uninit(), + position: 0, + } + } + + /// Creates a mutable iterator for writing to the array using `ptr::write`. + /// + /// Increment the position value given as a mutable reference as you iterate + /// to mark how many elements have been created. + #[doc(hidden)] + #[inline] + pub unsafe fn iter_position(&mut self) -> (slice::IterMut, &mut usize) { + ((&mut *self.array.as_mut_ptr()).iter_mut(), &mut self.position) + } + + /// When done writing (assuming all elements have been written to), + /// get the inner array. + #[doc(hidden)] + #[inline] + pub unsafe fn into_inner(self) -> GenericArray { + let array = ptr::read(&self.array); + + mem::forget(self); + + array.assume_init() + } +} + +impl> Drop for ArrayBuilder { + fn drop(&mut self) { + if mem::needs_drop::() { + unsafe { + for value in &mut (&mut *self.array.as_mut_ptr())[..self.position] { + ptr::drop_in_place(value); + } + } + } + } +} + +/// Consumes an array. +/// +/// Increment the position while iterating and any leftover elements +/// will be dropped if position does not go to N +#[doc(hidden)] +pub struct ArrayConsumer> { + array: ManuallyDrop>, + position: usize, +} + +impl> ArrayConsumer { + #[doc(hidden)] + #[inline] + pub unsafe fn new(array: GenericArray) -> ArrayConsumer { + ArrayConsumer { + array: ManuallyDrop::new(array), + position: 0, + } + } + + /// Creates an iterator and mutable reference to the internal position + /// to keep track of consumed elements. + /// + /// Increment the position as you iterate to mark off consumed elements + #[doc(hidden)] + #[inline] + pub unsafe fn iter_position(&mut self) -> (slice::Iter, &mut usize) { + (self.array.iter(), &mut self.position) + } +} + +impl> Drop for ArrayConsumer { + fn drop(&mut self) { + if mem::needs_drop::() { + for value in &mut self.array[self.position..N::USIZE] { + unsafe { + ptr::drop_in_place(value); + } + } + } + } +} + +impl<'a, T: 'a, N> IntoIterator for &'a GenericArray +where + N: ArrayLength, +{ + type IntoIter = slice::Iter<'a, T>; + type Item = &'a T; + + fn into_iter(self: &'a GenericArray) -> Self::IntoIter { + self.as_slice().iter() + } +} + +impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray +where + N: ArrayLength, +{ + type IntoIter = slice::IterMut<'a, T>; + type Item = &'a mut T; + + fn into_iter(self: &'a mut GenericArray) -> Self::IntoIter { + self.as_mut_slice().iter_mut() + } +} + +impl FromIterator for GenericArray +where + N: ArrayLength, +{ + fn from_iter(iter: I) -> GenericArray + where + I: IntoIterator, + { + unsafe { + let mut destination = ArrayBuilder::new(); + + { + let (destination_iter, position) = destination.iter_position(); + + iter.into_iter() + .zip(destination_iter) + .for_each(|(src, dst)| { + ptr::write(dst, src); + + *position += 1; + }); + } + + if destination.position < N::USIZE { + from_iter_length_fail(destination.position, N::USIZE); + } + + destination.into_inner() + } + } +} + +#[inline(never)] +#[cold] +fn from_iter_length_fail(length: usize, expected: usize) -> ! { + panic!( + "GenericArray::from_iter received {} elements but expected {}", + length, expected + ); +} + +unsafe impl GenericSequence for GenericArray +where + N: ArrayLength, + Self: IntoIterator, +{ + type Length = N; + type Sequence = Self; + + fn generate(mut f: F) -> GenericArray + where + F: FnMut(usize) -> T, + { + unsafe { + let mut destination = ArrayBuilder::new(); + + { + let (destination_iter, position) = destination.iter_position(); + + destination_iter.enumerate().for_each(|(i, dst)| { + ptr::write(dst, f(i)); + + *position += 1; + }); + } + + destination.into_inner() + } + } + + #[doc(hidden)] + fn inverted_zip( + self, + lhs: GenericArray, + mut f: F, + ) -> MappedSequence, B, U> + where + GenericArray: + GenericSequence + MappedGenericSequence, + Self: MappedGenericSequence, + Self::Length: ArrayLength + ArrayLength, + F: FnMut(B, Self::Item) -> U, + { + unsafe { + let mut left = ArrayConsumer::new(lhs); + let mut right = ArrayConsumer::new(self); + + let (left_array_iter, left_position) = left.iter_position(); + let (right_array_iter, right_position) = right.iter_position(); + + FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| { + let left_value = ptr::read(l); + let right_value = ptr::read(r); + + *left_position += 1; + *right_position += 1; + + f(left_value, right_value) + })) + } + } + + #[doc(hidden)] + fn inverted_zip2(self, lhs: Lhs, mut f: F) -> MappedSequence + where + Lhs: GenericSequence + MappedGenericSequence, + Self: MappedGenericSequence, + Self::Length: ArrayLength + ArrayLength, + F: FnMut(Lhs::Item, Self::Item) -> U, + { + unsafe { + let mut right = ArrayConsumer::new(self); + + let (right_array_iter, right_position) = right.iter_position(); + + FromIterator::from_iter( + lhs.into_iter() + .zip(right_array_iter) + .map(|(left_value, r)| { + let right_value = ptr::read(r); + + *right_position += 1; + + f(left_value, right_value) + }), + ) + } + } +} + +unsafe impl MappedGenericSequence for GenericArray +where + N: ArrayLength + ArrayLength, + GenericArray: GenericSequence, +{ + type Mapped = GenericArray; +} + +unsafe impl FunctionalSequence for GenericArray +where + N: ArrayLength, + Self: GenericSequence, +{ + fn map(self, mut f: F) -> MappedSequence + where + Self::Length: ArrayLength, + Self: MappedGenericSequence, + F: FnMut(T) -> U, + { + unsafe { + let mut source = ArrayConsumer::new(self); + + let (array_iter, position) = source.iter_position(); + + FromIterator::from_iter(array_iter.map(|src| { + let value = ptr::read(src); + + *position += 1; + + f(value) + })) + } + } + + #[inline] + fn zip(self, rhs: Rhs, f: F) -> MappedSequence + where + Self: MappedGenericSequence, + Rhs: MappedGenericSequence>, + Self::Length: ArrayLength + ArrayLength, + Rhs: GenericSequence, + F: FnMut(T, Rhs::Item) -> U, + { + rhs.inverted_zip(self, f) + } + + fn fold(self, init: U, mut f: F) -> U + where + F: FnMut(U, T) -> U, + { + unsafe { + let mut source = ArrayConsumer::new(self); + + let (array_iter, position) = source.iter_position(); + + array_iter.fold(init, |acc, src| { + let value = ptr::read(src); + + *position += 1; + + f(acc, value) + }) + } + } +} + +impl GenericArray +where + N: ArrayLength, +{ + /// Extracts a slice containing the entire array. + #[inline] + pub fn as_slice(&self) -> &[T] { + self.deref() + } + + /// Extracts a mutable slice containing the entire array. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self.deref_mut() + } + + /// Converts slice to a generic array reference with inferred length; + /// + /// # Panics + /// + /// Panics if the slice is not equal to the length of the array. + #[inline] + pub fn from_slice(slice: &[T]) -> &GenericArray { + slice.into() + } + + /// Converts mutable slice to a mutable generic array reference + /// + /// # Panics + /// + /// Panics if the slice is not equal to the length of the array. + #[inline] + pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray { + slice.into() + } +} + +impl<'a, T, N: ArrayLength> From<&'a [T]> for &'a GenericArray { + /// Converts slice to a generic array reference with inferred length; + /// + /// # Panics + /// + /// Panics if the slice is not equal to the length of the array. + #[inline] + fn from(slice: &[T]) -> &GenericArray { + assert_eq!(slice.len(), N::USIZE); + + unsafe { &*(slice.as_ptr() as *const GenericArray) } + } +} + +impl<'a, T, N: ArrayLength> From<&'a mut [T]> for &'a mut GenericArray { + /// Converts mutable slice to a mutable generic array reference + /// + /// # Panics + /// + /// Panics if the slice is not equal to the length of the array. + #[inline] + fn from(slice: &mut [T]) -> &mut GenericArray { + assert_eq!(slice.len(), N::USIZE); + + unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray) } + } +} + +impl GenericArray +where + N: ArrayLength, +{ + /// Construct a `GenericArray` from a slice by cloning its content + /// + /// # Panics + /// + /// Panics if the slice is not equal to the length of the array. + #[inline] + pub fn clone_from_slice(list: &[T]) -> GenericArray { + Self::from_exact_iter(list.iter().cloned()) + .expect("Slice must be the same length as the array") + } +} + +impl GenericArray +where + N: ArrayLength, +{ + /// Creates a new `GenericArray` instance from an iterator with a specific size. + /// + /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`. + pub fn from_exact_iter(iter: I) -> Option + where + I: IntoIterator, + { + let mut iter = iter.into_iter(); + + unsafe { + let mut destination = ArrayBuilder::new(); + + { + let (destination_iter, position) = destination.iter_position(); + + destination_iter.zip(&mut iter).for_each(|(dst, src)| { + ptr::write(dst, src); + + *position += 1; + }); + + // The iterator produced fewer than `N` elements. + if *position != N::USIZE { + return None; + } + + // The iterator produced more than `N` elements. + if iter.next().is_some() { + return None; + } + } + + Some(destination.into_inner()) + } + } +} + +/// A reimplementation of the `transmute` function, avoiding problems +/// when the compiler can't prove equal sizes. +#[inline] +#[doc(hidden)] +pub unsafe fn transmute(a: A) -> B { + let a = ManuallyDrop::new(a); + ::core::ptr::read(&*a as *const A as *const B) +} + +#[cfg(test)] +mod test { + // Compile with: + // cargo rustc --lib --profile test --release -- + // -C target-cpu=native -C opt-level=3 --emit asm + // and view the assembly to make sure test_assembly generates + // SIMD instructions instead of a naive loop. + + #[inline(never)] + pub fn black_box(val: T) -> T { + use core::{mem, ptr}; + + let ret = unsafe { ptr::read_volatile(&val) }; + mem::forget(val); + ret + } + + #[test] + fn test_assembly() { + use crate::functional::*; + + let a = black_box(arr![i32; 1, 3, 5, 7]); + let b = black_box(arr![i32; 2, 4, 6, 8]); + + let c = (&a).zip(b, |l, r| l + r); + + let d = a.fold(0, |a, x| a + x); + + assert_eq!(c, arr![i32; 3, 7, 11, 15]); + + assert_eq!(d, 16); + } +} diff --git a/anneal/v2/vendor/generic-array/src/sequence.rs b/anneal/v2/vendor/generic-array/src/sequence.rs new file mode 100644 index 0000000000..0119d3db67 --- /dev/null +++ b/anneal/v2/vendor/generic-array/src/sequence.rs @@ -0,0 +1,380 @@ +//! Useful traits for manipulating sequences of data stored in `GenericArray`s + +use super::*; +use core::ops::{Add, Sub}; +use core::mem::MaybeUninit; +use core::ptr; +use typenum::operator_aliases::*; + +/// Defines some sequence with an associated length and iteration capabilities. +/// +/// This is useful for passing N-length generic arrays as generics. +pub unsafe trait GenericSequence: Sized + IntoIterator { + /// `GenericArray` associated length + type Length: ArrayLength; + + /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence` + type Sequence: GenericSequence + FromIterator; + + /// Initializes a new sequence instance using the given function. + /// + /// If the generator function panics while initializing the sequence, + /// any already initialized elements will be dropped. + fn generate(f: F) -> Self::Sequence + where + F: FnMut(usize) -> T; + + #[doc(hidden)] + fn inverted_zip( + self, + lhs: GenericArray, + mut f: F, + ) -> MappedSequence, B, U> + where + GenericArray: GenericSequence + + MappedGenericSequence, + Self: MappedGenericSequence, + Self::Length: ArrayLength + ArrayLength, + F: FnMut(B, Self::Item) -> U, + { + unsafe { + let mut left = ArrayConsumer::new(lhs); + + let (left_array_iter, left_position) = left.iter_position(); + + FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map( + |(l, right_value)| { + let left_value = ptr::read(l); + + *left_position += 1; + + f(left_value, right_value) + }, + )) + } + } + + #[doc(hidden)] + fn inverted_zip2(self, lhs: Lhs, mut f: F) -> MappedSequence + where + Lhs: GenericSequence + MappedGenericSequence, + Self: MappedGenericSequence, + Self::Length: ArrayLength + ArrayLength, + F: FnMut(Lhs::Item, Self::Item) -> U, + { + FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r))) + } +} + +/// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item` +/// +/// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`, +/// this can be useful for keeping things organized. +pub type SequenceItem = ::Item; + +unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a S +where + &'a S: IntoIterator, +{ + type Length = S::Length; + type Sequence = S::Sequence; + + #[inline] + fn generate(f: F) -> Self::Sequence + where + F: FnMut(usize) -> T, + { + S::generate(f) + } +} + +unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a mut S +where + &'a mut S: IntoIterator, +{ + type Length = S::Length; + type Sequence = S::Sequence; + + #[inline] + fn generate(f: F) -> Self::Sequence + where + F: FnMut(usize) -> T, + { + S::generate(f) + } +} + +/// Defines any `GenericSequence` which can be lengthened or extended by appending +/// or prepending an element to it. +/// +/// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back` +pub unsafe trait Lengthen: Sized + GenericSequence { + /// `GenericSequence` that has one more element than `Self` + type Longer: Shorten; + + /// Returns a new array with the given element appended to the end of it. + /// + /// Example: + /// + /// ```rust + /// # use generic_array::{arr, sequence::Lengthen}; + /// # fn main() { + /// let a = arr![i32; 1, 2, 3]; + /// + /// let b = a.append(4); + /// + /// assert_eq!(b, arr![i32; 1, 2, 3, 4]); + /// # } + /// ``` + fn append(self, last: T) -> Self::Longer; + + /// Returns a new array with the given element prepended to the front of it. + /// + /// Example: + /// + /// ```rust + /// # use generic_array::{arr, sequence::Lengthen}; + /// # fn main() { + /// let a = arr![i32; 1, 2, 3]; + /// + /// let b = a.prepend(4); + /// + /// assert_eq!(b, arr![i32; 4, 1, 2, 3]); + /// # } + /// ``` + fn prepend(self, first: T) -> Self::Longer; +} + +/// Defines a `GenericSequence` which can be shortened by removing the first or last element from it. +/// +/// Additionally, any shortened sequence can be lengthened by +/// appending or prepending an element to it. +pub unsafe trait Shorten: Sized + GenericSequence { + /// `GenericSequence` that has one less element than `Self` + type Shorter: Lengthen; + + /// Returns a new array without the last element, and the last element. + /// + /// Example: + /// + /// ```rust + /// # use generic_array::{arr, sequence::Shorten}; + /// # fn main() { + /// let a = arr![i32; 1, 2, 3, 4]; + /// + /// let (init, last) = a.pop_back(); + /// + /// assert_eq!(init, arr![i32; 1, 2, 3]); + /// assert_eq!(last, 4); + /// # } + /// ``` + fn pop_back(self) -> (Self::Shorter, T); + + /// Returns a new array without the first element, and the first element. + /// Example: + /// + /// ```rust + /// # use generic_array::{arr, sequence::Shorten}; + /// # fn main() { + /// let a = arr![i32; 1, 2, 3, 4]; + /// + /// let (head, tail) = a.pop_front(); + /// + /// assert_eq!(head, 1); + /// assert_eq!(tail, arr![i32; 2, 3, 4]); + /// # } + /// ``` + fn pop_front(self) -> (T, Self::Shorter); +} + +unsafe impl> Lengthen for GenericArray +where + N: Add, + Add1: ArrayLength, + Add1: Sub, + Sub1>: ArrayLength, +{ + type Longer = GenericArray>; + + fn append(self, last: T) -> Self::Longer { + let mut longer: MaybeUninit = MaybeUninit::uninit(); + + // Note this is *mut Self, so add(1) increments by the whole array + let out_ptr = longer.as_mut_ptr() as *mut Self; + + unsafe { + // write self first + ptr::write(out_ptr, self); + // increment past self, then write the last + ptr::write(out_ptr.add(1) as *mut T, last); + + longer.assume_init() + } + } + + fn prepend(self, first: T) -> Self::Longer { + let mut longer: MaybeUninit = MaybeUninit::uninit(); + + // Note this is *mut T, so add(1) increments by a single T + let out_ptr = longer.as_mut_ptr() as *mut T; + + unsafe { + // write the first at the start + ptr::write(out_ptr, first); + // increment past the first, then write self + ptr::write(out_ptr.add(1) as *mut Self, self); + + longer.assume_init() + } + } +} + +unsafe impl> Shorten for GenericArray +where + N: Sub, + Sub1: ArrayLength, + Sub1: Add, + Add1>: ArrayLength, +{ + type Shorter = GenericArray>; + + fn pop_back(self) -> (Self::Shorter, T) { + let whole = ManuallyDrop::new(self); + + unsafe { + let init = ptr::read(whole.as_ptr() as _); + let last = ptr::read(whole.as_ptr().add(Sub1::::USIZE) as _); + + (init, last) + } + } + + fn pop_front(self) -> (T, Self::Shorter) { + // ensure this doesn't get dropped + let whole = ManuallyDrop::new(self); + + unsafe { + let head = ptr::read(whole.as_ptr() as _); + let tail = ptr::read(whole.as_ptr().offset(1) as _); + + (head, tail) + } + } +} + +/// Defines a `GenericSequence` that can be split into two parts at a given pivot index. +pub unsafe trait Split: GenericSequence +where + K: ArrayLength, +{ + /// First part of the resulting split array + type First: GenericSequence; + /// Second part of the resulting split array + type Second: GenericSequence; + + /// Splits an array at the given index, returning the separate parts of the array. + fn split(self) -> (Self::First, Self::Second); +} + +unsafe impl Split for GenericArray +where + N: ArrayLength, + K: ArrayLength, + N: Sub, + Diff: ArrayLength, +{ + type First = GenericArray; + type Second = GenericArray>; + + fn split(self) -> (Self::First, Self::Second) { + unsafe { + // ensure this doesn't get dropped + let whole = ManuallyDrop::new(self); + + let head = ptr::read(whole.as_ptr() as *const _); + let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _); + + (head, tail) + } + } +} + +unsafe impl<'a, T, N, K> Split for &'a GenericArray +where + N: ArrayLength, + K: ArrayLength + 'static, + N: Sub, + Diff: ArrayLength, +{ + type First = &'a GenericArray; + type Second = &'a GenericArray>; + + fn split(self) -> (Self::First, Self::Second) { + unsafe { + let ptr_to_first: *const T = self.as_ptr(); + let head = &*(ptr_to_first as *const _); + let tail = &*(ptr_to_first.add(K::USIZE) as *const _); + (head, tail) + } + } +} + +unsafe impl<'a, T, N, K> Split for &'a mut GenericArray +where + N: ArrayLength, + K: ArrayLength + 'static, + N: Sub, + Diff: ArrayLength, +{ + type First = &'a mut GenericArray; + type Second = &'a mut GenericArray>; + + fn split(self) -> (Self::First, Self::Second) { + unsafe { + let ptr_to_first: *mut T = self.as_mut_ptr(); + let head = &mut *(ptr_to_first as *mut _); + let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _); + (head, tail) + } + } +} + +/// Defines `GenericSequence`s which can be joined together, forming a larger array. +pub unsafe trait Concat: GenericSequence +where + M: ArrayLength, +{ + /// Sequence to be concatenated with `self` + type Rest: GenericSequence; + + /// Resulting sequence formed by the concatenation. + type Output: GenericSequence; + + /// Concatenate, or join, two sequences. + fn concat(self, rest: Self::Rest) -> Self::Output; +} + +unsafe impl Concat for GenericArray +where + N: ArrayLength + Add, + M: ArrayLength, + Sum: ArrayLength, +{ + type Rest = GenericArray; + type Output = GenericArray>; + + fn concat(self, rest: Self::Rest) -> Self::Output { + let mut output: MaybeUninit = MaybeUninit::uninit(); + + let out_ptr = output.as_mut_ptr() as *mut Self; + + unsafe { + // write all of self to the pointer + ptr::write(out_ptr, self); + // increment past self, then write the rest + ptr::write(out_ptr.add(1) as *mut _, rest); + + output.assume_init() + } + } +} diff --git a/anneal/v2/vendor/gimli/.cargo-checksum.json b/anneal/v2/vendor/gimli/.cargo-checksum.json new file mode 100644 index 0000000000..f0d7b13243 --- /dev/null +++ b/anneal/v2/vendor/gimli/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"bae9b5923acc9a419e4bc7060b19314aac48dc12f7ba31b7b0cb42edae19eb80","CHANGELOG.md":"29c98006f14bd25b1a6593518da388be81ddb7f0ca89413836f6ae296e4c18ea","Cargo.lock":"ec7efa297c5a89fa7849f276dfe5f64bede52a266660fa77608b100e6caf2854","Cargo.toml":"2b0d60ffc8705bf1de535e36ffa090511284747388d84056d5d96a5acbb0704a","Cargo.toml.orig":"96b821d1b85daa2afbbdd21c1260dbbc5dce9ee72e53eff1a8bfc11ee12c8a01","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"79fc2aa247ebf7b8a3562632aa2bfc466cd655a0886717d47e4bc693166e9745","src/arch.rs":"332ca34941a35a73eabfdcb0071709ae4ec7a745a9f5cbe539bb6438904628c6","src/common.rs":"18d6857c4c03b873a14a15a0e024cc8f3ecbf95226c17356a075ff96a54ac1fe","src/constants.rs":"40d3e2684774dbffd0f27cdfa0ee6f378d04dc74b2adb821fa7a68acd0772313","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"81a0ca0e8ba56e749af4588fe76179611234062f79be1e9fb8ea8a27516b372f","src/lib.rs":"8f6016f5664fcbc085d69fc957245c805fc55d425d1a848f8b25413670235d10","src/read/abbrev.rs":"a8e35c70c66ee05ee38fed73ee951caec055a6cacdd017cb5e077d24e89d9aa3","src/read/addr.rs":"1b3c52e7b2a6f77ed3817e0f1d6b402e00072bd632a1654f39fb667b8e184925","src/read/aranges.rs":"2cac0260f26001d3f674b45cf40540ccbb9a5f3474a002c2f49cc62f826faedb","src/read/cfi.rs":"d93d04d81abce8fbfb8ba164c151c3c6415d7cdc6e13489939bb407ca0bcd8d6","src/read/dwarf.rs":"7b49c04cab4ff2ed68042970588aacc08318109952208af1bc958a7754a1ce76","src/read/endian_reader.rs":"6e7bf5b26719b1a5e396159387bb10666b218c10e603a4552882ec9d4d5cb8be","src/read/endian_slice.rs":"5b44661714967780b8c9f52fdaf655a53e309c38cbd3daf11bf6b1d5f6d067bb","src/read/index.rs":"42c9aae82e87cf7451d4434f68cd5d84e6bb482e51742af213a711b053633085","src/read/line.rs":"1014bb445d478111fe030702d1cbebb11235660c71cbed1bf0e3af77514fdb2e","src/read/lists.rs":"5a4e33038ceedb48a8332a7713ee67a1be9b7a4031881a2ccb9b9259ba29356b","src/read/loclists.rs":"6b3e0faea833c264794914189ac301f68bca96c66ad4f7bebae3f2252fd86621","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/macros.rs":"3ad6e6387351804c4376b6c8390b7744cdef7b7afcc7e7f3c0f829e9eacfd762","src/read/mod.rs":"0b3da9dcbca295da73bd8182a98511fa6ea6a60a26f33e4615c0dcf34cfcb0dd","src/read/op.rs":"99f976309f4da7ea07aa2b09b4c26e97c8e78ba8c7b3016be22ab02869003c05","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"c9d5f303d4799b923bb24cc995c43e96725dc7d8bdd179af2dc420c8801254e4","src/read/relocate.rs":"6844b113eb8218152e29912accc54b26bc2498e97bfe4af824472ddb69b8601c","src/read/rnglists.rs":"8eb44055c8d782152503ff62fdaa165c947b2d9fc950e20e03880f1f1801808d","src/read/str.rs":"4dd98cc8d93ce6f06c194eae034bfe0a3d45a9f06fbeaca38d8f29a9c7cf15a5","src/read/unit.rs":"f2fc760be1337a6a0351e9921e6e2e6290b17b6cfada6db96e0ebb3fdee68c90","src/read/util.rs":"f15a2bfa2d46e90eeb72b29de5ec3a7f69c871fbbde8bcbc2b0192e4802176f2","src/read/value.rs":"1c0db3759c65ffda3520fcecd36118367dfb46845035d5d97fcba2f0ea780380","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"964321050337db6a9ff160e048806e9a60e1ba12ecc1f031b7845ec6d5f31159","src/write/dwarf.rs":"75e18ceb108828d987a406bbd51fa55e3f44a4e9e540745539938fe7f6331791","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"47f46b86c57786d19efae0d9077fe83ee9dd6915d66a7f3bccbf6686221b7665","src/write/loc.rs":"106544af89213151490d1f5314f9deb13a3527007c1bb1642057213c6b4b178b","src/write/mod.rs":"7ebf0af9d4b558e1c24c7e6b84ae9c75b7e75c83d09a03ef8608973052d31913","src/write/op.rs":"a9bda7a0137b7d8dc96c259cca6559500d3da55227dc0db398d13133395cbdb7","src/write/range.rs":"b92959825e33984df2bb26bc562413027638f013920701df1ceb050a2ea43c46","src/write/relocate.rs":"117b97eae3ca2aad9d5b242652ebbdb333440e877be37873a7ef5ba1a39ced43","src/write/section.rs":"ea0e7e77650ef4c8972b409ef945c98bfa771712b6887591140d3e7baca9c599","src/write/str.rs":"8fac921da9a17b2428cc3982886a2e4c7ab9873574ec698b3a3b0c45bd97af98","src/write/unit.rs":"8284dd27a5bfe13486c64fec65d87f7975c1ef4b7704308b3bef55e2adfdc024","src/write/writer.rs":"c7696a3c2cff032ad6ada696132e4bbef92c4af76c7370c9ce82dedf2cf3716b"},"package":"e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"} \ No newline at end of file diff --git a/anneal/v2/vendor/gimli/.cargo_vcs_info.json b/anneal/v2/vendor/gimli/.cargo_vcs_info.json new file mode 100644 index 0000000000..1f7dc46585 --- /dev/null +++ b/anneal/v2/vendor/gimli/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8bc8e622fcb9be20fc9f03c96bc6335d936b869d" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/gimli/CHANGELOG.md b/anneal/v2/vendor/gimli/CHANGELOG.md new file mode 100644 index 0000000000..a7a2b7ef4a --- /dev/null +++ b/anneal/v2/vendor/gimli/CHANGELOG.md @@ -0,0 +1,1280 @@ +# `gimli` Change Log + +-------------------------------------------------------------------------------- + +## 0.32.3 + +Released 2025/09/13. + +### Changed + +* Changed parsing to accept -2 for tombstone values in `.debug_line`, + `.debug_aranges`, `.debug_loclists`, and `.debug_rnglists`. + [#791](https://github.com/gimli-rs/gimli/pull/791) + +### Added + +* Added more x86-64 register definitions. + [#794](https://github.com/gimli-rs/gimli/pull/794) + +-------------------------------------------------------------------------------- + +## 0.32.2 + +Released 2025/08/26. + +### Changed + +* Removed `PartialEq` implementations for `UnitSectionOffset`. + These were an unintended breaking change. + [#789](https://github.com/gimli-rs/gimli/pull/789) + +-------------------------------------------------------------------------------- + +## 0.32.1 + +Released 2025/08/22. + +### Changed + +* Improved handling of invalid DIE references during writing. + [#777](https://github.com/gimli-rs/gimli/pull/777) + [#779](https://github.com/gimli-rs/gimli/pull/779) + +* Changed abbreviation parsing to allow a missing null terminator. + [#781](https://github.com/gimli-rs/gimli/pull/781) + +* Changed `write::LineProgram` to support any form for file source code. + [#784](https://github.com/gimli-rs/gimli/pull/784) + [#786](https://github.com/gimli-rs/gimli/pull/786) + +### Added + +* Added DWARF version 1.1 constant definitions. + [#775](https://github.com/gimli-rs/gimli/pull/775) + +-------------------------------------------------------------------------------- + +## 0.32.0 + +Released 2025/06/11. + +### Breaking changes + +* Added `read::Dwarf::debug_macinfo`, `read::Dwarf::debug_macro`, and associated + support. + [#759](https://github.com/gimli-rs/gimli/pull/759) + [#763](https://github.com/gimli-rs/gimli/pull/763) + [#772](https://github.com/gimli-rs/gimli/pull/772) + +* Removed `#[non_exhaustive]` from `read::CallFrameInstruction`. + [#764](https://github.com/gimli-rs/gimli/pull/764) + +* Added `source_dir` parameter to `write::LineProgram::new`. + [#768](https://github.com/gimli-rs/gimli/pull/768) + +### Changed + +* Fixed spelling in `Error::UnknownCallFrameInstruction` description. + [#758](https://github.com/gimli-rs/gimli/pull/758) + +* Removed `compiler-builtins` from `rustc-dep-of-std` dependencies. + [#769](https://github.com/gimli-rs/gimli/pull/769) + +* Changed `write::UnitTable::from` to ignore `DW_AT_GNU_locviews` attributes. + [#771](https://github.com/gimli-rs/gimli/pull/771) + +### Added + +* Added `DebugAddr::headers`. + [#760](https://github.com/gimli-rs/gimli/pull/760) + +-------------------------------------------------------------------------------- + +## 0.31.1 + +Released 2024/10/04. + +### Changed + +* Changed `read::Evaluation::evaluate` to validate `DW_OP_deref_size`. + [#739](https://github.com/gimli-rs/gimli/pull/739) + +* Changed `write::LineProgram` to allow use of file index 0 for DWARF version 5. + [#740](https://github.com/gimli-rs/gimli/pull/740) + +* Improved the workaround for reading zero length entries in `.debug_frame`. + [#741](https://github.com/gimli-rs/gimli/pull/741) + +* Implemented `Default` for `read::DwarfSections` and `read::DwarfPackageSections`. + [#742](https://github.com/gimli-rs/gimli/pull/742) + +* Changed `read::ArangeEntryIter` to handle tombstones in `.debug_aranges`. + [#743](https://github.com/gimli-rs/gimli/pull/743) + +* Improved handling handling of 0 for tombstones in `DW_LNE_set_address` + and address pairs in ranges and locations. + [#750](https://github.com/gimli-rs/gimli/pull/750) + +* Changed the `read::ArrayLike` trait implementation to use const generics. + [#752](https://github.com/gimli-rs/gimli/pull/752) + +### Added + +* Added `MIPS::HI` and `MIPS::LO`. + [#749](https://github.com/gimli-rs/gimli/pull/749) + +-------------------------------------------------------------------------------- + +## 0.31.0 + +Released 2024/07/16. + +### Breaking changes + +* Deleted support for segment selectors. + [#720](https://github.com/gimli-rs/gimli/pull/720) + +* Added `read::FileEntry::source` and deleted `Copy` implementation. + [#728](https://github.com/gimli-rs/gimli/pull/728) + +* Changed `read::LineRow::execute` to return a `Result`. + [#731](https://github.com/gimli-rs/gimli/pull/731) + +* Deleted `Display` implementation for `read::LineInstruction`. + [#734](https://github.com/gimli-rs/gimli/pull/734) + +* Changed `read::Error` to be non-exhaustive. + +### Changed + +* Fixed `Hash` implementation for `read::EndianReader`. + [#723](https://github.com/gimli-rs/gimli/pull/723) + +* Changed `read::EhFrameHdr::parse` to validate the FDE count encoding. + [#725](https://github.com/gimli-rs/gimli/pull/725) + +* Changed address overflow to be an error for `read::UnwindTableRow`, + `read::LineRow`, and `read::ArangeEntry`. + [#730](https://github.com/gimli-rs/gimli/pull/730) + [#731](https://github.com/gimli-rs/gimli/pull/731) + [#732](https://github.com/gimli-rs/gimli/pull/732) + +* Changed wrapping addition for 32-bit addresses to wrap at 32 bits instead of + at 64 bits. + [#733](https://github.com/gimli-rs/gimli/pull/733) + +* Added earlier validation of address sizes. + [#733](https://github.com/gimli-rs/gimli/pull/733) + +### Added + +* Added `read::IndexSectionId::section_id`. + [#719](https://github.com/gimli-rs/gimli/pull/719) + +* Added `read::FrameDescriptionEntry::end_address`. + [#727](https://github.com/gimli-rs/gimli/pull/727) + +* Added support for `DW_LNCT_LLVM_source`. + [#728](https://github.com/gimli-rs/gimli/pull/728) + +-------------------------------------------------------------------------------- + +## 0.30.0 + +Released 2024/05/26. + +### Breaking changes + +* Added context to some `read::Error` variants. + [#703](https://github.com/gimli-rs/gimli/pull/703) + +* Changed type of `read::UnitIndexSection::section` to `IndexSectionId`. + [#716](https://github.com/gimli-rs/gimli/pull/716) + +### Changed + +* Fixed `write::Operation::ImplicitPointer::size`. + [#712](https://github.com/gimli-rs/gimli/pull/712) + +* Changed `read::RngListIter` and `read::LocListIter` to skip ranges where + the end is before the beginning, instead of returning an error. + [#715](https://github.com/gimli-rs/gimli/pull/715) + +* Fixed clippy warnings. + [#713](https://github.com/gimli-rs/gimli/pull/713) + +### Added + +* Added `read::UnitRef`. + [#711](https://github.com/gimli-rs/gimli/pull/711) + +-------------------------------------------------------------------------------- + +## 0.29.0 + +Released 2024/04/11. + +### Breaking changes + +* Changed `Reader` type parameter to `ReaderOffset` for `read::UnwindContext` and related types. + Replaced `Expression` with `UnwindExpression` in unwind information types. + [#703](https://github.com/gimli-rs/gimli/pull/703) + +### Changed + +* Changed `write::Sections::for_each` and `for_each_mut` to specify section lifetime. + [#699](https://github.com/gimli-rs/gimli/pull/699) + +* Fixed writing unwind information with an LSDA encoding that is not `DW_EH_PE_absptr`. + [#704](https://github.com/gimli-rs/gimli/pull/704) + +* Fixed parsing for an empty DWP index. + [#706](https://github.com/gimli-rs/gimli/pull/706) + +* Improved error handling in `read::Unit::dwo_name`. + [#693](https://github.com/gimli-rs/gimli/pull/693) + +* Fixed warnings. + [#692](https://github.com/gimli-rs/gimli/pull/692) + [#694](https://github.com/gimli-rs/gimli/pull/694) + [#695](https://github.com/gimli-rs/gimli/pull/695) + [#696](https://github.com/gimli-rs/gimli/pull/696) + +### Added + +* Added MIPS register definitions. + [#690](https://github.com/gimli-rs/gimli/pull/690) + +* Added PowerPC register definitions. + [#691](https://github.com/gimli-rs/gimli/pull/691) + +* Added `read::DwarfSections` and `read::DwarfPackageSections`. + [#698](https://github.com/gimli-rs/gimli/pull/698) + +* Implemented `BitOr` for `DwEhPe`. + [#709](https://github.com/gimli-rs/gimli/pull/709) + +* Added `read::Relocate`, `read::RelocateReader`, and `write::RelocateWriter`. + [#709](https://github.com/gimli-rs/gimli/pull/709) + +-------------------------------------------------------------------------------- + +## 0.28.1 + +Released 2023/11/24. + +### Changed + +* Changed `read::AbbreviationsCache` to require manual population using + `Dwarf::populate_abbreviations_cache`. + [#679](https://github.com/gimli-rs/gimli/pull/679) + +* Changed the default `read::UnwindContextStorage` to use `Box` instead of `Vec` + so that its memory usage is limited. + [#687](https://github.com/gimli-rs/gimli/pull/687) + +* Changed `read::UnwindTable::new` to always reset the context, because + previous errors may have left the context in an invalid state. + [#684](https://github.com/gimli-rs/gimli/pull/684) + +* Changed the `Debug` implementation for `read::EndianSlice` to limit the number + of bytes it displays. + [#686](https://github.com/gimli-rs/gimli/pull/686) + +### Added + +* Added more AArch64 register definitions. + [#680](https://github.com/gimli-rs/gimli/pull/680) + +* Added `read::Unit::new_with_abbreviations`. + [#677](https://github.com/gimli-rs/gimli/pull/677) + +* Added `read::Evaluation::value_result`. + [#676](https://github.com/gimli-rs/gimli/pull/676) + +-------------------------------------------------------------------------------- + +## 0.28.0 + +Released 2023/08/12. + +### Breaking changes + +* Deleted `impl From for &[u8]`. Use `EndianSlice::slice` instead. + [#669](https://github.com/gimli-rs/gimli/pull/669) + +* Deleted `impl Index for EndianSlice` and + `impl Index> for EndianSlice`. + [#669](https://github.com/gimli-rs/gimli/pull/669) + +* Replaced `impl From for u64` with `Pointer::pointer`. + [#670](https://github.com/gimli-rs/gimli/pull/670) + +* Updated `fallible-iterator` to 0.3.0. + [#672](https://github.com/gimli-rs/gimli/pull/672) + +* Changed some optional dependencies to use the `dep:` feature syntax. + [#672](https://github.com/gimli-rs/gimli/pull/672) + +* Added `non_exhaustive` attribute to `read::RegisterRule`, + `read::CallFrameInstruction`, and `write::CallFrameInstruction`. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +### Changed + +* The minimum supported rust version for the `read` feature and its dependencies + increased to 1.60.0. + +* The minimum supported rust version for other features increased to 1.65.0. + +### Added + +* Added `Vendor`, `read::DebugFrame::set_vendor`, and `read::EhFrame::set_vendor`. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +* Added more ARM and AArch64 register definitions, and + `DW_CFA_AARCH64_negate_ra_state` support. + [#673](https://github.com/gimli-rs/gimli/pull/673) + +-------------------------------------------------------------------------------- + +## 0.27.3 + +Released 2023/06/14. + +### Changed + +* Excluded test fixtures from published package. + [#661](https://github.com/gimli-rs/gimli/pull/661) + +### Added + +* Added `FallibleIterator` implementation for `read::OperationIter`. + [#649](https://github.com/gimli-rs/gimli/pull/649) + +* Added `DW_AT_GNU_deleted` constant. + [#658](https://github.com/gimli-rs/gimli/pull/658) + +-------------------------------------------------------------------------------- + +## 0.27.2 + +Released 2023/02/15. + +### Added + +* Added support for tombstones in `read::LineRows`. + [#642](https://github.com/gimli-rs/gimli/pull/642) + +-------------------------------------------------------------------------------- + +## 0.27.1 + +Released 2023/01/23. + +### Added + +* Added `SectionId::xcoff_name` and `read::Section::xcoff_section_name`. + [#635](https://github.com/gimli-rs/gimli/pull/635) + +* Added `read::Dwarf::make_dwo` and `read::Unit::dwo_name`. + [#637](https://github.com/gimli-rs/gimli/pull/637) + +### Changed + +* Changed `read::DwarfPackage::sections` to handle supplementary files. + [#638](https://github.com/gimli-rs/gimli/pull/638) + +-------------------------------------------------------------------------------- + +## 0.27.0 + +Released 2022/11/23. + +### Breaking changes + +* Added `read::Dwarf::abbreviations_cache` to cache abbreviations at offset 0. + Changed `read::Dwarf::abbreviations` to return `Result>`, + and changed `read::Unit::abbreviations` to `Arc`. + [#628](https://github.com/gimli-rs/gimli/pull/628) + +### Added + +* Added LoongArch register definitions. + [#624](https://github.com/gimli-rs/gimli/pull/624) + +* Added support for tombstones in `read::LocListIter` and `read::RngListIter`. + [#631](https://github.com/gimli-rs/gimli/pull/631) + +-------------------------------------------------------------------------------- + +## 0.26.2 + +Released 2022/07/16. + +### Changed + +* Fixed CFI personality encoding when writing. + [#609](https://github.com/gimli-rs/gimli/pull/609) + +* Fixed use of raw pointer for mutation, detected by Miri. + [#614](https://github.com/gimli-rs/gimli/pull/614) + +* Fixed `DW_OP_GNU_implicit_pointer` handling for DWARF version 2. + [#618](https://github.com/gimli-rs/gimli/pull/618) + +### Added + +* Added `read::EhHdrTable::iter`. + [#619](https://github.com/gimli-rs/gimli/pull/619) + +-------------------------------------------------------------------------------- + +## 0.26.1 + +Released 2021/11/02. + +### Changed + +* Fixed segmentation fault in `ArrayVec>::into_vec`, which may be used by + `read::Evaluation::result`. This regression was introduced in 0.26.0. + [#601](https://github.com/gimli-rs/gimli/pull/601) + +-------------------------------------------------------------------------------- + +## 0.26.0 + +Released 2021/10/24. + +### Breaking changes + +* Removed `read::UninitializedUnwindContext`. Use `Box` instead. + [#593](https://github.com/gimli-rs/gimli/pull/593) + +* Renamed `read::Error::CfiStackFull` to `StackFull`. + [#595](https://github.com/gimli-rs/gimli/pull/595) + +* Added `UnwindContextStorage` type parameter to `read::UnwindContext`, `read::UnwindTable`, + `read::UnwindTableRow`, and `read::RegisterRuleMap`. + [#595](https://github.com/gimli-rs/gimli/pull/595) + +* Added `EvaluationStorage` type parameter to `read::Evaluation`. + [#595](https://github.com/gimli-rs/gimli/pull/595) + +* Added `read::SectionId::DebugCuIndex` and `read::SectionId::DebugTuIndex`. + [#588](https://github.com/gimli-rs/gimli/pull/588) + +### Changed + +* Fixed `DW_EH_PE_pcrel` handling in default `write::Writer::write_eh_pointer` implementation. + [#576](https://github.com/gimli-rs/gimli/pull/576) + +* Fixed `read::AttributeSpecification::size` for some forms. + [#597](https://github.com/gimli-rs/gimli/pull/597) + +* Display more unit details in dwarfdump. + [#584](https://github.com/gimli-rs/gimli/pull/584) + +### Added + +* Added `write::DebuggingInformationEntry::delete_child`. + [#570](https://github.com/gimli-rs/gimli/pull/570) + +* Added ARM and AArch64 register definitions. + [#574](https://github.com/gimli-rs/gimli/pull/574) + [#577](https://github.com/gimli-rs/gimli/pull/577) + +* Added RISC-V register definitions. + [#579](https://github.com/gimli-rs/gimli/pull/579) + +* Added `read::DwarfPackage`, `read::DebugCuIndex`, and `read::DebugTuIndex`. + [#588](https://github.com/gimli-rs/gimli/pull/588) + +* Added `read-core` feature to allow building without `liballoc`. + [#596](https://github.com/gimli-rs/gimli/pull/596) + +* Added `read::EntriesRaw::skip_attributes`. + [#597](https://github.com/gimli-rs/gimli/pull/597) + +-------------------------------------------------------------------------------- + +## 0.25.0 + +Released 2021/07/26. + +### Breaking changes + +* `read::FrameDescriptionEntry::unwind_info_for_address` now returns a reference + instead of cloning. + [#557](https://github.com/gimli-rs/gimli/pull/557) + +* `read::AttributeValue::RangeListsRef` now contains a `RawRangeListsOffset` + to allow handling of GNU split DWARF extensions. + Use `read::Dwarf::ranges_offset_from_raw` to handle it. + [#568](https://github.com/gimli-rs/gimli/pull/568) + [#569](https://github.com/gimli-rs/gimli/pull/569) + +* Added `read::Unit::dwo_id`. + [#569](https://github.com/gimli-rs/gimli/pull/569) + +### Changed + +* `.debug_aranges` parsing now accepts version 3. + [#560](https://github.com/gimli-rs/gimli/pull/560) + +* `read::Dwarf::attr_ranges_offset` and its callers now handle GNU split DWARF extensions. + [#568](https://github.com/gimli-rs/gimli/pull/568) + [#569](https://github.com/gimli-rs/gimli/pull/569) + +### Added + +* Added `read::DebugLineStr::new`. + [#556](https://github.com/gimli-rs/gimli/pull/556) + +* Added `read::UnwindTable::into_current_row`. + [#557](https://github.com/gimli-rs/gimli/pull/557) + +* Added more `DW_LANG` constants. + [#565](https://github.com/gimli-rs/gimli/pull/565) + +* dwarfdump: added DWO parent support. + [#568](https://github.com/gimli-rs/gimli/pull/568) + +* Added `read::Dwarf` methods: `ranges_offset_from_raw`, `raw_ranges`, and `raw_locations`. + [#568](https://github.com/gimli-rs/gimli/pull/568) + [#569](https://github.com/gimli-rs/gimli/pull/569) + +-------------------------------------------------------------------------------- + +## 0.24.0 + +Released 2021/05/01. + +### Breaking changes + +* Minimum Rust version increased to 1.42.0. + +* Added `read::Dwarf::debug_aranges`. + [#539](https://github.com/gimli-rs/gimli/pull/539) + +* Replaced `read::DebugAranges::items` with `read::DebugAranges::headers`. + [#539](https://github.com/gimli-rs/gimli/pull/539) + +* Added `read::Operation::Wasm*`. + [#546](https://github.com/gimli-rs/gimli/pull/546) + +* `read::LineRow::line` now returns `Option`. + The `read::ColumnType::Column` variant now contains a `NonZeroU64`. + [#551](https://github.com/gimli-rs/gimli/pull/551) + +* Replaced `read::Dwarf::debug_str_sup` with `read::Dwarf::sup`. + Deleted `sup` parameter of `read::Dwarf::load`. + Added `read::Dwarf::load_sup`. + [#554](https://github.com/gimli-rs/gimli/pull/554) + +### Added + +* dwarfdump: Supplementary object file support. + [#552](https://github.com/gimli-rs/gimli/pull/552) + +### Changed + +* Support `DW_FORM_addrx*` for `DW_AT_low_pc`/`DW_AT_high_pc` in `read::Dwarf`. + [#541](https://github.com/gimli-rs/gimli/pull/541) + +* Performance improvement in `EndianReader`. + [#549](https://github.com/gimli-rs/gimli/pull/549) + +-------------------------------------------------------------------------------- + +## 0.23.0 + +Released 2020/10/27. + +### Breaking changes + +* Added more variants to `read::UnitType`. + Added `read::AttributeValue::DwoId` + [#521](https://github.com/gimli-rs/gimli/pull/521) + +* Replaced `CompilationUnitHeader` and `TypeUnitHeader` with `UnitHeader`. + Replaced `CompilationUnitHeadersIter` with `DebugInfoUnitHeadersIter`. + Replaced `TypeUnitHeadersIter` with `DebugTypesUnitHeadersIter`. + [#523](https://github.com/gimli-rs/gimli/pull/523) + + +### Added + +* Added read support for split DWARF. + [#527](https://github.com/gimli-rs/gimli/pull/527) + [#529](https://github.com/gimli-rs/gimli/pull/529) + +* Added `read::Dwarf::attr_address`. + [#524](https://github.com/gimli-rs/gimli/pull/524) + +* Added read support for `DW_AT_GNU_addr_base` and `DW_AT_GNU_ranges_base`. + [#525](https://github.com/gimli-rs/gimli/pull/525) + +* dwarfdump: Display index values for attributes. + [#526](https://github.com/gimli-rs/gimli/pull/526) + +* Added `name_to_register`. + [#532](https://github.com/gimli-rs/gimli/pull/532) + +-------------------------------------------------------------------------------- + +## 0.22.0 + +Released 2020/07/03. + +### Breaking changes + +* Fixed `UnitHeader::size_of_header` for DWARF 5 units. + [#518](https://github.com/gimli-rs/gimli/pull/518) + +### Added + +* Added fuzz targets in CI. + [#512](https://github.com/gimli-rs/gimli/pull/512) + +* Added read support for `DW_OP_GNU_addr_index` and `DW_OP_GNU_const_index`. + [#516](https://github.com/gimli-rs/gimli/pull/516) + +* Added `.dwo` support to dwarfdump. + [#516](https://github.com/gimli-rs/gimli/pull/516) + +* Added `SectionId::dwo_name` and `Section::dwo_section_name`. + [#517](https://github.com/gimli-rs/gimli/pull/517) + +### Fixed + +* Fixed panic when reading `DW_FORM_indirect` combined with `DW_FORM_implicit_const`. + [#502](https://github.com/gimli-rs/gimli/pull/502) + +* Fixed panic for `read::Abbreviations::get(0)`. + [#505](https://github.com/gimli-rs/gimli/pull/505) + +* Fixed arithmetic overflow when reading `.debug_line`. + [#508](https://github.com/gimli-rs/gimli/pull/508) + +* Fixed arithmetic overflow when reading CFI. + [#509](https://github.com/gimli-rs/gimli/pull/509) + +* Fixed arithmetic overflow and division by zero when reading `.debug_aranges`. + [#510](https://github.com/gimli-rs/gimli/pull/510) + +* Don't return error from `read::Unit::new` when `DW_AT_name` or `DW_AT_comp_dir` is missing. + [#515](https://github.com/gimli-rs/gimli/pull/515) + +-------------------------------------------------------------------------------- + +## 0.21.0 + +Released 2020/05/12. + +### Breaking changes + +* Minimum Rust version increased to 1.38.0. + +* Replaced `read::Operation::Literal` with `Operation::UnsignedConstant` and `Operation::SignedConstant`. + Changed `read::Operation::Bra` and `read::Operation::Skip` to contain the target offset instead of the bytecode. + [#479](https://github.com/gimli-rs/gimli/pull/479) + +* Changed `write::Expression` to support references. Existing users can convert to use `Expression::raw`. + [#479](https://github.com/gimli-rs/gimli/pull/479) + +* Replaced `write::AttributeValue::AnyUnitEntryRef` with `DebugInfoRef`. + Renamed `write::AttributeValue::ThisUnitEntryRef` to `UnitRef`. + [#479](https://github.com/gimli-rs/gimli/pull/479) + +* Added more optional features: `endian-reader` and `fallible-iterator`. + [#495](https://github.com/gimli-rs/gimli/pull/495) + [#498](https://github.com/gimli-rs/gimli/pull/498) + +### Added + +* Added `read::Expression::operations` + [#479](https://github.com/gimli-rs/gimli/pull/479) + +### Fixed + +* Fixed newlines in `dwarfdump` example. + [#470](https://github.com/gimli-rs/gimli/pull/470) + +* Ignore zero terminators when reading `.debug_frame` sections. + [#486](https://github.com/gimli-rs/gimli/pull/486) + +* Increase the number of CFI register rules supported by `read::UnwindContext`. + [#487](https://github.com/gimli-rs/gimli/pull/487) + +* Fixed version handling and return register encoding when reading `.eh_frame` sections. + [#493](https://github.com/gimli-rs/gimli/pull/493) + +### Changed + +* Added `EhFrame` and `DebugFrame` to `write::Sections`. + [#492](https://github.com/gimli-rs/gimli/pull/492) + +* Improved performance of `write::LineProgram::generate_row`. + [#476](https://github.com/gimli-rs/gimli/pull/476) + +* Removed use of the `byteorder`, `arrayvec` and `smallvec` crates. + [#494](https://github.com/gimli-rs/gimli/pull/494) + [#496](https://github.com/gimli-rs/gimli/pull/496) + [#497](https://github.com/gimli-rs/gimli/pull/497) + +-------------------------------------------------------------------------------- + +## 0.20.0 + +Released 2020/01/11. + +### Breaking changes + +* Changed type of `DwTag`, `DwAt`, and `DwForm` constants. + [#451](https://github.com/gimli-rs/gimli/pull/451) + +* Added `read/write::AttributeValue::DebugMacroRef`, and returned where + required in `read::Attribute::value`. Added `SectionId::DebugMacro`. + [#454](https://github.com/gimli-rs/gimli/pull/454) + +* Deleted `alloc` feature, and fixed `no-std` builds with stable rust. + [#459](https://github.com/gimli-rs/gimli/pull/459) + +* Deleted `read::Error::description`, and changed `` + to display what was previously the description. + [#462](https://github.com/gimli-rs/gimli/pull/462) + +### Added + +* Added GNU view constants. + [#434](https://github.com/gimli-rs/gimli/pull/434) + +* Added `read::EntriesRaw` for low level DIE parsing. + [#455](https://github.com/gimli-rs/gimli/pull/455) + +* Added `examples/simple-line.rs`. + [#460](https://github.com/gimli-rs/gimli/pull/460) + +### Fixed + +* Fixed handling of CFI augmentations without data. + [#438](https://github.com/gimli-rs/gimli/pull/438) + +* dwarfdump: fix panic for malformed expressions. + [#447](https://github.com/gimli-rs/gimli/pull/447) + +* dwarfdump: fix handling of Mach-O relocations. + [#449](https://github.com/gimli-rs/gimli/pull/449) + +### Changed + +* Improved abbreviation parsing performance. + [#451](https://github.com/gimli-rs/gimli/pull/451) + +-------------------------------------------------------------------------------- + +## 0.19.0 + +Released 2019/07/08. + +### Breaking changes + +* Small API changes related to `.debug_loc` and `.debug_loclists`: + added `read::RawLocListEntry::AddressOrOffsetPair` enum variant, + added `write::Sections::debug_loc/debug_loclists` public members, + and replaced `write::AttributeValue::LocationListsRef` with `LocationListRef`. + [#425](https://github.com/gimli-rs/gimli/pull/425) + +### Added + +* Added `read::Attribute::exprloc_value` and `read::AttributeValue::exprloc_value`. + [#422](https://github.com/gimli-rs/gimli/pull/422) + +* Added support for writing `.debug_loc` and `.debug_loclists` sections. + [#425](https://github.com/gimli-rs/gimli/pull/425) + +* Added `-G` flag to `dwarfdump` example to display global offsets. + [#427](https://github.com/gimli-rs/gimli/pull/427) + +* Added `examples/simple.rs`. + [#429](https://github.com/gimli-rs/gimli/pull/429) + +### Fixed + +* `write::LineProgram::from` no longer requires `DW_AT_name` or `DW_AT_comp_dir` + attributes to be present in the unit DIE. + [#430](https://github.com/gimli-rs/gimli/pull/430) + +-------------------------------------------------------------------------------- + +## 0.18.0 + +Released 2019/04/25. + +The focus of this release has been on improving support for reading CFI, +and adding support for writing CFI. + +### Breaking changes + +* For types which have an `Offset` type parameter, the default `Offset` + has changed from `usize` to `R::Offset`. + [#392](https://github.com/gimli-rs/gimli/pull/392) + +* Added an `Offset` type parameter to the `read::Unit` type to allow variance. + [#393](https://github.com/gimli-rs/gimli/pull/393) + +* Changed the `UninitializedUnwindContext::initialize` method to borrow `self`, + and return `&mut UnwindContext`. Deleted the `InitializedUnwindContext` type. + [#395](https://github.com/gimli-rs/gimli/pull/395) + +* Deleted the `UnwindSection` type parameters from the `CommonInformationEntry`, + `FrameDescriptionEntry`, `UninitializedUnwindContext`, + `UnwindContext`, and `UnwindTable` types. + [#399](https://github.com/gimli-rs/gimli/pull/399) + +* Changed the signature of the `get_cie` callback parameter for various functions. + The signature now matches the `UnwindSection::cie_from_offset` method, so + that method can be used as the parameter. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Reduced the number of lifetime parameters for the `UnwindTable` type. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Updated `fallible-iterator` to version 0.2.0. + [#407](https://github.com/gimli-rs/gimli/pull/407) + +* Added a parameter to the `Error::UnexpectedEof` enum variant. + [#408](https://github.com/gimli-rs/gimli/pull/408) + +### Added + +* Update to 2018 edition. + [#391](https://github.com/gimli-rs/gimli/pull/391) + +* Added the `FrameDescriptionEntry::unwind_info_for_address` method. + [#396](https://github.com/gimli-rs/gimli/pull/396) + +* Added the `FrameDescriptionEntry::rows` method. + [#396](https://github.com/gimli-rs/gimli/pull/396) + +* Added the `EhHdrTable::unwind_info_for_address` method. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Added the `EhHdrTable::fde_for_address` method and deprecated the + `EhHdrTable::lookup_and_parse` method. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Added the `EhHdrTable::pointer_to_offset` method. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Added the `UnwindSection::fde_for_address` method. + [#396](https://github.com/gimli-rs/gimli/pull/396) + +* Added the `UnwindSection::fde_from_offset` method. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Added the `UnwindSection::partial_fde_from_offset` method. + [#400](https://github.com/gimli-rs/gimli/pull/400) + +* Added the `Section::id` method. + [#406](https://github.com/gimli-rs/gimli/pull/406) + +* Added the `Dwarf::load` method, and corresponding methods for individual sections. + [#406](https://github.com/gimli-rs/gimli/pull/406) + +* Added the `Dwarf::borrow` method, and corresponding methods for individual sections. + [#406](https://github.com/gimli-rs/gimli/pull/406) + +* Added the `Dwarf::format_error` method. + [#408](https://github.com/gimli-rs/gimli/pull/408) + +* Added the `Dwarf::die_ranges` method. + [#417](https://github.com/gimli-rs/gimli/pull/417) + +* Added the `Dwarf::unit_ranges` method. + [#417](https://github.com/gimli-rs/gimli/pull/417) + +* Added support for writing `.debug_frame` and `.eh_frame` sections. + [#412](https://github.com/gimli-rs/gimli/pull/412) + [#419](https://github.com/gimli-rs/gimli/pull/419) + +### Fixed + +* The `code_alignment_factor` is now used when evaluating CFI instructions + that advance the location. + [#401](https://github.com/gimli-rs/gimli/pull/401) + +* Fixed parsing of pointers encoded with `DW_EH_PE_funcrel`. + [#402](https://github.com/gimli-rs/gimli/pull/402) + +* Use the FDE address encoding from the augmentation when parsing `DW_CFA_set_loc`. + [#403](https://github.com/gimli-rs/gimli/pull/403) + +* Fixed setting of `.eh_frame` base addresses in dwarfdump. + [#410](https://github.com/gimli-rs/gimli/pull/410) + +## 0.17.0 + +Released 2019/02/21. + +The focus of this release has been on improving DWARF 5 support, and +adding support for writing DWARF. + +### Breaking changes + +* Changed register values to a `Register` type instead of `u8`/`u64`. + [#328](https://github.com/gimli-rs/gimli/pull/328) + +* Replaced `BaseAddresses::set_cfi` with `set_eh_frame_hdr` and `set_eh_frame`. + Replaced `BaseAddresses::set_data` with `set_got`. + You should now use the same `BaseAddresses` value for parsing both + `.eh_frame` and `.eh_frame_hdr`. + [#351](https://github.com/gimli-rs/gimli/pull/351) + +* Renamed many types and functions related to `.debug_line`. + Renamed `LineNumberProgram` to `LineProgram`. + Renamed `IncompleteLineNumberProgram` to `IncompleteLineProgram`. + Renamed `CompleteLineNumberProgram` to `CompleteLineProgram`. + Renamed `LineNumberProgramHeader` to `LineProgramHeader`. + Renamed `LineNumberRow` to `LineRow`. + Renamed `StateMachine` to `LineRows`. + Renamed `Opcode` to `LineInstruction`. + Renamed `OpcodesIter` to `LineInstructions`. + Renamed `LineNumberSequence` to `LineSequence`. + [#359](https://github.com/gimli-rs/gimli/pull/359) + +* Added `Offset` type parameter to `AttributeValue`, `LineProgram`, + `IncompleteLineProgram`, `CompleteLineProgram`, `LineRows`, `LineInstruction`, + and `FileEntry`. + [#324](https://github.com/gimli-rs/gimli/pull/324) + +* Changed `FileEntry::path_name`, `FileEntry::directory`, and + `LineProgramHeader::directory` to return an `AttributeValue` instead + of a `Reader`. + [#366](https://github.com/gimli-rs/gimli/pull/366) + +* Renamed `FileEntry::last_modification` to `FileEntry::timestamp` + and renamed `FileEntry::length` to `FileEntry::size`. + [#366](https://github.com/gimli-rs/gimli/pull/366) + +* Added an `Encoding` type. Changed many functions that previously accepted + `Format`, version or address size parameters to accept an `Encoding` + parameter instead. + Notable changes are `LocationLists::locations`, `RangeLists::ranges`, + and `Expression::evaluation`. + [#364](https://github.com/gimli-rs/gimli/pull/364) + +* Changed return type of `LocationLists::new` and `RangeLists::new`. + [#370](https://github.com/gimli-rs/gimli/pull/370) + +* Added parameters to `LocationsLists::locations` and `RangeLists::ranges` + to support `.debug_addr`. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Added more `AttributeValue` variants: `DebugAddrBase`, `DebugAddrIndex`, + `DebugLocListsBase`, `DebugLocListsIndex`, `DebugRngListsBase`, `DebugRngListsIndex`, + `DebugStrOffsetsBase`, `DebugStrOffsetsIndex`, `DebugLineStrRef`. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Changed `AttributeValue::Data*` attributes to native endian integers instead + of byte arrays. + [#365](https://github.com/gimli-rs/gimli/pull/365) + +* Replaced `EvaluationResult::TextBase` with + `EvaluationResult::RequiresRelocatedAddress`. The handling of `TextBase` + was incorrect. + [#335](https://github.com/gimli-rs/gimli/pull/335) + +* Added `EvaluationResult::IndexedAddress` for operations that require an + address from `.debug_addr`. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Added `Reader::read_slice`. Added a default implementation of + `Reader::read_u8_array` which uses this. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +### Added + +* Added initial support for writing DWARF. This is targeted at supporting + line number information only. + [#340](https://github.com/gimli-rs/gimli/pull/340) + [#344](https://github.com/gimli-rs/gimli/pull/344) + [#346](https://github.com/gimli-rs/gimli/pull/346) + [#361](https://github.com/gimli-rs/gimli/pull/361) + [#362](https://github.com/gimli-rs/gimli/pull/362) + [#365](https://github.com/gimli-rs/gimli/pull/365) + [#368](https://github.com/gimli-rs/gimli/pull/368) + [#382](https://github.com/gimli-rs/gimli/pull/382) + +* Added `read` and `write` Cargo features. Both are enabled by default. + [#343](https://github.com/gimli-rs/gimli/pull/343) + +* Added support for reading DWARF 5 `.debug_line` and `.debug_line_str` sections. + [#366](https://github.com/gimli-rs/gimli/pull/366) + +* Added support for reading DWARF 5 `.debug_str_offsets` sections, including + parsing `DW_FORM_strx*` attributes. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Added support for reading DWARF 5 `.debug_addr` sections, including parsing + `DW_FORM_addrx*` attributes and evaluating `DW_OP_addrx` and `DW_OP_constx` + operations. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Added support for reading DWARF 5 indexed addresses and offsets in + `.debug_loclists` and `.debug_rnglists`, including parsing `DW_FORM_rnglistx` + and `DW_FORM_loclistx` attributes. + [#358](https://github.com/gimli-rs/gimli/pull/358) + +* Added high level `Dwarf` and `Unit` types. Existing code does not need to + switch to using these types, but doing so will make DWARF 5 support simpler. + [#352](https://github.com/gimli-rs/gimli/pull/352) + [#380](https://github.com/gimli-rs/gimli/pull/380) + [#381](https://github.com/gimli-rs/gimli/pull/381) + +* Added `EhFrame::set_address_size` and `DebugFrame::set_address_size` methods + to allow parsing non-native CFI sections. The default address size is still + the native size. + [#325](https://github.com/gimli-rs/gimli/pull/325) + +* Added architecture specific definitions for `Register` values and names. + Changed dwarfdump to print them. + [#328](https://github.com/gimli-rs/gimli/pull/328) + +* Added support for reading relocatable DWARF sections. + [#337](https://github.com/gimli-rs/gimli/pull/337) + +* Added parsing of `DW_FORM_data16`. + [#366](https://github.com/gimli-rs/gimli/pull/366) + +### Fixed + +* Fixed parsing DWARF 5 ranges with `start == end == 0`. + [#323](https://github.com/gimli-rs/gimli/pull/323) + +* Changed `LineRows` to be covariant in its `Reader` type parameter. + [#324](https://github.com/gimli-rs/gimli/pull/324) + +* Fixed handling of empty units in dwarfdump. + [#330](https://github.com/gimli-rs/gimli/pull/330) + +* Fixed `UnitHeader::length_including_self` for `Dwarf64`. + [#342](https://github.com/gimli-rs/gimli/pull/342) + +* Fixed parsing of `DW_CFA_set_loc`. + [#355](https://github.com/gimli-rs/gimli/pull/355) + +* Fixed handling of multiple headers in `.debug_loclists` and `.debug_rnglists`. + [#370](https://github.com/gimli-rs/gimli/pull/370) + +-------------------------------------------------------------------------------- + +## 0.16.1 + +Released 2018/08/28. + +### Added + +* Added `EhFrameHdr::lookup_and_parse`. [#316][] +* Added support for `DW_CFA_GNU_args_size`. [#319][] + +### Fixed + +* Implement `Send`/`Sync` for `SubRange`. [#305][] +* Fixed `alloc` support on nightly. [#306][] [#310][] + +[#305]: https://github.com/gimli-rs/gimli/pull/305 +[#306]: https://github.com/gimli-rs/gimli/pull/306 +[#310]: https://github.com/gimli-rs/gimli/pull/310 +[#316]: https://github.com/gimli-rs/gimli/pull/316 +[#319]: https://github.com/gimli-rs/gimli/pull/319 + +-------------------------------------------------------------------------------- + +## 0.16.0 + +Released 2018/06/01. + +### Added + +* Added support for building in `#![no_std]` environments, when the `alloc` + crate is available. Disable the "std" feature and enable the "alloc" + feature. [#138][] [#271][] + +* Added support for DWARF 5 `.debug_rnglists` and `.debug_loclists` + sections. [#272][] + +* Added support for DWARF 5 `DW_FORM_ref_sup` and `DW_FORM_strp_sup` attribute + forms. [#288][] + +* Added support for DWARF 5 operations on typed values. [#293][] + +* A `dwarf-validate` example program that checks the integrity of the given + DWARF and its references between sections. [#290][] + +* Added the `EndianReader` type, an easy way to define a custom `Reader` + implementation with a reference to a generic buffer of bytes and an associated + endianity. [#298][] [#302][] + +### Changed + +* Various speed improvements for evaluating `.debug_line` line number + programs. [#276][] + +* The example `dwarfdump` clone is a [whole lot faster + now][dwarfdump-faster]. [#282][] [#284][] [#285][] + +### Deprecated + +* `EndianBuf` has been renamed to `EndianSlice`, use that name instead. [#295][] + +### Fixed + +* Evaluating the `DW_CFA_restore_state` opcode properly maintains the current + location. Previously it would incorrectly restore the old location when + popping from evaluation stack. [#274][] + +[#271]: https://github.com/gimli-rs/gimli/issues/271 +[#138]: https://github.com/gimli-rs/gimli/issues/138 +[#274]: https://github.com/gimli-rs/gimli/issues/274 +[#272]: https://github.com/gimli-rs/gimli/issues/272 +[#276]: https://github.com/gimli-rs/gimli/issues/276 +[#282]: https://github.com/gimli-rs/gimli/issues/282 +[#285]: https://github.com/gimli-rs/gimli/issues/285 +[#284]: https://github.com/gimli-rs/gimli/issues/284 +[#288]: https://github.com/gimli-rs/gimli/issues/288 +[#290]: https://github.com/gimli-rs/gimli/issues/290 +[#293]: https://github.com/gimli-rs/gimli/issues/293 +[#295]: https://github.com/gimli-rs/gimli/issues/295 +[#298]: https://github.com/gimli-rs/gimli/issues/298 +[#302]: https://github.com/gimli-rs/gimli/issues/302 +[dwarfdump-faster]: https://robert.ocallahan.org/2018/03/speeding-up-dwarfdump-with-rust.html + +-------------------------------------------------------------------------------- + +## 0.15.0 + +Released 2017/12/01. + +### Added + +* Added the `EndianBuf::to_string()` method. [#233][] + +* Added more robust error handling in our example `dwarfdump` clone. [#234][] + +* Added `FrameDescriptionEntry::initial_address` method. [#237][] + +* Added `FrameDescriptionEntry::len` method. [#237][] + +* Added the `FrameDescriptionEntry::entry_len` method. [#241][] + +* Added the `CommonInformationEntry::offset` method. [#241][] + +* Added the `CommonInformationEntry::entry_len` method. [#241][] + +* Added the `CommonInformationEntry::version` method. [#241][] + +* Added the `CommonInformationEntry::augmentation` method. [#241][] + +* Added the `CommonInformationEntry::code_alignment_factor` method. [#241][] + +* Added the `CommonInformationEntry::data_alignment_factor` method. [#241][] + +* Added the `CommonInformationEntry::return_address_register` method. [#241][] + +* Added support for printing `.eh_frame` sections to our example `dwarfdump` + clone. [#241][] + +* Added support for parsing the `.eh_frame_hdr` section. On Linux, the + `.eh_frame_hdr` section provides a pointer to the already-mapped-in-memory + `.eh_frame` data, so that it doesn't need to be duplicated, and a binary + search table of its entries for faster unwinding information lookups. [#250][] + +* Added support for parsing DWARF 5 compilation unit headers. [#257][] + +* Added support for DWARF 5's `DW_FORM_implicit_const`. [#257][] + +### Changed + +* Unwinding methods now give ownership of the unwinding context back to the + caller if errors are encountered, not just on the success path. This allows + recovering from errors in signal-safe code, where constructing a new unwinding + context is not an option because it requires allocation. This is a **breaking + change** affecting `UnwindSection::unwind_info_for_address` and + `UninitializedUnwindContext::initialize`. [#241][] + +* `CfaRule` and `RegisterRule` now expose their `DW_OP` expressions as + `Expression`. This is a minor **breaking change**. [#241][] + +* The `Error::UnknownVersion` variant now contains the unknown version + number. This is a minor **breaking change**. [#245][] + +* `EvaluationResult::RequiresEntryValue` requires an `Expression` instead of a + `Reader` now. This is a minor **breaking change**. [#256][] + + +[#233]: https://github.com/gimli-rs/gimli/pull/233 +[#234]: https://github.com/gimli-rs/gimli/pull/234 +[#237]: https://github.com/gimli-rs/gimli/pull/237 +[#241]: https://github.com/gimli-rs/gimli/pull/241 +[#245]: https://github.com/gimli-rs/gimli/pull/245 +[#250]: https://github.com/gimli-rs/gimli/pull/250 +[#256]: https://github.com/gimli-rs/gimli/pull/256 +[#257]: https://github.com/gimli-rs/gimli/pull/257 + +-------------------------------------------------------------------------------- + +## 0.14.0 + +Released 2017/08/08. + +### Added + +* All `pub` types now `derive(Hash)`. [#192][] + +* All the constants from DWARF 5 are now defined. [#193][] + +* Added support for the `DW_OP_GNU_parameter_ref` GNU extension to parsing and + evaluation DWARF opcodes. [#208][] + +* Improved LEB128 parsing performance. [#216][] + +* Improved `.debug_{aranges,pubnames,pubtypes}` parsing performance. [#218][] + +* Added the ability to choose endianity dynamically at run time, rather than + only statically at compile time. [#219][] + +### Changed + +* The biggest change of this release is that `gimli` no longer requires the + object file's section be fully loaded into memory. This enables using `gimli` + on 32 bit platforms where there often isn't enough contiguous virtual memory + address space to load debugging information into. The default behavior is + still geared for 64 bit platforms, where address space overfloweth, and you + can still load the whole sections of the object file (or the entire object + file) into memory. This is abstracted over with the `gimli::Reader` + trait. This manifests as small (but many) breaking changes to much of the + public API. [#182][] + +### Fixed + +* The `DW_END_*` constants for defining endianity of a compilation unit were + previously incorrect. [#193][] + +* The `DW_OP_addr` opcode is relative to the base address of the `.text` section + of the binary, but we were incorrectly treating it as an absolute value. [#210][] + +[GitHub]: https://github.com/gimli-rs/gimli +[crates.io]: https://crates.io/crates/gimli +[contributing]: https://github.com/gimli-rs/gimli/blob/master/CONTRIBUTING.md +[easy]: https://github.com/gimli-rs/gimli/issues?q=is%3Aopen+is%3Aissue+label%3Aeasy +[#192]: https://github.com/gimli-rs/gimli/pull/192 +[#193]: https://github.com/gimli-rs/gimli/pull/193 +[#182]: https://github.com/gimli-rs/gimli/issues/182 +[#208]: https://github.com/gimli-rs/gimli/pull/208 +[#210]: https://github.com/gimli-rs/gimli/pull/210 +[#216]: https://github.com/gimli-rs/gimli/pull/216 +[#218]: https://github.com/gimli-rs/gimli/pull/218 +[#219]: https://github.com/gimli-rs/gimli/pull/219 diff --git a/anneal/v2/vendor/gimli/Cargo.lock b/anneal/v2/vendor/gimli/Cargo.lock new file mode 100644 index 0000000000..d81e77c067 --- /dev/null +++ b/anneal/v2/vendor/gimli/Cargo.lock @@ -0,0 +1,76 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "gimli" +version = "0.32.3" +dependencies = [ + "fallible-iterator", + "indexmap", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", + "stable_deref_trait", + "test-assembler", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "test-assembler" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a6da51de149453f5c43fa67d5e73cccd75b3c5727a38a2f18c5f3c47f2db582" +dependencies = [ + "byteorder", +] diff --git a/anneal/v2/vendor/gimli/Cargo.toml b/anneal/v2/vendor/gimli/Cargo.toml new file mode 100644 index 0000000000..2041bdb967 --- /dev/null +++ b/anneal/v2/vendor/gimli/Cargo.toml @@ -0,0 +1,114 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.60" +name = "gimli" +version = "0.32.3" +build = false +include = [ + "/CHANGELOG.md", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A library for reading and writing the DWARF debugging format." +documentation = "https://docs.rs/gimli" +readme = "README.md" +keywords = [ + "DWARF", + "debug", + "ELF", + "eh_frame", +] +categories = [ + "development-tools::debugging", + "development-tools::profiling", + "parser-implementations", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/gimli-rs/gimli" +resolver = "2" + +[features] +default = [ + "read-all", + "write", +] +endian-reader = [ + "read", + "dep:stable_deref_trait", +] +fallible-iterator = ["dep:fallible-iterator"] +read = ["read-core"] +read-all = [ + "read", + "std", + "fallible-iterator", + "endian-reader", +] +read-core = [] +rustc-dep-of-std = [ + "dep:core", + "dep:alloc", +] +std = [ + "fallible-iterator?/std", + "stable_deref_trait?/std", +] +write = ["dep:indexmap"] + +[lib] +name = "gimli" +path = "src/lib.rs" + +[dependencies.alloc] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-alloc" + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.fallible-iterator] +version = "0.3.0" +optional = true +default-features = false + +[dependencies.indexmap] +version = "2.0.0" +optional = true + +[dependencies.stable_deref_trait] +version = "1.1.0" +optional = true +default-features = false + +[dev-dependencies.test-assembler] +version = "0.1.3" + +[profile.bench] +codegen-units = 1 +debug = 2 +split-debuginfo = "packed" + +[profile.test] +split-debuginfo = "packed" diff --git a/anneal/v2/vendor/gimli/Cargo.toml.orig b/anneal/v2/vendor/gimli/Cargo.toml.orig new file mode 100644 index 0000000000..6baee9c66b --- /dev/null +++ b/anneal/v2/vendor/gimli/Cargo.toml.orig @@ -0,0 +1,60 @@ +[package] +name = "gimli" +version = "0.32.3" +categories = ["development-tools::debugging", "development-tools::profiling", "parser-implementations"] +description = "A library for reading and writing the DWARF debugging format." +documentation = "https://docs.rs/gimli" +edition = "2018" +include = [ + "/CHANGELOG.md", + "/Cargo.toml", + "/LICENSE-APACHE", + "/LICENSE-MIT", + "/README.md", + "/src", +] +keywords = ["DWARF", "debug", "ELF", "eh_frame"] +license = "MIT OR Apache-2.0" +readme = "./README.md" +repository = "https://github.com/gimli-rs/gimli" +rust-version = "1.60" + +[dependencies] +fallible-iterator = { version = "0.3.0", default-features = false, optional = true } +indexmap = { version = "2.0.0", optional = true } +stable_deref_trait = { version = "1.1.0", default-features = false, optional = true } + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } + +[dev-dependencies] +test-assembler = "0.1.3" + +[features] +read-core = [] +read = ["read-core"] +read-all = ["read", "std", "fallible-iterator", "endian-reader"] +endian-reader = ["read", "dep:stable_deref_trait"] +fallible-iterator = ["dep:fallible-iterator"] +write = ["dep:indexmap"] +std = ["fallible-iterator?/std", "stable_deref_trait?/std"] +default = ["read-all", "write"] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ["dep:core", "dep:alloc"] + +[profile.test] +split-debuginfo = "packed" + +[profile.bench] +debug = true +codegen-units = 1 +split-debuginfo = "packed" + +[workspace] +members = ["crates/examples"] +default-members = [".", "crates/examples"] +resolver = "2" diff --git a/anneal/v2/vendor/gimli/LICENSE-APACHE b/anneal/v2/vendor/gimli/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/gimli/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/gimli/LICENSE-MIT b/anneal/v2/vendor/gimli/LICENSE-MIT new file mode 100644 index 0000000000..e69282e381 --- /dev/null +++ b/anneal/v2/vendor/gimli/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2015 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/gimli/README.md b/anneal/v2/vendor/gimli/README.md new file mode 100644 index 0000000000..03bf6b8c66 --- /dev/null +++ b/anneal/v2/vendor/gimli/README.md @@ -0,0 +1,84 @@ +# `gimli` + +[![](https://img.shields.io/crates/v/gimli.svg) ![](https://img.shields.io/crates/d/gimli.svg)](https://crates.io/crates/gimli) +[![](https://docs.rs/gimli/badge.svg)](https://docs.rs/gimli/) +[![Build Status](https://github.com/gimli-rs/gimli/workflows/Rust/badge.svg)](https://github.com/gimli-rs/gimli/actions) +[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/gimli/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/gimli?branch=master) + +`gimli` is a library for reading and writing the +[DWARF debugging format](https://dwarfstd.org/). + +* **Zero copy:** everything is just a reference to the original input buffer. No + copies of the input data get made. + +* **Lazy:** you can iterate compilation units without parsing their + contents. Parse only as many debugging information entry (DIE) trees as you + iterate over. `gimli` also uses `DW_AT_sibling` references to avoid parsing a + DIE's children to find its next sibling, when possible. + +* **Cross-platform:** `gimli` makes no assumptions about what kind of object + file you're working with. The flipside to that is that it's up to you to + provide an ELF loader on Linux or Mach-O loader on macOS. + + * Unsure which object file parser to use? Try the cross-platform + [`object`](https://github.com/gimli-rs/object) crate. See the + [`gimli-examples`](./crates/examples/src/bin) crate for usage with `gimli`. + +## Install + +To add a `gimli` dependency to your `Cargo.toml`, run: +```console +$ cargo add gimli +``` + +The minimum supported Rust version is: + +* 1.60.0 for the `read` feature and its dependencies. +* 1.65.0 for other features. + +## Documentation + +* [Documentation on docs.rs](https://docs.rs/gimli/) + +* Example programs: + + * [A simple `.debug_info` parser](./crates/examples/src/bin/simple.rs) + + * [A simple `.debug_line` parser](./crates/examples/src/bin/simple_line.rs) + + * [A simple DWARF writer](./crates/examples/src/bin/simple_write.rs) + + * [A simple DWARF converter](./crates/examples/src/bin/simple_convert.rs) + to read DWARF sections then write them back out again. + + * [A `dwarfdump` clone](./crates/examples/src/bin/dwarfdump.rs) + + * [An `addr2line` clone](https://github.com/gimli-rs/addr2line) + + * [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into + code generation by making debugging information readable. + + * [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the + compilers used to create each compilation unit within a shared library or + executable (via `DW_AT_producer`). + + * [`dwarf-validate`](./crates/examples/src/bin/dwarf-validate.rs), a program to validate the + integrity of some DWARF and its references between sections and compilation + units. + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT) + +at your option. + +## Contribution + +See [CONTRIBUTING.md](./CONTRIBUTING.md) for hacking. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/gimli/src/arch.rs b/anneal/v2/vendor/gimli/src/arch.rs new file mode 100644 index 0000000000..a005a16f3b --- /dev/null +++ b/anneal/v2/vendor/gimli/src/arch.rs @@ -0,0 +1,1118 @@ +use crate::common::Register; + +macro_rules! registers { + ($struct_name:ident, { $($name:ident = ($val:expr, $disp:expr)),+ $(,)? } + $(, aliases { $($alias_name:ident = ($alias_val:expr, $alias_disp:expr)),+ $(,)? })?) => { + #[allow(missing_docs)] + impl $struct_name { + $( + pub const $name: Register = Register($val); + )+ + $( + $(pub const $alias_name: Register = Register($alias_val);)+ + )* + } + + impl $struct_name { + /// The name of a register, or `None` if the register number is unknown. + /// + /// Only returns the primary name for registers that alias with others. + pub fn register_name(register: Register) -> Option<&'static str> { + match register { + $( + Self::$name => Some($disp), + )+ + _ => return None, + } + } + + /// Converts a register name into a register number. + pub fn name_to_register(value: &str) -> Option { + match value { + $( + $disp => Some(Self::$name), + )+ + $( + $($alias_disp => Some(Self::$alias_name),)+ + )* + _ => return None, + } + } + } + }; +} + +/// ARM architecture specific definitions. +/// +/// See [DWARF for the ARM Architecture]( +/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf32/aadwarf32.rst). +#[derive(Debug, Clone, Copy)] +pub struct Arm; + +registers!(Arm, { + R0 = (0, "R0"), + R1 = (1, "R1"), + R2 = (2, "R2"), + R3 = (3, "R3"), + R4 = (4, "R4"), + R5 = (5, "R5"), + R6 = (6, "R6"), + R7 = (7, "R7"), + R8 = (8, "R8"), + R9 = (9, "R9"), + R10 = (10, "R10"), + R11 = (11, "R11"), + R12 = (12, "R12"), + R13 = (13, "R13"), + R14 = (14, "R14"), + R15 = (15, "R15"), + + WCGR0 = (104, "wCGR0"), + WCGR1 = (105, "wCGR1"), + WCGR2 = (106, "wCGR2"), + WCGR3 = (107, "wCGR3"), + WCGR4 = (108, "wCGR4"), + WCGR5 = (109, "wCGR5"), + WCGR6 = (110, "wCGR6"), + WCGR7 = (111, "wCGR7"), + + WR0 = (112, "wR0"), + WR1 = (113, "wR1"), + WR2 = (114, "wR2"), + WR3 = (115, "wR3"), + WR4 = (116, "wR4"), + WR5 = (117, "wR5"), + WR6 = (118, "wR6"), + WR7 = (119, "wR7"), + WR8 = (120, "wR8"), + WR9 = (121, "wR9"), + WR10 = (122, "wR10"), + WR11 = (123, "wR11"), + WR12 = (124, "wR12"), + WR13 = (125, "wR13"), + WR14 = (126, "wR14"), + WR15 = (127, "wR15"), + + SPSR = (128, "SPSR"), + SPSR_FIQ = (129, "SPSR_FIQ"), + SPSR_IRQ = (130, "SPSR_IRQ"), + SPSR_ABT = (131, "SPSR_ABT"), + SPSR_UND = (132, "SPSR_UND"), + SPSR_SVC = (133, "SPSR_SVC"), + + RA_AUTH_CODE = (143, "RA_AUTH_CODE"), + + R8_USR = (144, "R8_USR"), + R9_USR = (145, "R9_USR"), + R10_USR = (146, "R10_USR"), + R11_USR = (147, "R11_USR"), + R12_USR = (148, "R12_USR"), + R13_USR = (149, "R13_USR"), + R14_USR = (150, "R14_USR"), + + R8_FIQ = (151, "R8_FIQ"), + R9_FIQ = (152, "R9_FIQ"), + R10_FIQ = (153, "R10_FIQ"), + R11_FIQ = (154, "R11_FIQ"), + R12_FIQ = (155, "R12_FIQ"), + R13_FIQ = (156, "R13_FIQ"), + R14_FIQ = (157, "R14_FIQ"), + + R13_IRQ = (158, "R13_IRQ"), + R14_IRQ = (159, "R14_IRQ"), + + R13_ABT = (160, "R13_ABT"), + R14_ABT = (161, "R14_ABT"), + + R13_UND = (162, "R13_UND"), + R14_UND = (163, "R14_UND"), + + R13_SVC = (164, "R13_SVC"), + R14_SVC = (165, "R14_SVC"), + + WC0 = (192, "wC0"), + WC1 = (193, "wC1"), + WC2 = (194, "wC2"), + WC3 = (195, "wC3"), + WC4 = (196, "wC4"), + WC5 = (197, "wC5"), + WC6 = (198, "wC6"), + WC7 = (199, "wC7"), + + D0 = (256, "D0"), + D1 = (257, "D1"), + D2 = (258, "D2"), + D3 = (259, "D3"), + D4 = (260, "D4"), + D5 = (261, "D5"), + D6 = (262, "D6"), + D7 = (263, "D7"), + D8 = (264, "D8"), + D9 = (265, "D9"), + D10 = (266, "D10"), + D11 = (267, "D11"), + D12 = (268, "D12"), + D13 = (269, "D13"), + D14 = (270, "D14"), + D15 = (271, "D15"), + D16 = (272, "D16"), + D17 = (273, "D17"), + D18 = (274, "D18"), + D19 = (275, "D19"), + D20 = (276, "D20"), + D21 = (277, "D21"), + D22 = (278, "D22"), + D23 = (279, "D23"), + D24 = (280, "D24"), + D25 = (281, "D25"), + D26 = (282, "D26"), + D27 = (283, "D27"), + D28 = (284, "D28"), + D29 = (285, "D29"), + D30 = (286, "D30"), + D31 = (287, "D31"), + + TPIDRURO = (320, "TPIDRURO"), + TPIDRURW = (321, "TPIDRURW"), + TPIDPR = (322, "TPIDPR"), + HTPIDPR = (323, "HTPIDPR"), +}, +aliases { + SP = (13, "SP"), + LR = (14, "LR"), + PC = (15, "PC"), + + ACC0 = (104, "ACC0"), + ACC1 = (105, "ACC1"), + ACC2 = (106, "ACC2"), + ACC3 = (107, "ACC3"), + ACC4 = (108, "ACC4"), + ACC5 = (109, "ACC5"), + ACC6 = (110, "ACC6"), + ACC7 = (111, "ACC7"), + + S0 = (256, "S0"), + S1 = (256, "S1"), + S2 = (257, "S2"), + S3 = (257, "S3"), + S4 = (258, "S4"), + S5 = (258, "S5"), + S6 = (259, "S6"), + S7 = (259, "S7"), + S8 = (260, "S8"), + S9 = (260, "S9"), + S10 = (261, "S10"), + S11 = (261, "S11"), + S12 = (262, "S12"), + S13 = (262, "S13"), + S14 = (263, "S14"), + S15 = (263, "S15"), + S16 = (264, "S16"), + S17 = (264, "S17"), + S18 = (265, "S18"), + S19 = (265, "S19"), + S20 = (266, "S20"), + S21 = (266, "S21"), + S22 = (267, "S22"), + S23 = (267, "S23"), + S24 = (268, "S24"), + S25 = (268, "S25"), + S26 = (269, "S26"), + S27 = (269, "S27"), + S28 = (270, "S28"), + S29 = (270, "S29"), + S30 = (271, "S30"), + S31 = (271, "S31"), +}); + +/// ARM 64-bit (AArch64) architecture specific definitions. +/// +/// See [DWARF for the ARM 64-bit Architecture]( +/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst). +#[derive(Debug, Clone, Copy)] +pub struct AArch64; + +registers!(AArch64, { + X0 = (0, "X0"), + X1 = (1, "X1"), + X2 = (2, "X2"), + X3 = (3, "X3"), + X4 = (4, "X4"), + X5 = (5, "X5"), + X6 = (6, "X6"), + X7 = (7, "X7"), + X8 = (8, "X8"), + X9 = (9, "X9"), + X10 = (10, "X10"), + X11 = (11, "X11"), + X12 = (12, "X12"), + X13 = (13, "X13"), + X14 = (14, "X14"), + X15 = (15, "X15"), + X16 = (16, "X16"), + X17 = (17, "X17"), + X18 = (18, "X18"), + X19 = (19, "X19"), + X20 = (20, "X20"), + X21 = (21, "X21"), + X22 = (22, "X22"), + X23 = (23, "X23"), + X24 = (24, "X24"), + X25 = (25, "X25"), + X26 = (26, "X26"), + X27 = (27, "X27"), + X28 = (28, "X28"), + X29 = (29, "X29"), + X30 = (30, "X30"), + SP = (31, "SP"), + PC = (32, "PC"), + ELR_MODE = (33, "ELR_mode"), + RA_SIGN_STATE = (34, "RA_SIGN_STATE"), + TPIDRRO_EL0 = (35, "TPIDRRO_EL0"), + TPIDR_EL0 = (36, "TPIDR_EL0"), + TPIDR_EL1 = (37, "TPIDR_EL1"), + TPIDR_EL2 = (38, "TPIDR_EL2"), + TPIDR_EL3 = (39, "TPIDR_EL3"), + + VG = (46, "VG"), + FFR = (47, "FFR"), + + P0 = (48, "P0"), + P1 = (49, "P1"), + P2 = (50, "P2"), + P3 = (51, "P3"), + P4 = (52, "P4"), + P5 = (53, "P5"), + P6 = (54, "P6"), + P7 = (55, "P7"), + P8 = (56, "P8"), + P9 = (57, "P9"), + P10 = (58, "P10"), + P11 = (59, "P11"), + P12 = (60, "P12"), + P13 = (61, "P13"), + P14 = (62, "P14"), + P15 = (63, "P15"), + + V0 = (64, "V0"), + V1 = (65, "V1"), + V2 = (66, "V2"), + V3 = (67, "V3"), + V4 = (68, "V4"), + V5 = (69, "V5"), + V6 = (70, "V6"), + V7 = (71, "V7"), + V8 = (72, "V8"), + V9 = (73, "V9"), + V10 = (74, "V10"), + V11 = (75, "V11"), + V12 = (76, "V12"), + V13 = (77, "V13"), + V14 = (78, "V14"), + V15 = (79, "V15"), + V16 = (80, "V16"), + V17 = (81, "V17"), + V18 = (82, "V18"), + V19 = (83, "V19"), + V20 = (84, "V20"), + V21 = (85, "V21"), + V22 = (86, "V22"), + V23 = (87, "V23"), + V24 = (88, "V24"), + V25 = (89, "V25"), + V26 = (90, "V26"), + V27 = (91, "V27"), + V28 = (92, "V28"), + V29 = (93, "V29"), + V30 = (94, "V30"), + V31 = (95, "V31"), + + Z0 = (96, "Z0"), + Z1 = (97, "Z1"), + Z2 = (98, "Z2"), + Z3 = (99, "Z3"), + Z4 = (100, "Z4"), + Z5 = (101, "Z5"), + Z6 = (102, "Z6"), + Z7 = (103, "Z7"), + Z8 = (104, "Z8"), + Z9 = (105, "Z9"), + Z10 = (106, "Z10"), + Z11 = (107, "Z11"), + Z12 = (108, "Z12"), + Z13 = (109, "Z13"), + Z14 = (110, "Z14"), + Z15 = (111, "Z15"), + Z16 = (112, "Z16"), + Z17 = (113, "Z17"), + Z18 = (114, "Z18"), + Z19 = (115, "Z19"), + Z20 = (116, "Z20"), + Z21 = (117, "Z21"), + Z22 = (118, "Z22"), + Z23 = (119, "Z23"), + Z24 = (120, "Z24"), + Z25 = (121, "Z25"), + Z26 = (122, "Z26"), + Z27 = (123, "Z27"), + Z28 = (124, "Z28"), + Z29 = (125, "Z29"), + Z30 = (126, "Z30"), + Z31 = (127, "Z31"), +}); + +/// LoongArch architecture specific definitions. +/// +/// See [LoongArch ELF psABI specification](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html). +#[derive(Debug, Clone, Copy)] +pub struct LoongArch; + +registers!(LoongArch, { + R0 = (0, "$r0"), + R1 = (1, "$r1"), + R2 = (2, "$r2"), + R3 = (3, "$r3"), + R4 = (4, "$r4"), + R5 = (5, "$r5"), + R6 = (6, "$r6"), + R7 = (7, "$r7"), + R8 = (8, "$r8"), + R9 = (9, "$r9"), + R10 = (10, "$r10"), + R11 = (11, "$r11"), + R12 = (12, "$r12"), + R13 = (13, "$r13"), + R14 = (14, "$r14"), + R15 = (15, "$r15"), + R16 = (16, "$r16"), + R17 = (17, "$r17"), + R18 = (18, "$r18"), + R19 = (19, "$r19"), + R20 = (20, "$r20"), + R21 = (21, "$r21"), + R22 = (22, "$r22"), + R23 = (23, "$r23"), + R24 = (24, "$r24"), + R25 = (25, "$r25"), + R26 = (26, "$r26"), + R27 = (27, "$r27"), + R28 = (28, "$r28"), + R29 = (29, "$r29"), + R30 = (30, "$r30"), + R31 = (31, "$r31"), + + F0 = (32, "$f0"), + F1 = (33, "$f1"), + F2 = (34, "$f2"), + F3 = (35, "$f3"), + F4 = (36, "$f4"), + F5 = (37, "$f5"), + F6 = (38, "$f6"), + F7 = (39, "$f7"), + F8 = (40, "$f8"), + F9 = (41, "$f9"), + F10 = (42, "$f10"), + F11 = (43, "$f11"), + F12 = (44, "$f12"), + F13 = (45, "$f13"), + F14 = (46, "$f14"), + F15 = (47, "$f15"), + F16 = (48, "$f16"), + F17 = (49, "$f17"), + F18 = (50, "$f18"), + F19 = (51, "$f19"), + F20 = (52, "$f20"), + F21 = (53, "$f21"), + F22 = (54, "$f22"), + F23 = (55, "$f23"), + F24 = (56, "$f24"), + F25 = (57, "$f25"), + F26 = (58, "$f26"), + F27 = (59, "$f27"), + F28 = (60, "$f28"), + F29 = (61, "$f29"), + F30 = (62, "$f30"), + F31 = (63, "$f31"), + FCC0 = (64, "$fcc0"), + FCC1 = (65, "$fcc1"), + FCC2 = (66, "$fcc2"), + FCC3 = (67, "$fcc3"), + FCC4 = (68, "$fcc4"), + FCC5 = (69, "$fcc5"), + FCC6 = (70, "$fcc6"), + FCC7 = (71, "$fcc7"), +}, +aliases { + ZERO = (0, "$zero"), + RA = (1, "$ra"), + TP = (2, "$tp"), + SP = (3, "$sp"), + A0 = (4, "$a0"), + A1 = (5, "$a1"), + A2 = (6, "$a2"), + A3 = (7, "$a3"), + A4 = (8, "$a4"), + A5 = (9, "$a5"), + A6 = (10, "$a6"), + A7 = (11, "$a7"), + T0 = (12, "$t0"), + T1 = (13, "$t1"), + T2 = (14, "$t2"), + T3 = (15, "$t3"), + T4 = (16, "$t4"), + T5 = (17, "$t5"), + T6 = (18, "$t6"), + T7 = (19, "$t7"), + T8 = (20, "$t8"), + FP = (22, "$fp"), + S0 = (23, "$s0"), + S1 = (24, "$s1"), + S2 = (25, "$s2"), + S3 = (26, "$s3"), + S4 = (27, "$s4"), + S5 = (28, "$s5"), + S6 = (29, "$s6"), + S7 = (30, "$s7"), + S8 = (31, "$s8"), + + FA0 = (32, "$fa0"), + FA1 = (33, "$fa1"), + FA2 = (34, "$fa2"), + FA3 = (35, "$fa3"), + FA4 = (36, "$fa4"), + FA5 = (37, "$fa5"), + FA6 = (38, "$fa6"), + FA7 = (39, "$fa7"), + FT0 = (40, "$ft0"), + FT1 = (41, "$ft1"), + FT2 = (42, "$ft2"), + FT3 = (43, "$ft3"), + FT4 = (44, "$ft4"), + FT5 = (45, "$ft5"), + FT6 = (46, "$ft6"), + FT7 = (47, "$ft7"), + FT8 = (48, "$ft8"), + FT9 = (49, "$ft9"), + FT10 = (50, "$ft10"), + FT11 = (51, "$ft11"), + FT12 = (52, "$ft12"), + FT13 = (53, "$ft13"), + FT14 = (54, "$ft14"), + FT15 = (55, "$ft15"), + FS0 = (56, "$fs0"), + FS1 = (57, "$fs1"), + FS2 = (58, "$fs2"), + FS3 = (59, "$fs3"), + FS4 = (60, "$fs4"), + FS5 = (61, "$fs5"), + FS6 = (62, "$fs6"), + FS7 = (63, "$fs7"), +}); + +/// MIPS architecture specific definitions. +/// +/// See [MIPS Details](https://en.wikibooks.org/wiki/MIPS_Assembly/MIPS_Details). +#[derive(Debug, Clone, Copy)] +pub struct MIPS; + +registers!(MIPS, { + R0 = (0, "$0"), + R1 = (1, "$1"), + R2 = (2, "$2"), + R3 = (3, "$3"), + R4 = (4, "$4"), + R5 = (5, "$5"), + R6 = (6, "$6"), + R7 = (7, "$7"), + R8 = (8, "$8"), + R9 = (9, "$9"), + R10 = (10, "$10"), + R11 = (11, "$11"), + R12 = (12, "$12"), + R13 = (13, "$13"), + R14 = (14, "$14"), + R15 = (15, "$15"), + R16 = (16, "$16"), + R17 = (17, "$17"), + R18 = (18, "$18"), + R19 = (19, "$19"), + R20 = (20, "$20"), + R21 = (21, "$21"), + R22 = (22, "$22"), + R23 = (23, "$23"), + R24 = (24, "$24"), + R25 = (25, "$25"), + R26 = (26, "$26"), + R27 = (27, "$27"), + R28 = (28, "$28"), + R29 = (29, "$29"), + R30 = (30, "$30"), + R31 = (31, "$31"), + + F0 = (32, "$f0"), + F1 = (33, "$f1"), + F2 = (34, "$f2"), + F3 = (35, "$f3"), + F4 = (36, "$f4"), + F5 = (37, "$f5"), + F6 = (38, "$f6"), + F7 = (39, "$f7"), + F8 = (40, "$f8"), + F9 = (41, "$f9"), + F10 = (42, "$f10"), + F11 = (43, "$f11"), + F12 = (44, "$f12"), + F13 = (45, "$f13"), + F14 = (46, "$f14"), + F15 = (47, "$f15"), + F16 = (48, "$f16"), + F17 = (49, "$f17"), + F18 = (50, "$f18"), + F19 = (51, "$f19"), + F20 = (52, "$f20"), + F21 = (53, "$f21"), + F22 = (54, "$f22"), + F23 = (55, "$f23"), + F24 = (56, "$f24"), + F25 = (57, "$f25"), + F26 = (58, "$f26"), + F27 = (59, "$f27"), + F28 = (60, "$f28"), + F29 = (61, "$f29"), + F30 = (62, "$f30"), + F31 = (63, "$f31"), + + HI = (64, "$hi"), + LO = (65, "$lo"), +}, +aliases { + ZERO = (0, "$zero"), + AT = (1, "$at"), + V0 = (2, "$v0"), + V1 = (3, "$v1"), + A0 = (4, "$a0"), + A1 = (5, "$a1"), + A2 = (6, "$a2"), + A3 = (7, "$a3"), + T0 = (8, "$t0"), + T1 = (9, "$t1"), + T2 = (10, "$t2"), + T3 = (11, "$t3"), + T4 = (12, "$t4"), + T5 = (13, "$t5"), + T6 = (14, "$t6"), + T7 = (15, "$t7"), + S0 = (16, "$s0"), + S1 = (17, "$s1"), + S2 = (18, "$s2"), + S3 = (19, "$s3"), + S4 = (20, "$s4"), + S5 = (21, "$s5"), + S6 = (22, "$s6"), + S7 = (23, "$s7"), + T8 = (24, "$t8"), + T9 = (25, "$t9"), + K0 = (26, "$k0"), + K1 = (27, "$k1"), + GP = (28, "$gp"), + SP = (29, "$sp"), + FP = (30, "$fp"), + RA = (31, "$ra"), + + S8 = (30, "$s8") +}); + +/// RISC-V architecture specific definitions. +/// +/// See [RISC-V ELF psABI specification](https://github.com/riscv/riscv-elf-psabi-doc). +#[derive(Debug, Clone, Copy)] +pub struct RiscV; + +registers!(RiscV, { + X0 = (0, "x0"), + X1 = (1, "x1"), + X2 = (2, "x2"), + X3 = (3, "x3"), + X4 = (4, "x4"), + X5 = (5, "x5"), + X6 = (6, "x6"), + X7 = (7, "x7"), + X8 = (8, "x8"), + X9 = (9, "x9"), + X10 = (10, "x10"), + X11 = (11, "x11"), + X12 = (12, "x12"), + X13 = (13, "x13"), + X14 = (14, "x14"), + X15 = (15, "x15"), + X16 = (16, "x16"), + X17 = (17, "x17"), + X18 = (18, "x18"), + X19 = (19, "x19"), + X20 = (20, "x20"), + X21 = (21, "x21"), + X22 = (22, "x22"), + X23 = (23, "x23"), + X24 = (24, "x24"), + X25 = (25, "x25"), + X26 = (26, "x26"), + X27 = (27, "x27"), + X28 = (28, "x28"), + X29 = (29, "x29"), + X30 = (30, "x30"), + X31 = (31, "x31"), + + F0 = (32, "f0"), + F1 = (33, "f1"), + F2 = (34, "f2"), + F3 = (35, "f3"), + F4 = (36, "f4"), + F5 = (37, "f5"), + F6 = (38, "f6"), + F7 = (39, "f7"), + F8 = (40, "f8"), + F9 = (41, "f9"), + F10 = (42, "f10"), + F11 = (43, "f11"), + F12 = (44, "f12"), + F13 = (45, "f13"), + F14 = (46, "f14"), + F15 = (47, "f15"), + F16 = (48, "f16"), + F17 = (49, "f17"), + F18 = (50, "f18"), + F19 = (51, "f19"), + F20 = (52, "f20"), + F21 = (53, "f21"), + F22 = (54, "f22"), + F23 = (55, "f23"), + F24 = (56, "f24"), + F25 = (57, "f25"), + F26 = (58, "f26"), + F27 = (59, "f27"), + F28 = (60, "f28"), + F29 = (61, "f29"), + F30 = (62, "f30"), + F31 = (63, "f31"), +}, +aliases { + ZERO = (0, "zero"), + RA = (1, "ra"), + SP = (2, "sp"), + GP = (3, "gp"), + TP = (4, "tp"), + T0 = (5, "t0"), + T1 = (6, "t1"), + T2 = (7, "t2"), + S0 = (8, "s0"), + S1 = (9, "s1"), + A0 = (10, "a0"), + A1 = (11, "a1"), + A2 = (12, "a2"), + A3 = (13, "a3"), + A4 = (14, "a4"), + A5 = (15, "a5"), + A6 = (16, "a6"), + A7 = (17, "a7"), + S2 = (18, "s2"), + S3 = (19, "s3"), + S4 = (20, "s4"), + S5 = (21, "s5"), + S6 = (22, "s6"), + S7 = (23, "s7"), + S8 = (24, "s8"), + S9 = (25, "s9"), + S10 = (26, "s10"), + S11 = (27, "s11"), + T3 = (28, "t3"), + T4 = (29, "t4"), + T5 = (30, "t5"), + T6 = (31, "t6"), + + FT0 = (32, "ft0"), + FT1 = (33, "ft1"), + FT2 = (34, "ft2"), + FT3 = (35, "ft3"), + FT4 = (36, "ft4"), + FT5 = (37, "ft5"), + FT6 = (38, "ft6"), + FT7 = (39, "ft7"), + FS0 = (40, "fs0"), + FS1 = (41, "fs1"), + FA0 = (42, "fa0"), + FA1 = (43, "fa1"), + FA2 = (44, "fa2"), + FA3 = (45, "fa3"), + FA4 = (46, "fa4"), + FA5 = (47, "fa5"), + FA6 = (48, "fa6"), + FA7 = (49, "fa7"), + FS2 = (50, "fs2"), + FS3 = (51, "fs3"), + FS4 = (52, "fs4"), + FS5 = (53, "fs5"), + FS6 = (54, "fs6"), + FS7 = (55, "fs7"), + FS8 = (56, "fs8"), + FS9 = (57, "fs9"), + FS10 = (58, "fs10"), + FS11 = (59, "fs11"), + FT8 = (60, "ft8"), + FT9 = (61, "ft9"), + FT10 = (62, "ft10"), + FT11 = (63, "ft11"), +}); + +/// Intel i386 architecture specific definitions. +/// +/// See section 2.4.2 of the [i386 psABI](https://gitlab.com/x86-psABIs/i386-ABI). +#[derive(Debug, Clone, Copy)] +pub struct X86; + +registers!(X86, { + EAX = (0, "eax"), + ECX = (1, "ecx"), + EDX = (2, "edx"), + EBX = (3, "ebx"), + ESP = (4, "esp"), + EBP = (5, "ebp"), + ESI = (6, "esi"), + EDI = (7, "edi"), + + // Return Address register. This is stored in `0(%esp, "")` and is not a physical register. + RA = (8, "RA"), + + ST0 = (11, "st0"), + ST1 = (12, "st1"), + ST2 = (13, "st2"), + ST3 = (14, "st3"), + ST4 = (15, "st4"), + ST5 = (16, "st5"), + ST6 = (17, "st6"), + ST7 = (18, "st7"), + + XMM0 = (21, "xmm0"), + XMM1 = (22, "xmm1"), + XMM2 = (23, "xmm2"), + XMM3 = (24, "xmm3"), + XMM4 = (25, "xmm4"), + XMM5 = (26, "xmm5"), + XMM6 = (27, "xmm6"), + XMM7 = (28, "xmm7"), + + MM0 = (29, "mm0"), + MM1 = (30, "mm1"), + MM2 = (31, "mm2"), + MM3 = (32, "mm3"), + MM4 = (33, "mm4"), + MM5 = (34, "mm5"), + MM6 = (35, "mm6"), + MM7 = (36, "mm7"), + + MXCSR = (39, "mxcsr"), + + ES = (40, "es"), + CS = (41, "cs"), + SS = (42, "ss"), + DS = (43, "ds"), + FS = (44, "fs"), + GS = (45, "gs"), + + TR = (48, "tr"), + LDTR = (49, "ldtr"), + + FS_BASE = (93, "fs.base"), + GS_BASE = (94, "gs.base"), +}); + +/// AMD64 architecture specific definitions. +/// +/// See section 3.6.2 of the [x86-64 psABI](https://gitlab.com/x86-psABIs/x86-64-ABI). +#[derive(Debug, Clone, Copy)] +pub struct X86_64; + +registers!(X86_64, { + RAX = (0, "rax"), + RDX = (1, "rdx"), + RCX = (2, "rcx"), + RBX = (3, "rbx"), + RSI = (4, "rsi"), + RDI = (5, "rdi"), + RBP = (6, "rbp"), + RSP = (7, "rsp"), + + R8 = (8, "r8"), + R9 = (9, "r9"), + R10 = (10, "r10"), + R11 = (11, "r11"), + R12 = (12, "r12"), + R13 = (13, "r13"), + R14 = (14, "r14"), + R15 = (15, "r15"), + + // Return Address register. This is stored in `0(%rsp, "")` and is not a physical register. + RA = (16, "RA"), + + XMM0 = (17, "xmm0"), + XMM1 = (18, "xmm1"), + XMM2 = (19, "xmm2"), + XMM3 = (20, "xmm3"), + XMM4 = (21, "xmm4"), + XMM5 = (22, "xmm5"), + XMM6 = (23, "xmm6"), + XMM7 = (24, "xmm7"), + + XMM8 = (25, "xmm8"), + XMM9 = (26, "xmm9"), + XMM10 = (27, "xmm10"), + XMM11 = (28, "xmm11"), + XMM12 = (29, "xmm12"), + XMM13 = (30, "xmm13"), + XMM14 = (31, "xmm14"), + XMM15 = (32, "xmm15"), + + ST0 = (33, "st0"), + ST1 = (34, "st1"), + ST2 = (35, "st2"), + ST3 = (36, "st3"), + ST4 = (37, "st4"), + ST5 = (38, "st5"), + ST6 = (39, "st6"), + ST7 = (40, "st7"), + + MM0 = (41, "mm0"), + MM1 = (42, "mm1"), + MM2 = (43, "mm2"), + MM3 = (44, "mm3"), + MM4 = (45, "mm4"), + MM5 = (46, "mm5"), + MM6 = (47, "mm6"), + MM7 = (48, "mm7"), + + RFLAGS = (49, "rFLAGS"), + ES = (50, "es"), + CS = (51, "cs"), + SS = (52, "ss"), + DS = (53, "ds"), + FS = (54, "fs"), + GS = (55, "gs"), + + FS_BASE = (58, "fs.base"), + GS_BASE = (59, "gs.base"), + + TR = (62, "tr"), + LDTR = (63, "ldtr"), + MXCSR = (64, "mxcsr"), + FCW = (65, "fcw"), + FSW = (66, "fsw"), + + XMM16 = (67, "xmm16"), + XMM17 = (68, "xmm17"), + XMM18 = (69, "xmm18"), + XMM19 = (70, "xmm19"), + XMM20 = (71, "xmm20"), + XMM21 = (72, "xmm21"), + XMM22 = (73, "xmm22"), + XMM23 = (74, "xmm23"), + XMM24 = (75, "xmm24"), + XMM25 = (76, "xmm25"), + XMM26 = (77, "xmm26"), + XMM27 = (78, "xmm27"), + XMM28 = (79, "xmm28"), + XMM29 = (80, "xmm29"), + XMM30 = (81, "xmm30"), + XMM31 = (82, "xmm31"), + + K0 = (118, "k0"), + K1 = (119, "k1"), + K2 = (120, "k2"), + K3 = (121, "k3"), + K4 = (122, "k4"), + K5 = (123, "k5"), + K6 = (124, "k6"), + K7 = (125, "k7"), + + R16 = (130, "r16"), + R17 = (131, "r17"), + R18 = (132, "r18"), + R19 = (133, "r19"), + R20 = (134, "r20"), + R21 = (135, "r21"), + R22 = (136, "r22"), + R23 = (137, "r23"), + R24 = (138, "r24"), + R25 = (139, "r25"), + R26 = (140, "r26"), + R27 = (141, "r27"), + R28 = (142, "r28"), + R29 = (143, "r29"), + R30 = (144, "r30"), + R31 = (145, "r31"), + + TMM0 = (146, "tmm0"), + TMM1 = (147, "tmm1"), + TMM2 = (148, "tmm2"), + TMM3 = (149, "tmm3"), + TMM4 = (150, "tmm4"), + TMM5 = (151, "tmm5"), + TMM6 = (152, "tmm6"), + TMM7 = (153, "tmm7"), + TILECFG = (154, "tilecfg"), +}); + +/// PowerPC 64bit +/// +/// See [64-bit ELF ABI Specification for OpenPOWER Architecture](https://openpowerfoundation.org/specifications/64bitelfabi/). +#[derive(Debug, Clone, Copy)] +pub struct PowerPc64; + +registers!(PowerPc64, { + R0 = (0, "r0"), + R1 = (1, "r1"), + R2 = (2, "r2"), + R3 = (3, "r3"), + R4 = (4, "r4"), + R5 = (5, "r5"), + R6 = (6, "r6"), + R7 = (7, "r7"), + R8 = (8, "r8"), + R9 = (9, "r9"), + R10 = (10, "r10"), + R11 = (11, "r11"), + R12 = (12, "r12"), + R13 = (13, "r13"), + R14 = (14, "r14"), + R15 = (15, "r15"), + R16 = (16, "r16"), + R17 = (17, "r17"), + R18 = (18, "r18"), + R19 = (19, "r19"), + R20 = (20, "r20"), + R21 = (21, "r21"), + R22 = (22, "r22"), + R23 = (23, "r23"), + R24 = (24, "r24"), + R25 = (25, "r25"), + R26 = (26, "r26"), + R27 = (27, "r27"), + R28 = (28, "r28"), + R29 = (29, "r29"), + R30 = (30, "r30"), + R31 = (31, "r31"), + + F0 = (32, "f0"), + F1 = (33, "f1"), + F2 = (34, "f2"), + F3 = (35, "f3"), + F4 = (36, "f4"), + F5 = (37, "f5"), + F6 = (38, "f6"), + F7 = (39, "f7"), + F8 = (40, "f8"), + F9 = (41, "f9"), + F10 = (42, "f10"), + F11 = (43, "f11"), + F12 = (44, "f12"), + F13 = (45, "f13"), + F14 = (46, "f14"), + F15 = (47, "f15"), + F16 = (48, "f16"), + F17 = (49, "f17"), + F18 = (50, "f18"), + F19 = (51, "f19"), + F20 = (52, "f20"), + F21 = (53, "f21"), + F22 = (54, "f22"), + F23 = (55, "f23"), + F24 = (56, "f24"), + F25 = (57, "f25"), + F26 = (58, "f26"), + F27 = (59, "f27"), + F28 = (60, "f28"), + F29 = (61, "f29"), + F30 = (62, "f30"), + F31 = (63, "f31"), + + LR = (65, "lr"), + CTR = (66, "ctr"), + + CR0 = (68, "cr0"), + CR1 = (69, "cr1"), + CR2 = (70, "cr2"), + CR3 = (71, "cr3"), + CR4 = (72, "cr4"), + CR5 = (73, "cr5"), + CR6 = (74, "cr6"), + CR7 = (75, "cr7"), + XER = (76, "xer"), + + VR0 = (77, "vr0"), + VR1 = (78, "vr1"), + VR2 = (79, "vr2"), + VR3 = (80, "vr3"), + VR4 = (81, "vr4"), + VR5 = (82, "vr5"), + VR6 = (83, "vr6"), + VR7 = (84, "vr7"), + VR8 = (85, "vr8"), + VR9 = (86, "vr9"), + VR10 = (87, "vr10"), + VR11 = (88, "vr11"), + VR12 = (89, "vr12"), + VR13 = (90, "vr13"), + VR14 = (91, "vr14"), + VR15 = (92, "vr15"), + VR16 = (93, "vr16"), + VR17 = (94, "vr17"), + VR18 = (95, "vr18"), + VR19 = (96, "vr19"), + VR20 = (97, "vr20"), + VR21 = (98, "vr21"), + VR22 = (99, "vr22"), + VR23 = (100, "vr23"), + VR24 = (101, "vr24"), + VR25 = (102, "vr25"), + VR26 = (103, "vr26"), + VR27 = (104, "vr27"), + VR28 = (105, "vr28"), + VR29 = (106, "vr29"), + VR30 = (107, "vr30"), + VR31 = (108, "vr31"), + + VSCR = (110, "vscr"), + TFHAR = (114, "tfhar"), + TFIAR = (115, "tfiar"), + TEXASR = (116, "texasr"), +}); + +#[cfg(test)] +mod tests { + + #[test] + #[cfg(feature = "std")] + fn test_aarch64_registers() { + use super::*; + use std::collections::HashSet; + + let mut names = HashSet::new(); + for n in (0..=39).chain(46..=127) { + let name = AArch64::register_name(Register(n)) + .unwrap_or_else(|| panic!("Register {} should have a name.", n)); + assert!(names.insert(name)); + } + } + + #[test] + #[cfg(feature = "std")] + fn test_power64_registers() { + use super::*; + use std::collections::HashSet; + + let mut names = HashSet::new(); + for n in (0..=63).chain(68..=75).chain(77..=108) { + let name = PowerPc64::register_name(Register(n)) + .unwrap_or_else(|| panic!("Register {} should have a name.", n)); + assert!(names.insert(name)); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/common.rs b/anneal/v2/vendor/gimli/src/common.rs new file mode 100644 index 0000000000..d7cc7f73c1 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/common.rs @@ -0,0 +1,401 @@ +/// Whether the format of a compilation unit is 32- or 64-bit. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Format { + /// 64-bit DWARF + Dwarf64 = 8, + /// 32-bit DWARF + Dwarf32 = 4, +} + +impl Format { + /// Return the serialized size of an initial length field for the format. + #[inline] + pub fn initial_length_size(self) -> u8 { + match self { + Format::Dwarf32 => 4, + Format::Dwarf64 => 12, + } + } + + /// Return the natural word size for the format + #[inline] + pub fn word_size(self) -> u8 { + match self { + Format::Dwarf32 => 4, + Format::Dwarf64 => 8, + } + } +} + +/// Which vendor extensions to support. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum Vendor { + /// A default set of extensions, including some common GNU extensions. + Default, + /// AAarch64 extensions. + AArch64, +} + +/// Encoding parameters that are commonly used for multiple DWARF sections. +/// +/// This is intended to be small enough to pass by value. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +// `address_size` and `format` are used more often than `version`, so keep +// them first. +#[repr(C)] +pub struct Encoding { + /// The size of an address. + pub address_size: u8, + + /// Whether the DWARF format is 32- or 64-bit. + pub format: Format, + + /// The DWARF version of the header. + pub version: u16, +} + +/// Encoding parameters for a line number program. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LineEncoding { + /// The size in bytes of the smallest target machine instruction. + pub minimum_instruction_length: u8, + + /// The maximum number of individual operations that may be encoded in an + /// instruction. + pub maximum_operations_per_instruction: u8, + + /// The initial value of the `is_stmt` register. + pub default_is_stmt: bool, + + /// The minimum value which a special opcode can add to the line register. + pub line_base: i8, + + /// The range of values which a special opcode can add to the line register. + pub line_range: u8, +} + +impl Default for LineEncoding { + fn default() -> Self { + // Values from LLVM. + LineEncoding { + minimum_instruction_length: 1, + maximum_operations_per_instruction: 1, + default_is_stmt: true, + line_base: -5, + line_range: 14, + } + } +} + +/// A DWARF register number. +/// +/// The meaning of this value is ABI dependent. This is generally encoded as +/// a ULEB128, but supported architectures need 16 bits at most. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Register(pub u16); + +/// An offset into the `.debug_abbrev` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DebugAbbrevOffset(pub T); + +/// An offset into the `.debug_addr` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugAddrOffset(pub T); + +/// An offset to a set of entries in the `.debug_addr` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugAddrBase(pub T); + +/// An index into a set of addresses in the `.debug_addr` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugAddrIndex(pub T); + +/// An offset into the `.debug_aranges` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugArangesOffset(pub T); + +/// An offset into the `.debug_info` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub struct DebugInfoOffset(pub T); + +/// An offset into the `.debug_line` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugLineOffset(pub T); + +/// An offset into the `.debug_line_str` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugLineStrOffset(pub T); + +/// An offset into either the `.debug_loc` section or the `.debug_loclists` section, +/// depending on the version of the unit the offset was contained in. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocationListsOffset(pub T); + +/// An offset to a set of location list offsets in the `.debug_loclists` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugLocListsBase(pub T); + +/// An index into a set of location list offsets in the `.debug_loclists` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugLocListsIndex(pub T); + +/// An offset into the `.debug_macinfo` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DebugMacinfoOffset(pub T); + +/// An offset into the `.debug_macro` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DebugMacroOffset(pub T); + +/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section, +/// depending on the version of the unit the offset was contained in. +/// +/// If this is from a DWARF 4 DWO file, then it must additionally be offset by the +/// value of `DW_AT_GNU_ranges_base`. You can use `Dwarf::ranges_offset_from_raw` to do this. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RawRangeListsOffset(pub T); + +/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section, +/// depending on the version of the unit the offset was contained in. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RangeListsOffset(pub T); + +/// An offset to a set of range list offsets in the `.debug_rnglists` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugRngListsBase(pub T); + +/// An index into a set of range list offsets in the `.debug_rnglists` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugRngListsIndex(pub T); + +/// An offset into the `.debug_str` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugStrOffset(pub T); + +/// An offset to a set of entries in the `.debug_str_offsets` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugStrOffsetsBase(pub T); + +/// An index into a set of entries in the `.debug_str_offsets` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DebugStrOffsetsIndex(pub T); + +/// An offset into the `.debug_types` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub struct DebugTypesOffset(pub T); + +/// A type signature as used in the `.debug_types` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DebugTypeSignature(pub u64); + +/// An offset into the `.debug_frame` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DebugFrameOffset(pub T); + +impl From for DebugFrameOffset { + #[inline] + fn from(o: T) -> Self { + DebugFrameOffset(o) + } +} + +/// An offset into the `.eh_frame` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EhFrameOffset(pub T); + +impl From for EhFrameOffset { + #[inline] + fn from(o: T) -> Self { + EhFrameOffset(o) + } +} + +/// An offset into the `.debug_info` or `.debug_types` sections. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub enum UnitSectionOffset { + /// An offset into the `.debug_info` section. + DebugInfoOffset(DebugInfoOffset), + /// An offset into the `.debug_types` section. + DebugTypesOffset(DebugTypesOffset), +} + +impl From> for UnitSectionOffset { + fn from(offset: DebugInfoOffset) -> Self { + UnitSectionOffset::DebugInfoOffset(offset) + } +} + +impl From> for UnitSectionOffset { + fn from(offset: DebugTypesOffset) -> Self { + UnitSectionOffset::DebugTypesOffset(offset) + } +} + +impl UnitSectionOffset +where + T: Clone, +{ + /// Returns the `DebugInfoOffset` inside, or `None` otherwise. + pub fn as_debug_info_offset(&self) -> Option> { + match self { + UnitSectionOffset::DebugInfoOffset(offset) => Some(offset.clone()), + UnitSectionOffset::DebugTypesOffset(_) => None, + } + } + /// Returns the `DebugTypesOffset` inside, or `None` otherwise. + pub fn as_debug_types_offset(&self) -> Option> { + match self { + UnitSectionOffset::DebugInfoOffset(_) => None, + UnitSectionOffset::DebugTypesOffset(offset) => Some(offset.clone()), + } + } +} + +/// An identifier for a DWARF section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub enum SectionId { + /// The `.debug_abbrev` section. + DebugAbbrev, + /// The `.debug_addr` section. + DebugAddr, + /// The `.debug_aranges` section. + DebugAranges, + /// The `.debug_cu_index` section. + DebugCuIndex, + /// The `.debug_frame` section. + DebugFrame, + /// The `.eh_frame` section. + EhFrame, + /// The `.eh_frame_hdr` section. + EhFrameHdr, + /// The `.debug_info` section. + DebugInfo, + /// The `.debug_line` section. + DebugLine, + /// The `.debug_line_str` section. + DebugLineStr, + /// The `.debug_loc` section. + DebugLoc, + /// The `.debug_loclists` section. + DebugLocLists, + /// The `.debug_macinfo` section. + DebugMacinfo, + /// The `.debug_macro` section. + DebugMacro, + /// The `.debug_pubnames` section. + DebugPubNames, + /// The `.debug_pubtypes` section. + DebugPubTypes, + /// The `.debug_ranges` section. + DebugRanges, + /// The `.debug_rnglists` section. + DebugRngLists, + /// The `.debug_str` section. + DebugStr, + /// The `.debug_str_offsets` section. + DebugStrOffsets, + /// The `.debug_tu_index` section. + DebugTuIndex, + /// The `.debug_types` section. + DebugTypes, +} + +impl SectionId { + /// Returns the ELF section name for this kind. + pub fn name(self) -> &'static str { + match self { + SectionId::DebugAbbrev => ".debug_abbrev", + SectionId::DebugAddr => ".debug_addr", + SectionId::DebugAranges => ".debug_aranges", + SectionId::DebugCuIndex => ".debug_cu_index", + SectionId::DebugFrame => ".debug_frame", + SectionId::EhFrame => ".eh_frame", + SectionId::EhFrameHdr => ".eh_frame_hdr", + SectionId::DebugInfo => ".debug_info", + SectionId::DebugLine => ".debug_line", + SectionId::DebugLineStr => ".debug_line_str", + SectionId::DebugLoc => ".debug_loc", + SectionId::DebugLocLists => ".debug_loclists", + SectionId::DebugMacinfo => ".debug_macinfo", + SectionId::DebugMacro => ".debug_macro", + SectionId::DebugPubNames => ".debug_pubnames", + SectionId::DebugPubTypes => ".debug_pubtypes", + SectionId::DebugRanges => ".debug_ranges", + SectionId::DebugRngLists => ".debug_rnglists", + SectionId::DebugStr => ".debug_str", + SectionId::DebugStrOffsets => ".debug_str_offsets", + SectionId::DebugTuIndex => ".debug_tu_index", + SectionId::DebugTypes => ".debug_types", + } + } + + /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file. + pub fn dwo_name(self) -> Option<&'static str> { + Some(match self { + SectionId::DebugAbbrev => ".debug_abbrev.dwo", + SectionId::DebugCuIndex => ".debug_cu_index", + SectionId::DebugInfo => ".debug_info.dwo", + SectionId::DebugLine => ".debug_line.dwo", + // The debug_loc section can be present in the dwo when using the + // GNU split-dwarf extension to DWARF4. + SectionId::DebugLoc => ".debug_loc.dwo", + SectionId::DebugLocLists => ".debug_loclists.dwo", + SectionId::DebugMacinfo => ".debug_macinfo.dwo", + SectionId::DebugMacro => ".debug_macro.dwo", + SectionId::DebugRngLists => ".debug_rnglists.dwo", + SectionId::DebugStr => ".debug_str.dwo", + SectionId::DebugStrOffsets => ".debug_str_offsets.dwo", + SectionId::DebugTuIndex => ".debug_tu_index", + SectionId::DebugTypes => ".debug_types.dwo", + _ => return None, + }) + } + + /// Returns the XCOFF section name for this kind. + pub fn xcoff_name(self) -> Option<&'static str> { + Some(match self { + SectionId::DebugAbbrev => ".dwabrev", + SectionId::DebugAranges => ".dwarnge", + SectionId::DebugFrame => ".dwframe", + SectionId::DebugInfo => ".dwinfo", + SectionId::DebugLine => ".dwline", + SectionId::DebugLoc => ".dwloc", + SectionId::DebugMacinfo => ".dwmac", + SectionId::DebugPubNames => ".dwpbnms", + SectionId::DebugPubTypes => ".dwpbtyp", + SectionId::DebugRanges => ".dwrnges", + SectionId::DebugStr => ".dwstr", + _ => return None, + }) + } + + /// Returns true if this is a mergeable string section. + /// + /// This is useful for determining the correct section flags. + pub fn is_string(self) -> bool { + matches!(self, SectionId::DebugStr | SectionId::DebugLineStr) + } +} + +/// An optionally-provided implementation-defined compilation unit ID to enable +/// split DWARF and linking a split compilation unit back together. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DwoId(pub u64); + +/// The "type" of file with DWARF debugging information. This determines, among other things, +/// which files DWARF sections should be loaded from. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DwarfFileType { + /// A normal executable or object file. + Main, + /// A .dwo split DWARF file. + Dwo, + // TODO: Supplementary files, .dwps? +} + +impl Default for DwarfFileType { + fn default() -> Self { + DwarfFileType::Main + } +} diff --git a/anneal/v2/vendor/gimli/src/constants.rs b/anneal/v2/vendor/gimli/src/constants.rs new file mode 100644 index 0000000000..4121033e1b --- /dev/null +++ b/anneal/v2/vendor/gimli/src/constants.rs @@ -0,0 +1,1495 @@ +// This file originally from https://github.com/philipc/rust-dwarf/ and +// distributed under either MIT or Apache 2.0 licenses. +// +// Copyright 2016 The rust-dwarf Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Constant definitions. +//! +//! The DWARF spec's `DW_AT_*` type is represented as `struct DwAt(u16)`, +//! `DW_FORM_*` as `DwForm(u16)`, etc. +//! +//! There are also exported const definitions for each constant. + +#![allow(non_upper_case_globals)] +#![allow(missing_docs)] + +use core::{fmt, ops}; + +// The `dw!` macro turns this: +// +// dw!(DwFoo(u32) { +// DW_FOO_bar = 0, +// DW_FOO_baz = 1, +// DW_FOO_bang = 2, +// }); +// +// into this: +// +// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +// pub struct DwFoo(pub u32); +// +// pub const DW_FOO_bar: DwFoo = DwFoo(0); +// pub const DW_FOO_baz: DwFoo = DwFoo(1); +// pub const DW_FOO_bang: DwFoo = DwFoo(2); +// +// impl DwFoo { +// pub fn static_string(&self) -> Option<&'static str> { +// ... +// } +// } +// +// impl fmt::Display for DwFoo { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +// ... +// } +// } +macro_rules! dw { + ($(#[$meta:meta])* $struct_name:ident($struct_type:ty) + { $($name:ident = $val:expr),+ $(,)? } + $(, aliases { $($alias_name:ident = $alias_val:expr),+ $(,)? })? + ) => { + $(#[$meta])* + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] + pub struct $struct_name(pub $struct_type); + + $( + pub const $name: $struct_name = $struct_name($val); + )+ + $($( + pub const $alias_name: $struct_name = $struct_name($alias_val); + )+)* + + impl $struct_name { + pub fn static_string(&self) -> Option<&'static str> { + Some(match *self { + $( + $name => stringify!($name), + )+ + _ => return None, + }) + } + } + + impl fmt::Display for $struct_name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + if let Some(s) = self.static_string() { + f.pad(s) + } else { + #[cfg(feature = "read")] + { + f.pad(&format!("Unknown {}: {}", stringify!($struct_name), self.0)) + } + #[cfg(not(feature = "read"))] + { + write!(f, "Unknown {}: {}", stringify!($struct_name), self.0) + } + } + } + } + }; +} + +dw!( +/// The section type field in a `.dwp` unit index. +/// +/// This is used for version 5 and later. +/// +/// See Section 7.3.5. +DwSect(u32) { + DW_SECT_INFO = 1, + DW_SECT_ABBREV = 3, + DW_SECT_LINE = 4, + DW_SECT_LOCLISTS = 5, + DW_SECT_STR_OFFSETS = 6, + DW_SECT_MACRO = 7, + DW_SECT_RNGLISTS = 8, +}); + +dw!( +/// The section type field in a `.dwp` unit index with version 2. +DwSectV2(u32) { + DW_SECT_V2_INFO = 1, + DW_SECT_V2_TYPES = 2, + DW_SECT_V2_ABBREV = 3, + DW_SECT_V2_LINE = 4, + DW_SECT_V2_LOC = 5, + DW_SECT_V2_STR_OFFSETS = 6, + DW_SECT_V2_MACINFO = 7, + DW_SECT_V2_MACRO = 8, +}); + +dw!( +/// The unit type field in a unit header. +/// +/// See Section 7.5.1, Table 7.2. +DwUt(u8) { + DW_UT_compile = 0x01, + DW_UT_type = 0x02, + DW_UT_partial = 0x03, + DW_UT_skeleton = 0x04, + DW_UT_split_compile = 0x05, + DW_UT_split_type = 0x06, + DW_UT_lo_user = 0x80, + DW_UT_hi_user = 0xff, +}); + +dw!( +/// The opcode for a call frame instruction. +/// +/// Section 7.24: +/// > Call frame instructions are encoded in one or more bytes. The primary +/// > opcode is encoded in the high order two bits of the first byte (that is, +/// > opcode = byte >> 6). An operand or extended opcode may be encoded in the +/// > low order 6 bits. Additional operands are encoded in subsequent bytes. +DwCfa(u8) { + DW_CFA_advance_loc = 0x01 << 6, + DW_CFA_offset = 0x02 << 6, + DW_CFA_restore = 0x03 << 6, + DW_CFA_nop = 0, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f, + + DW_CFA_MIPS_advance_loc8 = 0x1d, + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f, +}, +aliases { + DW_CFA_AARCH64_negate_ra_state = 0x2d, +}); + +dw!( +/// The child determination encodings for DIE attributes. +/// +/// See Section 7.5.3, Table 7.4. +DwChildren(u8) { + DW_CHILDREN_no = 0, + DW_CHILDREN_yes = 1, +}); + +dw!( +/// The tag encodings for DIE attributes. +/// +/// See Section 7.5.3, Table 7.3. +DwTag(u16) { + DW_TAG_null = 0x00, + +// DWARF 1 only, obsolete in DWARF 2+. + DW_TAG_global_subroutine = 0x06, + DW_TAG_global_variable = 0x07, + DW_TAG_local_variable = 0x0c, + DW_TAG_subroutine = 0x14, + +// DWARF 1. + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + +// DWARF 2. + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + +// DWARF 3. + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + +// DWARF 4. + DW_TAG_type_unit = 0x41, + DW_TAG_rvalue_reference_type = 0x42, + DW_TAG_template_alias = 0x43, + +// DWARF 5. + DW_TAG_coarray_type = 0x44, + DW_TAG_generic_subrange = 0x45, + DW_TAG_dynamic_type = 0x46, + DW_TAG_atomic_type = 0x47, + DW_TAG_call_site = 0x48, + DW_TAG_call_site_parameter = 0x49, + DW_TAG_skeleton_unit = 0x4a, + DW_TAG_immutable_type = 0x4b, + + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff, + +// SGI/MIPS extensions. + DW_TAG_MIPS_loop = 0x4081, + +// HP extensions. + DW_TAG_HP_array_descriptor = 0x4090, + DW_TAG_HP_Bliss_field = 0x4091, + DW_TAG_HP_Bliss_field_set = 0x4092, + +// GNU extensions. + DW_TAG_format_label = 0x4101, + DW_TAG_function_template = 0x4102, + DW_TAG_class_template = 0x4103, + DW_TAG_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105, + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, + DW_TAG_GNU_call_site = 0x4109, + DW_TAG_GNU_call_site_parameter = 0x410a, + + DW_TAG_APPLE_property = 0x4200, + +// SUN extensions. + DW_TAG_SUN_function_template = 0x4201, + DW_TAG_SUN_class_template = 0x4202, + DW_TAG_SUN_struct_template = 0x4203, + DW_TAG_SUN_union_template = 0x4204, + DW_TAG_SUN_indirect_inheritance = 0x4205, + DW_TAG_SUN_codeflags = 0x4206, + DW_TAG_SUN_memop_info = 0x4207, + DW_TAG_SUN_omp_child_func = 0x4208, + DW_TAG_SUN_rtti_descriptor = 0x4209, + DW_TAG_SUN_dtor_info = 0x420a, + DW_TAG_SUN_dtor = 0x420b, + DW_TAG_SUN_f90_interface = 0x420c, + DW_TAG_SUN_fortran_vax_structure = 0x420d, + +// ALTIUM extensions. + DW_TAG_ALTIUM_circ_type = 0x5101, + DW_TAG_ALTIUM_mwa_circ_type = 0x5102, + DW_TAG_ALTIUM_rev_carry_type = 0x5103, + DW_TAG_ALTIUM_rom = 0x5111, + +// Extensions for UPC. + DW_TAG_upc_shared_type = 0x8765, + DW_TAG_upc_strict_type = 0x8766, + DW_TAG_upc_relaxed_type = 0x8767, + +// PGI (STMicroelectronics) extensions. + DW_TAG_PGI_kanji_type = 0xa000, + DW_TAG_PGI_interface_block = 0xa020, + +// Borland extensions. + DW_TAG_BORLAND_property = 0xb000, + DW_TAG_BORLAND_Delphi_string = 0xb001, + DW_TAG_BORLAND_Delphi_dynamic_array = 0xb002, + DW_TAG_BORLAND_Delphi_set = 0xb003, + DW_TAG_BORLAND_Delphi_variant = 0xb004, +}); + +dw!( +/// The attribute encodings for DIE attributes. +/// +/// See Section 7.5.4, Table 7.5. +DwAt(u16) { + DW_AT_null = 0x00, + +// DWARF 1 only, obsolete in DWARF 2+. + DW_AT_fund_type = 0x05, + DW_AT_mod_fund_type = 0x06, + DW_AT_user_def_type = 0x07, + DW_AT_mod_u_d_type = 0x08, + DW_AT_subscr_data = 0x0a, + DW_AT_element_list = 0x0f, + DW_AT_member = 0x14, + DW_AT_friends = 0x1f, + DW_AT_program = 0x23, + DW_AT_private = 0x24, + DW_AT_protected = 0x26, + DW_AT_public = 0x28, + DW_AT_pure_virtual = 0x29, + DW_AT_virtual = 0x30, + +// Moved to 0x47 in DWARF 2+. + DW_AT_specification_v1 = 0x2b, + +// DWARF 1. + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + +// DWARF 2. + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + +// DWARF 3. + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + +// DWARF 4. + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + +// DWARF 5. + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_rnglists_base = 0x74, + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_macros = 0x79, + DW_AT_call_all_calls = 0x7a, + DW_AT_call_all_source_calls = 0x7b, + DW_AT_call_all_tail_calls = 0x7c, + DW_AT_call_return_pc = 0x7d, + DW_AT_call_value = 0x7e, + DW_AT_call_origin = 0x7f, + DW_AT_call_parameter = 0x80, + DW_AT_call_pc = 0x81, + DW_AT_call_tail_call = 0x82, + DW_AT_call_target = 0x83, + DW_AT_call_target_clobbered = 0x84, + DW_AT_call_data_location = 0x85, + DW_AT_call_data_value = 0x86, + DW_AT_noreturn = 0x87, + DW_AT_alignment = 0x88, + DW_AT_export_symbols = 0x89, + DW_AT_deleted = 0x8a, + DW_AT_defaulted = 0x8b, + DW_AT_loclists_base = 0x8c, + + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + +// SGI/MIPS extensions. + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + DW_AT_MIPS_stride_byte = 0x200c, + DW_AT_MIPS_stride_elem = 0x200d, + DW_AT_MIPS_ptr_dopetype = 0x200e, + DW_AT_MIPS_allocatable_dopetype = 0x200f, + DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + +// This one appears to have only been implemented by Open64 for +// fortran and may conflict with other extensions. + DW_AT_MIPS_assumed_size = 0x2011, + +// TODO: HP/CPQ extensions. +// These conflict with the MIPS extensions. + + DW_AT_INTEL_other_endian = 0x2026, + +// GNU extensions + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_guarded_by = 0x2108, + DW_AT_GNU_pt_guarded_by = 0x2109, + DW_AT_GNU_guarded = 0x210a, + DW_AT_GNU_pt_guarded = 0x210b, + DW_AT_GNU_locks_excluded = 0x210c, + DW_AT_GNU_exclusive_locks_required = 0x210d, + DW_AT_GNU_shared_locks_required = 0x210e, + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_call_site_value = 0x2111, + DW_AT_GNU_call_site_data_value = 0x2112, + DW_AT_GNU_call_site_target = 0x2113, + DW_AT_GNU_call_site_target_clobbered = 0x2114, + DW_AT_GNU_tail_call = 0x2115, + DW_AT_GNU_all_tail_call_sites = 0x2116, + DW_AT_GNU_all_call_sites = 0x2117, + DW_AT_GNU_all_source_call_sites = 0x2118, + DW_AT_GNU_macros = 0x2119, + DW_AT_GNU_deleted = 0x211a, + +// Extensions for Fission proposal. + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, + DW_AT_GNU_discriminator = 0x2136, + DW_AT_GNU_locviews = 0x2137, + DW_AT_GNU_entry_view = 0x2138, + +// Conflict with Sun. +// DW_AT_VMS_rtnbeg_pd_address = 0x2201, + +// Sun extensions. + DW_AT_SUN_template = 0x2201, + DW_AT_SUN_alignment = 0x2202, + DW_AT_SUN_vtable = 0x2203, + DW_AT_SUN_count_guarantee = 0x2204, + DW_AT_SUN_command_line = 0x2205, + DW_AT_SUN_vbase = 0x2206, + DW_AT_SUN_compile_options = 0x2207, + DW_AT_SUN_language = 0x2208, + DW_AT_SUN_browser_file = 0x2209, + DW_AT_SUN_vtable_abi = 0x2210, + DW_AT_SUN_func_offsets = 0x2211, + DW_AT_SUN_cf_kind = 0x2212, + DW_AT_SUN_vtable_index = 0x2213, + DW_AT_SUN_omp_tpriv_addr = 0x2214, + DW_AT_SUN_omp_child_func = 0x2215, + DW_AT_SUN_func_offset = 0x2216, + DW_AT_SUN_memop_type_ref = 0x2217, + DW_AT_SUN_profile_id = 0x2218, + DW_AT_SUN_memop_signature = 0x2219, + DW_AT_SUN_obj_dir = 0x2220, + DW_AT_SUN_obj_file = 0x2221, + DW_AT_SUN_original_name = 0x2222, + DW_AT_SUN_hwcprof_signature = 0x2223, + DW_AT_SUN_amd64_parmdump = 0x2224, + DW_AT_SUN_part_link_name = 0x2225, + DW_AT_SUN_link_name = 0x2226, + DW_AT_SUN_pass_with_const = 0x2227, + DW_AT_SUN_return_with_const = 0x2228, + DW_AT_SUN_import_by_name = 0x2229, + DW_AT_SUN_f90_pointer = 0x222a, + DW_AT_SUN_pass_by_ref = 0x222b, + DW_AT_SUN_f90_allocatable = 0x222c, + DW_AT_SUN_f90_assumed_shape_array = 0x222d, + DW_AT_SUN_c_vla = 0x222e, + DW_AT_SUN_return_value_ptr = 0x2230, + DW_AT_SUN_dtor_start = 0x2231, + DW_AT_SUN_dtor_length = 0x2232, + DW_AT_SUN_dtor_state_initial = 0x2233, + DW_AT_SUN_dtor_state_final = 0x2234, + DW_AT_SUN_dtor_state_deltas = 0x2235, + DW_AT_SUN_import_by_lname = 0x2236, + DW_AT_SUN_f90_use_only = 0x2237, + DW_AT_SUN_namelist_spec = 0x2238, + DW_AT_SUN_is_omp_child_func = 0x2239, + DW_AT_SUN_fortran_main_alias = 0x223a, + DW_AT_SUN_fortran_based = 0x223b, + + DW_AT_ALTIUM_loclist = 0x2300, + + DW_AT_use_GNAT_descriptive_type = 0x2301, + DW_AT_GNAT_descriptive_type = 0x2302, + DW_AT_GNU_numerator = 0x2303, + DW_AT_GNU_denominator = 0x2304, + DW_AT_GNU_bias = 0x2305, + + DW_AT_upc_threads_scaled = 0x3210, + +// PGI (STMicroelectronics) extensions. + DW_AT_PGI_lbase = 0x3a00, + DW_AT_PGI_soffset = 0x3a01, + DW_AT_PGI_lstride = 0x3a02, + +// Borland extensions. + DW_AT_BORLAND_property_read = 0x3b11, + DW_AT_BORLAND_property_write = 0x3b12, + DW_AT_BORLAND_property_implements = 0x3b13, + DW_AT_BORLAND_property_index = 0x3b14, + DW_AT_BORLAND_property_default = 0x3b15, + DW_AT_BORLAND_Delphi_unit = 0x3b20, + DW_AT_BORLAND_Delphi_class = 0x3b21, + DW_AT_BORLAND_Delphi_record = 0x3b22, + DW_AT_BORLAND_Delphi_metaclass = 0x3b23, + DW_AT_BORLAND_Delphi_constructor = 0x3b24, + DW_AT_BORLAND_Delphi_destructor = 0x3b25, + DW_AT_BORLAND_Delphi_anonymous_method = 0x3b26, + DW_AT_BORLAND_Delphi_interface = 0x3b27, + DW_AT_BORLAND_Delphi_ABI = 0x3b28, + DW_AT_BORLAND_Delphi_return = 0x3b29, + DW_AT_BORLAND_Delphi_frameptr = 0x3b30, + DW_AT_BORLAND_closure = 0x3b31, + +// LLVM project extensions. + DW_AT_LLVM_include_path = 0x3e00, + DW_AT_LLVM_config_macros = 0x3e01, + DW_AT_LLVM_isysroot = 0x3e02, + +// Apple extensions. + DW_AT_APPLE_optimized = 0x3fe1, + DW_AT_APPLE_flags = 0x3fe2, + DW_AT_APPLE_isa = 0x3fe3, + DW_AT_APPLE_block = 0x3fe4, + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6, + DW_AT_APPLE_omit_frame_ptr = 0x3fe7, + DW_AT_APPLE_property_name = 0x3fe8, + DW_AT_APPLE_property_getter = 0x3fe9, + DW_AT_APPLE_property_setter = 0x3fea, + DW_AT_APPLE_property_attribute = 0x3feb, + DW_AT_APPLE_objc_complete_type = 0x3fec, + DW_AT_APPLE_property = 0x3fed +}); + +dw!( +/// The attribute form encodings for DIE attributes. +/// +/// See Section 7.5.6, Table 7.6. +DwForm(u16) { + DW_FORM_null = 0x00, + +// DWARF 1 only, obsolete in DWARF 2+. + DW_FORM_ref = 0x02, + +// DWARF 1. + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + +// DWARF 2. + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + +// DWARF 4. + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_ref_sig8 = 0x20, + +// DWARF 5. + DW_FORM_strx = 0x1a, + DW_FORM_addrx = 0x1b, + DW_FORM_ref_sup4 = 0x1c, + DW_FORM_strp_sup = 0x1d, + DW_FORM_data16 = 0x1e, + DW_FORM_line_strp = 0x1f, + DW_FORM_implicit_const = 0x21, + DW_FORM_loclistx = 0x22, + DW_FORM_rnglistx = 0x23, + DW_FORM_ref_sup8 = 0x24, + DW_FORM_strx1 = 0x25, + DW_FORM_strx2 = 0x26, + DW_FORM_strx3 = 0x27, + DW_FORM_strx4 = 0x28, + DW_FORM_addrx1 = 0x29, + DW_FORM_addrx2 = 0x2a, + DW_FORM_addrx3 = 0x2b, + DW_FORM_addrx4 = 0x2c, + +// Extensions for Fission proposal + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + +// Alternate debug sections proposal (output of "dwz" tool). + DW_FORM_GNU_ref_alt = 0x1f20, + DW_FORM_GNU_strp_alt = 0x1f21 +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_encoding` attribute. +/// +/// See Section 7.8, Table 7.11. +DwAte(u8) { + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + +// DWARF 3. + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f , + +// DWARF 4. + DW_ATE_UTF = 0x10, + DW_ATE_UCS = 0x11, + DW_ATE_ASCII = 0x12, + + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff, +}); + +dw!( +/// The encodings of the constants used in location list entries. +/// +/// See Section 7.7.3, Table 7.10. +DwLle(u8) { + DW_LLE_end_of_list = 0x00, + DW_LLE_base_addressx = 0x01, + DW_LLE_startx_endx = 0x02, + DW_LLE_startx_length = 0x03, + DW_LLE_offset_pair = 0x04, + DW_LLE_default_location = 0x05, + DW_LLE_base_address = 0x06, + DW_LLE_start_end = 0x07, + DW_LLE_start_length = 0x08, + DW_LLE_GNU_view_pair = 0x09, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_decimal_sign` attribute. +/// +/// See Section 7.8, Table 7.12. +DwDs(u8) { + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_endianity` attribute. +/// +/// See Section 7.8, Table 7.13. +DwEnd(u8) { + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_accessibility` attribute. +/// +/// See Section 7.9, Table 7.14. +DwAccess(u8) { + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_visibility` attribute. +/// +/// See Section 7.10, Table 7.15. +DwVis(u8) { + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_virtuality` attribute. +/// +/// See Section 7.11, Table 7.16. +DwVirtuality(u8) { + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_language` attribute. +/// +/// See Section 7.12, Table 7.17. +DwLang(u16) { + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_Python = 0x0014, + DW_LANG_OpenCL = 0x0015, + DW_LANG_Go = 0x0016, + DW_LANG_Modula3 = 0x0017, + DW_LANG_Haskell = 0x0018, + DW_LANG_C_plus_plus_03 = 0x0019, + DW_LANG_C_plus_plus_11 = 0x001a, + DW_LANG_OCaml = 0x001b, + DW_LANG_Rust = 0x001c, + DW_LANG_C11 = 0x001d, + DW_LANG_Swift = 0x001e, + DW_LANG_Julia = 0x001f, + DW_LANG_Dylan = 0x0020, + DW_LANG_C_plus_plus_14 = 0x0021, + DW_LANG_Fortran03 = 0x0022, + DW_LANG_Fortran08 = 0x0023, + DW_LANG_RenderScript = 0x0024, + DW_LANG_BLISS = 0x0025, + DW_LANG_Kotlin = 0x0026, + DW_LANG_Zig = 0x0027, + DW_LANG_Crystal = 0x0028, + DW_LANG_C_plus_plus_17 = 0x002a, + DW_LANG_C_plus_plus_20 = 0x002b, + DW_LANG_C17 = 0x002c, + DW_LANG_Fortran18 = 0x002d, + DW_LANG_Ada2005 = 0x002e, + DW_LANG_Ada2012 = 0x002f, + + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff, + + DW_LANG_Mips_Assembler = 0x8001, + DW_LANG_GOOGLE_RenderScript = 0x8e57, + DW_LANG_SUN_Assembler = 0x9001, + DW_LANG_ALTIUM_Assembler = 0x9101, + DW_LANG_BORLAND_Delphi = 0xb000, +}); + +impl DwLang { + /// Get the default DW_AT_lower_bound for this language. + pub fn default_lower_bound(self) -> Option { + match self { + DW_LANG_C89 + | DW_LANG_C + | DW_LANG_C_plus_plus + | DW_LANG_Java + | DW_LANG_C99 + | DW_LANG_ObjC + | DW_LANG_ObjC_plus_plus + | DW_LANG_UPC + | DW_LANG_D + | DW_LANG_Python + | DW_LANG_OpenCL + | DW_LANG_Go + | DW_LANG_Haskell + | DW_LANG_C_plus_plus_03 + | DW_LANG_C_plus_plus_11 + | DW_LANG_OCaml + | DW_LANG_Rust + | DW_LANG_C11 + | DW_LANG_Swift + | DW_LANG_Dylan + | DW_LANG_C_plus_plus_14 + | DW_LANG_RenderScript + | DW_LANG_BLISS => Some(0), + DW_LANG_Ada83 | DW_LANG_Cobol74 | DW_LANG_Cobol85 | DW_LANG_Fortran77 + | DW_LANG_Fortran90 | DW_LANG_Pascal83 | DW_LANG_Modula2 | DW_LANG_Ada95 + | DW_LANG_Fortran95 | DW_LANG_PLI | DW_LANG_Modula3 | DW_LANG_Julia + | DW_LANG_Fortran03 | DW_LANG_Fortran08 => Some(1), + _ => None, + } + } +} + +dw!( +/// The encodings of the constants used in the `DW_AT_address_class` attribute. +/// +/// There is only one value that is common to all target architectures. +/// See Section 7.13. +DwAddr(u64) { + DW_ADDR_none = 0x00, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_identifier_case` attribute. +/// +/// See Section 7.14, Table 7.18. +DwId(u8) { + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_calling_convention` attribute. +/// +/// See Section 7.15, Table 7.19. +DwCc(u8) { + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_pass_by_reference = 0x04, + DW_CC_pass_by_value = 0x05, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_inline` attribute. +/// +/// See Section 7.16, Table 7.20. +DwInl(u8) { + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_ordering` attribute. +/// +/// See Section 7.17, Table 7.17. +DwOrd(u8) { + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_discr_list` attribute. +/// +/// See Section 7.18, Table 7.22. +DwDsc(u8) { + DW_DSC_label = 0x00, + DW_DSC_range = 0x01, +}); + +dw!( +/// Name index attribute encodings. +/// +/// See Section 7.19, Table 7.23. +DwIdx(u16) { + DW_IDX_compile_unit = 1, + DW_IDX_type_unit = 2, + DW_IDX_die_offset = 3, + DW_IDX_parent = 4, + DW_IDX_type_hash = 5, + DW_IDX_lo_user = 0x2000, + DW_IDX_hi_user = 0x3fff, +}); + +dw!( +/// The encodings of the constants used in the `DW_AT_defaulted` attribute. +/// +/// See Section 7.20, Table 7.24. +DwDefaulted(u8) { + DW_DEFAULTED_no = 0x00, + DW_DEFAULTED_in_class = 0x01, + DW_DEFAULTED_out_of_class = 0x02, +}); + +dw!( +/// The encodings for the standard opcodes for line number information. +/// +/// See Section 7.22, Table 7.25. +DwLns(u8) { + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c, +}); + +dw!( +/// The encodings for the extended opcodes for line number information. +/// +/// See Section 7.22, Table 7.26. +DwLne(u8) { + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_set_discriminator = 0x04, + + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff, +}); + +dw!( +/// The encodings for the line number header entry formats. +/// +/// See Section 7.22, Table 7.27. +DwLnct(u16) { + DW_LNCT_path = 0x1, + DW_LNCT_directory_index = 0x2, + DW_LNCT_timestamp = 0x3, + DW_LNCT_size = 0x4, + DW_LNCT_MD5 = 0x5, + // DW_LNCT_source = 0x6, + DW_LNCT_lo_user = 0x2000, + // We currently only implement the LLVM embedded source code extension for DWARF v5. + DW_LNCT_LLVM_source = 0x2001, + DW_LNCT_hi_user = 0x3fff, +}); + +dw!( +/// Type codes for macro definitions in the `.debug_macinfo` section. +/// +/// See Section 7.22, Figure 39 for DWARF 4. +DwMacinfo(u8) { + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff, +}); + +dw!( +/// The encodings for macro information entry types. +/// +/// See Section 7.23, Table 7.28 for DWARF 5. +DwMacro(u8) { + DW_MACRO_define = 0x01, + DW_MACRO_undef = 0x02, + DW_MACRO_start_file = 0x03, + DW_MACRO_end_file = 0x04, + DW_MACRO_define_strp = 0x05, + DW_MACRO_undef_strp = 0x06, + DW_MACRO_import = 0x07, + DW_MACRO_define_sup = 0x08, + DW_MACRO_undef_sup = 0x09, + DW_MACRO_import_sup = 0x0a, + DW_MACRO_define_strx = 0x0b, + DW_MACRO_undef_strx = 0x0c, + DW_MACRO_lo_user = 0xe0, + DW_MACRO_hi_user = 0xff, +}); + +dw!( +/// Range list entry encoding values. +/// +/// See Section 7.25, Table 7.30. +DwRle(u8) { + DW_RLE_end_of_list = 0x00, + DW_RLE_base_addressx = 0x01, + DW_RLE_startx_endx = 0x02, + DW_RLE_startx_length = 0x03, + DW_RLE_offset_pair = 0x04, + DW_RLE_base_address = 0x05, + DW_RLE_start_end = 0x06, + DW_RLE_start_length = 0x07, +}); + +dw!( +/// The encodings for DWARF expression operations. +/// +/// See Section 7.7.1, Table 7.9. +DwOp(u8) { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_skip = 0x2f, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3a, + DW_OP_lit11 = 0x3b, + DW_OP_lit12 = 0x3c, + DW_OP_lit13 = 0x3d, + DW_OP_lit14 = 0x3e, + DW_OP_lit15 = 0x3f, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4a, + DW_OP_lit27 = 0x4b, + DW_OP_lit28 = 0x4c, + DW_OP_lit29 = 0x4d, + DW_OP_lit30 = 0x4e, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5a, + DW_OP_reg11 = 0x5b, + DW_OP_reg12 = 0x5c, + DW_OP_reg13 = 0x5d, + DW_OP_reg14 = 0x5e, + DW_OP_reg15 = 0x5f, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6a, + DW_OP_reg27 = 0x6b, + DW_OP_reg28 = 0x6c, + DW_OP_reg29 = 0x6d, + DW_OP_reg30 = 0x6e, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7a, + DW_OP_breg11 = 0x7b, + DW_OP_breg12 = 0x7c, + DW_OP_breg13 = 0x7d, + DW_OP_breg14 = 0x7e, + DW_OP_breg15 = 0x7f, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8a, + DW_OP_breg27 = 0x8b, + DW_OP_breg28 = 0x8c, + DW_OP_breg29 = 0x8d, + DW_OP_breg30 = 0x8e, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b, + DW_OP_call_frame_cfa = 0x9c, + DW_OP_bit_piece = 0x9d, + DW_OP_implicit_value = 0x9e, + DW_OP_stack_value = 0x9f, + DW_OP_implicit_pointer = 0xa0, + DW_OP_addrx = 0xa1, + DW_OP_constx = 0xa2, + DW_OP_entry_value = 0xa3, + DW_OP_const_type = 0xa4, + DW_OP_regval_type = 0xa5, + DW_OP_deref_type = 0xa6, + DW_OP_xderef_type = 0xa7, + DW_OP_convert = 0xa8, + DW_OP_reinterpret = 0xa9, + + // GNU extensions + DW_OP_GNU_push_tls_address = 0xe0, + DW_OP_GNU_implicit_pointer = 0xf2, + DW_OP_GNU_entry_value = 0xf3, + DW_OP_GNU_const_type = 0xf4, + DW_OP_GNU_regval_type = 0xf5, + DW_OP_GNU_deref_type = 0xf6, + DW_OP_GNU_convert = 0xf7, + DW_OP_GNU_reinterpret = 0xf9, + DW_OP_GNU_parameter_ref = 0xfa, + DW_OP_GNU_addr_index = 0xfb, + DW_OP_GNU_const_index = 0xfc, + + // Wasm extensions + DW_OP_WASM_location = 0xed, +}); + +dw!( +/// Pointer encoding used by `.eh_frame`. +/// +/// The four lower bits describe the +/// format of the pointer, the upper four bits describe how the encoding should +/// be applied. +/// +/// Defined in `` +DwEhPe(u8) { +// Format of pointer encoding. + +// "Unsigned value is encoded using the Little Endian Base 128" + DW_EH_PE_uleb128 = 0x1, +// "A 2 bytes unsigned value." + DW_EH_PE_udata2 = 0x2, +// "A 4 bytes unsigned value." + DW_EH_PE_udata4 = 0x3, +// "An 8 bytes unsigned value." + DW_EH_PE_udata8 = 0x4, +// "Signed value is encoded using the Little Endian Base 128" + DW_EH_PE_sleb128 = 0x9, +// "A 2 bytes signed value." + DW_EH_PE_sdata2 = 0x0a, +// "A 4 bytes signed value." + DW_EH_PE_sdata4 = 0x0b, +// "An 8 bytes signed value." + DW_EH_PE_sdata8 = 0x0c, + +// How the pointer encoding should be applied. + +// `DW_EH_PE_pcrel` pointers are relative to their own location. + DW_EH_PE_pcrel = 0x10, +// "Value is relative to the beginning of the .text section." + DW_EH_PE_textrel = 0x20, +// "Value is relative to the beginning of the .got or .eh_frame_hdr section." + DW_EH_PE_datarel = 0x30, +// "Value is relative to the beginning of the function." + DW_EH_PE_funcrel = 0x40, +// "Value is aligned to an address unit sized boundary." + DW_EH_PE_aligned = 0x50, + +// This bit can be set for any of the above encoding applications. When set, +// the encoded value is the address of the real pointer result, not the +// pointer result itself. +// +// This isn't defined in the DWARF or the `.eh_frame` standards, but is +// generated by both GNU/Linux and macOS tooling. + DW_EH_PE_indirect = 0x80, + +// These constants apply to both the lower and upper bits. + +// "The Value is a literal pointer whose size is determined by the +// architecture." + DW_EH_PE_absptr = 0x0, +// The absence of a pointer and encoding. + DW_EH_PE_omit = 0xff, +}); + +const DW_EH_PE_FORMAT_MASK: u8 = 0b0000_1111; + +// Ignores indirection bit. +const DW_EH_PE_APPLICATION_MASK: u8 = 0b0111_0000; + +impl ops::BitOr for DwEhPe { + type Output = DwEhPe; + + fn bitor(self, rhs: DwEhPe) -> DwEhPe { + DwEhPe(self.0 | rhs.0) + } +} + +impl DwEhPe { + /// Get the pointer encoding's format. + #[inline] + pub fn format(self) -> DwEhPe { + DwEhPe(self.0 & DW_EH_PE_FORMAT_MASK) + } + + /// Get the pointer encoding's application. + #[inline] + pub fn application(self) -> DwEhPe { + DwEhPe(self.0 & DW_EH_PE_APPLICATION_MASK) + } + + /// Is this encoding the absent pointer encoding? + #[inline] + pub fn is_absent(self) -> bool { + self == DW_EH_PE_omit + } + + /// Is this coding indirect? If so, its encoded value is the address of the + /// real pointer result, not the pointer result itself. + #[inline] + pub fn is_indirect(self) -> bool { + self.0 & DW_EH_PE_indirect.0 != 0 + } + + /// Is this a known, valid pointer encoding? + pub fn is_valid_encoding(self) -> bool { + if self.is_absent() { + return true; + } + + match self.format() { + DW_EH_PE_absptr | DW_EH_PE_uleb128 | DW_EH_PE_udata2 | DW_EH_PE_udata4 + | DW_EH_PE_udata8 | DW_EH_PE_sleb128 | DW_EH_PE_sdata2 | DW_EH_PE_sdata4 + | DW_EH_PE_sdata8 => {} + _ => return false, + } + + match self.application() { + DW_EH_PE_absptr | DW_EH_PE_pcrel | DW_EH_PE_textrel | DW_EH_PE_datarel + | DW_EH_PE_funcrel | DW_EH_PE_aligned => {} + _ => return false, + } + + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dw_eh_pe_format() { + let encoding = DW_EH_PE_pcrel | DW_EH_PE_uleb128; + assert_eq!(encoding.format(), DW_EH_PE_uleb128); + } + + #[test] + fn test_dw_eh_pe_application() { + let encoding = DW_EH_PE_pcrel | DW_EH_PE_uleb128; + assert_eq!(encoding.application(), DW_EH_PE_pcrel); + } + + #[test] + fn test_dw_eh_pe_is_absent() { + assert!(!DW_EH_PE_absptr.is_absent()); + assert!(DW_EH_PE_omit.is_absent()); + } + + #[test] + fn test_dw_eh_pe_is_valid_encoding_ok() { + let encoding = DW_EH_PE_uleb128 | DW_EH_PE_pcrel; + assert!(encoding.is_valid_encoding()); + assert!(DW_EH_PE_absptr.is_valid_encoding()); + assert!(DW_EH_PE_omit.is_valid_encoding()); + } + + #[test] + fn test_dw_eh_pe_is_valid_encoding_bad_format() { + let encoding = DwEhPe((DW_EH_PE_sdata8.0 + 1) | DW_EH_PE_pcrel.0); + assert!(!encoding.is_valid_encoding()); + } + + #[test] + fn test_dw_eh_pe_is_valid_encoding_bad_application() { + let encoding = DwEhPe(DW_EH_PE_sdata8.0 | (DW_EH_PE_aligned.0 + 1)); + assert!(!encoding.is_valid_encoding()); + } +} diff --git a/anneal/v2/vendor/gimli/src/endianity.rs b/anneal/v2/vendor/gimli/src/endianity.rs new file mode 100644 index 0000000000..3201551f1b --- /dev/null +++ b/anneal/v2/vendor/gimli/src/endianity.rs @@ -0,0 +1,256 @@ +//! Types for compile-time and run-time endianity. + +use core::convert::TryInto; +use core::fmt::Debug; + +/// A trait describing the endianity of some buffer. +pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq { + /// Return true for big endian byte order. + fn is_big_endian(self) -> bool; + + /// Return true for little endian byte order. + #[inline] + fn is_little_endian(self) -> bool { + !self.is_big_endian() + } + + /// Reads an unsigned 16 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + #[inline] + fn read_u16(self, buf: &[u8]) -> u16 { + let bytes: &[u8; 2] = buf[..2].try_into().unwrap(); + if self.is_big_endian() { + u16::from_be_bytes(*bytes) + } else { + u16::from_le_bytes(*bytes) + } + } + + /// Reads an unsigned 32 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn read_u32(self, buf: &[u8]) -> u32 { + let bytes: &[u8; 4] = buf[..4].try_into().unwrap(); + if self.is_big_endian() { + u32::from_be_bytes(*bytes) + } else { + u32::from_le_bytes(*bytes) + } + } + + /// Reads an unsigned 64 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_u64(self, buf: &[u8]) -> u64 { + let bytes: &[u8; 8] = buf[..8].try_into().unwrap(); + if self.is_big_endian() { + u64::from_be_bytes(*bytes) + } else { + u64::from_le_bytes(*bytes) + } + } + + /// Read an unsigned n-bytes integer u64. + /// + /// # Panics + /// + /// Panics when `buf.len() < 1` or `buf.len() > 8`. + #[inline] + fn read_uint(&mut self, buf: &[u8]) -> u64 { + let mut tmp = [0; 8]; + if self.is_big_endian() { + tmp[8 - buf.len()..].copy_from_slice(buf); + } else { + tmp[..buf.len()].copy_from_slice(buf); + } + self.read_u64(&tmp) + } + + /// Reads a signed 16 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + #[inline] + fn read_i16(self, buf: &[u8]) -> i16 { + self.read_u16(buf) as i16 + } + + /// Reads a signed 32 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn read_i32(self, buf: &[u8]) -> i32 { + self.read_u32(buf) as i32 + } + + /// Reads a signed 64 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_i64(self, buf: &[u8]) -> i64 { + self.read_u64(buf) as i64 + } + + /// Reads a 32 bit floating point number from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_f32(self, buf: &[u8]) -> f32 { + f32::from_bits(self.read_u32(buf)) + } + + /// Reads a 32 bit floating point number from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_f64(self, buf: &[u8]) -> f64 { + f64::from_bits(self.read_u64(buf)) + } + + /// Writes an unsigned 16 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 2`. + #[inline] + fn write_u16(self, buf: &mut [u8], n: u16) { + let bytes = if self.is_big_endian() { + n.to_be_bytes() + } else { + n.to_le_bytes() + }; + buf[..2].copy_from_slice(&bytes); + } + + /// Writes an unsigned 32 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn write_u32(self, buf: &mut [u8], n: u32) { + let bytes = if self.is_big_endian() { + n.to_be_bytes() + } else { + n.to_le_bytes() + }; + buf[..4].copy_from_slice(&bytes); + } + + /// Writes an unsigned 64 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn write_u64(self, buf: &mut [u8], n: u64) { + let bytes = if self.is_big_endian() { + n.to_be_bytes() + } else { + n.to_le_bytes() + }; + buf[..8].copy_from_slice(&bytes); + } +} + +/// Byte order that is selectable at runtime. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum RunTimeEndian { + /// Little endian byte order. + Little, + /// Big endian byte order. + Big, +} + +impl Default for RunTimeEndian { + #[cfg(target_endian = "little")] + #[inline] + fn default() -> RunTimeEndian { + RunTimeEndian::Little + } + + #[cfg(target_endian = "big")] + #[inline] + fn default() -> RunTimeEndian { + RunTimeEndian::Big + } +} + +impl Endianity for RunTimeEndian { + #[inline] + fn is_big_endian(self) -> bool { + self != RunTimeEndian::Little + } +} + +/// Little endian byte order. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LittleEndian; + +impl Default for LittleEndian { + #[inline] + fn default() -> LittleEndian { + LittleEndian + } +} + +impl Endianity for LittleEndian { + #[inline] + fn is_big_endian(self) -> bool { + false + } +} + +/// Big endian byte order. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct BigEndian; + +impl Default for BigEndian { + #[inline] + fn default() -> BigEndian { + BigEndian + } +} + +impl Endianity for BigEndian { + #[inline] + fn is_big_endian(self) -> bool { + true + } +} + +/// The native endianity for the target platform. +#[cfg(target_endian = "little")] +pub type NativeEndian = LittleEndian; + +#[cfg(target_endian = "little")] +#[allow(non_upper_case_globals)] +#[doc(hidden)] +pub const NativeEndian: LittleEndian = LittleEndian; + +/// The native endianity for the target platform. +#[cfg(target_endian = "big")] +pub type NativeEndian = BigEndian; + +#[cfg(target_endian = "big")] +#[allow(non_upper_case_globals)] +#[doc(hidden)] +pub const NativeEndian: BigEndian = BigEndian; diff --git a/anneal/v2/vendor/gimli/src/leb128.rs b/anneal/v2/vendor/gimli/src/leb128.rs new file mode 100644 index 0000000000..c0ee303ae5 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/leb128.rs @@ -0,0 +1,612 @@ +//! Read and write DWARF's "Little Endian Base 128" (LEB128) variable length +//! integer encoding. +//! +//! The implementation is a direct translation of the psuedocode in the DWARF 4 +//! standard's appendix C. +//! +//! Read and write signed integers: +//! +//! ``` +//! # #[cfg(all(feature = "read", feature = "write"))] { +//! use gimli::{EndianSlice, NativeEndian, leb128}; +//! +//! let mut buf = [0; 1024]; +//! +//! // Write to anything that implements `std::io::Write`. +//! { +//! let mut writable = &mut buf[..]; +//! leb128::write::signed(&mut writable, -12345).expect("Should write number"); +//! } +//! +//! // Read from anything that implements `gimli::Reader`. +//! let mut readable = EndianSlice::new(&buf[..], NativeEndian); +//! let val = leb128::read::signed(&mut readable).expect("Should read number"); +//! assert_eq!(val, -12345); +//! # } +//! ``` +//! +//! Or read and write unsigned integers: +//! +//! ``` +//! # #[cfg(all(feature = "read", feature = "write"))] { +//! use gimli::{EndianSlice, NativeEndian, leb128}; +//! +//! let mut buf = [0; 1024]; +//! +//! { +//! let mut writable = &mut buf[..]; +//! leb128::write::unsigned(&mut writable, 98765).expect("Should write number"); +//! } +//! +//! let mut readable = EndianSlice::new(&buf[..], NativeEndian); +//! let val = leb128::read::unsigned(&mut readable).expect("Should read number"); +//! assert_eq!(val, 98765); +//! # } +//! ``` + +const CONTINUATION_BIT: u8 = 1 << 7; +#[cfg(feature = "read-core")] +const SIGN_BIT: u8 = 1 << 6; + +#[inline] +fn low_bits_of_byte(byte: u8) -> u8 { + byte & !CONTINUATION_BIT +} + +#[inline] +#[allow(dead_code)] +fn low_bits_of_u64(val: u64) -> u8 { + let byte = val & u64::from(u8::MAX); + low_bits_of_byte(byte as u8) +} + +/// A module for reading signed and unsigned integers that have been LEB128 +/// encoded. +#[cfg(feature = "read-core")] +pub mod read { + use super::{low_bits_of_byte, CONTINUATION_BIT, SIGN_BIT}; + use crate::read::{Error, Reader, Result}; + + /// Read bytes until the LEB128 continuation bit is not set. + pub fn skip(r: &mut R) -> Result<()> { + loop { + let byte = r.read_u8()?; + if byte & CONTINUATION_BIT == 0 { + return Ok(()); + } + } + } + + /// Read an unsigned LEB128 number from the given `Reader` and + /// return it or an error if reading failed. + pub fn unsigned(r: &mut R) -> Result { + let mut result = 0; + let mut shift = 0; + + loop { + let byte = r.read_u8()?; + if shift == 63 && byte != 0x00 && byte != 0x01 { + return Err(Error::BadUnsignedLeb128); + } + + let low_bits = u64::from(low_bits_of_byte(byte)); + result |= low_bits << shift; + + if byte & CONTINUATION_BIT == 0 { + return Ok(result); + } + + shift += 7; + } + } + + /// Read an LEB128 u16 from the given `Reader` and + /// return it or an error if reading failed. + pub fn u16(r: &mut R) -> Result { + let byte = r.read_u8()?; + let mut result = u16::from(low_bits_of_byte(byte)); + if byte & CONTINUATION_BIT == 0 { + return Ok(result); + } + + let byte = r.read_u8()?; + result |= u16::from(low_bits_of_byte(byte)) << 7; + if byte & CONTINUATION_BIT == 0 { + return Ok(result); + } + + let byte = r.read_u8()?; + if byte > 0x03 { + return Err(Error::BadUnsignedLeb128); + } + result += u16::from(byte) << 14; + Ok(result) + } + + /// Read a signed LEB128 number from the given `Reader` and + /// return it or an error if reading failed. + pub fn signed(r: &mut R) -> Result { + let mut result = 0; + let mut shift = 0; + let size = 64; + let mut byte; + + loop { + byte = r.read_u8()?; + if shift == 63 && byte != 0x00 && byte != 0x7f { + return Err(Error::BadSignedLeb128); + } + + let low_bits = i64::from(low_bits_of_byte(byte)); + result |= low_bits << shift; + shift += 7; + + if byte & CONTINUATION_BIT == 0 { + break; + } + } + + if shift < size && (SIGN_BIT & byte) == SIGN_BIT { + // Sign extend the result. + result |= !0 << shift; + } + + Ok(result) + } +} + +/// A module for writing integers encoded as LEB128. +#[cfg(feature = "write")] +pub mod write { + use super::{low_bits_of_u64, CONTINUATION_BIT}; + use std::io; + + /// Write the given unsigned number using the LEB128 encoding to the given + /// `std::io::Write`able. Returns the number of bytes written to `w`, or an + /// error if writing failed. + pub fn unsigned(w: &mut W, mut val: u64) -> Result + where + W: io::Write, + { + let mut bytes_written = 0; + loop { + let mut byte = low_bits_of_u64(val); + val >>= 7; + if val != 0 { + // More bytes to come, so set the continuation bit. + byte |= CONTINUATION_BIT; + } + + let buf = [byte]; + w.write_all(&buf)?; + bytes_written += 1; + + if val == 0 { + return Ok(bytes_written); + } + } + } + + /// Return the size of the LEB128 encoding of the given unsigned number. + pub fn uleb128_size(mut val: u64) -> usize { + let mut size = 0; + loop { + val >>= 7; + size += 1; + if val == 0 { + return size; + } + } + } + + /// Write the given signed number using the LEB128 encoding to the given + /// `std::io::Write`able. Returns the number of bytes written to `w`, or an + /// error if writing failed. + pub fn signed(w: &mut W, mut val: i64) -> Result + where + W: io::Write, + { + let mut bytes_written = 0; + loop { + let mut byte = val as u8; + // Keep the sign bit for testing + val >>= 6; + let done = val == 0 || val == -1; + if done { + byte &= !CONTINUATION_BIT; + } else { + // Remove the sign bit + val >>= 1; + // More bytes to come, so set the continuation bit. + byte |= CONTINUATION_BIT; + } + + let buf = [byte]; + w.write_all(&buf)?; + bytes_written += 1; + + if done { + return Ok(bytes_written); + } + } + } + + /// Return the size of the LEB128 encoding of the given signed number. + pub fn sleb128_size(mut val: i64) -> usize { + let mut size = 0; + loop { + val >>= 6; + let done = val == 0 || val == -1; + val >>= 1; + size += 1; + if done { + return size; + } + } + } +} + +#[cfg(test)] +#[cfg(all(feature = "read", feature = "write"))] +mod tests { + use super::{low_bits_of_byte, low_bits_of_u64, read, write, CONTINUATION_BIT}; + use crate::endianity::NativeEndian; + use crate::read::{EndianSlice, Error, ReaderOffsetId}; + + trait ResultExt { + fn map_eof(self, input: &[u8]) -> Self; + } + + impl ResultExt for Result { + fn map_eof(self, input: &[u8]) -> Self { + match self { + Err(Error::UnexpectedEof(id)) => { + let id = ReaderOffsetId(id.0 - input.as_ptr() as u64); + Err(Error::UnexpectedEof(id)) + } + r => r, + } + } + } + + #[test] + fn test_low_bits_of_byte() { + for i in 0..127 { + assert_eq!(i, low_bits_of_byte(i)); + assert_eq!(i, low_bits_of_byte(i | CONTINUATION_BIT)); + } + } + + #[test] + fn test_low_bits_of_u64() { + for i in 0u64..127 { + assert_eq!(i as u8, low_bits_of_u64(1 << 16 | i)); + assert_eq!( + i as u8, + low_bits_of_u64(i << 16 | i | (u64::from(CONTINUATION_BIT))) + ); + } + } + + // Examples from the DWARF 4 standard, section 7.6, figure 22. + #[test] + fn test_read_unsigned() { + let buf = [2u8]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 2, + read::unsigned(&mut readable).expect("Should read number") + ); + + let buf = [127u8]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 127, + read::unsigned(&mut readable).expect("Should read number") + ); + + let buf = [CONTINUATION_BIT, 1]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 128, + read::unsigned(&mut readable).expect("Should read number") + ); + + let buf = [1u8 | CONTINUATION_BIT, 1]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 129, + read::unsigned(&mut readable).expect("Should read number") + ); + + let buf = [2u8 | CONTINUATION_BIT, 1]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 130, + read::unsigned(&mut readable).expect("Should read number") + ); + + let buf = [57u8 | CONTINUATION_BIT, 100]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 12857, + read::unsigned(&mut readable).expect("Should read number") + ); + } + + // Examples from the DWARF 4 standard, section 7.6, figure 23. + #[test] + fn test_read_signed() { + let buf = [2u8]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!(2, read::signed(&mut readable).expect("Should read number")); + + let buf = [0x7eu8]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!(-2, read::signed(&mut readable).expect("Should read number")); + + let buf = [127u8 | CONTINUATION_BIT, 0]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 127, + read::signed(&mut readable).expect("Should read number") + ); + + let buf = [1u8 | CONTINUATION_BIT, 0x7f]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + -127, + read::signed(&mut readable).expect("Should read number") + ); + + let buf = [CONTINUATION_BIT, 1]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 128, + read::signed(&mut readable).expect("Should read number") + ); + + let buf = [CONTINUATION_BIT, 0x7f]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + -128, + read::signed(&mut readable).expect("Should read number") + ); + + let buf = [1u8 | CONTINUATION_BIT, 1]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + 129, + read::signed(&mut readable).expect("Should read number") + ); + + let buf = [0x7fu8 | CONTINUATION_BIT, 0x7e]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + -129, + read::signed(&mut readable).expect("Should read number") + ); + } + + #[test] + fn test_read_signed_63_bits() { + let buf = [ + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + CONTINUATION_BIT, + 0x40, + ]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + -0x4000_0000_0000_0000, + read::signed(&mut readable).expect("Should read number") + ); + } + + #[test] + fn test_read_unsigned_not_enough_data() { + let buf = [CONTINUATION_BIT]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + read::unsigned(&mut readable).map_eof(&buf), + Err(Error::UnexpectedEof(ReaderOffsetId(1))) + ); + } + + #[test] + fn test_read_signed_not_enough_data() { + let buf = [CONTINUATION_BIT]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + read::signed(&mut readable).map_eof(&buf), + Err(Error::UnexpectedEof(ReaderOffsetId(1))) + ); + } + + #[test] + fn test_write_unsigned_not_enough_space() { + let mut buf = [0; 1]; + let mut writable = &mut buf[..]; + match write::unsigned(&mut writable, 128) { + Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero), + otherwise => panic!("Unexpected: {:?}", otherwise), + } + } + + #[test] + fn test_write_signed_not_enough_space() { + let mut buf = [0; 1]; + let mut writable = &mut buf[..]; + match write::signed(&mut writable, 128) { + Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero), + otherwise => panic!("Unexpected: {:?}", otherwise), + } + } + + #[test] + fn dogfood_signed() { + fn inner(i: i64) { + let mut buf = [0u8; 1024]; + + { + let mut writable = &mut buf[..]; + write::signed(&mut writable, i).expect("Should write signed number"); + } + + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + let result = read::signed(&mut readable).expect("Should be able to read it back again"); + assert_eq!(i, result); + } + for i in -513..513 { + inner(i); + } + inner(i64::MIN); + } + + #[test] + fn dogfood_unsigned() { + for i in 0..1025 { + let mut buf = [0u8; 1024]; + + { + let mut writable = &mut buf[..]; + write::unsigned(&mut writable, i).expect("Should write signed number"); + } + + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + let result = + read::unsigned(&mut readable).expect("Should be able to read it back again"); + assert_eq!(i, result); + } + } + + #[test] + fn test_read_unsigned_overflow() { + let buf = [ + 2u8 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 1, + ]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert!(read::unsigned(&mut readable).is_err()); + } + + #[test] + fn test_read_signed_overflow() { + let buf = [ + 2u8 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 2 | CONTINUATION_BIT, + 1, + ]; + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert!(read::signed(&mut readable).is_err()); + } + + #[test] + fn test_read_multiple() { + let buf = [2u8 | CONTINUATION_BIT, 1u8, 1u8]; + + let mut readable = EndianSlice::new(&buf[..], NativeEndian); + assert_eq!( + read::unsigned(&mut readable).expect("Should read first number"), + 130u64 + ); + assert_eq!( + read::unsigned(&mut readable).expect("Should read first number"), + 1u64 + ); + } + + #[test] + fn test_read_u16() { + for (buf, val) in [ + (&[2][..], 2), + (&[0x7f][..], 0x7f), + (&[0x80, 1][..], 0x80), + (&[0x81, 1][..], 0x81), + (&[0x82, 1][..], 0x82), + (&[0xff, 0x7f][..], 0x3fff), + (&[0x80, 0x80, 1][..], 0x4000), + (&[0xff, 0xff, 1][..], 0x7fff), + (&[0xff, 0xff, 3][..], 0xffff), + ] + .iter() + { + let mut readable = EndianSlice::new(buf, NativeEndian); + assert_eq!(*val, read::u16(&mut readable).expect("Should read number")); + } + + for buf in [ + &[0x80][..], + &[0x80, 0x80][..], + &[0x80, 0x80, 4][..], + &[0x80, 0x80, 0x80, 3][..], + ] + .iter() + { + let mut readable = EndianSlice::new(buf, NativeEndian); + assert!(read::u16(&mut readable).is_err(), "{:?}", buf); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/lib.rs b/anneal/v2/vendor/gimli/src/lib.rs new file mode 100644 index 0000000000..cce4113f33 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/lib.rs @@ -0,0 +1,80 @@ +//! `gimli` is a library for reading and writing the +//! [DWARF debugging format](https://dwarfstd.org/). +//! +//! See the [read](./read/index.html) and [write](./write/index.html) modules +//! for examples and API documentation. +//! +//! ## Cargo Features +//! +//! Cargo features that can be enabled with `gimli`: +//! +//! * `std`: Enabled by default. Use the `std` library. Disabling this feature +//! allows using `gimli` in embedded environments that do not have access to +//! `std`. Note that even when `std` is disabled, `gimli` still requires an +//! implementation of the `alloc` crate. +//! +//! * `read`: Enabled by default. Enables the `read` module. Use of `std` is +//! optional. +//! +//! * `write`: Enabled by default. Enables the `write` module. Always uses +//! the `std` library. +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +// Selectively enable rust 2018 warnings +#![warn(bare_trait_objects)] +#![warn(unused_extern_crates)] +#![warn(ellipsis_inclusive_range_patterns)] +#![warn(elided_lifetimes_in_paths)] +#![warn(explicit_outlives_requirements)] +// Style. +#![allow(clippy::bool_to_int_with_if)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::comparison_chain)] +#![allow(clippy::manual_range_contains)] +#![allow(clippy::needless_late_init)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::needless_lifetimes)] +// False positives with `fallible_iterator`. +#![allow(clippy::should_implement_trait)] +// False positives. +#![allow(clippy::derive_partial_eq_without_eq)] +#![no_std] + +#[allow(unused_imports)] +#[cfg(any(feature = "read", feature = "write"))] +#[macro_use] +extern crate alloc; + +#[cfg(any(feature = "std", feature = "write"))] +#[macro_use] +extern crate std; + +#[cfg(feature = "endian-reader")] +pub use stable_deref_trait::{CloneStableDeref, StableDeref}; + +mod common; +pub use crate::common::*; + +mod arch; +pub use crate::arch::*; + +pub mod constants; +// For backwards compat. +pub use crate::constants::*; + +mod endianity; +pub use crate::endianity::*; + +pub mod leb128; + +#[cfg(feature = "read-core")] +pub mod read; +// For backwards compat. +#[cfg(feature = "read-core")] +pub use crate::read::*; + +#[cfg(feature = "write")] +pub mod write; + +#[cfg(test)] +mod test_util; diff --git a/anneal/v2/vendor/gimli/src/read/abbrev.rs b/anneal/v2/vendor/gimli/src/read/abbrev.rs new file mode 100644 index 0000000000..002cc9130f --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/abbrev.rs @@ -0,0 +1,1098 @@ +//! Functions for parsing DWARF debugging abbreviations. + +use alloc::collections::btree_map; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::TryFrom; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::ops::Deref; + +use crate::common::{DebugAbbrevOffset, Encoding, SectionId}; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::{ + DebugInfoUnitHeadersIter, EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader, +}; + +/// The `DebugAbbrev` struct represents the abbreviations describing +/// `DebuggingInformationEntry`s' attribute names and forms found in the +/// `.debug_abbrev` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugAbbrev { + debug_abbrev_section: R, +} + +impl<'input, Endian> DebugAbbrev> +where + Endian: Endianity, +{ + /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_abbrev` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugAbbrev, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_abbrev_section_somehow = || &buf; + /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_abbrev_section, endian)) + } +} + +impl DebugAbbrev { + /// Parse the abbreviations at the given `offset` within this + /// `.debug_abbrev` section. + /// + /// The `offset` should generally be retrieved from a unit header. + pub fn abbreviations( + &self, + debug_abbrev_offset: DebugAbbrevOffset, + ) -> Result { + let input = &mut self.debug_abbrev_section.clone(); + input.skip(debug_abbrev_offset.0)?; + Abbreviations::parse(input) + } +} + +impl DebugAbbrev { + /// Create a `DebugAbbrev` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev + where + F: FnMut(&'a T) -> R, + { + borrow(&self.debug_abbrev_section).into() + } +} + +impl Section for DebugAbbrev { + fn id() -> SectionId { + SectionId::DebugAbbrev + } + + fn reader(&self) -> &R { + &self.debug_abbrev_section + } +} + +impl From for DebugAbbrev { + fn from(debug_abbrev_section: R) -> Self { + DebugAbbrev { + debug_abbrev_section, + } + } +} + +/// The strategy to use for caching abbreviations. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum AbbreviationsCacheStrategy { + /// Cache abbreviations that are used more than once. + /// + /// This is useful if the units in the `.debug_info` section will be parsed only once. + Duplicates, + /// Cache all abbreviations. + /// + /// This is useful if the units in the `.debug_info` section will be parsed more than once. + All, +} + +/// A cache of previously parsed `Abbreviations`. +#[derive(Debug, Default)] +pub struct AbbreviationsCache { + abbreviations: btree_map::BTreeMap>>, +} + +impl AbbreviationsCache { + /// Create an empty abbreviations cache. + pub fn new() -> Self { + Self::default() + } + + /// Parse abbreviations and store them in the cache. + /// + /// This will iterate over the given units to determine the abbreviations + /// offsets. Any existing cache entries are discarded. + /// + /// Errors during parsing abbreviations are also stored in the cache. + /// Errors during iterating over the units are ignored. + pub fn populate( + &mut self, + strategy: AbbreviationsCacheStrategy, + debug_abbrev: &DebugAbbrev, + mut units: DebugInfoUnitHeadersIter, + ) { + let mut offsets = Vec::new(); + match strategy { + AbbreviationsCacheStrategy::Duplicates => { + while let Ok(Some(unit)) = units.next() { + offsets.push(unit.debug_abbrev_offset()); + } + offsets.sort_unstable_by_key(|offset| offset.0); + let mut prev_offset = R::Offset::from_u8(0); + let mut count = 0; + offsets.retain(|offset| { + if count == 0 || prev_offset != offset.0 { + prev_offset = offset.0; + count = 1; + } else { + count += 1; + } + count == 2 + }); + } + AbbreviationsCacheStrategy::All => { + while let Ok(Some(unit)) = units.next() { + offsets.push(unit.debug_abbrev_offset()); + } + offsets.sort_unstable_by_key(|offset| offset.0); + offsets.dedup(); + } + } + self.abbreviations = offsets + .into_iter() + .map(|offset| { + ( + offset.0.into_u64(), + debug_abbrev.abbreviations(offset).map(Arc::new), + ) + }) + .collect(); + } + + /// Set an entry in the abbreviations cache. + /// + /// This is only required if you want to manually populate the cache. + pub fn set( + &mut self, + offset: DebugAbbrevOffset, + abbreviations: Arc, + ) { + self.abbreviations + .insert(offset.0.into_u64(), Ok(abbreviations)); + } + + /// Parse the abbreviations at the given offset. + /// + /// This uses the cache if possible, but does not update it. + pub fn get( + &self, + debug_abbrev: &DebugAbbrev, + offset: DebugAbbrevOffset, + ) -> Result> { + match self.abbreviations.get(&offset.0.into_u64()) { + Some(entry) => entry.clone(), + None => debug_abbrev.abbreviations(offset).map(Arc::new), + } + } +} + +/// A set of type abbreviations. +/// +/// Construct an `Abbreviations` instance with the +/// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations) +/// method. +#[derive(Debug, Default, Clone)] +pub struct Abbreviations { + vec: Vec, + map: btree_map::BTreeMap, +} + +impl Abbreviations { + /// Construct a new, empty set of abbreviations. + fn empty() -> Abbreviations { + Abbreviations { + vec: Vec::new(), + map: btree_map::BTreeMap::new(), + } + } + + /// Insert an abbreviation into the set. + /// + /// Returns `Ok` if it is the first abbreviation in the set with its code, + /// `Err` if the code is a duplicate and there already exists an + /// abbreviation in the set with the given abbreviation's code. + fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> { + let code_usize = abbrev.code as usize; + if code_usize as u64 == abbrev.code { + // Optimize for sequential abbreviation codes by storing them + // in a Vec, as long as the map doesn't already contain them. + // A potential further optimization would be to allow some + // holes in the Vec, but there's no need for that yet. + if code_usize - 1 < self.vec.len() { + return Err(()); + } else if code_usize - 1 == self.vec.len() { + if !self.map.is_empty() && self.map.contains_key(&abbrev.code) { + return Err(()); + } else { + self.vec.push(abbrev); + return Ok(()); + } + } + } + match self.map.entry(abbrev.code) { + btree_map::Entry::Occupied(_) => Err(()), + btree_map::Entry::Vacant(entry) => { + entry.insert(abbrev); + Ok(()) + } + } + } + + /// Get the abbreviation associated with the given code. + #[inline] + pub fn get(&self, code: u64) -> Option<&Abbreviation> { + if let Ok(code) = usize::try_from(code) { + let index = code.checked_sub(1)?; + if index < self.vec.len() { + return Some(&self.vec[index]); + } + } + + self.map.get(&code) + } + + /// Parse a series of abbreviations, terminated by a null abbreviation. + fn parse(input: &mut R) -> Result { + let mut abbrevs = Abbreviations::empty(); + + while let Some(abbrev) = Abbreviation::parse(input)? { + if abbrevs.insert(abbrev).is_err() { + return Err(Error::DuplicateAbbreviationCode); + } + } + + Ok(abbrevs) + } +} + +/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type: +/// its code, tag type, whether it has children, and its set of attributes. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Abbreviation { + code: u64, + tag: constants::DwTag, + has_children: constants::DwChildren, + attributes: Attributes, +} + +impl Abbreviation { + /// Construct a new `Abbreviation`. + /// + /// ### Panics + /// + /// Panics if `code` is `0`. + pub(crate) fn new( + code: u64, + tag: constants::DwTag, + has_children: constants::DwChildren, + attributes: Attributes, + ) -> Abbreviation { + assert_ne!(code, 0); + Abbreviation { + code, + tag, + has_children, + attributes, + } + } + + /// Get this abbreviation's code. + #[inline] + pub fn code(&self) -> u64 { + self.code + } + + /// Get this abbreviation's tag. + #[inline] + pub fn tag(&self) -> constants::DwTag { + self.tag + } + + /// Return true if this abbreviation's type has children, false otherwise. + #[inline] + pub fn has_children(&self) -> bool { + self.has_children == constants::DW_CHILDREN_yes + } + + /// Get this abbreviation's attributes. + #[inline] + pub fn attributes(&self) -> &[AttributeSpecification] { + &self.attributes[..] + } + + /// Parse an abbreviation's tag. + fn parse_tag(input: &mut R) -> Result { + let val = input.read_uleb128_u16()?; + if val == 0 { + Err(Error::AbbreviationTagZero) + } else { + Ok(constants::DwTag(val)) + } + } + + /// Parse an abbreviation's "does the type have children?" byte. + fn parse_has_children(input: &mut R) -> Result { + let val = input.read_u8()?; + let val = constants::DwChildren(val); + if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes { + Ok(val) + } else { + Err(Error::BadHasChildren) + } + } + + /// Parse a series of attribute specifications, terminated by a null attribute + /// specification. + fn parse_attributes(input: &mut R) -> Result { + let mut attrs = Attributes::new(); + + while let Some(attr) = AttributeSpecification::parse(input)? { + attrs.push(attr); + } + + Ok(attrs) + } + + /// Parse an abbreviation. Return `None` for the null abbreviation, `Some` + /// for an actual abbreviation. + fn parse(input: &mut R) -> Result> { + if input.is_empty() { + // Try to recover from missing null terminator. + // If the input was actually truncated, then we'll return an error later + // when trying to find the missing abbreviation. + return Ok(None); + } + let code = input.read_uleb128()?; + if code == 0 { + return Ok(None); + } + + let tag = Self::parse_tag(input)?; + let has_children = Self::parse_has_children(input)?; + let attributes = Self::parse_attributes(input)?; + let abbrev = Abbreviation::new(code, tag, has_children, attributes); + Ok(Some(abbrev)) + } +} + +/// A list of attributes found in an `Abbreviation` +#[derive(Clone)] +pub(crate) enum Attributes { + Inline { + buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE], + len: usize, + }, + Heap(Vec), +} + +// Length of 5 based on benchmark results for both x86-64 and i686. +const MAX_ATTRIBUTES_INLINE: usize = 5; + +impl Attributes { + /// Returns a new empty list of attributes + fn new() -> Attributes { + let default = + AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None); + Attributes::Inline { + buf: [default; 5], + len: 0, + } + } + + /// Pushes a new value onto this list of attributes. + fn push(&mut self, attr: AttributeSpecification) { + match self { + Attributes::Heap(list) => list.push(attr), + Attributes::Inline { + buf, + len: MAX_ATTRIBUTES_INLINE, + } => { + let mut list = buf.to_vec(); + list.push(attr); + *self = Attributes::Heap(list); + } + Attributes::Inline { buf, len } => { + buf[*len] = attr; + *len += 1; + } + } + } +} + +impl Debug for Attributes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl PartialEq for Attributes { + fn eq(&self, other: &Attributes) -> bool { + **self == **other + } +} + +impl Eq for Attributes {} + +impl Deref for Attributes { + type Target = [AttributeSpecification]; + fn deref(&self) -> &[AttributeSpecification] { + match self { + Attributes::Inline { buf, len } => &buf[..*len], + Attributes::Heap(list) => list, + } + } +} + +impl FromIterator for Attributes { + fn from_iter(iter: I) -> Attributes + where + I: IntoIterator, + { + let mut list = Attributes::new(); + for item in iter { + list.push(item); + } + list + } +} + +impl From> for Attributes { + fn from(list: Vec) -> Attributes { + Attributes::Heap(list) + } +} + +/// The description of an attribute in an abbreviated type. It is a pair of name +/// and form. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct AttributeSpecification { + name: constants::DwAt, + form: constants::DwForm, + implicit_const_value: i64, +} + +impl AttributeSpecification { + /// Construct a new `AttributeSpecification` from the given name and form + /// and implicit const value. + #[inline] + pub fn new( + name: constants::DwAt, + form: constants::DwForm, + implicit_const_value: Option, + ) -> AttributeSpecification { + debug_assert!( + (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some()) + || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none()) + ); + AttributeSpecification { + name, + form, + implicit_const_value: implicit_const_value.unwrap_or(0), + } + } + + /// Get the attribute's name. + #[inline] + pub fn name(&self) -> constants::DwAt { + self.name + } + + /// Get the attribute's form. + #[inline] + pub fn form(&self) -> constants::DwForm { + self.form + } + + /// Get the attribute's implicit const value. + #[inline] + pub fn implicit_const_value(&self) -> Option { + if self.form == constants::DW_FORM_implicit_const { + Some(self.implicit_const_value) + } else { + None + } + } + + /// Return the size of the attribute, in bytes. + /// + /// Note that because some attributes are variably sized, the size cannot + /// always be known without parsing, in which case we return `None`. + pub fn size(&self, header: &UnitHeader) -> Option { + get_attribute_size(self.form, header.encoding()).map(usize::from) + } + + /// Parse an attribute's form. + fn parse_form(input: &mut R) -> Result { + let val = input.read_uleb128_u16()?; + if val == 0 { + Err(Error::AttributeFormZero) + } else { + Ok(constants::DwForm(val)) + } + } + + /// Parse an attribute specification. Returns `None` for the null attribute + /// specification, `Some` for an actual attribute specification. + fn parse(input: &mut R) -> Result> { + let name = input.read_uleb128_u16()?; + if name == 0 { + // Parse the null attribute specification. + let form = input.read_uleb128_u16()?; + return if form == 0 { + Ok(None) + } else { + Err(Error::ExpectedZero) + }; + } + + let name = constants::DwAt(name); + let form = Self::parse_form(input)?; + let implicit_const_value = if form == constants::DW_FORM_implicit_const { + Some(input.read_sleb128()?) + } else { + None + }; + let spec = AttributeSpecification::new(name, form, implicit_const_value); + Ok(Some(spec)) + } +} + +#[inline] +pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option { + match form { + constants::DW_FORM_addr => Some(encoding.address_size), + + constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0), + + constants::DW_FORM_data1 + | constants::DW_FORM_flag + | constants::DW_FORM_strx1 + | constants::DW_FORM_ref1 + | constants::DW_FORM_addrx1 => Some(1), + + constants::DW_FORM_data2 + | constants::DW_FORM_ref2 + | constants::DW_FORM_addrx2 + | constants::DW_FORM_strx2 => Some(2), + + constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3), + + constants::DW_FORM_data4 + | constants::DW_FORM_ref_sup4 + | constants::DW_FORM_ref4 + | constants::DW_FORM_strx4 + | constants::DW_FORM_addrx4 => Some(4), + + constants::DW_FORM_data8 + | constants::DW_FORM_ref8 + | constants::DW_FORM_ref_sig8 + | constants::DW_FORM_ref_sup8 => Some(8), + + constants::DW_FORM_data16 => Some(16), + + constants::DW_FORM_sec_offset + | constants::DW_FORM_GNU_ref_alt + | constants::DW_FORM_strp + | constants::DW_FORM_strp_sup + | constants::DW_FORM_GNU_strp_alt + | constants::DW_FORM_line_strp => Some(encoding.format.word_size()), + + constants::DW_FORM_ref_addr => { + // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr + // has the same size as an address on the target system. This was changed + // in DWARF version 3. + Some(if encoding.version == 2 { + encoding.address_size + } else { + encoding.format.word_size() + }) + } + + // Variably sized forms. + constants::DW_FORM_block + | constants::DW_FORM_block1 + | constants::DW_FORM_block2 + | constants::DW_FORM_block4 + | constants::DW_FORM_exprloc + | constants::DW_FORM_ref_udata + | constants::DW_FORM_string + | constants::DW_FORM_sdata + | constants::DW_FORM_udata + | constants::DW_FORM_indirect => None, + + // We don't know the size of unknown forms. + _ => None, + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use crate::constants; + use crate::endianity::LittleEndian; + use crate::read::{EndianSlice, Error}; + use crate::test_util::GimliSectionMethods; + #[cfg(target_pointer_width = "32")] + use core::u32; + use test_assembler::Section; + + pub trait AbbrevSectionMethods { + fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self; + fn abbrev_null(self) -> Self; + fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self; + fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self; + fn abbrev_attr_null(self) -> Self; + } + + impl AbbrevSectionMethods for Section { + fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self { + self.uleb(code).uleb(tag.0.into()).D8(children.0) + } + + fn abbrev_null(self) -> Self { + self.D8(0) + } + + fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self { + self.uleb(name.0.into()).uleb(form.0.into()) + } + + fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self { + self.uleb(name.0.into()) + .uleb(constants::DW_FORM_implicit_const.0.into()) + .sleb(value) + } + + fn abbrev_attr_null(self) -> Self { + self.D8(0).D8(0) + } + } + + #[test] + fn test_debug_abbrev_ok() { + let extra_start = [1, 2, 3, 4]; + let expected_rest = [5, 6, 7, 8]; + #[rustfmt::skip] + let buf = Section::new() + .append_bytes(&extra_start) + .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) + .abbrev_attr_null() + .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) + .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) + .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) + .abbrev_attr_null() + .abbrev_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + + let abbrev1 = Abbreviation::new( + 1, + constants::DW_TAG_compile_unit, + constants::DW_CHILDREN_yes, + vec![ + AttributeSpecification::new( + constants::DW_AT_producer, + constants::DW_FORM_strp, + None, + ), + AttributeSpecification::new( + constants::DW_AT_language, + constants::DW_FORM_data2, + None, + ), + ] + .into(), + ); + + let abbrev2 = Abbreviation::new( + 2, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_no, + vec![AttributeSpecification::new( + constants::DW_AT_name, + constants::DW_FORM_string, + None, + )] + .into(), + ); + + let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian); + let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len()); + let abbrevs = debug_abbrev + .abbreviations(debug_abbrev_offset) + .expect("Should parse abbreviations"); + assert_eq!(abbrevs.get(1), Some(&abbrev1)); + assert_eq!(abbrevs.get(2), Some(&abbrev2)); + } + + #[test] + fn test_abbreviations_insert() { + fn abbrev(code: u16) -> Abbreviation { + Abbreviation::new( + code.into(), + constants::DwTag(code), + constants::DW_CHILDREN_no, + vec![].into(), + ) + } + + fn assert_abbrev(abbrevs: &Abbreviations, code: u16) { + let abbrev = abbrevs.get(code.into()).unwrap(); + assert_eq!(abbrev.tag(), constants::DwTag(code)); + } + + // Sequential insert. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(1)).unwrap(); + abbrevs.insert(abbrev(2)).unwrap(); + assert_eq!(abbrevs.vec.len(), 2); + assert!(abbrevs.map.is_empty()); + assert_abbrev(&abbrevs, 1); + assert_abbrev(&abbrevs, 2); + + // Out of order insert. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(2)).unwrap(); + abbrevs.insert(abbrev(3)).unwrap(); + assert!(abbrevs.vec.is_empty()); + assert_abbrev(&abbrevs, 2); + assert_abbrev(&abbrevs, 3); + + // Mixed order insert. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(1)).unwrap(); + abbrevs.insert(abbrev(3)).unwrap(); + abbrevs.insert(abbrev(2)).unwrap(); + assert_eq!(abbrevs.vec.len(), 2); + assert_abbrev(&abbrevs, 1); + assert_abbrev(&abbrevs, 2); + assert_abbrev(&abbrevs, 3); + + // Duplicate code in vec. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(1)).unwrap(); + abbrevs.insert(abbrev(2)).unwrap(); + assert_eq!(abbrevs.insert(abbrev(1)), Err(())); + assert_eq!(abbrevs.insert(abbrev(2)), Err(())); + + // Duplicate code in map when adding to map. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(2)).unwrap(); + assert_eq!(abbrevs.insert(abbrev(2)), Err(())); + + // Duplicate code in map when adding to vec. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(2)).unwrap(); + abbrevs.insert(abbrev(1)).unwrap(); + assert_eq!(abbrevs.insert(abbrev(2)), Err(())); + + // 32-bit usize conversions. + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(2)).unwrap(); + } + + #[test] + #[cfg(target_pointer_width = "32")] + fn test_abbreviations_insert_32() { + fn abbrev(code: u64) -> Abbreviation { + Abbreviation::new( + code, + constants::DwTag(code as u16), + constants::DW_CHILDREN_no, + vec![].into(), + ) + } + + fn assert_abbrev(abbrevs: &Abbreviations, code: u64) { + let abbrev = abbrevs.get(code).unwrap(); + assert_eq!(abbrev.tag(), constants::DwTag(code as u16)); + } + + let mut abbrevs = Abbreviations::empty(); + abbrevs.insert(abbrev(1)).unwrap(); + + let wrap_code = (u32::MAX as u64 + 1) + 1; + // `get` should not treat the wrapped code as `1`. + assert_eq!(abbrevs.get(wrap_code), None); + // `insert` should not treat the wrapped code as `1`. + abbrevs.insert(abbrev(wrap_code)).unwrap(); + assert_abbrev(&abbrevs, 1); + assert_abbrev(&abbrevs, wrap_code); + } + + #[test] + fn test_parse_abbreviations_ok() { + let expected_rest = [1, 2, 3, 4]; + #[rustfmt::skip] + let buf = Section::new() + .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) + .abbrev_attr_null() + .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) + .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) + .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) + .abbrev_attr_null() + .abbrev_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let abbrev1 = Abbreviation::new( + 1, + constants::DW_TAG_compile_unit, + constants::DW_CHILDREN_yes, + vec![ + AttributeSpecification::new( + constants::DW_AT_producer, + constants::DW_FORM_strp, + None, + ), + AttributeSpecification::new( + constants::DW_AT_language, + constants::DW_FORM_data2, + None, + ), + ] + .into(), + ); + + let abbrev2 = Abbreviation::new( + 2, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_no, + vec![AttributeSpecification::new( + constants::DW_AT_name, + constants::DW_FORM_string, + None, + )] + .into(), + ); + + let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations"); + assert_eq!(abbrevs.get(1), Some(&abbrev1)); + assert_eq!(abbrevs.get(2), Some(&abbrev2)); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_abbreviations_duplicate() { + let expected_rest = [1, 2, 3, 4]; + #[rustfmt::skip] + let buf = Section::new() + .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) + .abbrev_attr_null() + .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) + .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) + .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) + .abbrev_attr_null() + .abbrev_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match Abbreviations::parse(buf) { + Err(Error::DuplicateAbbreviationCode) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_abbreviation_tag_ok() { + let buf = [0x01, 0x02]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + let tag = Abbreviation::parse_tag(rest).expect("Should parse tag"); + assert_eq!(tag, constants::DW_TAG_array_type); + assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian)); + } + + #[test] + fn test_parse_abbreviation_tag_zero() { + let buf = [0x00]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + match Abbreviation::parse_tag(buf) { + Err(Error::AbbreviationTagZero) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_abbreviation_has_children() { + let buf = [0x00, 0x01, 0x02]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + let val = Abbreviation::parse_has_children(rest).expect("Should parse children"); + assert_eq!(val, constants::DW_CHILDREN_no); + let val = Abbreviation::parse_has_children(rest).expect("Should parse children"); + assert_eq!(val, constants::DW_CHILDREN_yes); + match Abbreviation::parse_has_children(rest) { + Err(Error::BadHasChildren) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_abbreviation_ok() { + let expected_rest = [0x01, 0x02, 0x03, 0x04]; + let buf = Section::new() + .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) + .abbrev_attr_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let expect = Some(Abbreviation::new( + 1, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_no, + vec![AttributeSpecification::new( + constants::DW_AT_name, + constants::DW_FORM_string, + None, + )] + .into(), + )); + + let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation"); + assert_eq!(abbrev, expect); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_abbreviation_implicit_const_ok() { + let expected_rest = [0x01, 0x02, 0x03, 0x04]; + let buf = Section::new() + .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr_implicit_const(constants::DW_AT_name, -42) + .abbrev_attr_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let expect = Some(Abbreviation::new( + 1, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_no, + vec![AttributeSpecification::new( + constants::DW_AT_name, + constants::DW_FORM_implicit_const, + Some(-42), + )] + .into(), + )); + + let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation"); + assert_eq!(abbrev, expect); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_abbreviation_implicit_const_no_const() { + let buf = Section::new() + .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) + .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const) + .get_contents() + .unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match Abbreviation::parse(buf) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_parse_null_abbreviation_ok() { + let expected_rest = [0x01, 0x02, 0x03, 0x04]; + let buf = Section::new() + .abbrev_null() + .append_bytes(&expected_rest) + .get_contents() + .unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation"); + assert!(abbrev.is_none()); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_attribute_form_ok() { + let buf = [0x01, 0x02]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + let tag = AttributeSpecification::parse_form(rest).expect("Should parse form"); + assert_eq!(tag, constants::DW_FORM_addr); + assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian)); + } + + #[test] + fn test_parse_attribute_form_zero() { + let buf = [0x00]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + match AttributeSpecification::parse_form(buf) { + Err(Error::AttributeFormZero) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_null_attribute_specification_ok() { + let buf = [0x00, 0x00, 0x01]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + let attr = + AttributeSpecification::parse(rest).expect("Should parse null attribute specification"); + assert!(attr.is_none()); + assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian)); + } + + #[test] + fn test_parse_attribute_specifications_name_zero() { + let buf = [0x00, 0x01, 0x00, 0x00]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + match AttributeSpecification::parse(buf) { + Err(Error::ExpectedZero) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_attribute_specifications_form_zero() { + let buf = [0x01, 0x00, 0x00, 0x00]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + match AttributeSpecification::parse(buf) { + Err(Error::AttributeFormZero) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_get_abbrev_zero() { + let mut abbrevs = Abbreviations::empty(); + abbrevs + .insert(Abbreviation::new( + 1, + constants::DwTag(1), + constants::DW_CHILDREN_no, + vec![].into(), + )) + .unwrap(); + assert!(abbrevs.get(0).is_none()); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/addr.rs b/anneal/v2/vendor/gimli/src/read/addr.rs new file mode 100644 index 0000000000..5c715dbcfc --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/addr.rs @@ -0,0 +1,353 @@ +use crate::common::{DebugAddrBase, DebugAddrIndex, DebugAddrOffset, Encoding, SectionId}; +use crate::read::{Error, Reader, ReaderOffset, Result, Section}; + +/// The raw contents of the `.debug_addr` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugAddr { + section: R, +} + +impl DebugAddr { + /// Returns the address at the given `base` and `index`. + /// + /// A set of addresses in the `.debug_addr` section consists of a header + /// followed by a series of addresses. + /// + /// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE. + /// This is an offset that points to the first address following the header. + /// + /// The `index` is the value of a `DW_FORM_addrx` attribute. + /// + /// The `address_size` must be the size of the address for the compilation unit. + /// This value must also match the header. However, note that we do not parse the + /// header to validate this, since locating the header is unreliable, and the GNU + /// extensions do not emit it. + pub fn get_address( + &self, + address_size: u8, + base: DebugAddrBase, + index: DebugAddrIndex, + ) -> Result { + let input = &mut self.section.clone(); + input.skip(base.0)?; + input.skip(R::Offset::from_u64( + index.0.into_u64() * u64::from(address_size), + )?)?; + input.read_address(address_size) + } + + /// Iterate the sets of entries in the `.debug_addr` section. + /// + /// Each set of entries belongs to a single unit. + pub fn headers(&self) -> AddrHeaderIter { + AddrHeaderIter { + input: self.section.clone(), + offset: DebugAddrOffset(R::Offset::from_u8(0)), + } + } +} + +impl DebugAddr { + /// Create a `DebugAddr` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugAddr { + fn id() -> SectionId { + SectionId::DebugAddr + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugAddr { + fn from(section: R) -> Self { + DebugAddr { section } + } +} + +/// An iterator over the headers of a `.debug_addr` section. +#[derive(Clone, Debug)] +pub struct AddrHeaderIter { + input: R, + offset: DebugAddrOffset, +} + +impl AddrHeaderIter { + /// Advance the iterator to the next header. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + let len = self.input.len(); + match AddrHeader::parse(&mut self.input, self.offset) { + Ok(header) => { + self.offset.0 += len - self.input.len(); + Ok(Some(header)) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for AddrHeaderIter { + type Item = AddrHeader; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + AddrHeaderIter::next(self) + } +} + +/// A header for a set of entries in the `.debug_addr` section. +/// +/// These entries all belong to a single unit. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AddrHeader::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + offset: DebugAddrOffset, + encoding: Encoding, + length: Offset, + entries: R, +} + +impl AddrHeader +where + R: Reader, + Offset: ReaderOffset, +{ + fn parse(input: &mut R, offset: DebugAddrOffset) -> Result { + let (length, format) = input.read_initial_length()?; + let mut rest = input.split(length)?; + + // Check the version. The DWARF 5 spec says that this is always 5. + let version = rest.read_u16()?; + if version != 5 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + let address_size = rest.read_address_size()?; + let segment_size = rest.read_u8()?; + if segment_size != 0 { + return Err(Error::UnsupportedSegmentSize); + } + + // unit_length + version + address_size + segment_size + let header_length = format.initial_length_size() + 2 + 1 + 1; + + // The first tuple following the header in each set begins at an offset that is + // a multiple of the size of a single tuple (that is, the size of a segment, + // which must be zero, and an address). + let tuple_length = address_size; + if tuple_length == 0 { + return Err(Error::UnsupportedAddressSize(address_size)); + } + let padding = if header_length % tuple_length == 0 { + 0 + } else { + tuple_length - header_length % tuple_length + }; + rest.skip(R::Offset::from_u8(padding))?; + + let encoding = Encoding { + format, + version, + address_size, + }; + Ok(AddrHeader { + offset, + encoding, + length, + entries: rest, + }) + } + + /// Return the offset of this header within the `.debug_addr` section. + #[inline] + pub fn offset(&self) -> DebugAddrOffset { + self.offset + } + + /// Return the length of this set of entries, including the header. + #[inline] + pub fn length(&self) -> Offset { + self.length + } + + /// Return the encoding parameters for this set of entries. + #[inline] + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Return the address entries in this set. + #[inline] + pub fn entries(&self) -> AddrEntryIter { + AddrEntryIter { + input: self.entries.clone(), + encoding: self.encoding, + } + } +} + +/// An iterator over the addresses from a `.debug_addr` section. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Debug, Clone)] +pub struct AddrEntryIter { + input: R, + encoding: Encoding, +} + +impl AddrEntryIter { + /// Advance the iterator and return the next address. + /// + /// Returns the newly parsed address as `Ok(Some(addr))`. Returns `Ok(None)` + /// when iteration is complete and all addresses have already been parsed and + /// yielded. If an error occurs while parsing the next address, then this error + /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`. + pub fn next(&mut self) -> Result> { + if self.input.is_empty() { + return Ok(None); + } + + match self.input.read_address(self.encoding.address_size) { + Ok(entry) => Ok(Some(entry)), + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for AddrEntryIter { + type Item = u64; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + AddrEntryIter::next(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::read::EndianSlice; + use crate::test_util::GimliSectionMethods; + use crate::{Format, LittleEndian}; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_get_address() { + for format in [Format::Dwarf32, Format::Dwarf64] { + for address_size in [4, 8] { + let zero = Label::new(); + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .mark(&zero) + .initial_length(format, &length, &start) + .D16(5) + .D8(address_size) + .D8(0) + .mark(&first); + for i in 0..20 { + section = section.word(address_size, 1000 + i); + } + section = section.mark(&end); + length.set_const((&end - &start) as u64); + + let section = section.get_contents().unwrap(); + let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian)); + let base = DebugAddrBase((&first - &zero) as usize); + + assert_eq!( + debug_addr.get_address(address_size, base, DebugAddrIndex(0)), + Ok(1000) + ); + assert_eq!( + debug_addr.get_address(address_size, base, DebugAddrIndex(19)), + Ok(1019) + ); + } + } + } + + #[test] + fn test_iterator() { + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + // First CU. + let mut section = Section::with_endian(Endian::Little) + .initial_length(Format::Dwarf32, &length, &start) + .D16(5) // Version + .D8(4) // Address size + .D8(0) // Segment size + .word(4, 0x12345678) + .word(4, 0xdeadbeef) + .mark(&end); + length.set_const((&end - &start) as u64); + // Second CU. + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + section = section + .initial_length(Format::Dwarf64, &length, &start) + .D16(5) // Version + .D8(8) // Address size + .D8(0) // Segment size + .word(8, 0x123456789abcdef0) + .word(8, 0xdeadbeefdeadbeef) + .mark(&end); + length.set_const((&end - &start) as u64); + let section = section.get_contents().unwrap(); + let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian)); + let mut iter = debug_addr.headers(); + let first_header = iter.next().unwrap().unwrap(); + let first_encoding = first_header.encoding(); + assert_eq!(first_encoding.address_size, 4); + assert_eq!(first_encoding.format, Format::Dwarf32); + assert_eq!(first_encoding.version, 5); + assert_eq!(first_header.length(), 12); + let mut first_entries = first_header.entries(); + assert_eq!(first_entries.next(), Ok(Some(0x12345678))); + assert_eq!(first_entries.next(), Ok(Some(0xdeadbeef))); + assert_eq!(first_entries.next(), Ok(None)); + let second_header = iter.next().unwrap().unwrap(); + let second_encoding = second_header.encoding(); + assert_eq!(second_encoding.address_size, 8); + assert_eq!(second_encoding.format, Format::Dwarf64); + assert_eq!(second_encoding.version, 5); + assert_eq!(second_header.length(), 20); + let mut second_entries = second_header.entries(); + assert_eq!(second_entries.next(), Ok(Some(0x123456789abcdef0))); + assert_eq!(second_entries.next(), Ok(Some(0xdeadbeefdeadbeef))); + assert_eq!(second_entries.next(), Ok(None)); + assert_eq!(iter.next(), Ok(None)); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/aranges.rs b/anneal/v2/vendor/gimli/src/read/aranges.rs new file mode 100644 index 0000000000..e8cfbf3d3b --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/aranges.rs @@ -0,0 +1,809 @@ +use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId}; +use crate::endianity::Endianity; +use crate::read::{ + EndianSlice, Error, Range, Reader, ReaderAddress, ReaderOffset, Result, Section, +}; + +/// The `DebugAranges` struct represents the DWARF address range information +/// found in the `.debug_aranges` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugAranges { + section: R, +} + +impl<'input, Endian> DebugAranges> +where + Endian: Endianity, +{ + /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_aranges` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugAranges, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_aranges_section = || &buf; + /// let debug_aranges = + /// DebugAranges::new(read_debug_aranges_section(), LittleEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + DebugAranges { + section: EndianSlice::new(section, endian), + } + } +} + +impl DebugAranges { + /// Iterate the sets of entries in the `.debug_aranges` section. + /// + /// Each set of entries belongs to a single unit. + pub fn headers(&self) -> ArangeHeaderIter { + ArangeHeaderIter { + input: self.section.clone(), + offset: DebugArangesOffset(R::Offset::from_u8(0)), + } + } + + /// Get the header at the given offset. + pub fn header(&self, offset: DebugArangesOffset) -> Result> { + let mut input = self.section.clone(); + input.skip(offset.0)?; + ArangeHeader::parse(&mut input, offset) + } +} + +impl DebugAranges { + /// Create a `DebugAranges` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugAranges { + fn id() -> SectionId { + SectionId::DebugAranges + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugAranges { + fn from(section: R) -> Self { + DebugAranges { section } + } +} + +/// An iterator over the headers of a `.debug_aranges` section. +#[derive(Clone, Debug)] +pub struct ArangeHeaderIter { + input: R, + offset: DebugArangesOffset, +} + +impl ArangeHeaderIter { + /// Advance the iterator to the next header. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + let len = self.input.len(); + match ArangeHeader::parse(&mut self.input, self.offset) { + Ok(header) => { + self.offset.0 += len - self.input.len(); + Ok(Some(header)) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for ArangeHeaderIter { + type Item = ArangeHeader; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + ArangeHeaderIter::next(self) + } +} + +/// A header for a set of entries in the `.debug_arange` section. +/// +/// These entries all belong to a single unit. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ArangeHeader::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + offset: DebugArangesOffset, + encoding: Encoding, + length: Offset, + debug_info_offset: DebugInfoOffset, + entries: R, +} + +impl ArangeHeader +where + R: Reader, + Offset: ReaderOffset, +{ + fn parse(input: &mut R, offset: DebugArangesOffset) -> Result { + let (length, format) = input.read_initial_length()?; + let mut rest = input.split(length)?; + + // Check the version. The DWARF 5 spec says that this is always 2, but version 3 + // has been observed in the wild, potentially due to a bug; see + // https://github.com/gimli-rs/gimli/issues/559 for more information. + // lldb allows versions 2 through 5, possibly by mistake. + let version = rest.read_u16()?; + if version != 2 && version != 3 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?; + let address_size = rest.read_address_size()?; + let segment_size = rest.read_u8()?; + if segment_size != 0 { + return Err(Error::UnsupportedSegmentSize); + } + + // unit_length + version + offset + address_size + segment_size + let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1; + + // The first tuple following the header in each set begins at an offset that is + // a multiple of the size of a single tuple (that is, twice the size of an address). + let tuple_length = address_size + .checked_mul(2) + .ok_or(Error::UnsupportedAddressSize(address_size))?; + if tuple_length == 0 { + return Err(Error::UnsupportedAddressSize(address_size)); + } + let padding = if header_length % tuple_length == 0 { + 0 + } else { + tuple_length - header_length % tuple_length + }; + rest.skip(R::Offset::from_u8(padding))?; + + let encoding = Encoding { + format, + version, + address_size, + }; + Ok(ArangeHeader { + offset, + encoding, + length, + debug_info_offset, + entries: rest, + }) + } + + /// Return the offset of this header within the `.debug_aranges` section. + #[inline] + pub fn offset(&self) -> DebugArangesOffset { + self.offset + } + + /// Return the length of this set of entries, including the header. + #[inline] + pub fn length(&self) -> Offset { + self.length + } + + /// Return the encoding parameters for this set of entries. + #[inline] + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Return the offset into the .debug_info section for this set of arange entries. + #[inline] + pub fn debug_info_offset(&self) -> DebugInfoOffset { + self.debug_info_offset + } + + /// Return the arange entries in this set. + #[inline] + pub fn entries(&self) -> ArangeEntryIter { + ArangeEntryIter { + input: self.entries.clone(), + encoding: self.encoding, + } + } +} + +/// An iterator over the aranges from a `.debug_aranges` section. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Debug, Clone)] +pub struct ArangeEntryIter { + input: R, + encoding: Encoding, +} + +impl ArangeEntryIter { + /// Advance the iterator and return the next arange. + /// + /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)` + /// when iteration is complete and all aranges have already been parsed and + /// yielded. If an error occurs while parsing the next arange, then this error + /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`. + pub fn next(&mut self) -> Result> { + loop { + let raw_entry = match self.next_raw()? { + Some(entry) => entry, + None => return Ok(None), + }; + + let entry = self.convert_raw(raw_entry)?; + if entry.is_some() { + return Ok(entry); + } + } + } + + /// Advance the iterator and return the next arange without validating it. + /// + /// The returned entry will have `range.end` set to 0. + /// This will return tombstone entries as well. + pub fn next_raw(&mut self) -> Result> { + if self.input.is_empty() { + return Ok(None); + } + + match ArangeEntry::parse(&mut self.input, self.encoding) { + Ok(Some(entry)) => Ok(Some(entry)), + Ok(None) => { + self.input.empty(); + Ok(None) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } + + /// Convert a raw range into a range. + /// + /// The raw range should have been obtained from `next_raw`. + #[doc(hidden)] + pub fn convert_raw(&self, mut entry: ArangeEntry) -> Result> { + // Skip negative tombstone entries. + // Callers must handle tombstones of 0 or greater themselves + // because we have no way of knowing if they are valid or not. + let address_size = self.encoding.address_size; + if entry.range.begin >= u64::min_tombstone(address_size) { + return Ok(None); + } + + // Calculate end now so that we can handle overflow. + entry.range.end = entry.range.begin.add_sized(entry.length, address_size)?; + Ok(Some(entry)) + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for ArangeEntryIter { + type Item = ArangeEntry; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + ArangeEntryIter::next(self) + } +} + +/// A single parsed arange. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct ArangeEntry { + range: Range, + length: u64, +} + +impl ArangeEntry { + /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange. + fn parse(input: &mut R, encoding: Encoding) -> Result> { + let address_size = encoding.address_size; + + let tuple_length = R::Offset::from_u8(2 * address_size); + if tuple_length > input.len() { + input.empty(); + return Ok(None); + } + + let begin = input.read_address(address_size)?; + let length = input.read_address(address_size)?; + let range = Range { begin, end: 0 }; + + match (begin, length) { + // This is meant to be a null terminator, but in practice it can occur + // before the end, possibly due to a linker omitting a function and + // leaving an unrelocated entry. + (0, 0) => Self::parse(input, encoding), + _ => Ok(Some(ArangeEntry { range, length })), + } + } + + /// Return the beginning address of this arange. + #[inline] + pub fn address(&self) -> u64 { + self.range.begin + } + + /// Return the length of this arange. + #[inline] + pub fn length(&self) -> u64 { + self.length + } + + /// Return the range. + #[inline] + pub fn range(&self) -> Range { + self.range + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::common::{DebugInfoOffset, Format}; + use crate::endianity::LittleEndian; + use crate::read::EndianSlice; + + #[test] + fn test_iterate_headers() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 28. + 0x1c, 0x00, 0x00, 0x00, + // Version. + 0x02, 0x00, + // Offset. + 0x01, 0x02, 0x03, 0x04, + // Address size. + 0x04, + // Segment size. + 0x00, + // Dummy padding and arange tuples. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // 32-bit length = 36. + 0x24, 0x00, 0x00, 0x00, + // Version. + 0x02, 0x00, + // Offset. + 0x11, 0x12, 0x13, 0x14, + // Address size. + 0x04, + // Segment size. + 0x00, + // Dummy padding and arange tuples. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let debug_aranges = DebugAranges::new(&buf, LittleEndian); + let mut headers = debug_aranges.headers(); + + let header = headers + .next() + .expect("should parse header ok") + .expect("should have a header"); + assert_eq!(header.offset(), DebugArangesOffset(0)); + assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201)); + + let header = headers + .next() + .expect("should parse header ok") + .expect("should have a header"); + assert_eq!(header.offset(), DebugArangesOffset(0x20)); + assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211)); + } + + #[test] + fn test_parse_header_ok() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 28 (8 bytes header, 4 bytes padding, 16 bytes tuple data). + 0x1c, 0x00, 0x00, 0x00, + // Version. + 0x02, 0x00, + // Offset. + 0x01, 0x02, 0x03, 0x04, + // Address size. + 0x08, + // Segment size. + 0x00, + // Length to here = 12, tuple length = 16. + // Padding to tuple length multiple = 4. + 0x10, 0x00, 0x00, 0x00, + + // Dummy arange tuple data. + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next arange. + 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let header = + ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok"); + + assert_eq!( + *rest, + EndianSlice::new(&buf[buf.len() - 16..], LittleEndian) + ); + assert_eq!( + header, + ArangeHeader { + offset: DebugArangesOffset(0x10), + encoding: Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 8, + }, + length: 0x1c, + debug_info_offset: DebugInfoOffset(0x0403_0201), + entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian), + } + ); + } + + #[test] + fn test_parse_header_overflow_error() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 32. + 0x20, 0x00, 0x00, 0x00, + // Version. + 0x02, 0x00, + // Offset. + 0x01, 0x02, 0x03, 0x04, + // Address size. + 0xff, + // Segment size. + 0x00, + // Length to here = 12, tuple length = 20. + // Padding to tuple length multiple = 4. + 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy arange tuple data. + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next arange. + 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10)) + .expect_err("should fail to parse header"); + assert_eq!(error, Error::UnsupportedAddressSize(0xff)); + } + + #[test] + fn test_parse_header_div_by_zero_error() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 32. + 0x20, 0x00, 0x00, 0x00, + // Version. + 0x02, 0x00, + // Offset. + 0x01, 0x02, 0x03, 0x04, + // Address size = 0. Could cause a division by zero if we aren't + // careful. + 0x00, + // Segment size. + 0x00, + // Length to here = 12, tuple length = 20. + // Padding to tuple length multiple = 4. + 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy arange tuple data. + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next arange. + 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10)) + .expect_err("should fail to parse header"); + assert_eq!(error, Error::UnsupportedAddressSize(0)); + } + + #[test] + fn test_parse_entry_ok() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 4, + }; + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]; + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next().expect("should parse entry ok"); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0x0403_0201, + end: 0x0403_0201 + 0x0807_0605, + }, + length: 0x0807_0605, + }) + ); + } + + #[test] + fn test_parse_entry_zero() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 4, + }; + #[rustfmt::skip] + let buf = [ + // Zero tuple. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Address. + 0x01, 0x02, 0x03, 0x04, + // Length. + 0x05, 0x06, 0x07, 0x08, + // Next tuple. + 0x09 + ]; + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next().expect("should parse entry ok"); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0x0403_0201, + end: 0x0403_0201 + 0x0807_0605, + }, + length: 0x0807_0605, + }) + ); + } + + #[test] + fn test_parse_entry_overflow_32() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 4, + }; + #[rustfmt::skip] + let buf = [ + // Address. + 0x01, 0x02, 0x03, 0x84, + // Length. + 0x05, 0x06, 0x07, 0x88, + // Next tuple. + 0x09 + ]; + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!(entry, Err(Error::AddressOverflow)); + } + + #[test] + fn test_parse_entry_overflow_64() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 8, + }; + #[rustfmt::skip] + let buf = [ + // Address. + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x80, + // Length. + 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x80, + // Next tuple. + 0x09 + ]; + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!(entry, Err(Error::AddressOverflow)); + } + + #[test] + fn test_parse_entry_tombstone_32() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 4, + }; + #[rustfmt::skip] + let buf = [ + // Address. + 0xff, 0xff, 0xff, 0xff, + // Length. + 0x05, 0x06, 0x07, 0x08, + // Address. + 0x01, 0x02, 0x03, 0x04, + // Length. + 0x05, 0x06, 0x07, 0x08, + // Next tuple. + 0x09 + ]; + + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next_raw().unwrap(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 9..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0xffff_ffff, + end: 0, + }, + length: 0x0807_0605, + }) + ); + + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next().unwrap(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0x0403_0201, + end: 0x0403_0201 + 0x0807_0605, + }, + length: 0x0807_0605, + }) + ); + } + + #[test] + fn test_parse_entry_tombstone_64() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 8, + }; + #[rustfmt::skip] + let buf = [ + // Address. + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + // Length. + 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, + // Address. + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + // Length. + 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, + // Next tuple. + 0x09 + ]; + + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next_raw().unwrap(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 17..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0xffff_ffff_ffff_ffff, + end: 0, + }, + length: 0x0807_0605, + }) + ); + + let mut iter = ArangeEntryIter { + input: EndianSlice::new(&buf, LittleEndian), + encoding, + }; + let entry = iter.next().unwrap(); + assert_eq!( + iter.input, + EndianSlice::new(&buf[buf.len() - 1..], LittleEndian) + ); + assert_eq!( + entry, + Some(ArangeEntry { + range: Range { + begin: 0x0403_0201, + end: 0x0403_0201 + 0x0807_0605, + }, + length: 0x0807_0605, + }) + ); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/cfi.rs b/anneal/v2/vendor/gimli/src/read/cfi.rs new file mode 100644 index 0000000000..2c865c41c6 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/cfi.rs @@ -0,0 +1,7951 @@ +#[cfg(feature = "read")] +use alloc::boxed::Box; + +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::mem; +use core::num::Wrapping; + +use super::util::{ArrayLike, ArrayVec}; +use crate::common::{ + DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId, Vendor, +}; +use crate::constants::{self, DwEhPe}; +use crate::endianity::Endianity; +use crate::read::{ + EndianSlice, Error, Expression, Reader, ReaderAddress, ReaderOffset, Result, Section, + StoreOnHeap, +}; + +/// `DebugFrame` contains the `.debug_frame` section's frame unwinding +/// information required to unwind to and recover registers from older frames on +/// the stack. For example, this is useful for a debugger that wants to print +/// locals in a backtrace. +/// +/// Most interesting methods are defined in the +/// [`UnwindSection`](trait.UnwindSection.html) trait. +/// +/// ### Differences between `.debug_frame` and `.eh_frame` +/// +/// While the `.debug_frame` section's information has a lot of overlap with the +/// `.eh_frame` section's information, the `.eh_frame` information tends to only +/// encode the subset of information needed for exception handling. Often, only +/// one of `.eh_frame` or `.debug_frame` will be present in an object file. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct DebugFrame { + section: R, + address_size: u8, + vendor: Vendor, +} + +impl DebugFrame { + /// Set the size of a target address in bytes. + /// + /// This defaults to the native word size. + /// This is only used if the CIE version is less than 4. + pub fn set_address_size(&mut self, address_size: u8) { + self.address_size = address_size + } + + /// Set the vendor extensions to use. + /// + /// This defaults to `Vendor::Default`. + pub fn set_vendor(&mut self, vendor: Vendor) { + self.vendor = vendor; + } +} + +impl<'input, Endian> DebugFrame> +where + Endian: Endianity, +{ + /// Construct a new `DebugFrame` instance from the data in the + /// `.debug_frame` section. + /// + /// It is the caller's responsibility to read the section and present it as + /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O + /// loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugFrame, NativeEndian}; + /// + /// // Use with `.debug_frame` + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_frame_section_somehow = || &buf; + /// let debug_frame = DebugFrame::new(read_debug_frame_section_somehow(), NativeEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl Section for DebugFrame { + fn id() -> SectionId { + SectionId::DebugFrame + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugFrame { + fn from(section: R) -> Self { + // Default to native word size. + DebugFrame { + section, + address_size: mem::size_of::() as u8, + vendor: Vendor::Default, + } + } +} + +/// `EhFrameHdr` contains the information about the `.eh_frame_hdr` section. +/// +/// A pointer to the start of the `.eh_frame` data, and optionally, a binary +/// search table of pointers to the `.eh_frame` records that are found in this section. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct EhFrameHdr(R); + +/// `ParsedEhFrameHdr` contains the parsed information from the `.eh_frame_hdr` section. +#[derive(Clone, Debug)] +pub struct ParsedEhFrameHdr { + address_size: u8, + section: R, + + eh_frame_ptr: Pointer, + fde_count: u64, + table_enc: DwEhPe, + table: R, +} + +impl<'input, Endian> EhFrameHdr> +where + Endian: Endianity, +{ + /// Constructs a new `EhFrameHdr` instance from the data in the `.eh_frame_hdr` section. + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl EhFrameHdr { + /// Parses this `EhFrameHdr` to a `ParsedEhFrameHdr`. + pub fn parse(&self, bases: &BaseAddresses, address_size: u8) -> Result> { + let mut reader = self.0.clone(); + let version = reader.read_u8()?; + if version != 1 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + let eh_frame_ptr_enc = parse_pointer_encoding(&mut reader)?; + let fde_count_enc = parse_pointer_encoding(&mut reader)?; + let table_enc = parse_pointer_encoding(&mut reader)?; + + let parameters = PointerEncodingParameters { + bases: &bases.eh_frame_hdr, + func_base: None, + address_size, + section: &self.0, + }; + + // Omitting this pointer is not valid (defeats the purpose of .eh_frame_hdr entirely) + if eh_frame_ptr_enc == constants::DW_EH_PE_omit { + return Err(Error::CannotParseOmitPointerEncoding); + } + let eh_frame_ptr = parse_encoded_pointer(eh_frame_ptr_enc, ¶meters, &mut reader)?; + + let fde_count; + if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit { + fde_count = 0 + } else { + if fde_count_enc != fde_count_enc.format() { + return Err(Error::UnsupportedPointerEncoding); + } + fde_count = parse_encoded_value(fde_count_enc, ¶meters, &mut reader)?; + } + + Ok(ParsedEhFrameHdr { + address_size, + section: self.0.clone(), + + eh_frame_ptr, + fde_count, + table_enc, + table: reader, + }) + } +} + +impl Section for EhFrameHdr { + fn id() -> SectionId { + SectionId::EhFrameHdr + } + + fn reader(&self) -> &R { + &self.0 + } +} + +impl From for EhFrameHdr { + fn from(section: R) -> Self { + EhFrameHdr(section) + } +} + +impl ParsedEhFrameHdr { + /// Returns the address of the binary's `.eh_frame` section. + pub fn eh_frame_ptr(&self) -> Pointer { + self.eh_frame_ptr + } + + /// Retrieves the CFI binary search table, if there is one. + pub fn table(&self) -> Option> { + // There are two big edge cases here: + // * You search the table for an invalid address. As this is just a binary + // search table, we always have to return a valid result for that (unless + // you specify an address that is lower than the first address in the + // table). Since this means that you have to recheck that the FDE contains + // your address anyways, we just return the first FDE even when the address + // is too low. After all, we're just doing a normal binary search. + // * This falls apart when the table is empty - there is no entry we could + // return. We conclude that an empty table is not really a table at all. + if self.fde_count == 0 { + None + } else { + Some(EhHdrTable { hdr: self }) + } + } +} + +/// An iterator for `.eh_frame_hdr` section's binary search table. +/// +/// Each table entry consists of a tuple containing an `initial_location` and `address`. +/// The `initial location` represents the first address that the targeted FDE +/// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section. +/// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE. +#[derive(Debug)] +pub struct EhHdrTableIter<'a, 'bases, R: Reader> { + hdr: &'a ParsedEhFrameHdr, + table: R, + bases: &'bases BaseAddresses, + remain: u64, +} + +impl<'a, 'bases, R: Reader> EhHdrTableIter<'a, 'bases, R> { + /// Yield the next entry in the `EhHdrTableIter`. + pub fn next(&mut self) -> Result> { + if self.remain == 0 { + return Ok(None); + } + + let parameters = PointerEncodingParameters { + bases: &self.bases.eh_frame_hdr, + func_base: None, + address_size: self.hdr.address_size, + section: &self.hdr.section, + }; + + self.remain -= 1; + let from = parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut self.table)?; + let to = parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut self.table)?; + Ok(Some((from, to))) + } + /// Yield the nth entry in the `EhHdrTableIter` + pub fn nth(&mut self, n: usize) -> Result> { + use core::convert::TryFrom; + let size = match self.hdr.table_enc.format() { + constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => { + return Err(Error::VariableLengthSearchTable); + } + constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2, + constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4, + constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8, + _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)), + }; + + let row_size = size * 2; + let n = u64::try_from(n).map_err(|_| Error::UnsupportedOffset)?; + self.remain = self.remain.saturating_sub(n); + self.table.skip(R::Offset::from_u64(n * row_size)?)?; + self.next() + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'a, 'bases, R: Reader> fallible_iterator::FallibleIterator for EhHdrTableIter<'a, 'bases, R> { + type Item = (Pointer, Pointer); + type Error = Error; + fn next(&mut self) -> Result> { + EhHdrTableIter::next(self) + } + + fn size_hint(&self) -> (usize, Option) { + use core::convert::TryInto; + ( + self.remain.try_into().unwrap_or(0), + self.remain.try_into().ok(), + ) + } + + fn nth(&mut self, n: usize) -> Result> { + EhHdrTableIter::nth(self, n) + } +} + +/// The CFI binary search table that is an optional part of the `.eh_frame_hdr` section. +#[derive(Debug, Clone)] +pub struct EhHdrTable<'a, R: Reader> { + hdr: &'a ParsedEhFrameHdr, +} + +impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { + /// Return an iterator that can walk the `.eh_frame_hdr` table. + /// + /// Each table entry consists of a tuple containing an `initial_location` and `address`. + /// The `initial location` represents the first address that the targeted FDE + /// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section. + /// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE. + pub fn iter<'bases>(&self, bases: &'bases BaseAddresses) -> EhHdrTableIter<'_, 'bases, R> { + EhHdrTableIter { + hdr: self.hdr, + bases, + remain: self.hdr.fde_count, + table: self.hdr.table.clone(), + } + } + /// *Probably* returns a pointer to the FDE for the given address. + /// + /// This performs a binary search, so if there is no FDE for the given address, + /// this function **will** return a pointer to any other FDE that's close by. + /// + /// To be sure, you **must** call `contains` on the FDE. + pub fn lookup(&self, address: u64, bases: &BaseAddresses) -> Result { + let size = match self.hdr.table_enc.format() { + constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => { + return Err(Error::VariableLengthSearchTable); + } + constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2, + constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4, + constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8, + _ => return Err(Error::UnknownPointerEncoding(self.hdr.table_enc)), + }; + + let row_size = size * 2; + + let mut len = self.hdr.fde_count; + + let mut reader = self.hdr.table.clone(); + + let parameters = PointerEncodingParameters { + bases: &bases.eh_frame_hdr, + func_base: None, + address_size: self.hdr.address_size, + section: &self.hdr.section, + }; + + while len > 1 { + let head = reader.split(R::Offset::from_u64((len / 2) * row_size)?)?; + let tail = reader.clone(); + + let pivot = + parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut reader)?.direct()?; + + match pivot.cmp(&address) { + Ordering::Equal => { + reader = tail; + break; + } + Ordering::Less => { + reader = tail; + len = len - (len / 2); + } + Ordering::Greater => { + reader = head; + len /= 2; + } + } + } + + reader.skip(R::Offset::from_u64(size)?)?; + + parse_encoded_pointer(self.hdr.table_enc, ¶meters, &mut reader) + } + + /// Convert a `Pointer` to a section offset. + /// + /// This does not support indirect pointers. + pub fn pointer_to_offset(&self, ptr: Pointer) -> Result> { + let ptr = ptr.direct()?; + let eh_frame_ptr = self.hdr.eh_frame_ptr().direct()?; + + // Calculate the offset in the EhFrame section + R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset) + } + + /// Returns a parsed FDE for the given address, or `NoUnwindInfoForAddress` + /// if there are none. + /// + /// You must provide a function to get its associated CIE. See + /// `PartialFrameDescriptionEntry::parse` for more information. + /// + /// # Example + /// + /// ``` + /// # use gimli::{BaseAddresses, EhFrame, ParsedEhFrameHdr, EndianSlice, NativeEndian, Error, UnwindSection}; + /// # fn foo() -> Result<(), Error> { + /// # let eh_frame: EhFrame> = unreachable!(); + /// # let eh_frame_hdr: ParsedEhFrameHdr> = unimplemented!(); + /// # let addr = 0; + /// # let bases = unimplemented!(); + /// let table = eh_frame_hdr.table().unwrap(); + /// let fde = table.fde_for_address(&eh_frame, &bases, addr, EhFrame::cie_from_offset)?; + /// # Ok(()) + /// # } + /// ``` + pub fn fde_for_address( + &self, + frame: &EhFrame, + bases: &BaseAddresses, + address: u64, + get_cie: F, + ) -> Result> + where + F: FnMut( + &EhFrame, + &BaseAddresses, + EhFrameOffset, + ) -> Result>, + { + let fdeptr = self.lookup(address, bases)?; + let offset = self.pointer_to_offset(fdeptr)?; + let entry = frame.fde_from_offset(bases, offset, get_cie)?; + if entry.contains(address) { + Ok(entry) + } else { + Err(Error::NoUnwindInfoForAddress) + } + } + + #[inline] + #[doc(hidden)] + #[deprecated(note = "Method renamed to fde_for_address; use that instead.")] + pub fn lookup_and_parse( + &self, + address: u64, + bases: &BaseAddresses, + frame: EhFrame, + get_cie: F, + ) -> Result> + where + F: FnMut( + &EhFrame, + &BaseAddresses, + EhFrameOffset, + ) -> Result>, + { + self.fde_for_address(&frame, bases, address, get_cie) + } + + /// Returns the frame unwind information for the given address, + /// or `NoUnwindInfoForAddress` if there are none. + /// + /// You must provide a function to get the associated CIE. See + /// `PartialFrameDescriptionEntry::parse` for more information. + pub fn unwind_info_for_address<'ctx, F, S>( + &self, + frame: &EhFrame, + bases: &BaseAddresses, + ctx: &'ctx mut UnwindContext, + address: u64, + get_cie: F, + ) -> Result<&'ctx UnwindTableRow> + where + F: FnMut( + &EhFrame, + &BaseAddresses, + EhFrameOffset, + ) -> Result>, + S: UnwindContextStorage, + { + let fde = self.fde_for_address(frame, bases, address, get_cie)?; + fde.unwind_info_for_address(frame, bases, ctx, address) + } +} + +/// `EhFrame` contains the frame unwinding information needed during exception +/// handling found in the `.eh_frame` section. +/// +/// Most interesting methods are defined in the +/// [`UnwindSection`](trait.UnwindSection.html) trait. +/// +/// See +/// [`DebugFrame`](./struct.DebugFrame.html#differences-between-debug_frame-and-eh_frame) +/// for some discussion on the differences between `.debug_frame` and +/// `.eh_frame`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct EhFrame { + section: R, + address_size: u8, + vendor: Vendor, +} + +impl EhFrame { + /// Set the size of a target address in bytes. + /// + /// This defaults to the native word size. + pub fn set_address_size(&mut self, address_size: u8) { + self.address_size = address_size + } + + /// Set the vendor extensions to use. + /// + /// This defaults to `Vendor::Default`. + pub fn set_vendor(&mut self, vendor: Vendor) { + self.vendor = vendor; + } +} + +impl<'input, Endian> EhFrame> +where + Endian: Endianity, +{ + /// Construct a new `EhFrame` instance from the data in the + /// `.eh_frame` section. + /// + /// It is the caller's responsibility to read the section and present it as + /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O + /// loader on macOS, etc. + /// + /// ``` + /// use gimli::{EhFrame, EndianSlice, NativeEndian}; + /// + /// // Use with `.eh_frame` + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_eh_frame_section_somehow = || &buf; + /// let eh_frame = EhFrame::new(read_eh_frame_section_somehow(), NativeEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl Section for EhFrame { + fn id() -> SectionId { + SectionId::EhFrame + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for EhFrame { + fn from(section: R) -> Self { + // Default to native word size. + EhFrame { + section, + address_size: mem::size_of::() as u8, + vendor: Vendor::Default, + } + } +} + +// This has to be `pub` to silence a warning (that is deny(..)'d by default) in +// rustc. Eventually, not having this `pub` will become a hard error. +#[doc(hidden)] +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CieOffsetEncoding { + U32, + U64, +} + +/// An offset into an `UnwindSection`. +// +// Needed to avoid conflicting implementations of `Into`. +pub trait UnwindOffset: Copy + Debug + Eq + From +where + T: ReaderOffset, +{ + /// Convert an `UnwindOffset` into a `T`. + fn into(self) -> T; +} + +impl UnwindOffset for DebugFrameOffset +where + T: ReaderOffset, +{ + #[inline] + fn into(self) -> T { + self.0 + } +} + +impl UnwindOffset for EhFrameOffset +where + T: ReaderOffset, +{ + #[inline] + fn into(self) -> T { + self.0 + } +} + +/// This trait completely encapsulates everything that is different between +/// `.eh_frame` and `.debug_frame`, as well as all the bits that can change +/// between DWARF versions. +#[doc(hidden)] +pub trait _UnwindSectionPrivate { + /// Get the underlying section data. + fn section(&self) -> &R; + + /// Returns true if the section allows a zero terminator. + fn has_zero_terminator() -> bool; + + /// Return true if the given offset if the CIE sentinel, false otherwise. + fn is_cie(format: Format, id: u64) -> bool; + + /// Return the CIE offset/ID encoding used by this unwind section with the + /// given DWARF format. + fn cie_offset_encoding(format: Format) -> CieOffsetEncoding; + + /// For `.eh_frame`, CIE offsets are relative to the current position. For + /// `.debug_frame`, they are relative to the start of the section. We always + /// internally store them relative to the section, so we handle translating + /// `.eh_frame`'s relative offsets in this method. If the offset calculation + /// underflows, return `None`. + fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option; + + /// Does this version of this unwind section encode address and segment + /// sizes in its CIEs? + fn has_address_and_segment_sizes(version: u8) -> bool; + + /// The address size to use if `has_address_and_segment_sizes` returns false. + fn address_size(&self) -> u8; + + /// The vendor extensions to use. + fn vendor(&self) -> Vendor; +} + +/// A section holding unwind information: either `.debug_frame` or +/// `.eh_frame`. See [`DebugFrame`](./struct.DebugFrame.html) and +/// [`EhFrame`](./struct.EhFrame.html) respectively. +pub trait UnwindSection: Clone + Debug + _UnwindSectionPrivate { + /// The offset type associated with this CFI section. Either + /// `DebugFrameOffset` or `EhFrameOffset`. + type Offset: UnwindOffset; + + /// Iterate over the `CommonInformationEntry`s and `FrameDescriptionEntry`s + /// in this `.debug_frame` section. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + fn entries<'bases>(&self, bases: &'bases BaseAddresses) -> CfiEntriesIter<'bases, Self, R> { + CfiEntriesIter { + section: self.clone(), + bases, + input: self.section().clone(), + } + } + + /// Parse the `CommonInformationEntry` at the given offset. + fn cie_from_offset( + &self, + bases: &BaseAddresses, + offset: Self::Offset, + ) -> Result> { + let offset = UnwindOffset::into(offset); + let input = &mut self.section().clone(); + input.skip(offset)?; + CommonInformationEntry::parse(bases, self, input) + } + + /// Parse the `PartialFrameDescriptionEntry` at the given offset. + fn partial_fde_from_offset<'bases>( + &self, + bases: &'bases BaseAddresses, + offset: Self::Offset, + ) -> Result> { + let offset = UnwindOffset::into(offset); + let input = &mut self.section().clone(); + input.skip(offset)?; + PartialFrameDescriptionEntry::parse_partial(self, bases, input) + } + + /// Parse the `FrameDescriptionEntry` at the given offset. + fn fde_from_offset( + &self, + bases: &BaseAddresses, + offset: Self::Offset, + get_cie: F, + ) -> Result> + where + F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result>, + { + let partial = self.partial_fde_from_offset(bases, offset)?; + partial.parse(get_cie) + } + + /// Find the `FrameDescriptionEntry` for the given address. + /// + /// If found, the FDE is returned. If not found, + /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. + /// If parsing fails, the error is returned. + /// + /// You must provide a function to get its associated CIE. See + /// `PartialFrameDescriptionEntry::parse` for more information. + /// + /// Note: this iterates over all FDEs. If available, it is possible + /// to do a binary search with `EhFrameHdr::fde_for_address` instead. + fn fde_for_address( + &self, + bases: &BaseAddresses, + address: u64, + mut get_cie: F, + ) -> Result> + where + F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result>, + { + let mut entries = self.entries(bases); + while let Some(entry) = entries.next()? { + match entry { + CieOrFde::Cie(_) => {} + CieOrFde::Fde(partial) => { + let fde = partial.parse(&mut get_cie)?; + if fde.contains(address) { + return Ok(fde); + } + } + } + } + Err(Error::NoUnwindInfoForAddress) + } + + /// Find the frame unwind information for the given address. + /// + /// If found, the unwind information is returned. If not found, + /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or + /// CFI evaluation fails, the error is returned. + /// + /// ``` + /// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindContext, + /// UnwindSection}; + /// + /// # fn foo() -> gimli::Result<()> { + /// # let read_eh_frame_section = || unimplemented!(); + /// // Get the `.eh_frame` section from the object file. Alternatively, + /// // use `EhFrame` with the `.eh_frame` section of the object file. + /// let eh_frame = EhFrame::new(read_eh_frame_section(), NativeEndian); + /// + /// # let get_frame_pc = || unimplemented!(); + /// // Get the address of the PC for a frame you'd like to unwind. + /// let address = get_frame_pc(); + /// + /// // This context is reusable, which cuts down on heap allocations. + /// let ctx = UnwindContext::new(); + /// + /// // Optionally provide base addresses for any relative pointers. If a + /// // base address isn't provided and a pointer is found that is relative to + /// // it, we will return an `Err`. + /// # let address_of_text_section_in_memory = unimplemented!(); + /// # let address_of_got_section_in_memory = unimplemented!(); + /// let bases = BaseAddresses::default() + /// .set_text(address_of_text_section_in_memory) + /// .set_got(address_of_got_section_in_memory); + /// + /// let unwind_info = eh_frame.unwind_info_for_address( + /// &bases, + /// &mut ctx, + /// address, + /// EhFrame::cie_from_offset, + /// )?; + /// + /// # let do_stuff_with = |_| unimplemented!(); + /// do_stuff_with(unwind_info); + /// # let _ = ctx; + /// # unreachable!() + /// # } + /// ``` + #[inline] + fn unwind_info_for_address<'ctx, F, S>( + &self, + bases: &BaseAddresses, + ctx: &'ctx mut UnwindContext, + address: u64, + get_cie: F, + ) -> Result<&'ctx UnwindTableRow> + where + F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result>, + S: UnwindContextStorage, + { + let fde = self.fde_for_address(bases, address, get_cie)?; + fde.unwind_info_for_address(self, bases, ctx, address) + } +} + +impl _UnwindSectionPrivate for DebugFrame { + fn section(&self) -> &R { + &self.section + } + + fn has_zero_terminator() -> bool { + false + } + + fn is_cie(format: Format, id: u64) -> bool { + match format { + Format::Dwarf32 => id == 0xffff_ffff, + Format::Dwarf64 => id == 0xffff_ffff_ffff_ffff, + } + } + + fn cie_offset_encoding(format: Format) -> CieOffsetEncoding { + match format { + Format::Dwarf32 => CieOffsetEncoding::U32, + Format::Dwarf64 => CieOffsetEncoding::U64, + } + } + + fn resolve_cie_offset(&self, _: R::Offset, offset: R::Offset) -> Option { + Some(offset) + } + + fn has_address_and_segment_sizes(version: u8) -> bool { + version == 4 + } + + fn address_size(&self) -> u8 { + self.address_size + } + + fn vendor(&self) -> Vendor { + self.vendor + } +} + +impl UnwindSection for DebugFrame { + type Offset = DebugFrameOffset; +} + +impl _UnwindSectionPrivate for EhFrame { + fn section(&self) -> &R { + &self.section + } + + fn has_zero_terminator() -> bool { + true + } + + fn is_cie(_: Format, id: u64) -> bool { + id == 0 + } + + fn cie_offset_encoding(_format: Format) -> CieOffsetEncoding { + // `.eh_frame` offsets are always 4 bytes, regardless of the DWARF + // format. + CieOffsetEncoding::U32 + } + + fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option { + base.checked_sub(offset) + } + + fn has_address_and_segment_sizes(_version: u8) -> bool { + false + } + + fn address_size(&self) -> u8 { + self.address_size + } + + fn vendor(&self) -> Vendor { + self.vendor + } +} + +impl UnwindSection for EhFrame { + type Offset = EhFrameOffset; +} + +/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers. +/// +/// During CIE/FDE parsing, if a relative pointer is encountered for a base +/// address that is unknown, an Err will be returned. +/// +/// ``` +/// use gimli::BaseAddresses; +/// +/// # fn foo() { +/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!(); +/// # let address_of_eh_frame_section_in_memory = unimplemented!(); +/// # let address_of_text_section_in_memory = unimplemented!(); +/// # let address_of_got_section_in_memory = unimplemented!(); +/// # let address_of_the_start_of_current_func = unimplemented!(); +/// let bases = BaseAddresses::default() +/// .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory) +/// .set_eh_frame(address_of_eh_frame_section_in_memory) +/// .set_text(address_of_text_section_in_memory) +/// .set_got(address_of_got_section_in_memory); +/// # let _ = bases; +/// # } +/// ``` +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub struct BaseAddresses { + /// The base addresses to use for pointers in the `.eh_frame_hdr` section. + pub eh_frame_hdr: SectionBaseAddresses, + + /// The base addresses to use for pointers in the `.eh_frame` section. + pub eh_frame: SectionBaseAddresses, +} + +/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers +/// in a particular section. +/// +/// See `BaseAddresses` for methods that are helpful in setting these addresses. +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub struct SectionBaseAddresses { + /// The address of the section containing the pointer. + pub section: Option, + + /// The base address for text relative pointers. + /// This is generally the address of the `.text` section. + pub text: Option, + + /// The base address for data relative pointers. + /// + /// For pointers in the `.eh_frame_hdr` section, this is the address + /// of the `.eh_frame_hdr` section + /// + /// For pointers in the `.eh_frame` section, this is generally the + /// global pointer, such as the address of the `.got` section. + pub data: Option, +} + +impl BaseAddresses { + /// Set the `.eh_frame_hdr` section base address. + #[inline] + pub fn set_eh_frame_hdr(mut self, addr: u64) -> Self { + self.eh_frame_hdr.section = Some(addr); + self.eh_frame_hdr.data = Some(addr); + self + } + + /// Set the `.eh_frame` section base address. + #[inline] + pub fn set_eh_frame(mut self, addr: u64) -> Self { + self.eh_frame.section = Some(addr); + self + } + + /// Set the `.text` section base address. + #[inline] + pub fn set_text(mut self, addr: u64) -> Self { + self.eh_frame_hdr.text = Some(addr); + self.eh_frame.text = Some(addr); + self + } + + /// Set the `.got` section base address. + #[inline] + pub fn set_got(mut self, addr: u64) -> Self { + self.eh_frame.data = Some(addr); + self + } +} + +/// An iterator over CIE and FDE entries in a `.debug_frame` or `.eh_frame` +/// section. +/// +/// Some pointers may be encoded relative to various base addresses. Use the +/// [`BaseAddresses`](./struct.BaseAddresses.html) parameter to provide them. By +/// default, none are provided. If a relative pointer is encountered for a base +/// address that is unknown, an `Err` will be returned and iteration will abort. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +/// +/// ``` +/// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindSection}; +/// +/// # fn foo() -> gimli::Result<()> { +/// # let read_eh_frame_somehow = || unimplemented!(); +/// let eh_frame = EhFrame::new(read_eh_frame_somehow(), NativeEndian); +/// +/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!(); +/// # let address_of_eh_frame_section_in_memory = unimplemented!(); +/// # let address_of_text_section_in_memory = unimplemented!(); +/// # let address_of_got_section_in_memory = unimplemented!(); +/// # let address_of_the_start_of_current_func = unimplemented!(); +/// // Provide base addresses for relative pointers. +/// let bases = BaseAddresses::default() +/// .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory) +/// .set_eh_frame(address_of_eh_frame_section_in_memory) +/// .set_text(address_of_text_section_in_memory) +/// .set_got(address_of_got_section_in_memory); +/// +/// let mut entries = eh_frame.entries(&bases); +/// +/// # let do_stuff_with = |_| unimplemented!(); +/// while let Some(entry) = entries.next()? { +/// do_stuff_with(entry) +/// } +/// # unreachable!() +/// # } +/// ``` +#[derive(Clone, Debug)] +pub struct CfiEntriesIter<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + section: Section, + bases: &'bases BaseAddresses, + input: R, +} + +impl<'bases, Section, R> CfiEntriesIter<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + /// Advance the iterator to the next entry. + pub fn next(&mut self) -> Result>> { + loop { + if self.input.is_empty() { + return Ok(None); + } + + match parse_cfi_entry(self.bases, &self.section, &mut self.input) { + Ok(Some(entry)) => return Ok(Some(entry)), + Err(e) => { + self.input.empty(); + return Err(e); + } + Ok(None) => { + if Section::has_zero_terminator() { + self.input.empty(); + return Ok(None); + } + + // Hack: If we get to here, then we're reading `.debug_frame` and + // encountered a length of 0. This is a compiler or linker bug + // (originally seen for NASM, fixed in 2.15rc9). + // Skip this value and try again. + continue; + } + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'bases, Section, R> fallible_iterator::FallibleIterator for CfiEntriesIter<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + type Item = CieOrFde<'bases, Section, R>; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + CfiEntriesIter::next(self) + } +} + +/// Either a `CommonInformationEntry` (CIE) or a `FrameDescriptionEntry` (FDE). +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CieOrFde<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + /// This CFI entry is a `CommonInformationEntry`. + Cie(CommonInformationEntry), + /// This CFI entry is a `FrameDescriptionEntry`, however fully parsing it + /// requires parsing its CIE first, so it is left in a partially parsed + /// state. + Fde(PartialFrameDescriptionEntry<'bases, Section, R>), +} + +fn parse_cfi_entry<'bases, Section, R>( + bases: &'bases BaseAddresses, + section: &Section, + input: &mut R, +) -> Result>> +where + R: Reader, + Section: UnwindSection, +{ + let offset = input.offset_from(section.section()); + let (length, format) = input.read_initial_length()?; + if length.into_u64() == 0 { + return Ok(None); + } + + let mut rest = input.split(length)?; + let cie_offset_base = rest.offset_from(section.section()); + let cie_id_or_offset = match Section::cie_offset_encoding(format) { + CieOffsetEncoding::U32 => rest.read_u32().map(u64::from)?, + CieOffsetEncoding::U64 => rest.read_u64()?, + }; + + if Section::is_cie(format, cie_id_or_offset) { + let cie = CommonInformationEntry::parse_rest(offset, length, format, bases, section, rest)?; + Ok(Some(CieOrFde::Cie(cie))) + } else { + let cie_offset = R::Offset::from_u64(cie_id_or_offset)?; + let cie_offset = match section.resolve_cie_offset(cie_offset_base, cie_offset) { + None => return Err(Error::OffsetOutOfBounds), + Some(cie_offset) => cie_offset, + }; + + let fde = PartialFrameDescriptionEntry { + offset, + length, + format, + cie_offset: cie_offset.into(), + rest, + section: section.clone(), + bases, + }; + + Ok(Some(CieOrFde::Fde(fde))) + } +} + +/// We support the z-style augmentation [defined by `.eh_frame`][ehframe]. +/// +/// [ehframe]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct Augmentation { + /// > A 'L' may be present at any position after the first character of the + /// > string. This character may only be present if 'z' is the first character + /// > of the string. If present, it indicates the presence of one argument in + /// > the Augmentation Data of the CIE, and a corresponding argument in the + /// > Augmentation Data of the FDE. The argument in the Augmentation Data of + /// > the CIE is 1-byte and represents the pointer encoding used for the + /// > argument in the Augmentation Data of the FDE, which is the address of a + /// > language-specific data area (LSDA). The size of the LSDA pointer is + /// > specified by the pointer encoding used. + lsda: Option, + + /// > A 'P' may be present at any position after the first character of the + /// > string. This character may only be present if 'z' is the first character + /// > of the string. If present, it indicates the presence of two arguments in + /// > the Augmentation Data of the CIE. The first argument is 1-byte and + /// > represents the pointer encoding used for the second argument, which is + /// > the address of a personality routine handler. The size of the + /// > personality routine pointer is specified by the pointer encoding used. + personality: Option<(constants::DwEhPe, Pointer)>, + + /// > A 'R' may be present at any position after the first character of the + /// > string. This character may only be present if 'z' is the first character + /// > of the string. If present, The Augmentation Data shall include a 1 byte + /// > argument that represents the pointer encoding for the address pointers + /// > used in the FDE. + fde_address_encoding: Option, + + /// True if this CIE's FDEs are trampolines for signal handlers. + is_signal_trampoline: bool, +} + +impl Augmentation { + fn parse( + augmentation_str: &mut R, + bases: &BaseAddresses, + address_size: u8, + section: &Section, + input: &mut R, + ) -> Result + where + R: Reader, + Section: UnwindSection, + { + debug_assert!( + !augmentation_str.is_empty(), + "Augmentation::parse should only be called if we have an augmentation" + ); + + let mut augmentation = Augmentation::default(); + + let mut parsed_first = false; + let mut data = None; + + while !augmentation_str.is_empty() { + let ch = augmentation_str.read_u8()?; + match ch { + b'z' => { + if parsed_first { + return Err(Error::UnknownAugmentation); + } + + let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?; + data = Some(input.split(augmentation_length)?); + } + b'L' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; + let encoding = parse_pointer_encoding(rest)?; + augmentation.lsda = Some(encoding); + } + b'P' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; + let encoding = parse_pointer_encoding(rest)?; + let parameters = PointerEncodingParameters { + bases: &bases.eh_frame, + func_base: None, + address_size, + section: section.section(), + }; + + let personality = parse_encoded_pointer(encoding, ¶meters, rest)?; + augmentation.personality = Some((encoding, personality)); + } + b'R' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; + let encoding = parse_pointer_encoding(rest)?; + augmentation.fde_address_encoding = Some(encoding); + } + b'S' => augmentation.is_signal_trampoline = true, + _ => return Err(Error::UnknownAugmentation), + } + + parsed_first = true; + } + + Ok(augmentation) + } +} + +/// Parsed augmentation data for a `FrameDescriptEntry`. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +struct AugmentationData { + lsda: Option, +} + +impl AugmentationData { + fn parse( + augmentation: &Augmentation, + encoding_parameters: &PointerEncodingParameters<'_, R>, + input: &mut R, + ) -> Result { + // In theory, we should be iterating over the original augmentation + // string, interpreting each character, and reading the appropriate bits + // out of the augmentation data as we go. However, the only character + // that defines augmentation data in the FDE is the 'L' character, so we + // can just check for its presence directly. + + let aug_data_len = input.read_uleb128().and_then(R::Offset::from_u64)?; + let rest = &mut input.split(aug_data_len)?; + let mut augmentation_data = AugmentationData::default(); + if let Some(encoding) = augmentation.lsda { + let lsda = parse_encoded_pointer(encoding, encoding_parameters, rest)?; + augmentation_data.lsda = Some(lsda); + } + Ok(augmentation_data) + } +} + +/// > A Common Information Entry holds information that is shared among many +/// > Frame Description Entries. There is at least one CIE in every non-empty +/// > `.debug_frame` section. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CommonInformationEntry::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// The offset of this entry from the start of its containing section. + offset: Offset, + + /// > A constant that gives the number of bytes of the CIE structure, not + /// > including the length field itself (see Section 7.2.2). The size of the + /// > length field plus the value of length must be an integral multiple of + /// > the address size. + length: Offset, + + format: Format, + + /// > A version number (see Section 7.23). This number is specific to the + /// > call frame information and is independent of the DWARF version number. + version: u8, + + /// The parsed augmentation, if any. + augmentation: Option, + + /// > The size of a target address in this CIE and any FDEs that use it, in + /// > bytes. If a compilation unit exists for this frame, its address size + /// > must match the address size here. + address_size: u8, + + /// "A constant that is factored out of all advance location instructions + /// (see Section 6.4.2.1)." + code_alignment_factor: u64, + + /// > A constant that is factored out of certain offset instructions (see + /// > below). The resulting value is (operand * data_alignment_factor). + data_alignment_factor: i64, + + /// > An unsigned LEB128 constant that indicates which column in the rule + /// > table represents the return address of the function. Note that this + /// > column might not correspond to an actual machine register. + return_address_register: Register, + + /// > A sequence of rules that are interpreted to create the initial setting + /// > of each column in the table. + /// + /// > The default rule for all columns before interpretation of the initial + /// > instructions is the undefined rule. However, an ABI authoring body or a + /// > compilation system authoring body may specify an alternate default + /// > value for any or all columns. + /// + /// This is followed by `DW_CFA_nop` padding until the end of `length` bytes + /// in the input. + initial_instructions: R, +} + +impl CommonInformationEntry { + fn parse>( + bases: &BaseAddresses, + section: &Section, + input: &mut R, + ) -> Result> { + match parse_cfi_entry(bases, section, input)? { + Some(CieOrFde::Cie(cie)) => Ok(cie), + Some(CieOrFde::Fde(_)) => Err(Error::NotCieId), + None => Err(Error::NoEntryAtGivenOffset), + } + } + + fn parse_rest>( + offset: R::Offset, + length: R::Offset, + format: Format, + bases: &BaseAddresses, + section: &Section, + mut rest: R, + ) -> Result> { + let version = rest.read_u8()?; + + // Version 1 of `.debug_frame` corresponds to DWARF 2, and then for + // DWARF 3 and 4, I think they decided to just match the standard's + // version. + match version { + 1 | 3 | 4 => (), + _ => return Err(Error::UnknownVersion(u64::from(version))), + } + + let mut augmentation_string = rest.read_null_terminated_slice()?; + + let address_size = if Section::has_address_and_segment_sizes(version) { + let address_size = rest.read_address_size()?; + let segment_size = rest.read_u8()?; + if segment_size != 0 { + return Err(Error::UnsupportedSegmentSize); + } + address_size + } else { + section.address_size() + }; + + let code_alignment_factor = rest.read_uleb128()?; + let data_alignment_factor = rest.read_sleb128()?; + + let return_address_register = if version == 1 { + Register(rest.read_u8()?.into()) + } else { + rest.read_uleb128().and_then(Register::from_u64)? + }; + + let augmentation = if augmentation_string.is_empty() { + None + } else { + Some(Augmentation::parse( + &mut augmentation_string, + bases, + address_size, + section, + &mut rest, + )?) + }; + + let entry = CommonInformationEntry { + offset, + length, + format, + version, + augmentation, + address_size, + code_alignment_factor, + data_alignment_factor, + return_address_register, + initial_instructions: rest, + }; + + Ok(entry) + } +} + +/// # Signal Safe Methods +/// +/// These methods are guaranteed not to allocate, acquire locks, or perform any +/// other signal-unsafe operations. +impl CommonInformationEntry { + /// Get the offset of this entry from the start of its containing section. + pub fn offset(&self) -> R::Offset { + self.offset + } + + /// Return the encoding parameters for this CIE. + pub fn encoding(&self) -> Encoding { + Encoding { + format: self.format, + version: u16::from(self.version), + address_size: self.address_size, + } + } + + /// The size of addresses (in bytes) in this CIE. + pub fn address_size(&self) -> u8 { + self.address_size + } + + /// Iterate over this CIE's initial instructions. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn instructions<'a, Section>( + &self, + section: &'a Section, + bases: &'a BaseAddresses, + ) -> CallFrameInstructionIter<'a, R> + where + Section: UnwindSection, + { + CallFrameInstructionIter { + input: self.initial_instructions.clone(), + address_encoding: None, + parameters: PointerEncodingParameters { + bases: &bases.eh_frame, + func_base: None, + address_size: self.address_size, + section: section.section(), + }, + vendor: section.vendor(), + } + } + + /// > A constant that gives the number of bytes of the CIE structure, not + /// > including the length field itself (see Section 7.2.2). The size of the + /// > length field plus the value of length must be an integral multiple of + /// > the address size. + pub fn entry_len(&self) -> R::Offset { + self.length + } + + /// > A version number (see Section 7.23). This number is specific to the + /// > call frame information and is independent of the DWARF version number. + pub fn version(&self) -> u8 { + self.version + } + + /// Get the augmentation data, if any exists. + /// + /// The only augmentation understood by `gimli` is that which is defined by + /// `.eh_frame`. + pub fn augmentation(&self) -> Option<&Augmentation> { + self.augmentation.as_ref() + } + + /// True if this CIE's FDEs have a LSDA. + pub fn has_lsda(&self) -> bool { + self.augmentation.map_or(false, |a| a.lsda.is_some()) + } + + /// Return the encoding of the LSDA address for this CIE's FDEs. + pub fn lsda_encoding(&self) -> Option { + self.augmentation.and_then(|a| a.lsda) + } + + /// Return the encoding and address of the personality routine handler + /// for this CIE's FDEs. + pub fn personality_with_encoding(&self) -> Option<(constants::DwEhPe, Pointer)> { + self.augmentation.as_ref().and_then(|a| a.personality) + } + + /// Return the address of the personality routine handler + /// for this CIE's FDEs. + pub fn personality(&self) -> Option { + self.augmentation + .as_ref() + .and_then(|a| a.personality) + .map(|(_, p)| p) + } + + /// Return the encoding of the addresses for this CIE's FDEs. + pub fn fde_address_encoding(&self) -> Option { + self.augmentation.and_then(|a| a.fde_address_encoding) + } + + /// True if this CIE's FDEs are trampolines for signal handlers. + pub fn is_signal_trampoline(&self) -> bool { + self.augmentation.map_or(false, |a| a.is_signal_trampoline) + } + + /// > A constant that is factored out of all advance location instructions + /// > (see Section 6.4.2.1). + pub fn code_alignment_factor(&self) -> u64 { + self.code_alignment_factor + } + + /// > A constant that is factored out of certain offset instructions (see + /// > below). The resulting value is (operand * data_alignment_factor). + pub fn data_alignment_factor(&self) -> i64 { + self.data_alignment_factor + } + + /// > An unsigned ... constant that indicates which column in the rule + /// > table represents the return address of the function. Note that this + /// > column might not correspond to an actual machine register. + pub fn return_address_register(&self) -> Register { + self.return_address_register + } +} + +/// A partially parsed `FrameDescriptionEntry`. +/// +/// Fully parsing this FDE requires first parsing its CIE. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PartialFrameDescriptionEntry<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + offset: R::Offset, + length: R::Offset, + format: Format, + cie_offset: Section::Offset, + rest: R, + section: Section, + bases: &'bases BaseAddresses, +} + +impl<'bases, Section, R> PartialFrameDescriptionEntry<'bases, Section, R> +where + R: Reader, + Section: UnwindSection, +{ + fn parse_partial( + section: &Section, + bases: &'bases BaseAddresses, + input: &mut R, + ) -> Result> { + match parse_cfi_entry(bases, section, input)? { + Some(CieOrFde::Cie(_)) => Err(Error::NotFdePointer), + Some(CieOrFde::Fde(partial)) => Ok(partial), + None => Err(Error::NoEntryAtGivenOffset), + } + } + + /// Fully parse this FDE. + /// + /// You must provide a function get its associated CIE (either by parsing it + /// on demand, or looking it up in some table mapping offsets to CIEs that + /// you've already parsed, etc.) + pub fn parse(&self, get_cie: F) -> Result> + where + F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result>, + { + FrameDescriptionEntry::parse_rest( + self.offset, + self.length, + self.format, + self.cie_offset, + self.rest.clone(), + &self.section, + self.bases, + get_cie, + ) + } + + /// Get the offset of this entry from the start of its containing section. + pub fn offset(&self) -> R::Offset { + self.offset + } + + /// Get the offset of this FDE's CIE. + pub fn cie_offset(&self) -> Section::Offset { + self.cie_offset + } + + /// > A constant that gives the number of bytes of the header and + /// > instruction stream for this function, not including the length field + /// > itself (see Section 7.2.2). The size of the length field plus the value + /// > of length must be an integral multiple of the address size. + pub fn entry_len(&self) -> R::Offset { + self.length + } +} + +/// A `FrameDescriptionEntry` is a set of CFA instructions for an address range. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct FrameDescriptionEntry::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// The start of this entry within its containing section. + offset: Offset, + + /// > A constant that gives the number of bytes of the header and + /// > instruction stream for this function, not including the length field + /// > itself (see Section 7.2.2). The size of the length field plus the value + /// > of length must be an integral multiple of the address size. + length: Offset, + + format: Format, + + /// "A constant offset into the .debug_frame section that denotes the CIE + /// that is associated with this FDE." + /// + /// This is the CIE at that offset. + cie: CommonInformationEntry, + + /// > The address of the first location associated with this table entry. If + /// > the segment_size field of this FDE's CIE is non-zero, the initial + /// > location is preceded by a segment selector of the given length. + initial_address: u64, + + /// "The number of bytes of program instructions described by this entry." + address_range: u64, + + /// The parsed augmentation data, if we have any. + augmentation: Option, + + /// "A sequence of table defining instructions that are described below." + /// + /// This is followed by `DW_CFA_nop` padding until `length` bytes of the + /// input are consumed. + instructions: R, +} + +impl FrameDescriptionEntry { + fn parse_rest( + offset: R::Offset, + length: R::Offset, + format: Format, + cie_pointer: Section::Offset, + mut rest: R, + section: &Section, + bases: &BaseAddresses, + mut get_cie: F, + ) -> Result> + where + Section: UnwindSection, + F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result>, + { + let cie = get_cie(section, bases, cie_pointer)?; + + let mut parameters = PointerEncodingParameters { + bases: &bases.eh_frame, + func_base: None, + address_size: cie.address_size, + section: section.section(), + }; + + let (initial_address, address_range) = Self::parse_addresses(&mut rest, &cie, ¶meters)?; + parameters.func_base = Some(initial_address); + + let aug_data = if let Some(ref augmentation) = cie.augmentation { + Some(AugmentationData::parse( + augmentation, + ¶meters, + &mut rest, + )?) + } else { + None + }; + + let entry = FrameDescriptionEntry { + offset, + length, + format, + cie, + initial_address, + address_range, + augmentation: aug_data, + instructions: rest, + }; + + Ok(entry) + } + + fn parse_addresses( + input: &mut R, + cie: &CommonInformationEntry, + parameters: &PointerEncodingParameters<'_, R>, + ) -> Result<(u64, u64)> { + let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding); + if let Some(encoding) = encoding { + // Ignore indirection. + let initial_address = parse_encoded_pointer(encoding, parameters, input)?.pointer(); + let address_range = parse_encoded_value(encoding, parameters, input)?; + Ok((initial_address, address_range)) + } else { + let initial_address = input.read_address(cie.address_size)?; + let address_range = input.read_address(cie.address_size)?; + Ok((initial_address, address_range)) + } + } + + /// Return the table of unwind information for this FDE. + #[inline] + pub fn rows<'a, 'ctx, Section, S>( + &self, + section: &'a Section, + bases: &'a BaseAddresses, + ctx: &'ctx mut UnwindContext, + ) -> Result> + where + Section: UnwindSection, + S: UnwindContextStorage, + { + UnwindTable::new(section, bases, ctx, self) + } + + /// Find the frame unwind information for the given address. + /// + /// If found, the unwind information is returned along with the reset + /// context in the form `Ok((unwind_info, context))`. If not found, + /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or + /// CFI evaluation fails, the error is returned. + pub fn unwind_info_for_address<'ctx, Section, S>( + &self, + section: &Section, + bases: &BaseAddresses, + ctx: &'ctx mut UnwindContext, + address: u64, + ) -> Result<&'ctx UnwindTableRow> + where + Section: UnwindSection, + S: UnwindContextStorage, + { + let mut table = self.rows(section, bases, ctx)?; + while let Some(row) = table.next_row()? { + if row.contains(address) { + return Ok(table.ctx.row()); + } + } + Err(Error::NoUnwindInfoForAddress) + } +} + +/// # Signal Safe Methods +/// +/// These methods are guaranteed not to allocate, acquire locks, or perform any +/// other signal-unsafe operations. +#[allow(clippy::len_without_is_empty)] +impl FrameDescriptionEntry { + /// Get the offset of this entry from the start of its containing section. + pub fn offset(&self) -> R::Offset { + self.offset + } + + /// Get a reference to this FDE's CIE. + pub fn cie(&self) -> &CommonInformationEntry { + &self.cie + } + + /// > A constant that gives the number of bytes of the header and + /// > instruction stream for this function, not including the length field + /// > itself (see Section 7.2.2). The size of the length field plus the value + /// > of length must be an integral multiple of the address size. + pub fn entry_len(&self) -> R::Offset { + self.length + } + + /// Iterate over this FDE's instructions. + /// + /// Will not include the CIE's initial instructions, if you want those do + /// `fde.cie().instructions()` first. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn instructions<'a, Section>( + &self, + section: &'a Section, + bases: &'a BaseAddresses, + ) -> CallFrameInstructionIter<'a, R> + where + Section: UnwindSection, + { + CallFrameInstructionIter { + input: self.instructions.clone(), + address_encoding: self.cie.augmentation().and_then(|a| a.fde_address_encoding), + parameters: PointerEncodingParameters { + bases: &bases.eh_frame, + func_base: None, + address_size: self.cie.address_size, + section: section.section(), + }, + vendor: section.vendor(), + } + } + + /// The first address for which this entry has unwind information for. + pub fn initial_address(&self) -> u64 { + self.initial_address + } + + /// One more than the last address that this entry has unwind information for. + /// + /// This uses wrapping arithmetic, so the result may be less than + /// `initial_address`. + pub fn end_address(&self) -> u64 { + self.initial_address + .wrapping_add_sized(self.address_range, self.cie.address_size) + } + + /// The number of bytes of instructions that this entry has unwind + /// information for. + pub fn len(&self) -> u64 { + self.address_range + } + + /// Return `true` if the given address is within this FDE, `false` + /// otherwise. + /// + /// This is equivalent to `entry.initial_address() <= address < + /// entry.initial_address() + entry.len()`. + pub fn contains(&self, address: u64) -> bool { + self.initial_address() <= address && address < self.end_address() + } + + /// The address of this FDE's language-specific data area (LSDA), if it has + /// any. + pub fn lsda(&self) -> Option { + self.augmentation.as_ref().and_then(|a| a.lsda) + } + + /// Return true if this FDE's function is a trampoline for a signal handler. + #[inline] + pub fn is_signal_trampoline(&self) -> bool { + self.cie().is_signal_trampoline() + } + + /// Return the address of the FDE's function's personality routine + /// handler. The personality routine does language-specific clean up when + /// unwinding the stack frames with the intent to not run them again. + #[inline] + pub fn personality(&self) -> Option { + self.cie().personality() + } +} + +/// Specification of what storage should be used for [`UnwindContext`]. +/// +#[cfg_attr( + feature = "read", + doc = " +Normally you would only need to use [`StoreOnHeap`], which places the stack +on the heap using [`Box`]. This is the default storage type parameter for [`UnwindContext`]. + +You may want to supply your own storage type for one of the following reasons: + + 1. In rare cases you may run into failed unwinds due to the fixed stack size + used by [`StoreOnHeap`], so you may want to try a larger `Box`. If denial + of service is not a concern, then you could also try a `Vec`-based stack which + can grow as needed. + 2. You may want to avoid heap allocations entirely. You can use a fixed-size + stack with in-line arrays, which will place the entire storage in-line into + [`UnwindContext`]. +" +)] +/// +/// Here's an implementation which uses a fixed-size stack and allocates everything in-line, +/// which will cause `UnwindContext` to be large: +/// +/// ```rust,no_run +/// # use gimli::*; +/// # +/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry>) +/// # -> gimli::Result<()> { +/// # let eh_frame: gimli::EhFrame<_> = unreachable!(); +/// # let bases = unimplemented!(); +/// # +/// struct StoreOnStack; +/// +/// impl UnwindContextStorage for StoreOnStack { +/// type Rules = [(Register, RegisterRule); 192]; +/// type Stack = [UnwindTableRow; 4]; +/// } +/// +/// let mut ctx = UnwindContext::<_, StoreOnStack>::new_in(); +/// +/// // Initialize the context by evaluating the CIE's initial instruction program, +/// // and generate the unwind table. +/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?; +/// while let Some(row) = table.next_row()? { +/// // Do stuff with each row... +/// # let _ = row; +/// } +/// # unreachable!() +/// # } +/// ``` +pub trait UnwindContextStorage: Sized { + /// The storage used for register rules in a unwind table row. + /// + /// Note that this is nested within the stack. + type Rules: ArrayLike)>; + + /// The storage used for unwind table row stack. + type Stack: ArrayLike>; +} + +#[cfg(feature = "read")] +const MAX_RULES: usize = 192; +#[cfg(feature = "read")] +const MAX_UNWIND_STACK_DEPTH: usize = 4; + +#[cfg(feature = "read")] +impl UnwindContextStorage for StoreOnHeap { + type Rules = [(Register, RegisterRule); MAX_RULES]; + type Stack = Box<[UnwindTableRow; MAX_UNWIND_STACK_DEPTH]>; +} + +/// Common context needed when evaluating the call frame unwinding information. +/// +/// By default, this structure is small and allocates its internal storage +/// on the heap using [`Box`] during [`UnwindContext::new`]. +/// +/// This can be overridden by providing a custom [`UnwindContextStorage`] type parameter. +/// When using a custom storage with in-line arrays, the [`UnwindContext`] type itself +/// will be big, so in that case it's recommended to place [`UnwindContext`] on the +/// heap, e.g. using `Box::new(UnwindContext::::new_in())`. +/// +/// To avoid re-allocating the context multiple times when evaluating multiple +/// CFI programs, the same [`UnwindContext`] can be reused for multiple unwinds. +/// +/// ``` +/// use gimli::{UnwindContext, UnwindTable}; +/// +/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry>) +/// # -> gimli::Result<()> { +/// # let eh_frame: gimli::EhFrame<_> = unreachable!(); +/// # let bases = unimplemented!(); +/// // An uninitialized context. +/// let mut ctx = UnwindContext::new(); +/// +/// // Initialize the context by evaluating the CIE's initial instruction program, +/// // and generate the unwind table. +/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?; +/// while let Some(row) = table.next_row()? { +/// // Do stuff with each row... +/// # let _ = row; +/// } +/// # unreachable!() +/// # } +/// ``` +#[derive(Clone, PartialEq, Eq)] +pub struct UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + // Stack of rows. The last row is the row currently being built by the + // program. There is always at least one row. The vast majority of CFI + // programs will only ever have one row on the stack. + stack: ArrayVec, + + // If we are evaluating an FDE's instructions, then `is_initialized` will be + // `true`. If `initial_rule` is `Some`, then the initial register rules are either + // all default rules or have just 1 non-default rule, stored in `initial_rule`. + // If it's `None`, `stack[0]` will contain the initial register rules + // described by the CIE's initial instructions. These rules are used by + // `DW_CFA_restore`. Otherwise, when we are currently evaluating a CIE's + // initial instructions, `is_initialized` will be `false` and initial rules + // cannot be read. + initial_rule: Option<(Register, RegisterRule)>, + + is_initialized: bool, +} + +impl Debug for UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnwindContext") + .field("stack", &self.stack) + .field("initial_rule", &self.initial_rule) + .field("is_initialized", &self.is_initialized) + .finish() + } +} + +impl Default for UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn default() -> Self { + Self::new_in() + } +} + +#[cfg(feature = "read")] +impl UnwindContext { + /// Construct a new call frame unwinding context. + pub fn new() -> Self { + Self::new_in() + } +} + +/// # Signal Safe Methods +/// +/// These methods are guaranteed not to allocate, acquire locks, or perform any +/// other signal-unsafe operations, if an non-allocating storage is used. +impl UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + /// Construct a new call frame unwinding context. + pub fn new_in() -> Self { + let mut ctx = UnwindContext { + stack: Default::default(), + initial_rule: None, + is_initialized: false, + }; + ctx.reset(); + ctx + } + + /// Run the CIE's initial instructions and initialize this `UnwindContext`. + fn initialize( + &mut self, + section: &Section, + bases: &BaseAddresses, + cie: &CommonInformationEntry, + ) -> Result<()> + where + R: Reader, + Section: UnwindSection, + { + // Always reset because previous initialization failure may leave dirty state. + self.reset(); + + let mut table = UnwindTable::new_for_cie(section, bases, self, cie); + while table.next_row()?.is_some() {} + + self.save_initial_rules()?; + Ok(()) + } + + fn reset(&mut self) { + self.stack.clear(); + self.stack.try_push(UnwindTableRow::default()).unwrap(); + debug_assert!(self.stack[0].is_default()); + self.initial_rule = None; + self.is_initialized = false; + } + + fn row(&self) -> &UnwindTableRow { + self.stack.last().unwrap() + } + + fn row_mut(&mut self) -> &mut UnwindTableRow { + self.stack.last_mut().unwrap() + } + + fn save_initial_rules(&mut self) -> Result<()> { + debug_assert!(!self.is_initialized); + self.initial_rule = match *self.stack.last().unwrap().registers.rules { + // All rules are default (undefined). In this case just synthesize + // an undefined rule. + [] => Some((Register(0), RegisterRule::Undefined)), + [ref rule] => Some(rule.clone()), + _ => { + let rules = self.stack.last().unwrap().clone(); + self.stack + .try_insert(0, rules) + .map_err(|_| Error::StackFull)?; + None + } + }; + self.is_initialized = true; + Ok(()) + } + + fn start_address(&self) -> u64 { + self.row().start_address + } + + fn set_start_address(&mut self, start_address: u64) { + let row = self.row_mut(); + row.start_address = start_address; + } + + fn set_register_rule(&mut self, register: Register, rule: RegisterRule) -> Result<()> { + let row = self.row_mut(); + row.registers.set(register, rule) + } + + /// Returns `None` if we have not completed evaluation of a CIE's initial + /// instructions. + fn get_initial_rule(&self, register: Register) -> Option> { + if !self.is_initialized { + return None; + } + Some(match self.initial_rule { + None => self.stack[0].registers.get(register), + Some((r, ref rule)) if r == register => rule.clone(), + _ => RegisterRule::Undefined, + }) + } + + fn set_cfa(&mut self, cfa: CfaRule) { + self.row_mut().cfa = cfa; + } + + fn cfa_mut(&mut self) -> &mut CfaRule { + &mut self.row_mut().cfa + } + + fn push_row(&mut self) -> Result<()> { + let new_row = self.row().clone(); + self.stack.try_push(new_row).map_err(|_| Error::StackFull) + } + + fn pop_row(&mut self) -> Result<()> { + let min_size = if self.is_initialized && self.initial_rule.is_none() { + 2 + } else { + 1 + }; + if self.stack.len() <= min_size { + return Err(Error::PopWithEmptyStack); + } + self.stack.pop().unwrap(); + Ok(()) + } +} + +/// The `UnwindTable` iteratively evaluates a `FrameDescriptionEntry`'s +/// `CallFrameInstruction` program, yielding the each row one at a time. +/// +/// > 6.4.1 Structure of Call Frame Information +/// > +/// > DWARF supports virtual unwinding by defining an architecture independent +/// > basis for recording how procedures save and restore registers during their +/// > lifetimes. This basis must be augmented on some machines with specific +/// > information that is defined by an architecture specific ABI authoring +/// > committee, a hardware vendor, or a compiler producer. The body defining a +/// > specific augmentation is referred to below as the “augmenter.” +/// > +/// > Abstractly, this mechanism describes a very large table that has the +/// > following structure: +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// > +/// >
LOCCFAR0R1...RN
L0
L1
...
LN
+/// > +/// > The first column indicates an address for every location that contains code +/// > in a program. (In shared objects, this is an object-relative offset.) The +/// > remaining columns contain virtual unwinding rules that are associated with +/// > the indicated location. +/// > +/// > The CFA column defines the rule which computes the Canonical Frame Address +/// > value; it may be either a register and a signed offset that are added +/// > together, or a DWARF expression that is evaluated. +/// > +/// > The remaining columns are labeled by register number. This includes some +/// > registers that have special designation on some architectures such as the PC +/// > and the stack pointer register. (The actual mapping of registers for a +/// > particular architecture is defined by the augmenter.) The register columns +/// > contain rules that describe whether a given register has been saved and the +/// > rule to find the value for the register in the previous frame. +/// > +/// > ... +/// > +/// > This table would be extremely large if actually constructed as +/// > described. Most of the entries at any point in the table are identical to +/// > the ones above them. The whole table can be represented quite compactly by +/// > recording just the differences starting at the beginning address of each +/// > subroutine in the program. +#[derive(Debug)] +pub struct UnwindTable<'a, 'ctx, R, S = StoreOnHeap> +where + R: Reader, + S: UnwindContextStorage, +{ + code_alignment_factor: Wrapping, + data_alignment_factor: Wrapping, + address_size: u8, + next_start_address: u64, + last_end_address: u64, + returned_last_row: bool, + current_row_valid: bool, + instructions: CallFrameInstructionIter<'a, R>, + ctx: &'ctx mut UnwindContext, +} + +/// # Signal Safe Methods +/// +/// These methods are guaranteed not to allocate, acquire locks, or perform any +/// other signal-unsafe operations. +impl<'a, 'ctx, R, S> UnwindTable<'a, 'ctx, R, S> +where + R: Reader, + S: UnwindContextStorage, +{ + /// Construct a new `UnwindTable` for the given + /// `FrameDescriptionEntry`'s CFI unwinding program. + pub fn new>( + section: &'a Section, + bases: &'a BaseAddresses, + ctx: &'ctx mut UnwindContext, + fde: &FrameDescriptionEntry, + ) -> Result { + ctx.initialize(section, bases, fde.cie())?; + Ok(Self::new_for_fde(section, bases, ctx, fde)) + } + + fn new_for_fde>( + section: &'a Section, + bases: &'a BaseAddresses, + ctx: &'ctx mut UnwindContext, + fde: &FrameDescriptionEntry, + ) -> Self { + assert!(!ctx.stack.is_empty()); + UnwindTable { + code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()), + data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()), + address_size: fde.cie().address_size, + next_start_address: fde.initial_address(), + last_end_address: fde.end_address(), + returned_last_row: false, + current_row_valid: false, + instructions: fde.instructions(section, bases), + ctx, + } + } + + fn new_for_cie>( + section: &'a Section, + bases: &'a BaseAddresses, + ctx: &'ctx mut UnwindContext, + cie: &CommonInformationEntry, + ) -> Self { + assert!(!ctx.stack.is_empty()); + UnwindTable { + code_alignment_factor: Wrapping(cie.code_alignment_factor()), + data_alignment_factor: Wrapping(cie.data_alignment_factor()), + address_size: cie.address_size, + next_start_address: 0, + last_end_address: 0, + returned_last_row: false, + current_row_valid: false, + instructions: cie.instructions(section, bases), + ctx, + } + } + + /// Evaluate call frame instructions until the next row of the table is + /// completed, and return it. + /// + /// Unfortunately, this cannot be used with `FallibleIterator` because of + /// the restricted lifetime of the yielded item. + pub fn next_row(&mut self) -> Result>> { + assert!(!self.ctx.stack.is_empty()); + self.ctx.set_start_address(self.next_start_address); + self.current_row_valid = false; + + loop { + match self.instructions.next() { + Err(e) => return Err(e), + + Ok(None) => { + if self.returned_last_row { + return Ok(None); + } + + let row = self.ctx.row_mut(); + row.end_address = self.last_end_address; + + self.returned_last_row = true; + self.current_row_valid = true; + return Ok(Some(row)); + } + + Ok(Some(instruction)) => { + if self.evaluate(instruction)? { + self.current_row_valid = true; + return Ok(Some(self.ctx.row())); + } + } + }; + } + } + + /// Returns the current row with the lifetime of the context. + pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow> { + if self.current_row_valid { + Some(self.ctx.row()) + } else { + None + } + } + + /// Evaluate one call frame instruction. Return `Ok(true)` if the row is + /// complete, `Ok(false)` otherwise. + fn evaluate(&mut self, instruction: CallFrameInstruction) -> Result { + use crate::CallFrameInstruction::*; + + match instruction { + // Instructions that complete the current row and advance the + // address for the next row. + SetLoc { address } => { + if address < self.ctx.start_address() { + return Err(Error::InvalidAddressRange); + } + + self.next_start_address = address; + self.ctx.row_mut().end_address = self.next_start_address; + return Ok(true); + } + AdvanceLoc { delta } => { + let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor; + self.next_start_address = self + .ctx + .start_address() + .add_sized(delta.0, self.address_size)?; + self.ctx.row_mut().end_address = self.next_start_address; + return Ok(true); + } + + // Instructions that modify the CFA. + DefCfa { register, offset } => { + self.ctx.set_cfa(CfaRule::RegisterAndOffset { + register, + offset: offset as i64, + }); + } + DefCfaSf { + register, + factored_offset, + } => { + let data_align = self.data_alignment_factor; + self.ctx.set_cfa(CfaRule::RegisterAndOffset { + register, + offset: (Wrapping(factored_offset) * data_align).0, + }); + } + DefCfaRegister { register } => { + if let CfaRule::RegisterAndOffset { + register: ref mut reg, + .. + } = *self.ctx.cfa_mut() + { + *reg = register; + } else { + return Err(Error::CfiInstructionInInvalidContext); + } + } + DefCfaOffset { offset } => { + if let CfaRule::RegisterAndOffset { + offset: ref mut off, + .. + } = *self.ctx.cfa_mut() + { + *off = offset as i64; + } else { + return Err(Error::CfiInstructionInInvalidContext); + } + } + DefCfaOffsetSf { factored_offset } => { + if let CfaRule::RegisterAndOffset { + offset: ref mut off, + .. + } = *self.ctx.cfa_mut() + { + let data_align = self.data_alignment_factor; + *off = (Wrapping(factored_offset) * data_align).0; + } else { + return Err(Error::CfiInstructionInInvalidContext); + } + } + DefCfaExpression { expression } => { + self.ctx.set_cfa(CfaRule::Expression(expression)); + } + + // Instructions that define register rules. + Undefined { register } => { + self.ctx + .set_register_rule(register, RegisterRule::Undefined)?; + } + SameValue { register } => { + self.ctx + .set_register_rule(register, RegisterRule::SameValue)?; + } + Offset { + register, + factored_offset, + } => { + let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor; + self.ctx + .set_register_rule(register, RegisterRule::Offset(offset.0))?; + } + OffsetExtendedSf { + register, + factored_offset, + } => { + let offset = Wrapping(factored_offset) * self.data_alignment_factor; + self.ctx + .set_register_rule(register, RegisterRule::Offset(offset.0))?; + } + ValOffset { + register, + factored_offset, + } => { + let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor; + self.ctx + .set_register_rule(register, RegisterRule::ValOffset(offset.0))?; + } + ValOffsetSf { + register, + factored_offset, + } => { + let offset = Wrapping(factored_offset) * self.data_alignment_factor; + self.ctx + .set_register_rule(register, RegisterRule::ValOffset(offset.0))?; + } + Register { + dest_register, + src_register, + } => { + self.ctx + .set_register_rule(dest_register, RegisterRule::Register(src_register))?; + } + Expression { + register, + expression, + } => { + let expression = RegisterRule::Expression(expression); + self.ctx.set_register_rule(register, expression)?; + } + ValExpression { + register, + expression, + } => { + let expression = RegisterRule::ValExpression(expression); + self.ctx.set_register_rule(register, expression)?; + } + Restore { register } => { + let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) { + rule + } else { + // Can't restore the initial rule when we are + // evaluating the initial rules! + return Err(Error::CfiInstructionInInvalidContext); + }; + + self.ctx.set_register_rule(register, initial_rule)?; + } + + // Row push and pop instructions. + RememberState => { + self.ctx.push_row()?; + } + RestoreState => { + // Pop state while preserving current location. + let start_address = self.ctx.start_address(); + self.ctx.pop_row()?; + self.ctx.set_start_address(start_address); + } + + // GNU Extension. Save the size somewhere so the unwinder can use + // it when restoring IP + ArgsSize { size } => { + self.ctx.row_mut().saved_args_size = size; + } + + // AArch64 extension. + NegateRaState => { + let register = crate::AArch64::RA_SIGN_STATE; + let value = match self.ctx.row().register(register) { + RegisterRule::Undefined => 0, + RegisterRule::Constant(value) => value, + _ => return Err(Error::CfiInstructionInInvalidContext), + }; + self.ctx + .set_register_rule(register, RegisterRule::Constant(value ^ 1))?; + } + + // No operation. + Nop => {} + }; + + Ok(false) + } +} + +// We tend to have very few register rules: usually only a couple. Even if we +// have a rule for every register, on x86-64 with SSE and everything we're +// talking about ~100 rules. So rather than keeping the rules in a hash map, or +// a vector indexed by register number (which would lead to filling lots of +// empty entries), we store them as a vec of (register number, register rule) +// pairs. +// +// Additionally, because every register's default rule is implicitly +// `RegisterRule::Undefined`, we never store a register's rule in this vec if it +// is undefined and save a little bit more space and do a little fewer +// comparisons that way. +// +// The maximum number of rules preallocated by libunwind is 97 for AArch64, 128 +// for ARM, and even 188 for MIPS. It is extremely unlikely to encounter this +// many register rules in practice. +// +// See: +// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-x86_64/dwarf-config.h#L36 +// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-aarch64/dwarf-config.h#L32 +// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-arm/dwarf-config.h#L31 +// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-mips/dwarf-config.h#L31 +struct RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + rules: ArrayVec, +} + +impl Debug for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RegisterRuleMap") + .field("rules", &self.rules) + .finish() + } +} + +impl Clone for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn clone(&self) -> Self { + Self { + rules: self.rules.clone(), + } + } +} + +impl Default for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn default() -> Self { + RegisterRuleMap { + rules: Default::default(), + } + } +} + +/// # Signal Safe Methods +/// +/// These methods are guaranteed not to allocate, acquire locks, or perform any +/// other signal-unsafe operations. +impl RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn is_default(&self) -> bool { + self.rules.is_empty() + } + + fn get(&self, register: Register) -> RegisterRule { + self.rules + .iter() + .find(|rule| rule.0 == register) + .map(|r| { + debug_assert!(r.1.is_defined()); + r.1.clone() + }) + .unwrap_or(RegisterRule::Undefined) + } + + fn set(&mut self, register: Register, rule: RegisterRule) -> Result<()> { + if !rule.is_defined() { + let idx = self + .rules + .iter() + .enumerate() + .find(|&(_, r)| r.0 == register) + .map(|(i, _)| i); + if let Some(idx) = idx { + self.rules.swap_remove(idx); + } + return Ok(()); + } + + for &mut (reg, ref mut old_rule) in &mut *self.rules { + debug_assert!(old_rule.is_defined()); + if reg == register { + *old_rule = rule; + return Ok(()); + } + } + + self.rules + .try_push((register, rule)) + .map_err(|_| Error::TooManyRegisterRules) + } + + fn iter(&self) -> RegisterRuleIter<'_, T> { + RegisterRuleIter(self.rules.iter()) + } +} + +impl<'a, R, S> FromIterator<&'a (Register, RegisterRule)> for RegisterRuleMap +where + R: 'a + ReaderOffset, + S: UnwindContextStorage, +{ + fn from_iter(iter: T) -> Self + where + T: IntoIterator)>, + { + let iter = iter.into_iter(); + let mut rules = RegisterRuleMap::default(); + for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) { + rules.set(reg, rule.clone()).expect( + "This is only used in tests, impl isn't exposed publicly. + If you trip this, fix your test", + ); + } + rules + } +} + +impl PartialEq for RegisterRuleMap +where + T: ReaderOffset + PartialEq, + S: UnwindContextStorage, +{ + fn eq(&self, rhs: &Self) -> bool { + for &(reg, ref rule) in &*self.rules { + debug_assert!(rule.is_defined()); + if *rule != rhs.get(reg) { + return false; + } + } + + for &(reg, ref rhs_rule) in &*rhs.rules { + debug_assert!(rhs_rule.is_defined()); + if *rhs_rule != self.get(reg) { + return false; + } + } + + true + } +} + +impl Eq for RegisterRuleMap +where + T: ReaderOffset + Eq, + S: UnwindContextStorage, +{ +} + +/// An unordered iterator for register rules. +#[derive(Debug, Clone)] +pub struct RegisterRuleIter<'iter, T>(::core::slice::Iter<'iter, (Register, RegisterRule)>) +where + T: ReaderOffset; + +impl<'iter, T: ReaderOffset> Iterator for RegisterRuleIter<'iter, T> { + type Item = &'iter (Register, RegisterRule); + + fn next(&mut self) -> Option { + self.0.next() + } +} + +/// A row in the virtual unwind table that describes how to find the values of +/// the registers in the *previous* frame for a range of PC addresses. +#[derive(PartialEq, Eq)] +pub struct UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + start_address: u64, + end_address: u64, + saved_args_size: u64, + cfa: CfaRule, + registers: RegisterRuleMap, +} + +impl Debug for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnwindTableRow") + .field("start_address", &self.start_address) + .field("end_address", &self.end_address) + .field("saved_args_size", &self.saved_args_size) + .field("cfa", &self.cfa) + .field("registers", &self.registers) + .finish() + } +} + +impl Clone for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn clone(&self) -> Self { + Self { + start_address: self.start_address, + end_address: self.end_address, + saved_args_size: self.saved_args_size, + cfa: self.cfa.clone(), + registers: self.registers.clone(), + } + } +} + +impl Default for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn default() -> Self { + UnwindTableRow { + start_address: 0, + end_address: 0, + saved_args_size: 0, + cfa: Default::default(), + registers: Default::default(), + } + } +} + +impl UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ + fn is_default(&self) -> bool { + self.start_address == 0 + && self.end_address == 0 + && self.cfa.is_default() + && self.registers.is_default() + } + + /// Get the starting PC address that this row applies to. + pub fn start_address(&self) -> u64 { + self.start_address + } + + /// Get the end PC address where this row's register rules become + /// unapplicable. + /// + /// In other words, this row describes how to recover the last frame's + /// registers for all PCs where `row.start_address() <= PC < + /// row.end_address()`. This row does NOT describe how to recover registers + /// when `PC == row.end_address()`. + pub fn end_address(&self) -> u64 { + self.end_address + } + + /// Return `true` if the given `address` is within this row's address range, + /// `false` otherwise. + pub fn contains(&self, address: u64) -> bool { + self.start_address <= address && address < self.end_address + } + + /// Returns the amount of args currently on the stack. + /// + /// When unwinding, if the personality function requested a change in IP, + /// the SP needs to be adjusted by saved_args_size. + pub fn saved_args_size(&self) -> u64 { + self.saved_args_size + } + + /// Get the canonical frame address (CFA) recovery rule for this row. + pub fn cfa(&self) -> &CfaRule { + &self.cfa + } + + /// Get the register recovery rule for the given register number. + /// + /// The register number mapping is architecture dependent. For example, in + /// the x86-64 ABI the register number mapping is defined in Figure 3.36: + /// + /// > Figure 3.36: DWARF Register Number Mapping + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// > + /// >
Register Name Number Abbreviation
General Purpose Register RAX 0 %rax
General Purpose Register RDX 1 %rdx
General Purpose Register RCX 2 %rcx
General Purpose Register RBX 3 %rbx
General Purpose Register RSI 4 %rsi
General Purpose Register RDI 5 %rdi
General Purpose Register RBP 6 %rbp
Stack Pointer Register RSP 7 %rsp
Extended Integer Registers 8-15 8-15 %r8-%r15
Return Address RA 16
Vector Registers 0–7 17-24 %xmm0–%xmm7
Extended Vector Registers 8–15 25-32 %xmm8–%xmm15
Floating Point Registers 0–7 33-40 %st0–%st7
MMX Registers 0–7 41-48 %mm0–%mm7
Flag Register 49 %rFLAGS
Segment Register ES 50 %es
Segment Register CS 51 %cs
Segment Register SS 52 %ss
Segment Register DS 53 %ds
Segment Register FS 54 %fs
Segment Register GS 55 %gs
Reserved 56-57
FS Base address 58 %fs.base
GS Base address 59 %gs.base
Reserved 60-61
Task Register 62 %tr
LDT Register 63 %ldtr
128-bit Media Control and Status 64 %mxcsr
x87 Control Word 65 %fcw
x87 Status Word 66 %fsw
Upper Vector Registers 16–31 67-82 %xmm16–%xmm31
Reserved 83-117
Vector Mask Registers 0–7 118-125 %k0–%k7
Reserved 126-129
+ pub fn register(&self, register: Register) -> RegisterRule { + self.registers.get(register) + } + + /// Iterate over all defined register `(number, rule)` pairs. + /// + /// The rules are not iterated in any guaranteed order. Any register that + /// does not make an appearance in the iterator implicitly has the rule + /// `RegisterRule::Undefined`. + /// + /// ``` + /// # use gimli::{EndianSlice, LittleEndian, UnwindTableRow}; + /// # fn foo<'input>(unwind_table_row: UnwindTableRow) { + /// for &(register, ref rule) in unwind_table_row.registers() { + /// // ... + /// # drop(register); drop(rule); + /// } + /// # } + /// ``` + pub fn registers(&self) -> RegisterRuleIter<'_, T> { + self.registers.iter() + } +} + +/// The canonical frame address (CFA) recovery rules. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CfaRule { + /// The CFA is given offset from the given register's value. + RegisterAndOffset { + /// The register containing the base value. + register: Register, + /// The offset from the register's base value. + offset: i64, + }, + /// The CFA is obtained by evaluating a DWARF expression program. + Expression(UnwindExpression), +} + +impl Default for CfaRule { + fn default() -> Self { + CfaRule::RegisterAndOffset { + register: Register(0), + offset: 0, + } + } +} + +impl CfaRule { + fn is_default(&self) -> bool { + match *self { + CfaRule::RegisterAndOffset { register, offset } => { + register == Register(0) && offset == 0 + } + _ => false, + } + } +} + +/// An entry in the abstract CFI table that describes how to find the value of a +/// register. +/// +/// "The register columns contain rules that describe whether a given register +/// has been saved and the rule to find the value for the register in the +/// previous frame." +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum RegisterRule { + /// > A register that has this rule has no recoverable value in the previous + /// > frame. (By convention, it is not preserved by a callee.) + Undefined, + + /// > This register has not been modified from the previous frame. (By + /// > convention, it is preserved by the callee, but the callee has not + /// > modified it.) + SameValue, + + /// "The previous value of this register is saved at the address CFA+N where + /// CFA is the current CFA value and N is a signed offset." + Offset(i64), + + /// "The previous value of this register is the value CFA+N where CFA is the + /// current CFA value and N is a signed offset." + ValOffset(i64), + + /// "The previous value of this register is stored in another register + /// numbered R." + Register(Register), + + /// "The previous value of this register is located at the address produced + /// by executing the DWARF expression." + Expression(UnwindExpression), + + /// "The previous value of this register is the value produced by executing + /// the DWARF expression." + ValExpression(UnwindExpression), + + /// "The rule is defined externally to this specification by the augmenter." + Architectural, + + /// This is a pseudo-register with a constant value. + Constant(u64), +} + +impl RegisterRule { + fn is_defined(&self) -> bool { + !matches!(*self, RegisterRule::Undefined) + } +} + +/// A parsed call frame instruction. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum CallFrameInstruction { + // 6.4.2.1 Row Creation Methods + /// > 1. DW_CFA_set_loc + /// > + /// > The DW_CFA_set_loc instruction takes a single operand that represents + /// > a target address. The required action is to create a new table row + /// > using the specified address as the location. All other values in the + /// > new row are initially identical to the current row. The new location + /// > value is always greater than the current one. If the segment_size + /// > field of this FDE's CIE is non- zero, the initial location is preceded + /// > by a segment selector of the given length. + SetLoc { + /// The target address. + address: u64, + }, + + /// The `AdvanceLoc` instruction is used for all of `DW_CFA_advance_loc` and + /// `DW_CFA_advance_loc{1,2,4}`. + /// + /// > 2. DW_CFA_advance_loc + /// > + /// > The DW_CFA_advance instruction takes a single operand (encoded with + /// > the opcode) that represents a constant delta. The required action is + /// > to create a new table row with a location value that is computed by + /// > taking the current entry’s location value and adding the value of + /// > delta * code_alignment_factor. All other values in the new row are + /// > initially identical to the current row. + AdvanceLoc { + /// The delta to be added to the current address. + delta: u32, + }, + + // 6.4.2.2 CFA Definition Methods + /// > 1. DW_CFA_def_cfa + /// > + /// > The DW_CFA_def_cfa instruction takes two unsigned LEB128 operands + /// > representing a register number and a (non-factored) offset. The + /// > required action is to define the current CFA rule to use the provided + /// > register and offset. + DefCfa { + /// The target register's number. + register: Register, + /// The non-factored offset. + offset: u64, + }, + + /// > 2. DW_CFA_def_cfa_sf + /// > + /// > The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned + /// > LEB128 value representing a register number and a signed LEB128 + /// > factored offset. This instruction is identical to DW_CFA_def_cfa + /// > except that the second operand is signed and factored. The resulting + /// > offset is factored_offset * data_alignment_factor. + DefCfaSf { + /// The target register's number. + register: Register, + /// The factored offset. + factored_offset: i64, + }, + + /// > 3. DW_CFA_def_cfa_register + /// > + /// > The DW_CFA_def_cfa_register instruction takes a single unsigned LEB128 + /// > operand representing a register number. The required action is to + /// > define the current CFA rule to use the provided register (but to keep + /// > the old offset). This operation is valid only if the current CFA rule + /// > is defined to use a register and offset. + DefCfaRegister { + /// The target register's number. + register: Register, + }, + + /// > 4. DW_CFA_def_cfa_offset + /// > + /// > The DW_CFA_def_cfa_offset instruction takes a single unsigned LEB128 + /// > operand representing a (non-factored) offset. The required action is + /// > to define the current CFA rule to use the provided offset (but to keep + /// > the old register). This operation is valid only if the current CFA + /// > rule is defined to use a register and offset. + DefCfaOffset { + /// The non-factored offset. + offset: u64, + }, + + /// > 5. DW_CFA_def_cfa_offset_sf + /// > + /// > The DW_CFA_def_cfa_offset_sf instruction takes a signed LEB128 operand + /// > representing a factored offset. This instruction is identical to + /// > DW_CFA_def_cfa_offset except that the operand is signed and + /// > factored. The resulting offset is factored_offset * + /// > data_alignment_factor. This operation is valid only if the current CFA + /// > rule is defined to use a register and offset. + DefCfaOffsetSf { + /// The factored offset. + factored_offset: i64, + }, + + /// > 6. DW_CFA_def_cfa_expression + /// > + /// > The DW_CFA_def_cfa_expression instruction takes a single operand + /// > encoded as a DW_FORM_exprloc value representing a DWARF + /// > expression. The required action is to establish that expression as the + /// > means by which the current CFA is computed. + DefCfaExpression { + /// The location of the DWARF expression. + expression: UnwindExpression, + }, + + // 6.4.2.3 Register Rule Instructions + /// > 1. DW_CFA_undefined + /// > + /// > The DW_CFA_undefined instruction takes a single unsigned LEB128 + /// > operand that represents a register number. The required action is to + /// > set the rule for the specified register to “undefined.” + Undefined { + /// The target register's number. + register: Register, + }, + + /// > 2. DW_CFA_same_value + /// > + /// > The DW_CFA_same_value instruction takes a single unsigned LEB128 + /// > operand that represents a register number. The required action is to + /// > set the rule for the specified register to “same value.” + SameValue { + /// The target register's number. + register: Register, + }, + + /// The `Offset` instruction represents both `DW_CFA_offset` and + /// `DW_CFA_offset_extended`. + /// + /// > 3. DW_CFA_offset + /// > + /// > The DW_CFA_offset instruction takes two operands: a register number + /// > (encoded with the opcode) and an unsigned LEB128 constant representing + /// > a factored offset. The required action is to change the rule for the + /// > register indicated by the register number to be an offset(N) rule + /// > where the value of N is factored offset * data_alignment_factor. + Offset { + /// The target register's number. + register: Register, + /// The factored offset. + factored_offset: u64, + }, + + /// > 5. DW_CFA_offset_extended_sf + /// > + /// > The DW_CFA_offset_extended_sf instruction takes two operands: an + /// > unsigned LEB128 value representing a register number and a signed + /// > LEB128 factored offset. This instruction is identical to + /// > DW_CFA_offset_extended except that the second operand is signed and + /// > factored. The resulting offset is factored_offset * + /// > data_alignment_factor. + OffsetExtendedSf { + /// The target register's number. + register: Register, + /// The factored offset. + factored_offset: i64, + }, + + /// > 6. DW_CFA_val_offset + /// > + /// > The DW_CFA_val_offset instruction takes two unsigned LEB128 operands + /// > representing a register number and a factored offset. The required + /// > action is to change the rule for the register indicated by the + /// > register number to be a val_offset(N) rule where the value of N is + /// > factored_offset * data_alignment_factor. + ValOffset { + /// The target register's number. + register: Register, + /// The factored offset. + factored_offset: u64, + }, + + /// > 7. DW_CFA_val_offset_sf + /// > + /// > The DW_CFA_val_offset_sf instruction takes two operands: an unsigned + /// > LEB128 value representing a register number and a signed LEB128 + /// > factored offset. This instruction is identical to DW_CFA_val_offset + /// > except that the second operand is signed and factored. The resulting + /// > offset is factored_offset * data_alignment_factor. + ValOffsetSf { + /// The target register's number. + register: Register, + /// The factored offset. + factored_offset: i64, + }, + + /// > 8. DW_CFA_register + /// > + /// > The DW_CFA_register instruction takes two unsigned LEB128 operands + /// > representing register numbers. The required action is to set the rule + /// > for the first register to be register(R) where R is the second + /// > register. + Register { + /// The number of the register whose rule is being changed. + dest_register: Register, + /// The number of the register where the other register's value can be + /// found. + src_register: Register, + }, + + /// > 9. DW_CFA_expression + /// > + /// > The DW_CFA_expression instruction takes two operands: an unsigned + /// > LEB128 value representing a register number, and a DW_FORM_block value + /// > representing a DWARF expression. The required action is to change the + /// > rule for the register indicated by the register number to be an + /// > expression(E) rule where E is the DWARF expression. That is, the DWARF + /// > expression computes the address. The value of the CFA is pushed on the + /// > DWARF evaluation stack prior to execution of the DWARF expression. + Expression { + /// The target register's number. + register: Register, + /// The location of the DWARF expression. + expression: UnwindExpression, + }, + + /// > 10. DW_CFA_val_expression + /// > + /// > The DW_CFA_val_expression instruction takes two operands: an unsigned + /// > LEB128 value representing a register number, and a DW_FORM_block value + /// > representing a DWARF expression. The required action is to change the + /// > rule for the register indicated by the register number to be a + /// > val_expression(E) rule where E is the DWARF expression. That is, the + /// > DWARF expression computes the value of the given register. The value + /// > of the CFA is pushed on the DWARF evaluation stack prior to execution + /// > of the DWARF expression. + ValExpression { + /// The target register's number. + register: Register, + /// The location of the DWARF expression. + expression: UnwindExpression, + }, + + /// The `Restore` instruction represents both `DW_CFA_restore` and + /// `DW_CFA_restore_extended`. + /// + /// > 11. DW_CFA_restore + /// > + /// > The DW_CFA_restore instruction takes a single operand (encoded with + /// > the opcode) that represents a register number. The required action is + /// > to change the rule for the indicated register to the rule assigned it + /// > by the initial_instructions in the CIE. + Restore { + /// The register to be reset. + register: Register, + }, + + // 6.4.2.4 Row State Instructions + /// > 1. DW_CFA_remember_state + /// > + /// > The DW_CFA_remember_state instruction takes no operands. The required + /// > action is to push the set of rules for every register onto an implicit + /// > stack. + RememberState, + + /// > 2. DW_CFA_restore_state + /// > + /// > The DW_CFA_restore_state instruction takes no operands. The required + /// > action is to pop the set of rules off the implicit stack and place + /// > them in the current row. + RestoreState, + + /// > DW_CFA_GNU_args_size + /// > + /// > GNU Extension + /// > + /// > The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand + /// > representing an argument size. This instruction specifies the total of + /// > the size of the arguments which have been pushed onto the stack. + ArgsSize { + /// The size of the arguments which have been pushed onto the stack + size: u64, + }, + + /// > DW_CFA_AARCH64_negate_ra_state + /// > + /// > AArch64 Extension + /// > + /// > The DW_CFA_AARCH64_negate_ra_state operation negates bit 0 of the + /// > RA_SIGN_STATE pseudo-register. It does not take any operands. The + /// > DW_CFA_AARCH64_negate_ra_state must not be mixed with other DWARF Register + /// > Rule Instructions on the RA_SIGN_STATE pseudo-register in one Common + /// > Information Entry (CIE) and Frame Descriptor Entry (FDE) program sequence. + NegateRaState, + + // 6.4.2.5 Padding Instruction + /// > 1. DW_CFA_nop + /// > + /// > The DW_CFA_nop instruction has no operands and no required actions. It + /// > is used as padding to make a CIE or FDE an appropriate size. + Nop, +} + +const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000; +const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK; + +impl CallFrameInstruction { + fn parse>( + input: &mut R, + address_encoding: Option, + parameters: &PointerEncodingParameters<'_, R>, + vendor: Vendor, + ) -> Result> { + let instruction = input.read_u8()?; + let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK; + + if high_bits == constants::DW_CFA_advance_loc.0 { + let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK; + return Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(delta), + }); + } + + if high_bits == constants::DW_CFA_offset.0 { + let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into()); + let offset = input.read_uleb128()?; + return Ok(CallFrameInstruction::Offset { + register, + factored_offset: offset, + }); + } + + if high_bits == constants::DW_CFA_restore.0 { + let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into()); + return Ok(CallFrameInstruction::Restore { register }); + } + + debug_assert_eq!(high_bits, 0); + let instruction = constants::DwCfa(instruction); + + match instruction { + constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop), + + constants::DW_CFA_set_loc => { + let address = if let Some(encoding) = address_encoding { + parse_encoded_pointer(encoding, parameters, input)?.direct()? + } else { + input.read_address(parameters.address_size)? + }; + Ok(CallFrameInstruction::SetLoc { address }) + } + + constants::DW_CFA_advance_loc1 => { + let delta = input.read_u8()?; + Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(delta), + }) + } + + constants::DW_CFA_advance_loc2 => { + let delta = input.read_u16()?; + Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(delta), + }) + } + + constants::DW_CFA_advance_loc4 => { + let delta = input.read_u32()?; + Ok(CallFrameInstruction::AdvanceLoc { delta }) + } + + constants::DW_CFA_offset_extended => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_uleb128()?; + Ok(CallFrameInstruction::Offset { + register, + factored_offset: offset, + }) + } + + constants::DW_CFA_restore_extended => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + Ok(CallFrameInstruction::Restore { register }) + } + + constants::DW_CFA_undefined => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + Ok(CallFrameInstruction::Undefined { register }) + } + + constants::DW_CFA_same_value => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + Ok(CallFrameInstruction::SameValue { register }) + } + + constants::DW_CFA_register => { + let dest = input.read_uleb128().and_then(Register::from_u64)?; + let src = input.read_uleb128().and_then(Register::from_u64)?; + Ok(CallFrameInstruction::Register { + dest_register: dest, + src_register: src, + }) + } + + constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState), + + constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState), + + constants::DW_CFA_def_cfa => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_uleb128()?; + Ok(CallFrameInstruction::DefCfa { register, offset }) + } + + constants::DW_CFA_def_cfa_register => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + Ok(CallFrameInstruction::DefCfaRegister { register }) + } + + constants::DW_CFA_def_cfa_offset => { + let offset = input.read_uleb128()?; + Ok(CallFrameInstruction::DefCfaOffset { offset }) + } + + constants::DW_CFA_def_cfa_expression => { + let length = input.read_uleb128().and_then(R::Offset::from_u64)?; + let offset = input.offset_from(parameters.section); + input.skip(length)?; + Ok(CallFrameInstruction::DefCfaExpression { + expression: UnwindExpression { offset, length }, + }) + } + + constants::DW_CFA_expression => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let length = input.read_uleb128().and_then(R::Offset::from_u64)?; + let offset = input.offset_from(parameters.section); + input.skip(length)?; + Ok(CallFrameInstruction::Expression { + register, + expression: UnwindExpression { offset, length }, + }) + } + + constants::DW_CFA_offset_extended_sf => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_sleb128()?; + Ok(CallFrameInstruction::OffsetExtendedSf { + register, + factored_offset: offset, + }) + } + + constants::DW_CFA_def_cfa_sf => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_sleb128()?; + Ok(CallFrameInstruction::DefCfaSf { + register, + factored_offset: offset, + }) + } + + constants::DW_CFA_def_cfa_offset_sf => { + let offset = input.read_sleb128()?; + Ok(CallFrameInstruction::DefCfaOffsetSf { + factored_offset: offset, + }) + } + + constants::DW_CFA_val_offset => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_uleb128()?; + Ok(CallFrameInstruction::ValOffset { + register, + factored_offset: offset, + }) + } + + constants::DW_CFA_val_offset_sf => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let offset = input.read_sleb128()?; + Ok(CallFrameInstruction::ValOffsetSf { + register, + factored_offset: offset, + }) + } + + constants::DW_CFA_val_expression => { + let register = input.read_uleb128().and_then(Register::from_u64)?; + let length = input.read_uleb128().and_then(R::Offset::from_u64)?; + let offset = input.offset_from(parameters.section); + input.skip(length)?; + Ok(CallFrameInstruction::ValExpression { + register, + expression: UnwindExpression { offset, length }, + }) + } + + constants::DW_CFA_GNU_args_size => { + let size = input.read_uleb128()?; + Ok(CallFrameInstruction::ArgsSize { size }) + } + + constants::DW_CFA_AARCH64_negate_ra_state if vendor == Vendor::AArch64 => { + Ok(CallFrameInstruction::NegateRaState) + } + + otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)), + } + } +} + +/// A lazy iterator parsing call frame instructions. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Clone, Debug)] +pub struct CallFrameInstructionIter<'a, R: Reader> { + input: R, + address_encoding: Option, + parameters: PointerEncodingParameters<'a, R>, + vendor: Vendor, +} + +impl<'a, R: Reader> CallFrameInstructionIter<'a, R> { + /// Parse the next call frame instruction. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + match CallFrameInstruction::parse( + &mut self.input, + self.address_encoding, + &self.parameters, + self.vendor, + ) { + Ok(instruction) => Ok(Some(instruction)), + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'a, R: Reader> fallible_iterator::FallibleIterator for CallFrameInstructionIter<'a, R> { + type Item = CallFrameInstruction; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + CallFrameInstructionIter::next(self) + } +} + +/// The location of a DWARF expression within an unwind section. +/// +/// This is stored as an offset and length within the section instead of as a +/// `Reader` to avoid lifetime issues when reusing [`UnwindContext`]. +/// +/// # Example +/// ``` +/// # use gimli::{EhFrame, EndianSlice, NativeEndian, Error, FrameDescriptionEntry, UnwindExpression, EvaluationResult}; +/// # fn foo() -> Result<(), Error> { +/// # let eh_frame: EhFrame> = unreachable!(); +/// # let fde: FrameDescriptionEntry> = unimplemented!(); +/// # let unwind_expression: UnwindExpression<_> = unimplemented!(); +/// let expression = unwind_expression.get(&eh_frame)?; +/// let mut evaluation = expression.evaluation(fde.cie().encoding()); +/// let mut result = evaluation.evaluate()?; +/// loop { +/// match result { +/// EvaluationResult::Complete => break, +/// // Provide information to the evaluation. +/// _ => { unimplemented!()} +/// } +/// } +/// let value = evaluation.value_result(); +/// # Ok(()) +/// # } +/// ``` +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct UnwindExpression { + /// The offset of the expression within the section. + pub offset: T, + /// The length of the expression. + pub length: T, +} + +impl UnwindExpression { + /// Get the expression from the section. + /// + /// The offset and length were previously validated when the + /// `UnwindExpression` was created, so this should not fail. + pub fn get(&self, section: &S) -> Result> + where + R: Reader, + S: UnwindSection, + { + let input = &mut section.section().clone(); + input.skip(self.offset)?; + let data = input.split(self.length)?; + Ok(Expression(data)) + } +} + +/// Parse a `DW_EH_PE_*` pointer encoding. +#[doc(hidden)] +#[inline] +fn parse_pointer_encoding(input: &mut R) -> Result { + let eh_pe = input.read_u8()?; + let eh_pe = constants::DwEhPe(eh_pe); + + if eh_pe.is_valid_encoding() { + Ok(eh_pe) + } else { + Err(Error::UnknownPointerEncoding(eh_pe)) + } +} + +/// A decoded pointer. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Pointer { + /// This value is the decoded pointer value. + Direct(u64), + + /// This value is *not* the pointer value, but points to the address of + /// where the real pointer value lives. In other words, deref this pointer + /// to get the real pointer value. + /// + /// Chase this pointer at your own risk: do you trust the DWARF data it came + /// from? + Indirect(u64), +} + +impl Default for Pointer { + #[inline] + fn default() -> Self { + Pointer::Direct(0) + } +} + +impl Pointer { + #[inline] + fn new(encoding: constants::DwEhPe, address: u64) -> Pointer { + if encoding.is_indirect() { + Pointer::Indirect(address) + } else { + Pointer::Direct(address) + } + } + + /// Return the direct pointer value. + #[inline] + pub fn direct(self) -> Result { + match self { + Pointer::Direct(p) => Ok(p), + Pointer::Indirect(_) => Err(Error::UnsupportedPointerEncoding), + } + } + + /// Return the pointer value, discarding indirectness information. + #[inline] + pub fn pointer(self) -> u64 { + match self { + Pointer::Direct(p) | Pointer::Indirect(p) => p, + } + } +} + +#[derive(Clone, Debug)] +struct PointerEncodingParameters<'a, R: Reader> { + bases: &'a SectionBaseAddresses, + func_base: Option, + address_size: u8, + section: &'a R, +} + +fn parse_encoded_pointer( + encoding: constants::DwEhPe, + parameters: &PointerEncodingParameters<'_, R>, + input: &mut R, +) -> Result { + // TODO: check this once only in parse_pointer_encoding + if !encoding.is_valid_encoding() { + return Err(Error::UnknownPointerEncoding(encoding)); + } + + if encoding == constants::DW_EH_PE_omit { + return Err(Error::CannotParseOmitPointerEncoding); + } + + let base = match encoding.application() { + constants::DW_EH_PE_absptr => 0, + constants::DW_EH_PE_pcrel => { + if let Some(section_base) = parameters.bases.section { + let offset_from_section = input.offset_from(parameters.section); + section_base + .wrapping_add_sized(offset_from_section.into_u64(), parameters.address_size) + } else { + return Err(Error::PcRelativePointerButSectionBaseIsUndefined); + } + } + constants::DW_EH_PE_textrel => { + if let Some(text) = parameters.bases.text { + text + } else { + return Err(Error::TextRelativePointerButTextBaseIsUndefined); + } + } + constants::DW_EH_PE_datarel => { + if let Some(data) = parameters.bases.data { + data + } else { + return Err(Error::DataRelativePointerButDataBaseIsUndefined); + } + } + constants::DW_EH_PE_funcrel => { + if let Some(func) = parameters.func_base { + func + } else { + return Err(Error::FuncRelativePointerInBadContext); + } + } + constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding), + _ => unreachable!(), + }; + + let offset = parse_encoded_value(encoding, parameters, input)?; + Ok(Pointer::new( + encoding, + base.wrapping_add_sized(offset, parameters.address_size), + )) +} + +fn parse_encoded_value( + encoding: constants::DwEhPe, + parameters: &PointerEncodingParameters<'_, R>, + input: &mut R, +) -> Result { + match encoding.format() { + // Unsigned variants. + constants::DW_EH_PE_absptr => input.read_address(parameters.address_size), + constants::DW_EH_PE_uleb128 => input.read_uleb128(), + constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from), + constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from), + constants::DW_EH_PE_udata8 => input.read_u64(), + + // Signed variants. Here we sign extend the values (happens by + // default when casting a signed integer to a larger range integer + // in Rust), return them as u64, and rely on wrapping addition to do + // the right thing when adding these offsets to their bases. + constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64), + constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64), + constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64), + constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64), + + // That was all of the valid encoding formats. + _ => unreachable!(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext}; + use crate::common::Format; + use crate::constants; + use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian}; + use crate::read::{ + EndianSlice, Error, Pointer, ReaderOffsetId, Result, Section as ReadSection, + }; + use crate::test_util::GimliSectionMethods; + use alloc::boxed::Box; + use alloc::vec::Vec; + use core::marker::PhantomData; + use core::mem; + use test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum}; + + // Ensure each test tries to read the same section kind that it wrote. + #[derive(Clone, Copy)] + struct SectionKind

(PhantomData
); + + impl SectionKind { + fn endian<'input, E>(self) -> Endian + where + E: Endianity, + T: UnwindSection>, + T::Offset: UnwindOffset, + { + if E::default().is_big_endian() { + Endian::Big + } else { + Endian::Little + } + } + + fn section<'input, E>(self, contents: &'input [u8]) -> T + where + E: Endianity, + T: UnwindSection> + ReadSection>, + T::Offset: UnwindOffset, + { + EndianSlice::new(contents, E::default()).into() + } + } + + fn debug_frame_le<'a>() -> SectionKind>> { + SectionKind(PhantomData) + } + + fn debug_frame_be<'a>() -> SectionKind>> { + SectionKind(PhantomData) + } + + fn eh_frame_le<'a>() -> SectionKind>> { + SectionKind(PhantomData) + } + + fn parse_fde( + section: Section, + input: &mut R, + get_cie: F, + ) -> Result> + where + R: Reader, + Section: UnwindSection, + O: UnwindOffset, + F: FnMut(&Section, &BaseAddresses, O) -> Result>, + { + let bases = Default::default(); + match parse_cfi_entry(&bases, §ion, input) { + Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie), + Ok(_) => Err(Error::NoEntryAtGivenOffset), + Err(e) => Err(e), + } + } + + // Mixin methods for `Section` to help define binary test data. + + trait CfiSectionMethods: GimliSectionMethods { + fn cie<'aug, 'input, E, T>( + self, + _kind: SectionKind, + augmentation: Option<&'aug str>, + cie: &mut CommonInformationEntry>, + ) -> Self + where + E: Endianity, + T: UnwindSection>, + T::Offset: UnwindOffset; + fn fde<'a, 'input, E, T, L>( + self, + _kind: SectionKind, + cie_offset: L, + fde: &mut FrameDescriptionEntry>, + ) -> Self + where + E: Endianity, + T: UnwindSection>, + T::Offset: UnwindOffset, + L: ToLabelOrNum<'a, u64>; + } + + impl CfiSectionMethods for Section { + fn cie<'aug, 'input, E, T>( + self, + _kind: SectionKind, + augmentation: Option<&'aug str>, + cie: &mut CommonInformationEntry>, + ) -> Self + where + E: Endianity, + T: UnwindSection>, + T::Offset: UnwindOffset, + { + cie.offset = self.size() as _; + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = match cie.format { + Format::Dwarf32 => self.D32(&length).mark(&start).D32(0xffff_ffff), + Format::Dwarf64 => { + let section = self.D32(0xffff_ffff); + section.D64(&length).mark(&start).D64(0xffff_ffff_ffff_ffff) + } + }; + + let mut section = section.D8(cie.version); + + if let Some(augmentation) = augmentation { + section = section.append_bytes(augmentation.as_bytes()); + } + + // Null terminator for augmentation string. + let section = section.D8(0); + + let section = if T::has_address_and_segment_sizes(cie.version) { + section.D8(cie.address_size).D8(0) + } else { + section + }; + + let section = section + .uleb(cie.code_alignment_factor) + .sleb(cie.data_alignment_factor) + .uleb(cie.return_address_register.0.into()) + .append_bytes(cie.initial_instructions.slice()) + .mark(&end); + + cie.length = (&end - &start) as usize; + length.set_const(cie.length as u64); + + section + } + + fn fde<'a, 'input, E, T, L>( + self, + _kind: SectionKind, + cie_offset: L, + fde: &mut FrameDescriptionEntry>, + ) -> Self + where + E: Endianity, + T: UnwindSection>, + T::Offset: UnwindOffset, + L: ToLabelOrNum<'a, u64>, + { + fde.offset = self.size() as _; + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + assert_eq!(fde.format, fde.cie.format); + + let section = match T::cie_offset_encoding(fde.format) { + CieOffsetEncoding::U32 => { + let section = self.D32(&length).mark(&start); + match cie_offset.to_labelornum() { + LabelOrNum::Label(ref l) => section.D32(l), + LabelOrNum::Num(o) => section.D32(o as u32), + } + } + CieOffsetEncoding::U64 => { + let section = self.D32(0xffff_ffff); + section.D64(&length).mark(&start).D64(cie_offset) + } + }; + + let section = match fde.cie.address_size { + 4 => section + .D32(fde.initial_address() as u32) + .D32(fde.len() as u32), + 8 => section.D64(fde.initial_address()).D64(fde.len()), + x => panic!("Unsupported address size: {}", x), + }; + + let section = if let Some(ref augmentation) = fde.augmentation { + let cie_aug = fde + .cie + .augmentation + .expect("FDE has augmentation, but CIE doesn't"); + + if let Some(lsda) = augmentation.lsda { + // We only support writing `DW_EH_PE_absptr` here. + assert_eq!( + cie_aug + .lsda + .expect("FDE has lsda, but CIE doesn't") + .format(), + constants::DW_EH_PE_absptr + ); + + // Augmentation data length + let section = section.uleb(u64::from(fde.cie.address_size)); + match fde.cie.address_size { + 4 => section.D32({ + let x: u64 = lsda.pointer(); + x as u32 + }), + 8 => section.D64({ + let x: u64 = lsda.pointer(); + x + }), + x => panic!("Unsupported address size: {}", x), + } + } else { + // Even if we don't have any augmentation data, if there is + // an augmentation defined, we need to put the length in. + section.uleb(0) + } + } else { + section + }; + + let section = section.append_bytes(fde.instructions.slice()).mark(&end); + + fde.length = (&end - &start) as usize; + length.set_const(fde.length as u64); + + section + } + } + + trait ResultExt { + fn map_eof(self, input: &[u8]) -> Self; + } + + impl ResultExt for Result { + fn map_eof(self, input: &[u8]) -> Self { + match self { + Err(Error::UnexpectedEof(id)) => { + let id = ReaderOffsetId(id.0 - input.as_ptr() as u64); + Err(Error::UnexpectedEof(id)) + } + r => r, + } + } + } + + fn assert_parse_cie<'input, E>( + kind: SectionKind>>, + section: Section, + address_size: u8, + expected: Result<( + EndianSlice<'input, E>, + CommonInformationEntry>, + )>, + ) where + E: Endianity, + { + let section = section.get_contents().unwrap(); + let mut debug_frame = kind.section(§ion); + debug_frame.set_address_size(address_size); + let input = &mut EndianSlice::new(§ion, E::default()); + let bases = Default::default(); + let result = CommonInformationEntry::parse(&bases, &debug_frame, input); + let result = result.map(|cie| (*input, cie)).map_eof(§ion); + assert_eq!(result, expected); + } + + #[test] + fn test_parse_cie_incomplete_length_32() { + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()).L16(5); + assert_parse_cie( + kind, + section, + 8, + Err(Error::UnexpectedEof(ReaderOffsetId(0))), + ); + } + + #[test] + fn test_parse_cie_incomplete_length_64() { + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .L32(0xffff_ffff) + .L32(12345); + assert_parse_cie( + kind, + section, + 8, + Err(Error::UnexpectedEof(ReaderOffsetId(4))), + ); + } + + #[test] + fn test_parse_cie_incomplete_id_32() { + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + // The length is not large enough to contain the ID. + .B32(3) + .B32(0xffff_ffff); + assert_parse_cie( + kind, + section, + 8, + Err(Error::UnexpectedEof(ReaderOffsetId(4))), + ); + } + + #[test] + fn test_parse_cie_bad_id_32() { + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + // Initial length + .B32(4) + // Not the CIE Id. + .B32(0xbad1_bad2); + assert_parse_cie(kind, section, 8, Err(Error::NotCieId)); + } + + #[test] + fn test_parse_cie_32_bad_version() { + let mut cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 99, + augmentation: None, + address_size: 4, + code_alignment_factor: 1, + data_alignment_factor: 2, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&[], LittleEndian), + }; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie); + assert_parse_cie(kind, section, 4, Err(Error::UnknownVersion(99))); + } + + #[test] + fn test_parse_cie_unknown_augmentation() { + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let augmentation = "replicant"; + let expected_rest = [1, 2, 3]; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + // Initial length + .L32(&length) + .mark(&start) + // CIE Id + .L32(0xffff_ffff) + // Version + .D8(4) + // Augmentation + .append_bytes(augmentation.as_bytes()) + // Null terminator + .D8(0) + // Extra augmented data that we can't understand. + .L32(1) + .L32(2) + .L32(3) + .L32(4) + .L32(5) + .L32(6) + .mark(&end) + .append_bytes(&expected_rest); + + let expected_length = (&end - &start) as u64; + length.set_const(expected_length); + + assert_parse_cie(kind, section, 8, Err(Error::UnknownAugmentation)); + } + + fn test_parse_cie(format: Format, version: u8, address_size: u8) { + let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie = CommonInformationEntry { + offset: 0, + length: 0, + format, + version, + augmentation: None, + address_size, + code_alignment_factor: 16, + data_alignment_factor: 32, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian), + }; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .cie(kind, None, &mut cie) + .append_bytes(&expected_rest); + + assert_parse_cie( + kind, + section, + address_size, + Ok((EndianSlice::new(&expected_rest, LittleEndian), cie)), + ); + } + + #[test] + fn test_parse_cie_32_ok() { + test_parse_cie(Format::Dwarf32, 1, 4); + test_parse_cie(Format::Dwarf32, 1, 8); + test_parse_cie(Format::Dwarf32, 4, 4); + test_parse_cie(Format::Dwarf32, 4, 8); + } + + #[test] + fn test_parse_cie_64_ok() { + test_parse_cie(Format::Dwarf64, 1, 4); + test_parse_cie(Format::Dwarf64, 1, 8); + test_parse_cie(Format::Dwarf64, 4, 4); + test_parse_cie(Format::Dwarf64, 4, 8); + } + + #[test] + fn test_parse_cie_length_too_big() { + let expected_instrs: Vec<_> = (0..13).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 0, + data_alignment_factor: 0, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian), + }; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie); + + let mut contents = section.get_contents().unwrap(); + + // Overwrite the length to be too big. + contents[0] = 0; + contents[1] = 0; + contents[2] = 0; + contents[3] = 255; + + let debug_frame = DebugFrame::new(&contents, LittleEndian); + let bases = Default::default(); + assert_eq!( + CommonInformationEntry::parse( + &bases, + &debug_frame, + &mut EndianSlice::new(&contents, LittleEndian) + ) + .map_eof(&contents), + Err(Error::UnexpectedEof(ReaderOffsetId(4))) + ); + } + + #[test] + fn test_parse_fde_incomplete_length_32() { + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()).L16(5); + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, LittleEndian); + assert_eq!( + parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion), + Err(Error::UnexpectedEof(ReaderOffsetId(0))) + ); + } + + #[test] + fn test_parse_fde_incomplete_length_64() { + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .L32(0xffff_ffff) + .L32(12345); + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, LittleEndian); + assert_eq!( + parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion), + Err(Error::UnexpectedEof(ReaderOffsetId(4))) + ); + } + + #[test] + fn test_parse_fde_incomplete_cie_pointer_32() { + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + // The length is not large enough to contain the CIE pointer. + .B32(3) + .B32(1994); + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, BigEndian); + assert_eq!( + parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(§ion), + Err(Error::UnexpectedEof(ReaderOffsetId(4))) + ); + } + + #[test] + fn test_parse_fde_32_ok() { + let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let cie_offset = 0xbad0_bad1; + let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect(); + + let cie = CommonInformationEntry { + offset: 0, + length: 100, + format: Format::Dwarf32, + version: 4, + augmentation: None, + // DWARF32 with a 64 bit address size! Holy moly! + address_size: 8, + code_alignment_factor: 3, + data_alignment_factor: 2, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&[], LittleEndian), + }; + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_beef, + address_range: 39, + augmentation: None, + instructions: EndianSlice::new(&expected_instrs, LittleEndian), + }; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&expected_rest); + + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, LittleEndian); + + let get_cie = |_: &_, _: &_, offset| { + assert_eq!(offset, DebugFrameOffset(cie_offset as usize)); + Ok(cie.clone()) + }; + + assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde)); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_fde_64_ok() { + let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let cie_offset = 0xbad0_bad1; + let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect(); + + let cie = CommonInformationEntry { + offset: 0, + length: 100, + format: Format::Dwarf64, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 3, + data_alignment_factor: 2, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&[], LittleEndian), + }; + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf64, + cie: cie.clone(), + initial_address: 0xfeed_beef, + address_range: 999, + augmentation: None, + instructions: EndianSlice::new(&expected_instrs, LittleEndian), + }; + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&expected_rest); + + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, LittleEndian); + + let get_cie = |_: &_, _: &_, offset| { + assert_eq!(offset, DebugFrameOffset(cie_offset as usize)); + Ok(cie.clone()) + }; + + assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde)); + assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_entry_on_cie_32_ok() { + let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 16, + data_alignment_factor: 32, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&expected_instrs, BigEndian), + }; + + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + .cie(kind, None, &mut cie) + .append_bytes(&expected_rest); + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, BigEndian); + + let bases = Default::default(); + assert_eq!( + parse_cfi_entry(&bases, &debug_frame, rest), + Ok(Some(CieOrFde::Cie(cie))) + ); + assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian)); + } + + #[test] + fn test_parse_cfi_entry_on_fde_32_ok() { + let cie_offset = 0x1234_5678; + let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect(); + + let cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 16, + data_alignment_factor: 32, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&[], BigEndian), + }; + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_beef, + address_range: 39, + augmentation: None, + instructions: EndianSlice::new(&expected_instrs, BigEndian), + }; + + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&expected_rest); + + let section = section.get_contents().unwrap(); + let debug_frame = kind.section(§ion); + let rest = &mut EndianSlice::new(§ion, BigEndian); + + let bases = Default::default(); + match parse_cfi_entry(&bases, &debug_frame, rest) { + Ok(Some(CieOrFde::Fde(partial))) => { + assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian)); + + assert_eq!(partial.length, fde.length); + assert_eq!(partial.format, fde.format); + assert_eq!(partial.cie_offset, DebugFrameOffset(cie_offset as usize)); + + let get_cie = |_: &_, _: &_, offset| { + assert_eq!(offset, DebugFrameOffset(cie_offset as usize)); + Ok(cie.clone()) + }; + + assert_eq!(partial.parse(get_cie), Ok(fde)); + } + otherwise => panic!("Unexpected result: {:#?}", otherwise), + } + } + + #[test] + fn test_cfi_entries_iter() { + let expected_instrs1: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect(); + + let expected_instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect(); + + let expected_instrs3: Vec<_> = (0..12).map(|_| constants::DW_CFA_nop.0).collect(); + + let expected_instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie1 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 1, + data_alignment_factor: 2, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&expected_instrs1, BigEndian), + }; + + let mut cie2 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 3, + data_alignment_factor: 2, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&expected_instrs2, BigEndian), + }; + + let cie1_location = Label::new(); + let cie2_location = Label::new(); + + // Write the CIEs first so that their length gets set before we clone + // them into the FDEs and our equality assertions down the line end up + // with all the CIEs always having he correct length. + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + .mark(&cie1_location) + .cie(kind, None, &mut cie1) + .mark(&cie2_location) + .cie(kind, None, &mut cie2); + + let mut fde1 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie1.clone(), + initial_address: 0xfeed_beef, + address_range: 39, + augmentation: None, + instructions: EndianSlice::new(&expected_instrs3, BigEndian), + }; + + let mut fde2 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie2.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: None, + instructions: EndianSlice::new(&expected_instrs4, BigEndian), + }; + + let section = + section + .fde(kind, &cie1_location, &mut fde1) + .fde(kind, &cie2_location, &mut fde2); + + section.start().set_const(0); + + let cie1_offset = cie1_location.value().unwrap() as usize; + let cie2_offset = cie2_location.value().unwrap() as usize; + + let contents = section.get_contents().unwrap(); + let debug_frame = kind.section(&contents); + + let bases = Default::default(); + let mut entries = debug_frame.entries(&bases); + + assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie1.clone())))); + assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie2.clone())))); + + match entries.next() { + Ok(Some(CieOrFde::Fde(partial))) => { + assert_eq!(partial.length, fde1.length); + assert_eq!(partial.format, fde1.format); + assert_eq!(partial.cie_offset, DebugFrameOffset(cie1_offset)); + + let get_cie = |_: &_, _: &_, offset| { + assert_eq!(offset, DebugFrameOffset(cie1_offset)); + Ok(cie1.clone()) + }; + assert_eq!(partial.parse(get_cie), Ok(fde1)); + } + otherwise => panic!("Unexpected result: {:#?}", otherwise), + } + + match entries.next() { + Ok(Some(CieOrFde::Fde(partial))) => { + assert_eq!(partial.length, fde2.length); + assert_eq!(partial.format, fde2.format); + assert_eq!(partial.cie_offset, DebugFrameOffset(cie2_offset)); + + let get_cie = |_: &_, _: &_, offset| { + assert_eq!(offset, DebugFrameOffset(cie2_offset)); + Ok(cie2.clone()) + }; + assert_eq!(partial.parse(get_cie), Ok(fde2)); + } + otherwise => panic!("Unexpected result: {:#?}", otherwise), + } + + assert_eq!(entries.next(), Ok(None)); + } + + #[test] + fn test_parse_cie_from_offset() { + let filler = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let instrs: Vec<_> = (0..5).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf64, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 4, + data_alignment_factor: 8, + return_address_register: Register(12), + initial_instructions: EndianSlice::new(&instrs, LittleEndian), + }; + + let cie_location = Label::new(); + + let kind = debug_frame_le(); + let section = Section::with_endian(kind.endian()) + .append_bytes(&filler) + .mark(&cie_location) + .cie(kind, None, &mut cie) + .append_bytes(&filler); + + section.start().set_const(0); + + let cie_offset = DebugFrameOffset(cie_location.value().unwrap() as usize); + + let contents = section.get_contents().unwrap(); + let debug_frame = kind.section(&contents); + let bases = Default::default(); + + assert_eq!(debug_frame.cie_from_offset(&bases, cie_offset), Ok(cie)); + } + + fn parse_cfi_instruction( + input: &mut R, + address_size: u8, + ) -> Result> { + let section = input.clone(); + let parameters = &PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size, + section: §ion, + }; + CallFrameInstruction::parse(input, None, parameters, Vendor::Default) + } + + #[test] + fn test_parse_cfi_instruction_advance_loc() { + let expected_rest = [1, 2, 3, 4]; + let expected_delta = 42; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_advance_loc.0 | expected_delta) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(expected_delta), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_offset() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 3; + let expected_offset = 1997; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_offset.0 | expected_reg) + .uleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Offset { + register: Register(expected_reg.into()), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_restore() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 3; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_restore.0 | expected_reg) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Restore { + register: Register(expected_reg.into()), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_nop() { + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_nop.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Nop) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_set_loc() { + let expected_rest = [1, 2, 3, 4]; + let expected_addr = 0xdead_beef; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_set_loc.0) + .L64(expected_addr) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::SetLoc { + address: expected_addr, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_set_loc_encoding() { + let text_base = 0xfeed_face; + let addr_offset = 0xbeef; + let expected_addr = text_base + addr_offset; + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_set_loc.0) + .L64(addr_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + let parameters = &PointerEncodingParameters { + bases: &BaseAddresses::default().set_text(text_base).eh_frame, + func_base: None, + address_size: 8, + section: &EndianSlice::new(&[], LittleEndian), + }; + assert_eq!( + CallFrameInstruction::parse( + input, + Some(constants::DW_EH_PE_textrel), + parameters, + Vendor::Default + ), + Ok(CallFrameInstruction::SetLoc { + address: expected_addr, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_advance_loc1() { + let expected_rest = [1, 2, 3, 4]; + let expected_delta = 8; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_advance_loc1.0) + .D8(expected_delta) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(expected_delta), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_advance_loc2() { + let expected_rest = [1, 2, 3, 4]; + let expected_delta = 500; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_advance_loc2.0) + .L16(expected_delta) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::AdvanceLoc { + delta: u32::from(expected_delta), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_advance_loc4() { + let expected_rest = [1, 2, 3, 4]; + let expected_delta = 1 << 20; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_advance_loc4.0) + .L32(expected_delta) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::AdvanceLoc { + delta: expected_delta, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_offset_extended() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 7; + let expected_offset = 33; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_offset_extended.0) + .uleb(expected_reg.into()) + .uleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Offset { + register: Register(expected_reg), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_restore_extended() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 7; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_restore_extended.0) + .uleb(expected_reg.into()) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Restore { + register: Register(expected_reg), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_undefined() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 7; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_undefined.0) + .uleb(expected_reg.into()) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Undefined { + register: Register(expected_reg), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_same_value() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 7; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_same_value.0) + .uleb(expected_reg.into()) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::SameValue { + register: Register(expected_reg), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_register() { + let expected_rest = [1, 2, 3, 4]; + let expected_dest_reg = 7; + let expected_src_reg = 8; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_register.0) + .uleb(expected_dest_reg.into()) + .uleb(expected_src_reg.into()) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Register { + dest_register: Register(expected_dest_reg), + src_register: Register(expected_src_reg), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_remember_state() { + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_remember_state.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::RememberState) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_restore_state() { + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_restore_state.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::RestoreState) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 2; + let expected_offset = 0; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa.0) + .uleb(expected_reg.into()) + .uleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfa { + register: Register(expected_reg), + offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa_register() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 2; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa_register.0) + .uleb(expected_reg.into()) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfaRegister { + register: Register(expected_reg), + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa_offset() { + let expected_rest = [1, 2, 3, 4]; + let expected_offset = 23; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa_offset.0) + .uleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfaOffset { + offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa_expression() { + let expected_rest = [1, 2, 3, 4]; + let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa_expression.0) + .D8(&length) + .mark(&start) + .append_bytes(&expected_expr) + .mark(&end) + .append_bytes(&expected_rest); + + length.set_const((&end - &start) as u64); + let expected_expression = UnwindExpression { + offset: (&start - §ion.start()) as usize, + length: (&end - &start) as usize, + }; + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfaExpression { + expression: expected_expression, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_expression() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 99; + let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_expression.0) + .uleb(expected_reg.into()) + .D8(&length) + .mark(&start) + .append_bytes(&expected_expr) + .mark(&end) + .append_bytes(&expected_rest); + + length.set_const((&end - &start) as u64); + let expected_expression = UnwindExpression { + offset: (&start - §ion.start()) as usize, + length: (&end - &start) as usize, + }; + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::Expression { + register: Register(expected_reg), + expression: expected_expression, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_offset_extended_sf() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 7; + let expected_offset = -33; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_offset_extended_sf.0) + .uleb(expected_reg.into()) + .sleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::OffsetExtendedSf { + register: Register(expected_reg), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa_sf() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 2; + let expected_offset = -9999; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa_sf.0) + .uleb(expected_reg.into()) + .sleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfaSf { + register: Register(expected_reg), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_def_cfa_offset_sf() { + let expected_rest = [1, 2, 3, 4]; + let expected_offset = -123; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_def_cfa_offset_sf.0) + .sleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::DefCfaOffsetSf { + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_val_offset() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 50; + let expected_offset = 23; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_val_offset.0) + .uleb(expected_reg.into()) + .uleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::ValOffset { + register: Register(expected_reg), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_val_offset_sf() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 50; + let expected_offset = -23; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_val_offset_sf.0) + .uleb(expected_reg.into()) + .sleb(expected_offset) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::ValOffsetSf { + register: Register(expected_reg), + factored_offset: expected_offset, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_val_expression() { + let expected_rest = [1, 2, 3, 4]; + let expected_reg = 50; + let expected_expr = [2, 2, 1, 1, 5, 5]; + + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_val_expression.0) + .uleb(expected_reg.into()) + .D8(&length) + .mark(&start) + .append_bytes(&expected_expr) + .mark(&end) + .append_bytes(&expected_rest); + + length.set_const((&end - &start) as u64); + let expected_expression = UnwindExpression { + offset: (&start - §ion.start()) as usize, + length: (&end - &start) as usize, + }; + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + + assert_eq!( + parse_cfi_instruction(input, 8), + Ok(CallFrameInstruction::ValExpression { + register: Register(expected_reg), + expression: expected_expression, + }) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_negate_ra_state() { + let expected_rest = [1, 2, 3, 4]; + let section = Section::with_endian(Endian::Little) + .D8(constants::DW_CFA_AARCH64_negate_ra_state.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + let parameters = &PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &EndianSlice::default(), + }; + assert_eq!( + CallFrameInstruction::parse(input, None, parameters, Vendor::AArch64), + Ok(CallFrameInstruction::NegateRaState) + ); + assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_cfi_instruction_unknown_instruction() { + let expected_rest = [1, 2, 3, 4]; + let unknown_instr = constants::DwCfa(0b0011_1111); + let section = Section::with_endian(Endian::Little) + .D8(unknown_instr.0) + .append_bytes(&expected_rest); + let contents = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&contents, LittleEndian); + assert_eq!( + parse_cfi_instruction(input, 8), + Err(Error::UnknownCallFrameInstruction(unknown_instr)) + ); + } + + #[test] + fn test_call_frame_instruction_iter_ok() { + let expected_reg = 50; + let expected_expr = [2, 2, 1, 1, 5, 5]; + let expected_delta = 230; + + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = Section::with_endian(Endian::Big) + .D8(constants::DW_CFA_val_expression.0) + .uleb(expected_reg.into()) + .D8(&length) + .mark(&start) + .append_bytes(&expected_expr) + .mark(&end) + .D8(constants::DW_CFA_advance_loc1.0) + .D8(expected_delta); + + length.set_const((&end - &start) as u64); + let expected_expression = UnwindExpression { + offset: (&start - §ion.start()) as usize, + length: (&end - &start) as usize, + }; + let contents = section.get_contents().unwrap(); + let input = EndianSlice::new(&contents, BigEndian); + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &input, + }; + let mut iter = CallFrameInstructionIter { + input, + address_encoding: None, + parameters, + vendor: Vendor::Default, + }; + + assert_eq!( + iter.next(), + Ok(Some(CallFrameInstruction::ValExpression { + register: Register(expected_reg), + expression: expected_expression, + })) + ); + + assert_eq!( + iter.next(), + Ok(Some(CallFrameInstruction::AdvanceLoc { + delta: u32::from(expected_delta), + })) + ); + + assert_eq!(iter.next(), Ok(None)); + } + + #[test] + fn test_call_frame_instruction_iter_err() { + // DW_CFA_advance_loc1 without an operand. + let section = Section::with_endian(Endian::Big).D8(constants::DW_CFA_advance_loc1.0); + + let contents = section.get_contents().unwrap(); + let input = EndianSlice::new(&contents, BigEndian); + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &EndianSlice::default(), + }; + let mut iter = CallFrameInstructionIter { + input, + address_encoding: None, + parameters, + vendor: Vendor::Default, + }; + + assert_eq!( + iter.next().map_eof(&contents), + Err(Error::UnexpectedEof(ReaderOffsetId(1))) + ); + assert_eq!(iter.next(), Ok(None)); + } + + fn assert_eval<'a, I>( + mut initial_ctx: UnwindContext, + expected_ctx: UnwindContext, + cie: CommonInformationEntry>, + fde: Option>>, + instructions: I, + ) where + I: AsRef<[(Result, CallFrameInstruction)]>, + { + { + let section = &DebugFrame::from(EndianSlice::default()); + let bases = &BaseAddresses::default(); + let mut table = match fde { + Some(fde) => UnwindTable::new_for_fde(section, bases, &mut initial_ctx, &fde), + None => UnwindTable::new_for_cie(section, bases, &mut initial_ctx, &cie), + }; + for (expected_result, instruction) in instructions.as_ref() { + assert_eq!(*expected_result, table.evaluate(instruction.clone())); + } + } + + assert_eq!(expected_ctx, initial_ctx); + } + + fn make_test_cie<'a>() -> CommonInformationEntry> { + CommonInformationEntry { + offset: 0, + format: Format::Dwarf64, + length: 0, + return_address_register: Register(0), + version: 4, + address_size: mem::size_of::() as u8, + initial_instructions: EndianSlice::new(&[], LittleEndian), + augmentation: None, + data_alignment_factor: 2, + code_alignment_factor: 3, + } + } + + #[test] + fn test_eval_set_loc() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected.row_mut().end_address = 42; + let instructions = [(Ok(true), CallFrameInstruction::SetLoc { address: 42 })]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_set_loc_backwards() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.row_mut().start_address = 999; + let expected = ctx.clone(); + let instructions = [( + Err(Error::InvalidAddressRange), + CallFrameInstruction::SetLoc { address: 42 }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_advance_loc() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.row_mut().start_address = 3; + let mut expected = ctx.clone(); + expected.row_mut().end_address = 3 + 2 * cie.code_alignment_factor; + let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 2 })]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_advance_loc_overflow_32() { + let mut cie = make_test_cie(); + cie.address_size = 4; + let mut ctx = UnwindContext::new(); + ctx.row_mut().start_address = u32::MAX.into(); + let expected = ctx.clone(); + let instructions = [( + Err(Error::AddressOverflow), + CallFrameInstruction::AdvanceLoc { delta: 42 }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_advance_loc_overflow_64() { + let mut cie = make_test_cie(); + cie.address_size = 8; + let mut ctx = UnwindContext::new(); + ctx.row_mut().start_address = u64::MAX; + let expected = ctx.clone(); + let instructions = [( + Err(Error::AddressOverflow), + CallFrameInstruction::AdvanceLoc { delta: 42 }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected.set_cfa(CfaRule::RegisterAndOffset { + register: Register(42), + offset: 36, + }); + let instructions = [( + Ok(false), + CallFrameInstruction::DefCfa { + register: Register(42), + offset: 36, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_sf() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected.set_cfa(CfaRule::RegisterAndOffset { + register: Register(42), + offset: 36 * cie.data_alignment_factor as i64, + }); + let instructions = [( + Ok(false), + CallFrameInstruction::DefCfaSf { + register: Register(42), + factored_offset: 36, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_register() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.set_cfa(CfaRule::RegisterAndOffset { + register: Register(3), + offset: 8, + }); + let mut expected = ctx.clone(); + expected.set_cfa(CfaRule::RegisterAndOffset { + register: Register(42), + offset: 8, + }); + let instructions = [( + Ok(false), + CallFrameInstruction::DefCfaRegister { + register: Register(42), + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_register_invalid_context() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.set_cfa(CfaRule::Expression(UnwindExpression { + offset: 0, + length: 0, + })); + let expected = ctx.clone(); + let instructions = [( + Err(Error::CfiInstructionInInvalidContext), + CallFrameInstruction::DefCfaRegister { + register: Register(42), + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_offset() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.set_cfa(CfaRule::RegisterAndOffset { + register: Register(3), + offset: 8, + }); + let mut expected = ctx.clone(); + expected.set_cfa(CfaRule::RegisterAndOffset { + register: Register(3), + offset: 42, + }); + let instructions = [(Ok(false), CallFrameInstruction::DefCfaOffset { offset: 42 })]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_offset_invalid_context() { + let cie = make_test_cie(); + let mut ctx = UnwindContext::new(); + ctx.set_cfa(CfaRule::Expression(UnwindExpression { + offset: 10, + length: 11, + })); + let expected = ctx.clone(); + let instructions = [( + Err(Error::CfiInstructionInInvalidContext), + CallFrameInstruction::DefCfaOffset { offset: 1993 }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_def_cfa_expression() { + let expr = UnwindExpression { + offset: 10, + length: 11, + }; + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected.set_cfa(CfaRule::Expression(expr)); + let instructions = [( + Ok(false), + CallFrameInstruction::DefCfaExpression { expression: expr }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_undefined() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(Register(5), RegisterRule::Undefined) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::Undefined { + register: Register(5), + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_same_value() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(Register(0), RegisterRule::SameValue) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::SameValue { + register: Register(0), + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_offset() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + Register(2), + RegisterRule::Offset(3 * cie.data_alignment_factor), + ) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::Offset { + register: Register(2), + factored_offset: 3, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_offset_extended_sf() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + Register(4), + RegisterRule::Offset(-3 * cie.data_alignment_factor), + ) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::OffsetExtendedSf { + register: Register(4), + factored_offset: -3, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_val_offset() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + Register(5), + RegisterRule::ValOffset(7 * cie.data_alignment_factor), + ) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::ValOffset { + register: Register(5), + factored_offset: 7, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_val_offset_sf() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + Register(5), + RegisterRule::ValOffset(-7 * cie.data_alignment_factor), + ) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::ValOffsetSf { + register: Register(5), + factored_offset: -7, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_expression() { + let expr = UnwindExpression { + offset: 10, + length: 11, + }; + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(Register(9), RegisterRule::Expression(expr)) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::Expression { + register: Register(9), + expression: expr, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_val_expression() { + let expr = UnwindExpression { + offset: 10, + length: 11, + }; + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(Register(9), RegisterRule::ValExpression(expr)) + .unwrap(); + let instructions = [( + Ok(false), + CallFrameInstruction::ValExpression { + register: Register(9), + expression: expr, + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_restore() { + let cie = make_test_cie(); + let fde = FrameDescriptionEntry { + offset: 0, + format: Format::Dwarf64, + length: 0, + address_range: 0, + augmentation: None, + initial_address: 0, + cie: cie.clone(), + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let mut ctx = UnwindContext::new(); + ctx.set_register_rule(Register(0), RegisterRule::Offset(1)) + .unwrap(); + ctx.save_initial_rules().unwrap(); + let expected = ctx.clone(); + ctx.set_register_rule(Register(0), RegisterRule::Offset(2)) + .unwrap(); + + let instructions = [( + Ok(false), + CallFrameInstruction::Restore { + register: Register(0), + }, + )]; + assert_eval(ctx, expected, cie, Some(fde), instructions); + } + + #[test] + fn test_eval_restore_havent_saved_initial_context() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let expected = ctx.clone(); + let instructions = [( + Err(Error::CfiInstructionInInvalidContext), + CallFrameInstruction::Restore { + register: Register(0), + }, + )]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_remember_state() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected.push_row().unwrap(); + let instructions = [(Ok(false), CallFrameInstruction::RememberState)]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_restore_state() { + let cie = make_test_cie(); + + let mut ctx = UnwindContext::new(); + ctx.set_start_address(1); + ctx.set_register_rule(Register(0), RegisterRule::SameValue) + .unwrap(); + let mut expected = ctx.clone(); + ctx.push_row().unwrap(); + ctx.set_start_address(2); + ctx.set_register_rule(Register(0), RegisterRule::Offset(16)) + .unwrap(); + + // Restore state should preserve current location. + expected.set_start_address(2); + + let instructions = [ + // First one pops just fine. + (Ok(false), CallFrameInstruction::RestoreState), + // Second pop would try to pop out of bounds. + ( + Err(Error::PopWithEmptyStack), + CallFrameInstruction::RestoreState, + ), + ]; + + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_negate_ra_state() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(1)) + .unwrap(); + let instructions = [(Ok(false), CallFrameInstruction::NegateRaState)]; + assert_eval(ctx, expected, cie, None, instructions); + + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule(crate::AArch64::RA_SIGN_STATE, RegisterRule::Constant(0)) + .unwrap(); + let instructions = [ + (Ok(false), CallFrameInstruction::NegateRaState), + (Ok(false), CallFrameInstruction::NegateRaState), + ]; + assert_eval(ctx, expected, cie, None, instructions); + + // NegateRaState can't be used with other instructions. + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let mut expected = ctx.clone(); + expected + .set_register_rule( + crate::AArch64::RA_SIGN_STATE, + RegisterRule::Offset(cie.data_alignment_factor as i64), + ) + .unwrap(); + let instructions = [ + ( + Ok(false), + CallFrameInstruction::Offset { + register: crate::AArch64::RA_SIGN_STATE, + factored_offset: 1, + }, + ), + ( + Err(Error::CfiInstructionInInvalidContext), + CallFrameInstruction::NegateRaState, + ), + ]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_eval_nop() { + let cie = make_test_cie(); + let ctx = UnwindContext::new(); + let expected = ctx.clone(); + let instructions = [(Ok(false), CallFrameInstruction::Nop)]; + assert_eval(ctx, expected, cie, None, instructions); + } + + #[test] + fn test_unwind_table_cie_no_rule() { + let initial_instructions = Section::with_endian(Endian::Little) + // The CFA is -12 from register 4. + .D8(constants::DW_CFA_def_cfa_sf.0) + .uleb(4) + .sleb(-12) + .append_repeated(constants::DW_CFA_nop.0, 4); + let initial_instructions = initial_instructions.get_contents().unwrap(); + + let cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian), + }; + + let instructions = Section::with_endian(Endian::Little) + // A bunch of nop padding. + .append_repeated(constants::DW_CFA_nop.0, 8); + let instructions = instructions.get_contents().unwrap(); + + let fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0, + address_range: 100, + augmentation: None, + instructions: EndianSlice::new(&instructions, LittleEndian), + }; + + let section = &DebugFrame::from(EndianSlice::default()); + let bases = &BaseAddresses::default(); + let mut ctx = Box::new(UnwindContext::new()); + + let mut table = fde + .rows(section, bases, &mut ctx) + .expect("Should run initial program OK"); + assert!(table.ctx.is_initialized); + let expected_initial_rule = (Register(0), RegisterRule::Undefined); + assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule)); + + { + let row = table.next_row().expect("Should evaluate first row OK"); + let expected = UnwindTableRow { + start_address: 0, + end_address: 100, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [].iter().collect(), + }; + assert_eq!(Some(&expected), row); + } + + // All done! + assert_eq!(Ok(None), table.next_row()); + assert_eq!(Ok(None), table.next_row()); + } + + #[test] + fn test_unwind_table_cie_single_rule() { + let initial_instructions = Section::with_endian(Endian::Little) + // The CFA is -12 from register 4. + .D8(constants::DW_CFA_def_cfa_sf.0) + .uleb(4) + .sleb(-12) + // Register 3 is 4 from the CFA. + .D8(constants::DW_CFA_offset.0 | 3) + .uleb(4) + .append_repeated(constants::DW_CFA_nop.0, 4); + let initial_instructions = initial_instructions.get_contents().unwrap(); + + let cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian), + }; + + let instructions = Section::with_endian(Endian::Little) + // A bunch of nop padding. + .append_repeated(constants::DW_CFA_nop.0, 8); + let instructions = instructions.get_contents().unwrap(); + + let fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0, + address_range: 100, + augmentation: None, + instructions: EndianSlice::new(&instructions, LittleEndian), + }; + + let section = &DebugFrame::from(EndianSlice::default()); + let bases = &BaseAddresses::default(); + let mut ctx = Box::new(UnwindContext::new()); + + let mut table = fde + .rows(section, bases, &mut ctx) + .expect("Should run initial program OK"); + assert!(table.ctx.is_initialized); + let expected_initial_rule = (Register(3), RegisterRule::Offset(4)); + assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule)); + + { + let row = table.next_row().expect("Should evaluate first row OK"); + let expected = UnwindTableRow { + start_address: 0, + end_address: 100, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [(Register(3), RegisterRule::Offset(4))].iter().collect(), + }; + assert_eq!(Some(&expected), row); + } + + // All done! + assert_eq!(Ok(None), table.next_row()); + assert_eq!(Ok(None), table.next_row()); + } + + #[test] + fn test_unwind_table_cie_invalid_rule() { + let initial_instructions1 = Section::with_endian(Endian::Little) + // Test that stack length is reset. + .D8(constants::DW_CFA_remember_state.0) + // Test that stack value is reset (different register from that used later). + .D8(constants::DW_CFA_offset.0 | 4) + .uleb(8) + // Invalid due to missing operands. + .D8(constants::DW_CFA_offset.0); + let initial_instructions1 = initial_instructions1.get_contents().unwrap(); + + let cie1 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&initial_instructions1, LittleEndian), + }; + + let initial_instructions2 = Section::with_endian(Endian::Little) + // Register 3 is 4 from the CFA. + .D8(constants::DW_CFA_offset.0 | 3) + .uleb(4) + .append_repeated(constants::DW_CFA_nop.0, 4); + let initial_instructions2 = initial_instructions2.get_contents().unwrap(); + + let cie2 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&initial_instructions2, LittleEndian), + }; + + let fde1 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie1.clone(), + initial_address: 0, + address_range: 100, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let fde2 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie2.clone(), + initial_address: 0, + address_range: 100, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let section = &DebugFrame::from(EndianSlice::default()); + let bases = &BaseAddresses::default(); + let mut ctx = Box::new(UnwindContext::new()); + + let table = fde1 + .rows(section, bases, &mut ctx) + .map_eof(&initial_instructions1); + assert_eq!(table.err(), Some(Error::UnexpectedEof(ReaderOffsetId(4)))); + assert!(!ctx.is_initialized); + assert_eq!(ctx.stack.len(), 2); + assert_eq!(ctx.initial_rule, None); + + let _table = fde2 + .rows(section, bases, &mut ctx) + .expect("Should run initial program OK"); + assert!(ctx.is_initialized); + assert_eq!(ctx.stack.len(), 1); + let expected_initial_rule = (Register(3), RegisterRule::Offset(4)); + assert_eq!(ctx.initial_rule, Some(expected_initial_rule)); + } + + #[test] + fn test_unwind_table_next_row() { + #[allow(clippy::identity_op)] + let initial_instructions = Section::with_endian(Endian::Little) + // The CFA is -12 from register 4. + .D8(constants::DW_CFA_def_cfa_sf.0) + .uleb(4) + .sleb(-12) + // Register 0 is 8 from the CFA. + .D8(constants::DW_CFA_offset.0 | 0) + .uleb(8) + // Register 3 is 4 from the CFA. + .D8(constants::DW_CFA_offset.0 | 3) + .uleb(4) + .append_repeated(constants::DW_CFA_nop.0, 4); + let initial_instructions = initial_instructions.get_contents().unwrap(); + + let cie = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian), + }; + + let instructions = Section::with_endian(Endian::Little) + // Initial instructions form a row, advance the address by 1. + .D8(constants::DW_CFA_advance_loc1.0) + .D8(1) + // Register 0 is -16 from the CFA. + .D8(constants::DW_CFA_offset_extended_sf.0) + .uleb(0) + .sleb(-16) + // Finish this row, advance the address by 32. + .D8(constants::DW_CFA_advance_loc1.0) + .D8(32) + // Register 3 is -4 from the CFA. + .D8(constants::DW_CFA_offset_extended_sf.0) + .uleb(3) + .sleb(-4) + // Finish this row, advance the address by 64. + .D8(constants::DW_CFA_advance_loc1.0) + .D8(64) + // Register 5 is 4 from the CFA. + .D8(constants::DW_CFA_offset.0 | 5) + .uleb(4) + // A bunch of nop padding. + .append_repeated(constants::DW_CFA_nop.0, 8); + let instructions = instructions.get_contents().unwrap(); + + let fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0, + address_range: 100, + augmentation: None, + instructions: EndianSlice::new(&instructions, LittleEndian), + }; + + let section = &DebugFrame::from(EndianSlice::default()); + let bases = &BaseAddresses::default(); + let mut ctx = Box::new(UnwindContext::new()); + + let mut table = fde + .rows(section, bases, &mut ctx) + .expect("Should run initial program OK"); + assert!(table.ctx.is_initialized); + assert!(table.ctx.initial_rule.is_none()); + let expected_initial_rules: RegisterRuleMap<_> = [ + (Register(0), RegisterRule::Offset(8)), + (Register(3), RegisterRule::Offset(4)), + ] + .iter() + .collect(); + assert_eq!(table.ctx.stack[0].registers, expected_initial_rules); + + { + let row = table.next_row().expect("Should evaluate first row OK"); + let expected = UnwindTableRow { + start_address: 0, + end_address: 1, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [ + (Register(0), RegisterRule::Offset(8)), + (Register(3), RegisterRule::Offset(4)), + ] + .iter() + .collect(), + }; + assert_eq!(Some(&expected), row); + } + + { + let row = table.next_row().expect("Should evaluate second row OK"); + let expected = UnwindTableRow { + start_address: 1, + end_address: 33, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [ + (Register(0), RegisterRule::Offset(-16)), + (Register(3), RegisterRule::Offset(4)), + ] + .iter() + .collect(), + }; + assert_eq!(Some(&expected), row); + } + + { + let row = table.next_row().expect("Should evaluate third row OK"); + let expected = UnwindTableRow { + start_address: 33, + end_address: 97, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [ + (Register(0), RegisterRule::Offset(-16)), + (Register(3), RegisterRule::Offset(-4)), + ] + .iter() + .collect(), + }; + assert_eq!(Some(&expected), row); + } + + { + let row = table.next_row().expect("Should evaluate fourth row OK"); + let expected = UnwindTableRow { + start_address: 97, + end_address: 100, + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [ + (Register(0), RegisterRule::Offset(-16)), + (Register(3), RegisterRule::Offset(-4)), + (Register(5), RegisterRule::Offset(4)), + ] + .iter() + .collect(), + }; + assert_eq!(Some(&expected), row); + } + + // All done! + assert_eq!(Ok(None), table.next_row()); + assert_eq!(Ok(None), table.next_row()); + } + + #[test] + fn test_unwind_info_for_address_ok() { + let instrs1 = Section::with_endian(Endian::Big) + // The CFA is -12 from register 4. + .D8(constants::DW_CFA_def_cfa_sf.0) + .uleb(4) + .sleb(-12); + let instrs1 = instrs1.get_contents().unwrap(); + + let instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect(); + + let instrs3 = Section::with_endian(Endian::Big) + // Initial instructions form a row, advance the address by 100. + .D8(constants::DW_CFA_advance_loc1.0) + .D8(100) + // Register 0 is -16 from the CFA. + .D8(constants::DW_CFA_offset_extended_sf.0) + .uleb(0) + .sleb(-16); + let instrs3 = instrs3.get_contents().unwrap(); + + let instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect(); + + let mut cie1 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 8, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(3), + initial_instructions: EndianSlice::new(&instrs1, BigEndian), + }; + + let mut cie2 = CommonInformationEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + version: 4, + augmentation: None, + address_size: 4, + code_alignment_factor: 1, + data_alignment_factor: 1, + return_address_register: Register(1), + initial_instructions: EndianSlice::new(&instrs2, BigEndian), + }; + + let cie1_location = Label::new(); + let cie2_location = Label::new(); + + // Write the CIEs first so that their length gets set before we clone + // them into the FDEs and our equality assertions down the line end up + // with all the CIEs always having he correct length. + let kind = debug_frame_be(); + let section = Section::with_endian(kind.endian()) + .mark(&cie1_location) + .cie(kind, None, &mut cie1) + .mark(&cie2_location) + .cie(kind, None, &mut cie2); + + let mut fde1 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie1.clone(), + initial_address: 0xfeed_beef, + address_range: 200, + augmentation: None, + instructions: EndianSlice::new(&instrs3, BigEndian), + }; + + let mut fde2 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie2.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: None, + instructions: EndianSlice::new(&instrs4, BigEndian), + }; + + let section = + section + .fde(kind, &cie1_location, &mut fde1) + .fde(kind, &cie2_location, &mut fde2); + section.start().set_const(0); + + let contents = section.get_contents().unwrap(); + let debug_frame = kind.section(&contents); + + // Get the second row of the unwind table in `instrs3`. + let bases = Default::default(); + let mut ctx = Box::new(UnwindContext::new()); + let result = debug_frame.unwind_info_for_address( + &bases, + &mut ctx, + 0xfeed_beef + 150, + DebugFrame::cie_from_offset, + ); + assert!(result.is_ok()); + let unwind_info = result.unwrap(); + + assert_eq!( + *unwind_info, + UnwindTableRow { + start_address: fde1.initial_address() + 100, + end_address: fde1.end_address(), + saved_args_size: 0, + cfa: CfaRule::RegisterAndOffset { + register: Register(4), + offset: -12, + }, + registers: [(Register(0), RegisterRule::Offset(-16))].iter().collect(), + } + ); + } + + #[test] + fn test_unwind_info_for_address_not_found() { + let debug_frame = DebugFrame::new(&[], NativeEndian); + let bases = Default::default(); + let mut ctx = Box::new(UnwindContext::new()); + let result = debug_frame.unwind_info_for_address( + &bases, + &mut ctx, + 0xbadb_ad99, + DebugFrame::cie_from_offset, + ); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress); + } + + #[test] + fn test_eh_frame_hdr_unknown_version() { + let bases = BaseAddresses::default(); + let buf = &[42]; + let result = EhFrameHdr::new(buf, NativeEndian).parse(&bases, 8); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), Error::UnknownVersion(42)); + } + + #[test] + fn test_eh_frame_hdr_omit_ehptr() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0xff) + .L8(0x03) + .L8(0x0b) + .L32(2) + .L32(10) + .L32(1) + .L32(20) + .L32(2) + .L32(0); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), Error::CannotParseOmitPointerEncoding); + } + + #[test] + fn test_eh_frame_hdr_omit_count() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x0b) + .L8(0xff) + .L8(0x0b) + .L32(0x12345); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345)); + assert!(result.table().is_none()); + } + + #[test] + fn test_eh_frame_hdr_omit_table() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x0b) + .L8(0x03) + .L8(0xff) + .L32(0x12345) + .L32(2); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345)); + assert!(result.table().is_none()); + } + + #[test] + fn test_eh_frame_hdr_varlen_table() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x0b) + .L8(0x03) + .L8(0x01) + .L32(0x12345) + .L32(2); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345)); + let table = result.table(); + assert!(table.is_some()); + let table = table.unwrap(); + assert_eq!( + table.lookup(0, &bases), + Err(Error::VariableLengthSearchTable) + ); + } + + #[test] + fn test_eh_frame_hdr_indirect_length() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x0b) + .L8(0x83) + .L8(0x0b) + .L32(0x12345) + .L32(2); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding); + } + + #[test] + fn test_eh_frame_hdr_indirect_ptrs() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x8b) + .L8(0x03) + .L8(0x8b) + .L32(0x12345) + .L32(2) + .L32(10) + .L32(1) + .L32(20) + .L32(2); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!(result.eh_frame_ptr(), Pointer::Indirect(0x12345)); + let table = result.table(); + assert!(table.is_some()); + let table = table.unwrap(); + assert_eq!( + table.lookup(0, &bases), + Err(Error::UnsupportedPointerEncoding) + ); + } + + #[test] + fn test_eh_frame_hdr_good() { + let section = Section::with_endian(Endian::Little) + .L8(1) + .L8(0x0b) + .L8(0x03) + .L8(0x0b) + .L32(0x12345) + .L32(2) + .L32(10) + .L32(1) + .L32(20) + .L32(2); + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let result = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(result.is_ok()); + let result = result.unwrap(); + assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345)); + let table = result.table(); + assert!(table.is_some()); + let table = table.unwrap(); + assert_eq!(table.lookup(0, &bases), Ok(Pointer::Direct(1))); + assert_eq!(table.lookup(9, &bases), Ok(Pointer::Direct(1))); + assert_eq!(table.lookup(10, &bases), Ok(Pointer::Direct(1))); + assert_eq!(table.lookup(11, &bases), Ok(Pointer::Direct(1))); + assert_eq!(table.lookup(19, &bases), Ok(Pointer::Direct(1))); + assert_eq!(table.lookup(20, &bases), Ok(Pointer::Direct(2))); + assert_eq!(table.lookup(21, &bases), Ok(Pointer::Direct(2))); + assert_eq!(table.lookup(100_000, &bases), Ok(Pointer::Direct(2))); + } + + #[test] + fn test_eh_frame_fde_for_address_good() { + // First, setup eh_frame + // Write the CIE first so that its length gets set before we clone it + // into the FDE. + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + + let start_of_cie = Label::new(); + let end_of_cie = Label::new(); + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .append_repeated(0, 16) + .mark(&start_of_cie) + .cie(kind, None, &mut cie) + .mark(&end_of_cie); + + let mut fde1 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 9, + address_range: 4, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + let mut fde2 = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 20, + address_range: 8, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let start_of_fde1 = Label::new(); + let start_of_fde2 = Label::new(); + + let section = section + // +4 for the FDE length before the CIE offset. + .mark(&start_of_fde1) + .fde(kind, (&start_of_fde1 - &start_of_cie + 4) as u64, &mut fde1) + .mark(&start_of_fde2) + .fde(kind, (&start_of_fde2 - &start_of_cie + 4) as u64, &mut fde2); + + section.start().set_const(0); + let section = section.get_contents().unwrap(); + let eh_frame = kind.section(§ion); + + // Setup eh_frame_hdr + let section = Section::with_endian(kind.endian()) + .L8(1) + .L8(0x0b) + .L8(0x03) + .L8(0x0b) + .L32(0x12345) + .L32(2) + .L32(10) + .L32(0x12345 + start_of_fde1.value().unwrap() as u32) + .L32(20) + .L32(0x12345 + start_of_fde2.value().unwrap() as u32); + + let section = section.get_contents().unwrap(); + let bases = BaseAddresses::default(); + let eh_frame_hdr = EhFrameHdr::new(§ion, LittleEndian).parse(&bases, 8); + assert!(eh_frame_hdr.is_ok()); + let eh_frame_hdr = eh_frame_hdr.unwrap(); + + let table = eh_frame_hdr.table(); + assert!(table.is_some()); + let table = table.unwrap(); + + let bases = Default::default(); + let mut iter = table.iter(&bases); + assert_eq!( + iter.next(), + Ok(Some(( + Pointer::Direct(10), + Pointer::Direct(0x12345 + start_of_fde1.value().unwrap()) + ))) + ); + assert_eq!( + iter.next(), + Ok(Some(( + Pointer::Direct(20), + Pointer::Direct(0x12345 + start_of_fde2.value().unwrap()) + ))) + ); + assert_eq!(iter.next(), Ok(None)); + + assert_eq!( + table.iter(&bases).nth(0), + Ok(Some(( + Pointer::Direct(10), + Pointer::Direct(0x12345 + start_of_fde1.value().unwrap()) + ))) + ); + + assert_eq!( + table.iter(&bases).nth(1), + Ok(Some(( + Pointer::Direct(20), + Pointer::Direct(0x12345 + start_of_fde2.value().unwrap()) + ))) + ); + assert_eq!(table.iter(&bases).nth(2), Ok(None)); + + let f = |_: &_, _: &_, o: EhFrameOffset| { + assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize)); + Ok(cie.clone()) + }; + assert_eq!( + table.fde_for_address(&eh_frame, &bases, 9, f), + Ok(fde1.clone()) + ); + assert_eq!( + table.fde_for_address(&eh_frame, &bases, 10, f), + Ok(fde1.clone()) + ); + assert_eq!(table.fde_for_address(&eh_frame, &bases, 11, f), Ok(fde1)); + assert_eq!( + table.fde_for_address(&eh_frame, &bases, 19, f), + Err(Error::NoUnwindInfoForAddress) + ); + assert_eq!( + table.fde_for_address(&eh_frame, &bases, 20, f), + Ok(fde2.clone()) + ); + assert_eq!(table.fde_for_address(&eh_frame, &bases, 21, f), Ok(fde2)); + assert_eq!( + table.fde_for_address(&eh_frame, &bases, 100_000, f), + Err(Error::NoUnwindInfoForAddress) + ); + } + + #[test] + fn test_eh_frame_stops_at_zero_length() { + let mut cie = make_test_cie(); + let kind = eh_frame_le(); + let section = Section::with_endian(Endian::Little) + .L32(0) + .cie(kind, None, &mut cie) + .L32(0); + let contents = section.get_contents().unwrap(); + let eh_frame = kind.section(&contents); + let bases = Default::default(); + + let mut entries = eh_frame.entries(&bases); + assert_eq!(entries.next(), Ok(None)); + + assert_eq!( + eh_frame.cie_from_offset(&bases, EhFrameOffset(0)), + Err(Error::NoEntryAtGivenOffset) + ); + } + + #[test] + fn test_debug_frame_skips_zero_length() { + let mut cie = make_test_cie(); + let kind = debug_frame_le(); + let section = Section::with_endian(Endian::Little) + .L32(0) + .cie(kind, None, &mut cie) + .L32(0); + let contents = section.get_contents().unwrap(); + let debug_frame = kind.section(&contents); + let bases = Default::default(); + + let mut entries = debug_frame.entries(&bases); + assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie)))); + assert_eq!(entries.next(), Ok(None)); + + assert_eq!( + debug_frame.cie_from_offset(&bases, DebugFrameOffset(0)), + Err(Error::NoEntryAtGivenOffset) + ); + } + + fn resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result { + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf64, + cie: make_test_cie(), + initial_address: 0xfeed_beef, + address_range: 39, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .append_bytes(buf) + .fde(kind, cie_offset as u64, &mut fde) + .append_bytes(buf); + + let section = section.get_contents().unwrap(); + let eh_frame = kind.section(§ion); + let input = &mut EndianSlice::new(§ion[buf.len()..], LittleEndian); + + let bases = Default::default(); + match parse_cfi_entry(&bases, &eh_frame, input) { + Ok(Some(CieOrFde::Fde(partial))) => Ok(partial.cie_offset.0), + Err(e) => Err(e), + otherwise => panic!("Unexpected result: {:#?}", otherwise), + } + } + + #[test] + fn test_eh_frame_resolve_cie_offset_ok() { + let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let cie_offset = 2; + // + 4 for size of length field + assert_eq!( + resolve_cie_offset(&buf, buf.len() + 4 - cie_offset), + Ok(cie_offset) + ); + } + + #[test] + fn test_eh_frame_resolve_cie_offset_out_of_bounds() { + let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + assert_eq!( + resolve_cie_offset(&buf, buf.len() + 4 + 2), + Err(Error::OffsetOutOfBounds) + ); + } + + #[test] + fn test_eh_frame_resolve_cie_offset_underflow() { + let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + assert_eq!( + resolve_cie_offset(&buf, usize::MAX), + Err(Error::OffsetOutOfBounds) + ); + } + + #[test] + fn test_eh_frame_fde_ok() { + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + + let start_of_cie = Label::new(); + let end_of_cie = Label::new(); + + // Write the CIE first so that its length gets set before we clone it + // into the FDE. + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .append_repeated(0, 16) + .mark(&start_of_cie) + .cie(kind, None, &mut cie) + .mark(&end_of_cie); + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_beef, + address_range: 999, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let section = section + // +4 for the FDE length before the CIE offset. + .fde(kind, (&end_of_cie - &start_of_cie + 4) as u64, &mut fde); + + section.start().set_const(0); + let section = section.get_contents().unwrap(); + let eh_frame = kind.section(§ion); + let section = EndianSlice::new(§ion, LittleEndian); + + let mut offset = None; + let result = parse_fde( + eh_frame, + &mut section.range_from(end_of_cie.value().unwrap() as usize..), + |_, _, o| { + offset = Some(o); + assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize)); + Ok(cie.clone()) + }, + ); + match result { + Ok(actual) => assert_eq!(actual, fde), + otherwise => panic!("Unexpected result {:?}", otherwise), + } + assert!(offset.is_some()); + } + + #[test] + fn test_eh_frame_fde_out_of_bounds() { + let mut cie = make_test_cie(); + cie.version = 1; + + let end_of_cie = Label::new(); + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf64, + cie: cie.clone(), + initial_address: 0xfeed_beef, + address_range: 999, + augmentation: None, + instructions: EndianSlice::new(&[], LittleEndian), + }; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .cie(kind, None, &mut cie) + .mark(&end_of_cie) + .fde(kind, 99_999_999_999_999, &mut fde); + + section.start().set_const(0); + let section = section.get_contents().unwrap(); + let eh_frame = kind.section(§ion); + let section = EndianSlice::new(§ion, LittleEndian); + + let result = parse_fde( + eh_frame, + &mut section.range_from(end_of_cie.value().unwrap() as usize..), + UnwindSection::cie_from_offset, + ); + assert_eq!(result, Err(Error::OffsetOutOfBounds)); + } + + #[test] + fn test_augmentation_parse_not_z_augmentation() { + let augmentation = &mut EndianSlice::new(b"wtf", NativeEndian); + let bases = Default::default(); + let address_size = 8; + let section = EhFrame::new(&[], NativeEndian); + let input = &mut EndianSlice::new(&[], NativeEndian); + assert_eq!( + Augmentation::parse(augmentation, &bases, address_size, §ion, input), + Err(Error::UnknownAugmentation) + ); + } + + #[test] + fn test_augmentation_parse_just_signal_trampoline() { + let aug_str = &mut EndianSlice::new(b"S", LittleEndian); + let bases = Default::default(); + let address_size = 8; + let section = EhFrame::new(&[], LittleEndian); + let input = &mut EndianSlice::new(&[], LittleEndian); + + let augmentation = Augmentation { + is_signal_trampoline: true, + ..Default::default() + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + } + + #[test] + fn test_augmentation_parse_unknown_part_of_z_augmentation() { + // The 'Z' character is not defined by the z-style augmentation. + let bases = Default::default(); + let address_size = 8; + let section = Section::with_endian(Endian::Little) + .uleb(4) + .append_repeated(4, 4) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let augmentation = &mut EndianSlice::new(b"zZ", LittleEndian); + assert_eq!( + Augmentation::parse(augmentation, &bases, address_size, §ion, input), + Err(Error::UnknownAugmentation) + ); + } + + #[test] + #[allow(non_snake_case)] + fn test_augmentation_parse_L() { + let bases = Default::default(); + let address_size = 8; + let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let section = Section::with_endian(Endian::Little) + .uleb(1) + .D8(constants::DW_EH_PE_uleb128.0) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let aug_str = &mut EndianSlice::new(b"zL", LittleEndian); + + let augmentation = Augmentation { + lsda: Some(constants::DW_EH_PE_uleb128), + ..Default::default() + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + #[allow(non_snake_case)] + fn test_augmentation_parse_P() { + let bases = Default::default(); + let address_size = 8; + let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let section = Section::with_endian(Endian::Little) + .uleb(9) + .D8(constants::DW_EH_PE_udata8.0) + .L64(0xf00d_f00d) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let aug_str = &mut EndianSlice::new(b"zP", LittleEndian); + + let augmentation = Augmentation { + personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0xf00d_f00d))), + ..Default::default() + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + #[allow(non_snake_case)] + fn test_augmentation_parse_R() { + let bases = Default::default(); + let address_size = 8; + let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let section = Section::with_endian(Endian::Little) + .uleb(1) + .D8(constants::DW_EH_PE_udata4.0) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let aug_str = &mut EndianSlice::new(b"zR", LittleEndian); + + let augmentation = Augmentation { + fde_address_encoding: Some(constants::DW_EH_PE_udata4), + ..Default::default() + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + #[allow(non_snake_case)] + fn test_augmentation_parse_S() { + let bases = Default::default(); + let address_size = 8; + let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let section = Section::with_endian(Endian::Little) + .uleb(0) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let aug_str = &mut EndianSlice::new(b"zS", LittleEndian); + + let augmentation = Augmentation { + is_signal_trampoline: true, + ..Default::default() + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_augmentation_parse_all() { + let bases = Default::default(); + let address_size = 8; + let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let section = Section::with_endian(Endian::Little) + .uleb(1 + 9 + 1) + // L + .D8(constants::DW_EH_PE_uleb128.0) + // P + .D8(constants::DW_EH_PE_udata8.0) + .L64(0x1bad_f00d) + // R + .D8(constants::DW_EH_PE_uleb128.0) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + let input = &mut section.section().clone(); + let aug_str = &mut EndianSlice::new(b"zLPRS", LittleEndian); + + let augmentation = Augmentation { + lsda: Some(constants::DW_EH_PE_uleb128), + personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0x1bad_f00d))), + fde_address_encoding: Some(constants::DW_EH_PE_uleb128), + is_signal_trampoline: true, + }; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_eh_frame_fde_no_augmentation() { + let instrs = [1, 2, 3, 4]; + let cie_offset = 1; + + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: None, + instructions: EndianSlice::new(&instrs, LittleEndian), + }; + + let rest = [1, 2, 3, 4]; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = kind.section(§ion); + let input = &mut section.section().clone(); + + let result = parse_fde(section, input, |_, _, _| Ok(cie.clone())); + assert_eq!(result, Ok(fde)); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_eh_frame_fde_empty_augmentation() { + let instrs = [1, 2, 3, 4]; + let cie_offset = 1; + + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + cie.augmentation = Some(Augmentation::default()); + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: Some(AugmentationData::default()), + instructions: EndianSlice::new(&instrs, LittleEndian), + }; + + let rest = [1, 2, 3, 4]; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = kind.section(§ion); + let input = &mut section.section().clone(); + + let result = parse_fde(section, input, |_, _, _| Ok(cie.clone())); + assert_eq!(result, Ok(fde)); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_eh_frame_fde_lsda_augmentation() { + let instrs = [1, 2, 3, 4]; + let cie_offset = 1; + + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + cie.augmentation = Some(Augmentation::default()); + cie.augmentation.as_mut().unwrap().lsda = Some(constants::DW_EH_PE_absptr); + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: Some(AugmentationData { + lsda: Some(Pointer::Direct(0x1122_3344)), + }), + instructions: EndianSlice::new(&instrs, LittleEndian), + }; + + let rest = [1, 2, 3, 4]; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = kind.section(§ion); + let input = &mut section.section().clone(); + + let result = parse_fde(section, input, |_, _, _| Ok(cie.clone())); + assert_eq!(result, Ok(fde)); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_eh_frame_fde_lsda_function_relative() { + let instrs = [1, 2, 3, 4]; + let cie_offset = 1; + + let mut cie = make_test_cie(); + cie.format = Format::Dwarf32; + cie.version = 1; + cie.augmentation = Some(Augmentation::default()); + cie.augmentation.as_mut().unwrap().lsda = + Some(constants::DW_EH_PE_funcrel | constants::DW_EH_PE_absptr); + + let mut fde = FrameDescriptionEntry { + offset: 0, + length: 0, + format: Format::Dwarf32, + cie: cie.clone(), + initial_address: 0xfeed_face, + address_range: 9000, + augmentation: Some(AugmentationData { + lsda: Some(Pointer::Direct(0xbeef)), + }), + instructions: EndianSlice::new(&instrs, LittleEndian), + }; + + let rest = [1, 2, 3, 4]; + + let kind = eh_frame_le(); + let section = Section::with_endian(kind.endian()) + .append_repeated(10, 10) + .fde(kind, cie_offset, &mut fde) + .append_bytes(&rest) + .get_contents() + .unwrap(); + let section = kind.section(§ion); + let input = &mut section.section().range_from(10..); + + // Adjust the FDE's augmentation to be relative to the function. + fde.augmentation.as_mut().unwrap().lsda = Some(Pointer::Direct(0xfeed_face + 0xbeef)); + + let result = parse_fde(section, input, |_, _, _| Ok(cie.clone())); + assert_eq!(result, Ok(fde)); + assert_eq!(*input, EndianSlice::new(&rest, LittleEndian)); + } + + #[test] + fn test_eh_frame_cie_personality_function_relative_bad_context() { + let instrs = [1, 2, 3, 4]; + + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let aug_len = Label::new(); + let aug_start = Label::new(); + let aug_end = Label::new(); + + let section = Section::with_endian(Endian::Little) + // Length + .L32(&length) + .mark(&start) + // CIE ID + .L32(0) + // Version + .D8(1) + // Augmentation + .append_bytes(b"zP\0") + // Code alignment factor + .uleb(1) + // Data alignment factor + .sleb(1) + // Return address register + .uleb(1) + // Augmentation data length. This is a uleb, be we rely on the value + // being less than 2^7 and therefore a valid uleb (can't use Label + // with uleb). + .D8(&aug_len) + .mark(&aug_start) + // Augmentation data. Personality encoding and then encoded pointer. + .D8(constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_uleb128.0) + .uleb(1) + .mark(&aug_end) + // Initial instructions + .append_bytes(&instrs) + .mark(&end); + + length.set_const((&end - &start) as u64); + aug_len.set_const((&aug_end - &aug_start) as u64); + + let section = section.get_contents().unwrap(); + let section = EhFrame::new(§ion, LittleEndian); + + let bases = BaseAddresses::default(); + let mut iter = section.entries(&bases); + assert_eq!(iter.next(), Err(Error::FuncRelativePointerInBadContext)); + } + + #[test] + fn register_rule_map_eq() { + // Different order, but still equal. + let map1: RegisterRuleMap = [ + (Register(0), RegisterRule::SameValue), + (Register(3), RegisterRule::Offset(1)), + ] + .iter() + .collect(); + let map2: RegisterRuleMap = [ + (Register(3), RegisterRule::Offset(1)), + (Register(0), RegisterRule::SameValue), + ] + .iter() + .collect(); + assert_eq!(map1, map2); + assert_eq!(map2, map1); + + // Not equal. + let map3: RegisterRuleMap = [ + (Register(0), RegisterRule::SameValue), + (Register(2), RegisterRule::Offset(1)), + ] + .iter() + .collect(); + let map4: RegisterRuleMap = [ + (Register(3), RegisterRule::Offset(1)), + (Register(0), RegisterRule::SameValue), + ] + .iter() + .collect(); + assert!(map3 != map4); + assert!(map4 != map3); + + // One has undefined explicitly set, other implicitly has undefined. + let mut map5 = RegisterRuleMap::::default(); + map5.set(Register(0), RegisterRule::SameValue).unwrap(); + map5.set(Register(0), RegisterRule::Undefined).unwrap(); + let map6 = RegisterRuleMap::::default(); + assert_eq!(map5, map6); + assert_eq!(map6, map5); + } + + #[test] + fn iter_register_rules() { + let row = UnwindTableRow:: { + registers: [ + (Register(0), RegisterRule::SameValue), + (Register(1), RegisterRule::Offset(1)), + (Register(2), RegisterRule::ValOffset(2)), + ] + .iter() + .collect(), + ..Default::default() + }; + + let mut found0 = false; + let mut found1 = false; + let mut found2 = false; + + for &(register, ref rule) in row.registers() { + match register.0 { + 0 => { + assert!(!found0); + found0 = true; + assert_eq!(*rule, RegisterRule::SameValue); + } + 1 => { + assert!(!found1); + found1 = true; + assert_eq!(*rule, RegisterRule::Offset(1)); + } + 2 => { + assert!(!found2); + found2 = true; + assert_eq!(*rule, RegisterRule::ValOffset(2)); + } + x => panic!("Unexpected register rule: ({}, {:?})", x, rule), + } + } + + assert!(found0); + assert!(found1); + assert!(found2); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn size_of_unwind_ctx() { + use core::mem; + let size = mem::size_of::>(); + let max_size = 30968; + if size > max_size { + assert_eq!(size, max_size); + } + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn size_of_register_rule_map() { + use core::mem; + let size = mem::size_of::>(); + let max_size = 6152; + if size > max_size { + assert_eq!(size, max_size); + } + } + + #[test] + fn test_parse_pointer_encoding_ok() { + use crate::endianity::NativeEndian; + let expected = constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_pcrel; + let input = [expected.0, 1, 2, 3, 4]; + let input = &mut EndianSlice::new(&input, NativeEndian); + assert_eq!(parse_pointer_encoding(input), Ok(expected)); + assert_eq!(*input, EndianSlice::new(&[1, 2, 3, 4], NativeEndian)); + } + + #[test] + fn test_parse_pointer_encoding_bad_encoding() { + use crate::endianity::NativeEndian; + let expected = + constants::DwEhPe((constants::DW_EH_PE_sdata8.0 + 1) | constants::DW_EH_PE_pcrel.0); + let input = [expected.0, 1, 2, 3, 4]; + let input = &mut EndianSlice::new(&input, NativeEndian); + assert_eq!( + Err(Error::UnknownPointerEncoding(expected)), + parse_pointer_encoding(input) + ); + } + + #[test] + fn test_parse_encoded_pointer_absptr() { + let encoding = constants::DW_EH_PE_absptr; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L32(0xf00d_f00d) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0xf00d_f00d)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_pcrel() { + let encoding = constants::DW_EH_PE_pcrel; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .append_repeated(0, 0x10) + .L32(0x1) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input.range_from(0x10..); + + let parameters = PointerEncodingParameters { + bases: &BaseAddresses::default().set_eh_frame(0x100).eh_frame, + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x111)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_pcrel_undefined() { + let encoding = constants::DW_EH_PE_pcrel; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::PcRelativePointerButSectionBaseIsUndefined) + ); + } + + #[test] + fn test_parse_encoded_pointer_textrel() { + let encoding = constants::DW_EH_PE_textrel; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L32(0x1) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &BaseAddresses::default().set_text(0x10).eh_frame, + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x11)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_textrel_undefined() { + let encoding = constants::DW_EH_PE_textrel; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::TextRelativePointerButTextBaseIsUndefined) + ); + } + + #[test] + fn test_parse_encoded_pointer_datarel() { + let encoding = constants::DW_EH_PE_datarel; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L32(0x1) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &BaseAddresses::default().set_got(0x10).eh_frame, + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x11)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_datarel_undefined() { + let encoding = constants::DW_EH_PE_datarel; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::DataRelativePointerButDataBaseIsUndefined) + ); + } + + #[test] + fn test_parse_encoded_pointer_funcrel() { + let encoding = constants::DW_EH_PE_funcrel; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L32(0x1) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: Some(0x10), + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x11)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_funcrel_undefined() { + let encoding = constants::DW_EH_PE_funcrel; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::FuncRelativePointerInBadContext) + ); + } + + #[test] + fn test_parse_encoded_pointer_uleb128() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_uleb128; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .uleb(0x12_3456) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x12_3456)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_udata2() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata2; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L16(0x1234) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x1234)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_udata4() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata4; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L32(0x1234_5678) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x1234_5678)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_udata8() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_udata8; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .L64(0x1234_5678_1234_5678) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x1234_5678_1234_5678)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_sleb128() { + let encoding = constants::DW_EH_PE_textrel | constants::DW_EH_PE_sleb128; + let expected_rest = [1, 2, 3, 4]; + + let input = Section::with_endian(Endian::Little) + .sleb(-0x1111) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &BaseAddresses::default().set_text(0x1111_1111).eh_frame, + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(0x1111_0000)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_sdata2() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata2; + let expected_rest = [1, 2, 3, 4]; + let expected = 0x111_i16; + + let input = Section::with_endian(Endian::Little) + .L16(expected as u16) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(expected as u64)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_sdata4() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata4; + let expected_rest = [1, 2, 3, 4]; + let expected = 0x111_1111_i32; + + let input = Section::with_endian(Endian::Little) + .L32(expected as u32) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(expected as u64)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_sdata8() { + let encoding = constants::DW_EH_PE_absptr | constants::DW_EH_PE_sdata8; + let expected_rest = [1, 2, 3, 4]; + let expected = -0x11_1111_1222_2222_i64; + + let input = Section::with_endian(Endian::Little) + .L64(expected as u64) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 8, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Direct(expected as u64)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_encoded_pointer_omit() { + let encoding = constants::DW_EH_PE_omit; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::CannotParseOmitPointerEncoding) + ); + assert_eq!(rest, input); + } + + #[test] + fn test_parse_encoded_pointer_bad_encoding() { + let encoding = constants::DwEhPe(constants::DW_EH_PE_sdata8.0 + 1); + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::UnknownPointerEncoding(encoding)) + ); + } + + #[test] + fn test_parse_encoded_pointer_aligned() { + // FIXME: support this encoding! + + let encoding = constants::DW_EH_PE_aligned; + + let input = Section::with_endian(Endian::Little).L32(0x1); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Err(Error::UnsupportedPointerEncoding) + ); + } + + #[test] + fn test_parse_encoded_pointer_indirect() { + let expected_rest = [1, 2, 3, 4]; + let encoding = constants::DW_EH_PE_indirect; + + let input = Section::with_endian(Endian::Little) + .L32(0x1234_5678) + .append_bytes(&expected_rest); + let input = input.get_contents().unwrap(); + let input = EndianSlice::new(&input, LittleEndian); + let mut rest = input; + + let parameters = PointerEncodingParameters { + bases: &SectionBaseAddresses::default(), + func_base: None, + address_size: 4, + section: &input, + }; + assert_eq!( + parse_encoded_pointer(encoding, ¶meters, &mut rest), + Ok(Pointer::Indirect(0x1234_5678)) + ); + assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian)); + } + + #[test] + fn test_unwind_context_reuse() { + fn unwind_one(ctx: &mut UnwindContext, data: &[u8]) { + let debug_frame = DebugFrame::new(data, NativeEndian); + let bases = Default::default(); + let result = debug_frame.unwind_info_for_address( + &bases, + ctx, + 0xbadb_ad99, + DebugFrame::cie_from_offset, + ); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress); + } + + // Use the same context for two different data lifetimes. + let mut ctx: UnwindContext = UnwindContext::new(); + { + let data1 = vec![]; + unwind_one(&mut ctx, &data1); + } + { + let data2 = vec![]; + unwind_one(&mut ctx, &data2); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/read/dwarf.rs b/anneal/v2/vendor/gimli/src/read/dwarf.rs new file mode 100644 index 0000000000..efb37b62b3 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/dwarf.rs @@ -0,0 +1,1724 @@ +use alloc::string::String; +use alloc::sync::Arc; + +use crate::common::{ + DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase, + DebugLocListsIndex, DebugMacinfoOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, + DebugStrOffsetsBase, DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwarfFileType, + DwoId, Encoding, LocationListsOffset, RangeListsOffset, RawRangeListsOffset, SectionId, + UnitSectionOffset, +}; +use crate::read::{ + Abbreviations, AbbreviationsCache, AbbreviationsCacheStrategy, AttributeValue, DebugAbbrev, + DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine, + DebugLineStr, DebugLoc, DebugLocLists, DebugMacinfo, DebugMacro, DebugRanges, DebugRngLists, + DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter, + DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error, + IncompleteLineProgram, IndexSectionId, LocListIter, LocationLists, MacroIter, Range, + RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result, + RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType, +}; +use crate::{constants, DebugMacroOffset}; + +/// All of the commonly used DWARF sections. +/// +/// This is useful for storing sections when `T` does not implement `Reader`. +/// It can be used to create a `Dwarf` that references the data in `self`. +/// If `T` does implement `Reader`, then use `Dwarf` directly. +/// +/// ## Example Usage +/// +/// It can be useful to load DWARF sections into owned data structures, +/// such as `Vec`. However, we do not implement the `Reader` trait +/// for `Vec`, because it would be very inefficient, but this trait +/// is required for all of the methods that parse the DWARF data. +/// So we first load the DWARF sections into `Vec`s, and then use +/// `borrow` to create `Reader`s that reference the data. +/// +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; +/// // Read the DWARF sections into `Vec`s with whatever object loader you're using. +/// let dwarf_sections: gimli::DwarfSections> = gimli::DwarfSections::load(loader)?; +/// // Create references to the DWARF sections. +/// let dwarf: gimli::Dwarf<_> = dwarf_sections.borrow(|section| { +/// gimli::EndianSlice::new(§ion, gimli::LittleEndian) +/// }); +/// # unreachable!() +/// # } +/// ``` +#[derive(Debug, Default)] +pub struct DwarfSections { + /// The `.debug_abbrev` section. + pub debug_abbrev: DebugAbbrev, + /// The `.debug_addr` section. + pub debug_addr: DebugAddr, + /// The `.debug_aranges` section. + pub debug_aranges: DebugAranges, + /// The `.debug_info` section. + pub debug_info: DebugInfo, + /// The `.debug_line` section. + pub debug_line: DebugLine, + /// The `.debug_line_str` section. + pub debug_line_str: DebugLineStr, + /// The `.debug_macinfo` section. + pub debug_macinfo: DebugMacinfo, + /// The `.debug_macro` section. + pub debug_macro: DebugMacro, + /// The `.debug_str` section. + pub debug_str: DebugStr, + /// The `.debug_str_offsets` section. + pub debug_str_offsets: DebugStrOffsets, + /// The `.debug_types` section. + pub debug_types: DebugTypes, + /// The `.debug_loc` section. + pub debug_loc: DebugLoc, + /// The `.debug_loclists` section. + pub debug_loclists: DebugLocLists, + /// The `.debug_ranges` section. + pub debug_ranges: DebugRanges, + /// The `.debug_rnglists` section. + pub debug_rnglists: DebugRngLists, +} + +impl DwarfSections { + /// Try to load the DWARF sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + pub fn load(mut section: F) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + { + Ok(DwarfSections { + // Section types are inferred. + debug_abbrev: Section::load(&mut section)?, + debug_addr: Section::load(&mut section)?, + debug_aranges: Section::load(&mut section)?, + debug_info: Section::load(&mut section)?, + debug_line: Section::load(&mut section)?, + debug_line_str: Section::load(&mut section)?, + debug_macinfo: Section::load(&mut section)?, + debug_macro: Section::load(&mut section)?, + debug_str: Section::load(&mut section)?, + debug_str_offsets: Section::load(&mut section)?, + debug_types: Section::load(&mut section)?, + debug_loc: Section::load(&mut section)?, + debug_loclists: Section::load(&mut section)?, + debug_ranges: Section::load(&mut section)?, + debug_rnglists: Section::load(&mut section)?, + }) + } + + /// Create a `Dwarf` structure that references the data in `self`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf + where + F: FnMut(&'a T) -> R, + { + Dwarf::from_sections(DwarfSections { + debug_abbrev: self.debug_abbrev.borrow(&mut borrow), + debug_addr: self.debug_addr.borrow(&mut borrow), + debug_aranges: self.debug_aranges.borrow(&mut borrow), + debug_info: self.debug_info.borrow(&mut borrow), + debug_line: self.debug_line.borrow(&mut borrow), + debug_line_str: self.debug_line_str.borrow(&mut borrow), + debug_macinfo: self.debug_macinfo.borrow(&mut borrow), + debug_macro: self.debug_macro.borrow(&mut borrow), + debug_str: self.debug_str.borrow(&mut borrow), + debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow), + debug_types: self.debug_types.borrow(&mut borrow), + debug_loc: self.debug_loc.borrow(&mut borrow), + debug_loclists: self.debug_loclists.borrow(&mut borrow), + debug_ranges: self.debug_ranges.borrow(&mut borrow), + debug_rnglists: self.debug_rnglists.borrow(&mut borrow), + }) + } + + /// Create a `Dwarf` structure that references the data in `self` and `sup`. + /// + /// This is like `borrow`, but also includes the supplementary object file. + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// ## Example Usage + /// + /// ```rust,no_run + /// # fn example() -> Result<(), gimli::Error> { + /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// // Read the DWARF sections into `Vec`s with whatever object loader you're using. + /// let dwarf_sections: gimli::DwarfSections> = gimli::DwarfSections::load(loader)?; + /// let dwarf_sup_sections: gimli::DwarfSections> = gimli::DwarfSections::load(sup_loader)?; + /// // Create references to the DWARF sections. + /// let dwarf = dwarf_sections.borrow_with_sup(&dwarf_sup_sections, |section| { + /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) + /// }); + /// # unreachable!() + /// # } + /// ``` + pub fn borrow_with_sup<'a, F, R>(&'a self, sup: &'a Self, mut borrow: F) -> Dwarf + where + F: FnMut(&'a T) -> R, + { + let mut dwarf = self.borrow(&mut borrow); + dwarf.set_sup(sup.borrow(&mut borrow)); + dwarf + } +} + +/// All of the commonly used DWARF sections, and other common information. +#[derive(Debug, Default)] +pub struct Dwarf { + /// The `.debug_abbrev` section. + pub debug_abbrev: DebugAbbrev, + + /// The `.debug_addr` section. + pub debug_addr: DebugAddr, + + /// The `.debug_aranges` section. + pub debug_aranges: DebugAranges, + + /// The `.debug_info` section. + pub debug_info: DebugInfo, + + /// The `.debug_line` section. + pub debug_line: DebugLine, + + /// The `.debug_line_str` section. + pub debug_line_str: DebugLineStr, + + /// The `.debug_macinfo` section. + pub debug_macinfo: DebugMacinfo, + + /// The `.debug_macro` section. + pub debug_macro: DebugMacro, + + /// The `.debug_str` section. + pub debug_str: DebugStr, + + /// The `.debug_str_offsets` section. + pub debug_str_offsets: DebugStrOffsets, + + /// The `.debug_types` section. + pub debug_types: DebugTypes, + + /// The location lists in the `.debug_loc` and `.debug_loclists` sections. + pub locations: LocationLists, + + /// The range lists in the `.debug_ranges` and `.debug_rnglists` sections. + pub ranges: RangeLists, + + /// The type of this file. + pub file_type: DwarfFileType, + + /// The DWARF sections for a supplementary object file. + pub sup: Option>>, + + /// A cache of previously parsed abbreviations for units in this file. + pub abbreviations_cache: AbbreviationsCache, +} + +impl Dwarf { + /// Try to load the DWARF sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + /// + /// After loading, the user should set the `file_type` field and + /// call `load_sup` if required. + pub fn load(section: F) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + { + let sections = DwarfSections::load(section)?; + Ok(Self::from_sections(sections)) + } + + /// Load the DWARF sections from the supplementary object file. + /// + /// `section` operates the same as for `load`. + /// + /// Sets `self.sup`, replacing any previous value. + pub fn load_sup(&mut self, section: F) -> core::result::Result<(), E> + where + F: FnMut(SectionId) -> core::result::Result, + { + self.set_sup(Self::load(section)?); + Ok(()) + } + + /// Create a `Dwarf` structure from the given sections. + /// + /// The caller should set the `file_type` and `sup` fields if required. + fn from_sections(sections: DwarfSections) -> Self { + Dwarf { + debug_abbrev: sections.debug_abbrev, + debug_addr: sections.debug_addr, + debug_aranges: sections.debug_aranges, + debug_info: sections.debug_info, + debug_line: sections.debug_line, + debug_line_str: sections.debug_line_str, + debug_macinfo: sections.debug_macinfo, + debug_macro: sections.debug_macro, + debug_str: sections.debug_str, + debug_str_offsets: sections.debug_str_offsets, + debug_types: sections.debug_types, + locations: LocationLists::new(sections.debug_loc, sections.debug_loclists), + ranges: RangeLists::new(sections.debug_ranges, sections.debug_rnglists), + file_type: DwarfFileType::Main, + sup: None, + abbreviations_cache: AbbreviationsCache::new(), + } + } + + /// Create a `Dwarf` structure that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// ## Example Usage + /// + /// It can be useful to load DWARF sections into owned data structures, + /// such as `Vec`. However, we do not implement the `Reader` trait + /// for `Vec`, because it would be very inefficient, but this trait + /// is required for all of the methods that parse the DWARF data. + /// So we first load the DWARF sections into `Vec`s, and then use + /// `borrow` to create `Reader`s that reference the data. + /// + /// ```rust,no_run + /// # fn example() -> Result<(), gimli::Error> { + /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; + /// // Read the DWARF sections into `Vec`s with whatever object loader you're using. + /// let mut owned_dwarf: gimli::Dwarf> = gimli::Dwarf::load(loader)?; + /// owned_dwarf.load_sup(sup_loader)?; + /// // Create references to the DWARF sections. + /// let dwarf = owned_dwarf.borrow(|section| { + /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) + /// }); + /// # unreachable!() + /// # } + /// ``` + #[deprecated(note = "use `DwarfSections::borrow` instead")] + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf + where + F: FnMut(&'a T) -> R, + { + Dwarf { + debug_abbrev: self.debug_abbrev.borrow(&mut borrow), + debug_addr: self.debug_addr.borrow(&mut borrow), + debug_aranges: self.debug_aranges.borrow(&mut borrow), + debug_info: self.debug_info.borrow(&mut borrow), + debug_line: self.debug_line.borrow(&mut borrow), + debug_line_str: self.debug_line_str.borrow(&mut borrow), + debug_macinfo: self.debug_macinfo.borrow(&mut borrow), + debug_macro: self.debug_macro.borrow(&mut borrow), + debug_str: self.debug_str.borrow(&mut borrow), + debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow), + debug_types: self.debug_types.borrow(&mut borrow), + locations: self.locations.borrow(&mut borrow), + ranges: self.ranges.borrow(&mut borrow), + file_type: self.file_type, + sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))), + abbreviations_cache: AbbreviationsCache::new(), + } + } + + /// Store the DWARF sections for the supplementary object file. + pub fn set_sup(&mut self, sup: Dwarf) { + self.sup = Some(Arc::new(sup)); + } + + /// Return a reference to the DWARF sections for the supplementary object file. + pub fn sup(&self) -> Option<&Dwarf> { + self.sup.as_ref().map(Arc::as_ref) + } +} + +impl Dwarf { + /// Parse abbreviations and store them in the cache. + /// + /// This will iterate over the units in `self.debug_info` to determine the + /// abbreviations offsets. + /// + /// Errors during parsing abbreviations are also stored in the cache. + /// Errors during iterating over the units are ignored. + pub fn populate_abbreviations_cache(&mut self, strategy: AbbreviationsCacheStrategy) { + self.abbreviations_cache + .populate(strategy, &self.debug_abbrev, self.debug_info.units()); + } + + /// Iterate the unit headers in the `.debug_info` section. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + #[inline] + pub fn units(&self) -> DebugInfoUnitHeadersIter { + self.debug_info.units() + } + + /// Construct a new `Unit` from the given unit header. + #[inline] + pub fn unit(&self, header: UnitHeader) -> Result> { + Unit::new(self, header) + } + + /// Iterate the type-unit headers in the `.debug_types` section. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + #[inline] + pub fn type_units(&self) -> DebugTypesUnitHeadersIter { + self.debug_types.units() + } + + /// Parse the abbreviations for a compilation unit. + #[inline] + pub fn abbreviations(&self, unit: &UnitHeader) -> Result> { + self.abbreviations_cache + .get(&self.debug_abbrev, unit.debug_abbrev_offset()) + } + + /// Return the string offset at the given index. + #[inline] + pub fn string_offset( + &self, + unit: &Unit, + index: DebugStrOffsetsIndex, + ) -> Result> { + self.debug_str_offsets + .get_str_offset(unit.header.format(), unit.str_offsets_base, index) + } + + /// Return the string at the given offset in `.debug_str`. + #[inline] + pub fn string(&self, offset: DebugStrOffset) -> Result { + self.debug_str.get_str(offset) + } + + /// Return the string at the given offset in `.debug_line_str`. + #[inline] + pub fn line_string(&self, offset: DebugLineStrOffset) -> Result { + self.debug_line_str.get_str(offset) + } + + /// Return the string at the given offset in the `.debug_str` + /// in the supplementary object file. + #[inline] + pub fn sup_string(&self, offset: DebugStrOffset) -> Result { + if let Some(sup) = self.sup() { + sup.debug_str.get_str(offset) + } else { + Err(Error::ExpectedStringAttributeValue) + } + } + + /// Return an attribute value as a string slice. + /// + /// If the attribute value is one of: + /// + /// - an inline `DW_FORM_string` string + /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section + /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary + /// object file + /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str` + /// section + /// - a `DW_FORM_strx` index into the `.debug_str_offsets` entries for the unit + /// + /// then return the attribute's string value. Returns an error if the attribute + /// value does not have a string form, or if a string form has an invalid value. + pub fn attr_string(&self, unit: &Unit, attr: AttributeValue) -> Result { + match attr { + AttributeValue::String(string) => Ok(string), + AttributeValue::DebugStrRef(offset) => self.string(offset), + AttributeValue::DebugStrRefSup(offset) => self.sup_string(offset), + AttributeValue::DebugLineStrRef(offset) => self.line_string(offset), + AttributeValue::DebugStrOffsetsIndex(index) => { + let offset = self.string_offset(unit, index)?; + self.string(offset) + } + _ => Err(Error::ExpectedStringAttributeValue), + } + } + + /// Return the address at the given index. + pub fn address(&self, unit: &Unit, index: DebugAddrIndex) -> Result { + self.debug_addr + .get_address(unit.encoding().address_size, unit.addr_base, index) + } + + /// Try to return an attribute value as an address. + /// + /// If the attribute value is one of: + /// + /// - a `DW_FORM_addr` + /// - a `DW_FORM_addrx` index into the `.debug_addr` entries for the unit + /// + /// then return the address. + /// Returns `None` for other forms. + pub fn attr_address(&self, unit: &Unit, attr: AttributeValue) -> Result> { + match attr { + AttributeValue::Addr(addr) => Ok(Some(addr)), + AttributeValue::DebugAddrIndex(index) => self.address(unit, index).map(Some), + _ => Ok(None), + } + } + + /// Return the range list offset for the given raw offset. + /// + /// This handles adding `DW_AT_GNU_ranges_base` if required. + pub fn ranges_offset_from_raw( + &self, + unit: &Unit, + offset: RawRangeListsOffset, + ) -> RangeListsOffset { + if self.file_type == DwarfFileType::Dwo && unit.header.version() < 5 { + RangeListsOffset(offset.0.wrapping_add(unit.rnglists_base.0)) + } else { + RangeListsOffset(offset.0) + } + } + + /// Return the range list offset at the given index. + pub fn ranges_offset( + &self, + unit: &Unit, + index: DebugRngListsIndex, + ) -> Result> { + self.ranges + .get_offset(unit.encoding(), unit.rnglists_base, index) + } + + /// Iterate over the `RangeListEntry`s starting at the given offset. + pub fn ranges( + &self, + unit: &Unit, + offset: RangeListsOffset, + ) -> Result> { + self.ranges.ranges( + offset, + unit.encoding(), + unit.low_pc, + &self.debug_addr, + unit.addr_base, + ) + } + + /// Iterate over the `RawRngListEntry`ies starting at the given offset. + pub fn raw_ranges( + &self, + unit: &Unit, + offset: RangeListsOffset, + ) -> Result> { + self.ranges.raw_ranges(offset, unit.encoding()) + } + + /// Try to return an attribute value as a range list offset. + /// + /// If the attribute value is one of: + /// + /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections + /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit + /// + /// then return the range list offset of the range list. + /// Returns `None` for other forms. + pub fn attr_ranges_offset( + &self, + unit: &Unit, + attr: AttributeValue, + ) -> Result>> { + match attr { + AttributeValue::RangeListsRef(offset) => { + Ok(Some(self.ranges_offset_from_raw(unit, offset))) + } + AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some), + _ => Ok(None), + } + } + + /// Try to return an attribute value as a range list entry iterator. + /// + /// If the attribute value is one of: + /// + /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections + /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit + /// + /// then return an iterator over the entries in the range list. + /// Returns `None` for other forms. + pub fn attr_ranges( + &self, + unit: &Unit, + attr: AttributeValue, + ) -> Result>> { + match self.attr_ranges_offset(unit, attr)? { + Some(offset) => Ok(Some(self.ranges(unit, offset)?)), + None => Ok(None), + } + } + + /// Return an iterator for the address ranges of a `DebuggingInformationEntry`. + /// + /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`. + pub fn die_ranges( + &self, + unit: &Unit, + entry: &DebuggingInformationEntry<'_, '_, R>, + ) -> Result> { + let mut low_pc = None; + let mut high_pc = None; + let mut size = None; + let mut attrs = entry.attrs(); + while let Some(attr) = attrs.next()? { + match attr.name() { + constants::DW_AT_low_pc => { + low_pc = Some( + self.attr_address(unit, attr.value())? + .ok_or(Error::UnsupportedAttributeForm)?, + ); + } + constants::DW_AT_high_pc => match attr.value() { + AttributeValue::Udata(val) => size = Some(val), + attr => { + high_pc = Some( + self.attr_address(unit, attr)? + .ok_or(Error::UnsupportedAttributeForm)?, + ); + } + }, + constants::DW_AT_ranges => { + if let Some(list) = self.attr_ranges(unit, attr.value())? { + return Ok(RangeIter(RangeIterInner::List(list))); + } + } + _ => {} + } + } + let range = low_pc.and_then(|begin| { + let end = size.map(|size| begin + size).or(high_pc); + // TODO: perhaps return an error if `end` is `None` + end.map(|end| Range { begin, end }) + }); + Ok(RangeIter(RangeIterInner::Single(range))) + } + + /// Return an iterator for the address ranges of a `Unit`. + /// + /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the + /// root `DebuggingInformationEntry`. + pub fn unit_ranges(&self, unit: &Unit) -> Result> { + let mut cursor = unit.header.entries(&unit.abbreviations); + cursor.next_dfs()?; + let root = cursor.current().ok_or(Error::MissingUnitDie)?; + self.die_ranges(unit, root) + } + + /// Return the location list offset at the given index. + pub fn locations_offset( + &self, + unit: &Unit, + index: DebugLocListsIndex, + ) -> Result> { + self.locations + .get_offset(unit.encoding(), unit.loclists_base, index) + } + + /// Iterate over the `LocationListEntry`s starting at the given offset. + pub fn locations( + &self, + unit: &Unit, + offset: LocationListsOffset, + ) -> Result> { + match self.file_type { + DwarfFileType::Main => self.locations.locations( + offset, + unit.encoding(), + unit.low_pc, + &self.debug_addr, + unit.addr_base, + ), + DwarfFileType::Dwo => self.locations.locations_dwo( + offset, + unit.encoding(), + unit.low_pc, + &self.debug_addr, + unit.addr_base, + ), + } + } + + /// Iterate over the raw `LocationListEntry`s starting at the given offset. + pub fn raw_locations( + &self, + unit: &Unit, + offset: LocationListsOffset, + ) -> Result> { + match self.file_type { + DwarfFileType::Main => self.locations.raw_locations(offset, unit.encoding()), + DwarfFileType::Dwo => self.locations.raw_locations_dwo(offset, unit.encoding()), + } + } + + /// Try to return an attribute value as a location list offset. + /// + /// If the attribute value is one of: + /// + /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections + /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit + /// + /// then return the location list offset of the location list. + /// Returns `None` for other forms. + pub fn attr_locations_offset( + &self, + unit: &Unit, + attr: AttributeValue, + ) -> Result>> { + match attr { + AttributeValue::LocationListsRef(offset) => Ok(Some(offset)), + AttributeValue::DebugLocListsIndex(index) => { + self.locations_offset(unit, index).map(Some) + } + _ => Ok(None), + } + } + + /// Try to return an attribute value as a location list entry iterator. + /// + /// If the attribute value is one of: + /// + /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections + /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit + /// + /// then return an iterator over the entries in the location list. + /// Returns `None` for other forms. + pub fn attr_locations( + &self, + unit: &Unit, + attr: AttributeValue, + ) -> Result>> { + match self.attr_locations_offset(unit, attr)? { + Some(offset) => Ok(Some(self.locations(unit, offset)?)), + None => Ok(None), + } + } + + /// Call `Reader::lookup_offset_id` for each section, and return the first match. + /// + /// The first element of the tuple is `true` for supplementary sections. + pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(bool, SectionId, R::Offset)> { + None.or_else(|| self.debug_abbrev.lookup_offset_id(id)) + .or_else(|| self.debug_addr.lookup_offset_id(id)) + .or_else(|| self.debug_aranges.lookup_offset_id(id)) + .or_else(|| self.debug_info.lookup_offset_id(id)) + .or_else(|| self.debug_line.lookup_offset_id(id)) + .or_else(|| self.debug_line_str.lookup_offset_id(id)) + .or_else(|| self.debug_str.lookup_offset_id(id)) + .or_else(|| self.debug_str_offsets.lookup_offset_id(id)) + .or_else(|| self.debug_types.lookup_offset_id(id)) + .or_else(|| self.locations.lookup_offset_id(id)) + .or_else(|| self.ranges.lookup_offset_id(id)) + .map(|(id, offset)| (false, id, offset)) + .or_else(|| { + self.sup() + .and_then(|sup| sup.lookup_offset_id(id)) + .map(|(_, id, offset)| (true, id, offset)) + }) + } + + /// Returns a string representation of the given error. + /// + /// This uses information from the DWARF sections to provide more information in some cases. + pub fn format_error(&self, err: Error) -> String { + #[allow(clippy::single_match)] + match err { + Error::UnexpectedEof(id) => match self.lookup_offset_id(id) { + Some((sup, section, offset)) => { + return format!( + "{} at {}{}+0x{:x}", + err, + section.name(), + if sup { "(sup)" } else { "" }, + offset.into_u64(), + ); + } + None => {} + }, + _ => {} + } + err.description().into() + } + + /// Return a fallible iterator over the macro information from `.debug_macinfo` for the given offset. + pub fn macinfo(&self, offset: DebugMacinfoOffset) -> Result> { + self.debug_macinfo.get_macinfo(offset) + } + + /// Return a fallible iterator over the macro information from `.debug_macro` for the given offset. + pub fn macros(&self, offset: DebugMacroOffset) -> Result> { + self.debug_macro.get_macros(offset) + } +} + +impl Dwarf { + /// Assuming `self` was loaded from a .dwo, take the appropriate + /// sections from `parent` (which contains the skeleton unit for this + /// dwo) such as `.debug_addr` and merge them into this `Dwarf`. + pub fn make_dwo(&mut self, parent: &Dwarf) { + self.file_type = DwarfFileType::Dwo; + // These sections are always taken from the parent file and not the dwo. + self.debug_addr = parent.debug_addr.clone(); + // .debug_rnglists comes from the DWO, .debug_ranges comes from the + // parent file. + self.ranges + .set_debug_ranges(parent.ranges.debug_ranges().clone()); + self.sup.clone_from(&parent.sup); + } +} + +/// The sections from a `.dwp` file. +/// +/// This is useful for storing sections when `T` does not implement `Reader`. +/// It can be used to create a `DwarfPackage` that references the data in `self`. +/// If `T` does implement `Reader`, then use `DwarfPackage` directly. +/// +/// ## Example Usage +/// +/// It can be useful to load DWARF sections into owned data structures, +/// such as `Vec`. However, we do not implement the `Reader` trait +/// for `Vec`, because it would be very inefficient, but this trait +/// is required for all of the methods that parse the DWARF data. +/// So we first load the DWARF sections into `Vec`s, and then use +/// `borrow` to create `Reader`s that reference the data. +/// +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() }; +/// // Read the DWARF sections into `Vec`s with whatever object loader you're using. +/// let dwp_sections: gimli::DwarfPackageSections> = gimli::DwarfPackageSections::load(loader)?; +/// // Create references to the DWARF sections. +/// let dwp: gimli::DwarfPackage<_> = dwp_sections.borrow( +/// |section| gimli::EndianSlice::new(§ion, gimli::LittleEndian), +/// gimli::EndianSlice::new(&[], gimli::LittleEndian), +/// )?; +/// # unreachable!() +/// # } +/// ``` +#[derive(Debug, Default)] +pub struct DwarfPackageSections { + /// The `.debug_cu_index` section. + pub cu_index: DebugCuIndex, + /// The `.debug_tu_index` section. + pub tu_index: DebugTuIndex, + /// The `.debug_abbrev.dwo` section. + pub debug_abbrev: DebugAbbrev, + /// The `.debug_info.dwo` section. + pub debug_info: DebugInfo, + /// The `.debug_line.dwo` section. + pub debug_line: DebugLine, + /// The `.debug_str.dwo` section. + pub debug_str: DebugStr, + /// The `.debug_str_offsets.dwo` section. + pub debug_str_offsets: DebugStrOffsets, + /// The `.debug_loc.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_loc: DebugLoc, + /// The `.debug_loclists.dwo` section. + pub debug_loclists: DebugLocLists, + /// The `.debug_rnglists.dwo` section. + pub debug_rnglists: DebugRngLists, + /// The `.debug_types.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_types: DebugTypes, +} + +impl DwarfPackageSections { + /// Try to load the `.dwp` sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + pub fn load(mut section: F) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + E: From, + { + Ok(DwarfPackageSections { + // Section types are inferred. + cu_index: Section::load(&mut section)?, + tu_index: Section::load(&mut section)?, + debug_abbrev: Section::load(&mut section)?, + debug_info: Section::load(&mut section)?, + debug_line: Section::load(&mut section)?, + debug_str: Section::load(&mut section)?, + debug_str_offsets: Section::load(&mut section)?, + debug_loc: Section::load(&mut section)?, + debug_loclists: Section::load(&mut section)?, + debug_rnglists: Section::load(&mut section)?, + debug_types: Section::load(&mut section)?, + }) + } + + /// Create a `DwarfPackage` structure that references the data in `self`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F, empty: R) -> Result> + where + F: FnMut(&'a T) -> R, + R: Reader, + { + DwarfPackage::from_sections( + DwarfPackageSections { + cu_index: self.cu_index.borrow(&mut borrow), + tu_index: self.tu_index.borrow(&mut borrow), + debug_abbrev: self.debug_abbrev.borrow(&mut borrow), + debug_info: self.debug_info.borrow(&mut borrow), + debug_line: self.debug_line.borrow(&mut borrow), + debug_str: self.debug_str.borrow(&mut borrow), + debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow), + debug_loc: self.debug_loc.borrow(&mut borrow), + debug_loclists: self.debug_loclists.borrow(&mut borrow), + debug_rnglists: self.debug_rnglists.borrow(&mut borrow), + debug_types: self.debug_types.borrow(&mut borrow), + }, + empty, + ) + } +} + +/// The sections from a `.dwp` file, with parsed indices. +#[derive(Debug)] +pub struct DwarfPackage { + /// The compilation unit index in the `.debug_cu_index` section. + pub cu_index: UnitIndex, + + /// The type unit index in the `.debug_tu_index` section. + pub tu_index: UnitIndex, + + /// The `.debug_abbrev.dwo` section. + pub debug_abbrev: DebugAbbrev, + + /// The `.debug_info.dwo` section. + pub debug_info: DebugInfo, + + /// The `.debug_line.dwo` section. + pub debug_line: DebugLine, + + /// The `.debug_str.dwo` section. + pub debug_str: DebugStr, + + /// The `.debug_str_offsets.dwo` section. + pub debug_str_offsets: DebugStrOffsets, + + /// The `.debug_loc.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_loc: DebugLoc, + + /// The `.debug_loclists.dwo` section. + pub debug_loclists: DebugLocLists, + + /// The `.debug_rnglists.dwo` section. + pub debug_rnglists: DebugRngLists, + + /// The `.debug_types.dwo` section. + /// + /// Only present when using GNU split-dwarf extension to DWARF 4. + pub debug_types: DebugTypes, + + /// An empty section. + /// + /// Used when creating `Dwarf`. + pub empty: R, +} + +impl DwarfPackage { + /// Try to load the `.dwp` sections using the given loader function. + /// + /// `section` loads a DWARF section from the object file. + /// It should return an empty section if the section does not exist. + pub fn load(section: F, empty: R) -> core::result::Result + where + F: FnMut(SectionId) -> core::result::Result, + E: From, + { + let sections = DwarfPackageSections::load(section)?; + Ok(Self::from_sections(sections, empty)?) + } + + /// Create a `DwarfPackage` structure from the given sections. + fn from_sections(sections: DwarfPackageSections, empty: R) -> Result { + Ok(DwarfPackage { + cu_index: sections.cu_index.index()?, + tu_index: sections.tu_index.index()?, + debug_abbrev: sections.debug_abbrev, + debug_info: sections.debug_info, + debug_line: sections.debug_line, + debug_str: sections.debug_str, + debug_str_offsets: sections.debug_str_offsets, + debug_loc: sections.debug_loc, + debug_loclists: sections.debug_loclists, + debug_rnglists: sections.debug_rnglists, + debug_types: sections.debug_types, + empty, + }) + } + + /// Find the compilation unit with the given DWO identifier and return its section + /// contributions. + /// + /// ## Example Usage + /// + /// ```rust,no_run + /// # fn example( + /// # dwarf: &gimli::Dwarf, + /// # dwp: &gimli::DwarfPackage, + /// # dwo_id: gimli::DwoId, + /// # ) -> Result<(), gimli::Error> { + /// if let Some(dwo) = dwp.find_cu(dwo_id, dwarf)? { + /// let dwo_header = dwo.units().next()?.expect("DWO should have one unit"); + /// let dwo_unit = dwo.unit(dwo_header)?; + /// // Do something with `dwo_unit`. + /// } + /// # unreachable!() + /// # } + pub fn find_cu(&self, id: DwoId, parent: &Dwarf) -> Result>> { + let row = match self.cu_index.find(id.0) { + Some(row) => row, + None => return Ok(None), + }; + self.cu_sections(row, parent).map(Some) + } + + /// Find the type unit with the given type signature and return its section + /// contributions. + pub fn find_tu( + &self, + signature: DebugTypeSignature, + parent: &Dwarf, + ) -> Result>> { + let row = match self.tu_index.find(signature.0) { + Some(row) => row, + None => return Ok(None), + }; + self.tu_sections(row, parent).map(Some) + } + + /// Return the section contributions of the compilation unit at the given index. + /// + /// The index must be in the range `1..cu_index.unit_count`. + /// + /// This function should only be needed by low level parsers. + pub fn cu_sections(&self, index: u32, parent: &Dwarf) -> Result> { + self.sections(self.cu_index.sections(index)?, parent) + } + + /// Return the section contributions of the compilation unit at the given index. + /// + /// The index must be in the range `1..tu_index.unit_count`. + /// + /// This function should only be needed by low level parsers. + pub fn tu_sections(&self, index: u32, parent: &Dwarf) -> Result> { + self.sections(self.tu_index.sections(index)?, parent) + } + + /// Return the section contributions of a unit. + /// + /// This function should only be needed by low level parsers. + pub fn sections( + &self, + sections: UnitIndexSectionIterator<'_, R>, + parent: &Dwarf, + ) -> Result> { + let mut abbrev_offset = 0; + let mut abbrev_size = 0; + let mut info_offset = 0; + let mut info_size = 0; + let mut line_offset = 0; + let mut line_size = 0; + let mut loc_offset = 0; + let mut loc_size = 0; + let mut loclists_offset = 0; + let mut loclists_size = 0; + let mut str_offsets_offset = 0; + let mut str_offsets_size = 0; + let mut rnglists_offset = 0; + let mut rnglists_size = 0; + let mut types_offset = 0; + let mut types_size = 0; + for section in sections { + match section.section { + IndexSectionId::DebugAbbrev => { + abbrev_offset = section.offset; + abbrev_size = section.size; + } + IndexSectionId::DebugInfo => { + info_offset = section.offset; + info_size = section.size; + } + IndexSectionId::DebugLine => { + line_offset = section.offset; + line_size = section.size; + } + IndexSectionId::DebugLoc => { + loc_offset = section.offset; + loc_size = section.size; + } + IndexSectionId::DebugLocLists => { + loclists_offset = section.offset; + loclists_size = section.size; + } + IndexSectionId::DebugStrOffsets => { + str_offsets_offset = section.offset; + str_offsets_size = section.size; + } + IndexSectionId::DebugRngLists => { + rnglists_offset = section.offset; + rnglists_size = section.size; + } + IndexSectionId::DebugTypes => { + types_offset = section.offset; + types_size = section.size; + } + IndexSectionId::DebugMacro | IndexSectionId::DebugMacinfo => { + // These are valid but we can't parse these yet. + } + } + } + + let debug_abbrev = self.debug_abbrev.dwp_range(abbrev_offset, abbrev_size)?; + let debug_info = self.debug_info.dwp_range(info_offset, info_size)?; + let debug_line = self.debug_line.dwp_range(line_offset, line_size)?; + let debug_loc = self.debug_loc.dwp_range(loc_offset, loc_size)?; + let debug_loclists = self + .debug_loclists + .dwp_range(loclists_offset, loclists_size)?; + let debug_str_offsets = self + .debug_str_offsets + .dwp_range(str_offsets_offset, str_offsets_size)?; + let debug_rnglists = self + .debug_rnglists + .dwp_range(rnglists_offset, rnglists_size)?; + let debug_types = self.debug_types.dwp_range(types_offset, types_size)?; + + let debug_str = self.debug_str.clone(); + + let debug_addr = parent.debug_addr.clone(); + let debug_ranges = parent.ranges.debug_ranges().clone(); + + let debug_aranges = self.empty.clone().into(); + let debug_line_str = self.empty.clone().into(); + let debug_macinfo = self.empty.clone().into(); + let debug_macro = self.empty.clone().into(); + + Ok(Dwarf { + debug_abbrev, + debug_addr, + debug_aranges, + debug_info, + debug_line, + debug_line_str, + debug_macinfo, + debug_macro, + debug_str, + debug_str_offsets, + debug_types, + locations: LocationLists::new(debug_loc, debug_loclists), + ranges: RangeLists::new(debug_ranges, debug_rnglists), + file_type: DwarfFileType::Dwo, + sup: parent.sup.clone(), + abbreviations_cache: AbbreviationsCache::new(), + }) + } +} + +/// All of the commonly used information for a unit in the `.debug_info` or `.debug_types` +/// sections. +#[derive(Debug)] +pub struct Unit::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// The header of the unit. + pub header: UnitHeader, + + /// The parsed abbreviations for the unit. + pub abbreviations: Arc, + + /// The `DW_AT_name` attribute of the unit. + pub name: Option, + + /// The `DW_AT_comp_dir` attribute of the unit. + pub comp_dir: Option, + + /// The `DW_AT_low_pc` attribute of the unit. Defaults to 0. + pub low_pc: u64, + + /// The `DW_AT_str_offsets_base` attribute of the unit. Defaults to 0. + pub str_offsets_base: DebugStrOffsetsBase, + + /// The `DW_AT_addr_base` attribute of the unit. Defaults to 0. + pub addr_base: DebugAddrBase, + + /// The `DW_AT_loclists_base` attribute of the unit. Defaults to 0. + pub loclists_base: DebugLocListsBase, + + /// The `DW_AT_rnglists_base` attribute of the unit. Defaults to 0. + pub rnglists_base: DebugRngListsBase, + + /// The line number program of the unit. + pub line_program: Option>, + + /// The DWO ID of a skeleton unit or split compilation unit. + pub dwo_id: Option, +} + +impl Unit { + /// Construct a new `Unit` from the given unit header. + #[inline] + pub fn new(dwarf: &Dwarf, header: UnitHeader) -> Result { + let abbreviations = dwarf.abbreviations(&header)?; + Self::new_with_abbreviations(dwarf, header, abbreviations) + } + + /// Construct a new `Unit` from the given unit header and abbreviations. + /// + /// The abbreviations for this call can be obtained using `dwarf.abbreviations(&header)`. + /// The caller may implement caching to reuse the `Abbreviations` across units with the + /// same `header.debug_abbrev_offset()` value. + #[inline] + pub fn new_with_abbreviations( + dwarf: &Dwarf, + header: UnitHeader, + abbreviations: Arc, + ) -> Result { + let mut unit = Unit { + abbreviations, + name: None, + comp_dir: None, + low_pc: 0, + str_offsets_base: DebugStrOffsetsBase::default_for_encoding_and_file( + header.encoding(), + dwarf.file_type, + ), + // NB: Because the .debug_addr section never lives in a .dwo, we can assume its base is always 0 or provided. + addr_base: DebugAddrBase(R::Offset::from_u8(0)), + loclists_base: DebugLocListsBase::default_for_encoding_and_file( + header.encoding(), + dwarf.file_type, + ), + rnglists_base: DebugRngListsBase::default_for_encoding_and_file( + header.encoding(), + dwarf.file_type, + ), + line_program: None, + dwo_id: match header.type_() { + UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => Some(dwo_id), + _ => None, + }, + header, + }; + let mut name = None; + let mut comp_dir = None; + let mut line_program_offset = None; + let mut low_pc_attr = None; + + { + let mut cursor = unit.header.entries(&unit.abbreviations); + cursor.next_dfs()?; + let root = cursor.current().ok_or(Error::MissingUnitDie)?; + let mut attrs = root.attrs(); + while let Some(attr) = attrs.next()? { + match attr.name() { + constants::DW_AT_name => { + name = Some(attr.value()); + } + constants::DW_AT_comp_dir => { + comp_dir = Some(attr.value()); + } + constants::DW_AT_low_pc => { + low_pc_attr = Some(attr.value()); + } + constants::DW_AT_stmt_list => { + if let AttributeValue::DebugLineRef(offset) = attr.value() { + line_program_offset = Some(offset); + } + } + constants::DW_AT_str_offsets_base => { + if let AttributeValue::DebugStrOffsetsBase(base) = attr.value() { + unit.str_offsets_base = base; + } + } + constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => { + if let AttributeValue::DebugAddrBase(base) = attr.value() { + unit.addr_base = base; + } + } + constants::DW_AT_loclists_base => { + if let AttributeValue::DebugLocListsBase(base) = attr.value() { + unit.loclists_base = base; + } + } + constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => { + if let AttributeValue::DebugRngListsBase(base) = attr.value() { + unit.rnglists_base = base; + } + } + constants::DW_AT_GNU_dwo_id => { + if unit.dwo_id.is_none() { + if let AttributeValue::DwoId(dwo_id) = attr.value() { + unit.dwo_id = Some(dwo_id); + } + } + } + _ => {} + } + } + } + + unit.name = match name { + Some(val) => dwarf.attr_string(&unit, val).ok(), + None => None, + }; + unit.comp_dir = match comp_dir { + Some(val) => dwarf.attr_string(&unit, val).ok(), + None => None, + }; + unit.line_program = match line_program_offset { + Some(offset) => Some(dwarf.debug_line.program( + offset, + unit.header.address_size(), + unit.comp_dir.clone(), + unit.name.clone(), + )?), + None => None, + }; + if let Some(low_pc_attr) = low_pc_attr { + if let Some(addr) = dwarf.attr_address(&unit, low_pc_attr)? { + unit.low_pc = addr; + } + } + Ok(unit) + } + + /// Return a reference to this unit and its associated `Dwarf`. + pub fn unit_ref<'a>(&'a self, dwarf: &'a Dwarf) -> UnitRef<'a, R> { + UnitRef::new(dwarf, self) + } + + /// Return the encoding parameters for this unit. + #[inline] + pub fn encoding(&self) -> Encoding { + self.header.encoding() + } + + /// Read the `DebuggingInformationEntry` at the given offset. + pub fn entry( + &self, + offset: UnitOffset, + ) -> Result> { + self.header.entry(&self.abbreviations, offset) + } + + /// Navigate this unit's `DebuggingInformationEntry`s. + #[inline] + pub fn entries(&self) -> EntriesCursor<'_, '_, R> { + self.header.entries(&self.abbreviations) + } + + /// Navigate this unit's `DebuggingInformationEntry`s + /// starting at the given offset. + #[inline] + pub fn entries_at_offset( + &self, + offset: UnitOffset, + ) -> Result> { + self.header.entries_at_offset(&self.abbreviations, offset) + } + + /// Navigate this unit's `DebuggingInformationEntry`s as a tree + /// starting at the given offset. + #[inline] + pub fn entries_tree( + &self, + offset: Option>, + ) -> Result> { + self.header.entries_tree(&self.abbreviations, offset) + } + + /// Read the raw data that defines the Debugging Information Entries. + #[inline] + pub fn entries_raw( + &self, + offset: Option>, + ) -> Result> { + self.header.entries_raw(&self.abbreviations, offset) + } + + /// Copy attributes that are subject to relocation from another unit. This is intended + /// to be used to copy attributes from a skeleton compilation unit to the corresponding + /// split compilation unit. + pub fn copy_relocated_attributes(&mut self, other: &Unit) { + self.low_pc = other.low_pc; + self.addr_base = other.addr_base; + if self.header.version() < 5 { + self.rnglists_base = other.rnglists_base; + } + } + + /// Find the dwo name (if any) for this unit, automatically handling the differences + /// between the standardized DWARF 5 split DWARF format and the pre-DWARF 5 GNU + /// extension. + /// + /// The returned value is relative to this unit's `comp_dir`. + pub fn dwo_name(&self) -> Result>> { + let mut entries = self.entries(); + entries.next_entry()?; + let entry = entries.current().ok_or(Error::MissingUnitDie)?; + if self.header.version() < 5 { + entry.attr_value(constants::DW_AT_GNU_dwo_name) + } else { + entry.attr_value(constants::DW_AT_dwo_name) + } + } +} + +/// A reference to a `Unit` and its associated `Dwarf`. +/// +/// These often need to be passed around together, so this struct makes that easier. +/// +/// It implements `Deref` to `Unit`, so you can use it as if it were a `Unit`. +/// It also implements methods that correspond to methods on `Dwarf` that take a `Unit`. +#[derive(Debug)] +pub struct UnitRef<'a, R: Reader> { + /// The `Dwarf` that contains the unit. + pub dwarf: &'a Dwarf, + + /// The `Unit` being referenced. + pub unit: &'a Unit, +} + +impl<'a, R: Reader> Clone for UnitRef<'a, R> { + fn clone(&self) -> Self { + *self + } +} + +impl<'a, R: Reader> Copy for UnitRef<'a, R> {} + +impl<'a, R: Reader> core::ops::Deref for UnitRef<'a, R> { + type Target = Unit; + + fn deref(&self) -> &Self::Target { + self.unit + } +} + +impl<'a, R: Reader> UnitRef<'a, R> { + /// Construct a new `UnitRef` from a `Dwarf` and a `Unit`. + pub fn new(dwarf: &'a Dwarf, unit: &'a Unit) -> Self { + UnitRef { dwarf, unit } + } + + /// Return the string offset at the given index. + #[inline] + pub fn string_offset( + &self, + index: DebugStrOffsetsIndex, + ) -> Result> { + self.dwarf.string_offset(self.unit, index) + } + + /// Return the string at the given offset in `.debug_str`. + #[inline] + pub fn string(&self, offset: DebugStrOffset) -> Result { + self.dwarf.string(offset) + } + + /// Return the string at the given offset in `.debug_line_str`. + #[inline] + pub fn line_string(&self, offset: DebugLineStrOffset) -> Result { + self.dwarf.line_string(offset) + } + + /// Return the string at the given offset in the `.debug_str` + /// in the supplementary object file. + #[inline] + pub fn sup_string(&self, offset: DebugStrOffset) -> Result { + self.dwarf.sup_string(offset) + } + + /// Return an attribute value as a string slice. + /// + /// See [`Dwarf::attr_string`] for more information. + pub fn attr_string(&self, attr: AttributeValue) -> Result { + self.dwarf.attr_string(self.unit, attr) + } + + /// Return the address at the given index. + pub fn address(&self, index: DebugAddrIndex) -> Result { + self.dwarf.address(self.unit, index) + } + + /// Try to return an attribute value as an address. + /// + /// See [`Dwarf::attr_address`] for more information. + pub fn attr_address(&self, attr: AttributeValue) -> Result> { + self.dwarf.attr_address(self.unit, attr) + } + + /// Return the range list offset for the given raw offset. + /// + /// This handles adding `DW_AT_GNU_ranges_base` if required. + pub fn ranges_offset_from_raw( + &self, + offset: RawRangeListsOffset, + ) -> RangeListsOffset { + self.dwarf.ranges_offset_from_raw(self.unit, offset) + } + + /// Return the range list offset at the given index. + pub fn ranges_offset( + &self, + index: DebugRngListsIndex, + ) -> Result> { + self.dwarf.ranges_offset(self.unit, index) + } + + /// Iterate over the `RangeListEntry`s starting at the given offset. + pub fn ranges(&self, offset: RangeListsOffset) -> Result> { + self.dwarf.ranges(self.unit, offset) + } + + /// Iterate over the `RawRngListEntry`ies starting at the given offset. + pub fn raw_ranges(&self, offset: RangeListsOffset) -> Result> { + self.dwarf.raw_ranges(self.unit, offset) + } + + /// Try to return an attribute value as a range list offset. + /// + /// See [`Dwarf::attr_ranges_offset`] for more information. + pub fn attr_ranges_offset( + &self, + attr: AttributeValue, + ) -> Result>> { + self.dwarf.attr_ranges_offset(self.unit, attr) + } + + /// Try to return an attribute value as a range list entry iterator. + /// + /// See [`Dwarf::attr_ranges`] for more information. + pub fn attr_ranges(&self, attr: AttributeValue) -> Result>> { + self.dwarf.attr_ranges(self.unit, attr) + } + + /// Return an iterator for the address ranges of a `DebuggingInformationEntry`. + /// + /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`. + pub fn die_ranges(&self, entry: &DebuggingInformationEntry<'_, '_, R>) -> Result> { + self.dwarf.die_ranges(self.unit, entry) + } + + /// Return an iterator for the address ranges of the `Unit`. + /// + /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the + /// root `DebuggingInformationEntry`. + pub fn unit_ranges(&self) -> Result> { + self.dwarf.unit_ranges(self.unit) + } + + /// Return the location list offset at the given index. + pub fn locations_offset( + &self, + index: DebugLocListsIndex, + ) -> Result> { + self.dwarf.locations_offset(self.unit, index) + } + + /// Iterate over the `LocationListEntry`s starting at the given offset. + pub fn locations(&self, offset: LocationListsOffset) -> Result> { + self.dwarf.locations(self.unit, offset) + } + + /// Iterate over the raw `LocationListEntry`s starting at the given offset. + pub fn raw_locations( + &self, + offset: LocationListsOffset, + ) -> Result> { + self.dwarf.raw_locations(self.unit, offset) + } + + /// Try to return an attribute value as a location list offset. + /// + /// See [`Dwarf::attr_locations_offset`] for more information. + pub fn attr_locations_offset( + &self, + attr: AttributeValue, + ) -> Result>> { + self.dwarf.attr_locations_offset(self.unit, attr) + } + + /// Try to return an attribute value as a location list entry iterator. + /// + /// See [`Dwarf::attr_locations`] for more information. + pub fn attr_locations(&self, attr: AttributeValue) -> Result>> { + self.dwarf.attr_locations(self.unit, attr) + } + + /// Try to return an iterator for the list of macros at the given `.debug_macinfo` offset. + pub fn macinfo(&self, offset: DebugMacinfoOffset) -> Result> { + self.dwarf.macinfo(offset) + } + + /// Try to return an iterator for the list of macros at the given `.debug_macro` offset. + pub fn macros(&self, offset: DebugMacroOffset) -> Result> { + self.dwarf.macros(offset) + } +} + +impl UnitSectionOffset { + /// Convert an offset to be relative to the start of the given unit, + /// instead of relative to the start of the section. + /// + /// Returns `None` if the offset is not within the unit entries. + pub fn to_unit_offset(&self, unit: &Unit) -> Option> + where + R: Reader, + { + let (offset, unit_offset) = match (self, unit.header.offset()) { + ( + UnitSectionOffset::DebugInfoOffset(offset), + UnitSectionOffset::DebugInfoOffset(unit_offset), + ) => (offset.0, unit_offset.0), + ( + UnitSectionOffset::DebugTypesOffset(offset), + UnitSectionOffset::DebugTypesOffset(unit_offset), + ) => (offset.0, unit_offset.0), + _ => return None, + }; + let offset = match offset.checked_sub(unit_offset) { + Some(offset) => UnitOffset(offset), + None => return None, + }; + if !unit.header.is_valid_offset(offset) { + return None; + } + Some(offset) + } +} + +impl UnitOffset { + /// Convert an offset to be relative to the start of the .debug_info section, + /// instead of relative to the start of the given compilation unit. + /// + /// Does not check that the offset is valid. + pub fn to_unit_section_offset(&self, unit: &Unit) -> UnitSectionOffset + where + R: Reader, + { + match unit.header.offset() { + UnitSectionOffset::DebugInfoOffset(unit_offset) => { + DebugInfoOffset(unit_offset.0 + self.0).into() + } + UnitSectionOffset::DebugTypesOffset(unit_offset) => { + DebugTypesOffset(unit_offset.0 + self.0).into() + } + } + } +} + +/// An iterator for the address ranges of a `DebuggingInformationEntry`. +/// +/// Returned by `Dwarf::die_ranges` and `Dwarf::unit_ranges`. +#[derive(Debug)] +pub struct RangeIter(RangeIterInner); + +#[derive(Debug)] +enum RangeIterInner { + Single(Option), + List(RngListIter), +} + +impl Default for RangeIter { + fn default() -> Self { + RangeIter(RangeIterInner::Single(None)) + } +} + +impl RangeIter { + /// Advance the iterator to the next range. + pub fn next(&mut self) -> Result> { + match self.0 { + RangeIterInner::Single(ref mut range) => Ok(range.take()), + RangeIterInner::List(ref mut list) => list.next(), + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for RangeIter { + type Item = Range; + type Error = Error; + + #[inline] + fn next(&mut self) -> ::core::result::Result, Self::Error> { + RangeIter::next(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::read::EndianSlice; + use crate::{Endianity, LittleEndian}; + + /// Ensure that `Dwarf` is covariant wrt R. + #[test] + fn test_dwarf_variance() { + /// This only needs to compile. + fn _f<'a: 'b, 'b, E: Endianity>(x: Dwarf>) -> Dwarf> { + x + } + } + + /// Ensure that `Unit` is covariant wrt R. + #[test] + fn test_dwarf_unit_variance() { + /// This only needs to compile. + fn _f<'a: 'b, 'b, E: Endianity>(x: Unit>) -> Unit> { + x + } + } + + #[test] + fn test_send() { + fn assert_is_send() {} + assert_is_send::>>(); + assert_is_send::>>(); + } + + #[test] + fn test_format_error() { + let dwarf_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap(); + let sup_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap(); + let dwarf = dwarf_sections.borrow_with_sup(&sup_sections, |section| { + EndianSlice::new(section, LittleEndian) + }); + + match dwarf.debug_str.get_str(DebugStrOffset(1)) { + Ok(r) => panic!("Unexpected str {:?}", r), + Err(e) => { + assert_eq!( + dwarf.format_error(e), + "Hit the end of input before it was expected at .debug_str+0x1" + ); + } + } + match dwarf.sup().unwrap().debug_str.get_str(DebugStrOffset(1)) { + Ok(r) => panic!("Unexpected str {:?}", r), + Err(e) => { + assert_eq!( + dwarf.format_error(e), + "Hit the end of input before it was expected at .debug_str(sup)+0x1" + ); + } + } + assert_eq!(dwarf.format_error(Error::Io), Error::Io.description()); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/endian_reader.rs b/anneal/v2/vendor/gimli/src/read/endian_reader.rs new file mode 100644 index 0000000000..5e65b4d1cf --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/endian_reader.rs @@ -0,0 +1,651 @@ +//! Defining custom `Reader`s quickly. + +use alloc::borrow::Cow; +use alloc::rc::Rc; +use alloc::string::String; +use alloc::sync::Arc; +use core::fmt::Debug; +use core::hash::{Hash, Hasher}; +use core::ops::{Deref, Index, Range, RangeFrom, RangeTo}; +use core::slice; +use core::str; +use stable_deref_trait::CloneStableDeref; + +use crate::endianity::Endianity; +use crate::read::{Error, Reader, ReaderOffsetId, Result}; + +/// A reference counted, non-thread-safe slice of bytes and associated +/// endianity. +/// +/// ``` +/// # #[cfg(feature = "std")] { +/// use std::rc::Rc; +/// +/// let buf = Rc::from(&[1, 2, 3, 4][..]); +/// let reader = gimli::EndianRcSlice::new(buf, gimli::NativeEndian); +/// # let _ = reader; +/// # } +/// ``` +pub type EndianRcSlice = EndianReader>; + +/// An atomically reference counted, thread-safe slice of bytes and associated +/// endianity. +/// +/// ``` +/// # #[cfg(feature = "std")] { +/// use std::sync::Arc; +/// +/// let buf = Arc::from(&[1, 2, 3, 4][..]); +/// let reader = gimli::EndianArcSlice::new(buf, gimli::NativeEndian); +/// # let _ = reader; +/// # } +/// ``` +pub type EndianArcSlice = EndianReader>; + +/// An easy way to define a custom `Reader` implementation with a reference to a +/// generic buffer of bytes and an associated endianity. +/// +/// Note that the whole original buffer is kept alive in memory even if there is +/// only one reader that references only a handful of bytes from that original +/// buffer. That is, `EndianReader` will not do any copying, moving, or +/// compacting in order to free up unused regions of the original buffer. If you +/// require this kind of behavior, it is up to you to implement `Reader` +/// directly by-hand. +/// +/// # Example +/// +/// Say you have an `mmap`ed file that you want to serve as a `gimli::Reader`. +/// You can wrap that `mmap`ed file up in a `MmapFile` type and use +/// `EndianReader>` or `EndianReader>` as readers as +/// long as `MmapFile` dereferences to the underlying `[u8]` data. +/// +/// ``` +/// use std::io; +/// use std::ops::Deref; +/// use std::path::Path; +/// use std::slice; +/// use std::sync::Arc; +/// +/// /// A type that represents an `mmap`ed file. +/// #[derive(Debug)] +/// pub struct MmapFile { +/// ptr: *const u8, +/// len: usize, +/// } +/// +/// impl MmapFile { +/// pub fn new(path: &Path) -> io::Result { +/// // Call `mmap` and check for errors and all that... +/// # unimplemented!() +/// } +/// } +/// +/// impl Drop for MmapFile { +/// fn drop(&mut self) { +/// // Call `munmap` to clean up after ourselves... +/// # unimplemented!() +/// } +/// } +/// +/// // And `MmapFile` can deref to a slice of the `mmap`ed region of memory. +/// impl Deref for MmapFile { +/// type Target = [u8]; +/// fn deref(&self) -> &[u8] { +/// unsafe { +/// slice::from_raw_parts(self.ptr, self.len) +/// } +/// } +/// } +/// +/// /// A type that represents a shared `mmap`ed file. +/// #[derive(Debug, Clone)] +/// pub struct ArcMmapFile(Arc); +/// +/// // And `ArcMmapFile` can deref to a slice of the `mmap`ed region of memory. +/// impl Deref for ArcMmapFile { +/// type Target = [u8]; +/// fn deref(&self) -> &[u8] { +/// &self.0 +/// } +/// } +/// +/// // These are both valid for any `Rc` or `Arc`. +/// unsafe impl gimli::StableDeref for ArcMmapFile {} +/// unsafe impl gimli::CloneStableDeref for ArcMmapFile {} +/// +/// /// A `gimli::Reader` that is backed by an `mmap`ed file! +/// pub type MmapFileReader = gimli::EndianReader; +/// # fn test(_: &MmapFileReader) { } +/// ``` +#[derive(Debug, Clone, Copy)] +pub struct EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + range: SubRange, + endian: Endian, +} + +impl PartialEq> for EndianReader +where + Endian: Endianity, + T1: CloneStableDeref + Debug, + T2: CloneStableDeref + Debug, +{ + fn eq(&self, rhs: &EndianReader) -> bool { + self.bytes() == rhs.bytes() + } +} + +impl Eq for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ +} + +impl Hash for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + fn hash(&self, state: &mut H) { + // This must match the `PartialEq` implementation. + self.bytes().hash(state); + } +} + +// This is separated out from `EndianReader` so that we can avoid running afoul +// of borrowck. We need to `read_slice(&mut self, ...) -> &[u8]` and then call +// `self.endian.read_whatever` on the result. The problem is that the returned +// slice keeps the `&mut self` borrow active, so we wouldn't be able to access +// `self.endian`. Splitting the sub-range out from the endian lets us work +// around this, making it so that only the `self.range` borrow is held active, +// not all of `self`. +// +// This also serves to encapsulate the unsafe code concerning `CloneStableDeref`. +// The `bytes` member is held so that the bytes live long enough, and the +// `CloneStableDeref` ensures these bytes never move. The `ptr` and `len` +// members point inside `bytes`, and are updated during read operations. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +struct SubRange +where + T: CloneStableDeref + Debug, +{ + bytes: T, + ptr: *const u8, + len: usize, +} + +unsafe impl Send for SubRange where T: CloneStableDeref + Debug + Send {} + +unsafe impl Sync for SubRange where T: CloneStableDeref + Debug + Sync {} + +impl SubRange +where + T: CloneStableDeref + Debug, +{ + #[inline] + fn new(bytes: T) -> Self { + let ptr = bytes.as_ptr(); + let len = bytes.len(); + SubRange { bytes, ptr, len } + } + + #[inline] + fn bytes(&self) -> &[u8] { + // Safe because `T` implements `CloneStableDeref`, `bytes` can't be modified, + // and all operations that modify `ptr` and `len` ensure they stay in range. + unsafe { slice::from_raw_parts(self.ptr, self.len) } + } + + #[inline] + fn len(&self) -> usize { + self.len + } + + #[inline] + fn truncate(&mut self, len: usize) { + assert!(len <= self.len); + self.len = len; + } + + #[inline] + fn skip(&mut self, len: usize) { + assert!(len <= self.len); + self.ptr = unsafe { self.ptr.add(len) }; + self.len -= len; + } + + #[inline] + fn read_slice(&mut self, len: usize) -> Option<&[u8]> { + if self.len() < len { + None + } else { + // Same as for `bytes()`. + let bytes = unsafe { slice::from_raw_parts(self.ptr, len) }; + self.skip(len); + Some(bytes) + } + } +} + +impl EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + /// Construct a new `EndianReader` with the given bytes. + #[inline] + pub fn new(bytes: T, endian: Endian) -> EndianReader { + EndianReader { + range: SubRange::new(bytes), + endian, + } + } + + /// Return a reference to the raw bytes underlying this reader. + #[inline] + pub fn bytes(&self) -> &[u8] { + self.range.bytes() + } +} + +/// # Range Methods +/// +/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't +/// implement `Index>` to return a new `EndianReader` the way we +/// would like to. Instead, we abandon fancy indexing operators and have these +/// plain old methods. +impl EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + /// Take the given `start..end` range of the underlying buffer and return a + /// new `EndianReader`. + /// + /// ``` + /// # #[cfg(feature = "std")] { + /// use gimli::{EndianReader, LittleEndian}; + /// use std::sync::Arc; + /// + /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]); + /// let reader = EndianReader::new(buf.clone(), LittleEndian); + /// assert_eq!(reader.range(1..3), + /// EndianReader::new(&buf[1..3], LittleEndian)); + /// # } + /// ``` + /// + /// # Panics + /// + /// Panics if the range is out of bounds. + pub fn range(&self, idx: Range) -> EndianReader { + let mut r = self.clone(); + r.range.skip(idx.start); + r.range.truncate(idx.len()); + r + } + + /// Take the given `start..` range of the underlying buffer and return a new + /// `EndianReader`. + /// + /// ``` + /// # #[cfg(feature = "std")] { + /// use gimli::{EndianReader, LittleEndian}; + /// use std::sync::Arc; + /// + /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]); + /// let reader = EndianReader::new(buf.clone(), LittleEndian); + /// assert_eq!(reader.range_from(2..), + /// EndianReader::new(&buf[2..], LittleEndian)); + /// # } + /// ``` + /// + /// # Panics + /// + /// Panics if the range is out of bounds. + pub fn range_from(&self, idx: RangeFrom) -> EndianReader { + let mut r = self.clone(); + r.range.skip(idx.start); + r + } + + /// Take the given `..end` range of the underlying buffer and return a new + /// `EndianReader`. + /// + /// ``` + /// # #[cfg(feature = "std")] { + /// use gimli::{EndianReader, LittleEndian}; + /// use std::sync::Arc; + /// + /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]); + /// let reader = EndianReader::new(buf.clone(), LittleEndian); + /// assert_eq!(reader.range_to(..3), + /// EndianReader::new(&buf[..3], LittleEndian)); + /// # } + /// ``` + /// + /// # Panics + /// + /// Panics if the range is out of bounds. + pub fn range_to(&self, idx: RangeTo) -> EndianReader { + let mut r = self.clone(); + r.range.truncate(idx.end); + r + } +} + +impl Index for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + type Output = u8; + fn index(&self, idx: usize) -> &Self::Output { + &self.bytes()[idx] + } +} + +impl Index> for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + type Output = [u8]; + fn index(&self, idx: RangeFrom) -> &Self::Output { + &self.bytes()[idx] + } +} + +impl Deref for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + type Target = [u8]; + fn deref(&self) -> &Self::Target { + self.bytes() + } +} + +impl Reader for EndianReader +where + Endian: Endianity, + T: CloneStableDeref + Debug, +{ + type Endian = Endian; + type Offset = usize; + + #[inline] + fn endian(&self) -> Endian { + self.endian + } + + #[inline] + fn len(&self) -> usize { + self.range.len() + } + + #[inline] + fn empty(&mut self) { + self.range.truncate(0); + } + + #[inline] + fn truncate(&mut self, len: usize) -> Result<()> { + if self.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + self.range.truncate(len); + Ok(()) + } + } + + #[inline] + fn offset_from(&self, base: &EndianReader) -> usize { + let base_ptr = base.bytes().as_ptr() as usize; + let ptr = self.bytes().as_ptr() as usize; + debug_assert!(base_ptr <= ptr); + debug_assert!(ptr + self.bytes().len() <= base_ptr + base.bytes().len()); + ptr - base_ptr + } + + #[inline] + fn offset_id(&self) -> ReaderOffsetId { + ReaderOffsetId(self.bytes().as_ptr() as u64) + } + + #[inline] + fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option { + let id = id.0; + let self_id = self.bytes().as_ptr() as u64; + let self_len = self.bytes().len() as u64; + if id >= self_id && id <= self_id + self_len { + Some((id - self_id) as usize) + } else { + None + } + } + + #[inline] + fn find(&self, byte: u8) -> Result { + self.bytes() + .iter() + .position(|x| *x == byte) + .ok_or_else(|| Error::UnexpectedEof(self.offset_id())) + } + + #[inline] + fn skip(&mut self, len: usize) -> Result<()> { + if self.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + self.range.skip(len); + Ok(()) + } + } + + #[inline] + fn split(&mut self, len: usize) -> Result { + if self.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + let mut r = self.clone(); + r.range.truncate(len); + self.range.skip(len); + Ok(r) + } + } + + #[inline] + fn to_slice(&self) -> Result> { + Ok(self.bytes().into()) + } + + #[inline] + fn to_string(&self) -> Result> { + match str::from_utf8(self.bytes()) { + Ok(s) => Ok(s.into()), + _ => Err(Error::BadUtf8), + } + } + + #[inline] + fn to_string_lossy(&self) -> Result> { + Ok(String::from_utf8_lossy(self.bytes())) + } + + #[inline] + fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> { + match self.range.read_slice(buf.len()) { + Some(slice) => { + buf.copy_from_slice(slice); + Ok(()) + } + None => Err(Error::UnexpectedEof(self.offset_id())), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::endianity::NativeEndian; + use crate::read::Reader; + + fn native_reader + Debug>( + bytes: T, + ) -> EndianReader { + EndianReader::new(bytes, NativeEndian) + } + + const BUF: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + + #[test] + fn test_reader_split() { + let mut reader = native_reader(BUF); + let left = reader.split(3).unwrap(); + assert_eq!(left, native_reader(&BUF[..3])); + assert_eq!(reader, native_reader(&BUF[3..])); + } + + #[test] + fn test_reader_split_out_of_bounds() { + let mut reader = native_reader(BUF); + assert!(reader.split(30).is_err()); + } + + #[test] + fn bytes_and_len_and_range_and_eq() { + let reader = native_reader(BUF); + assert_eq!(reader.len(), BUF.len()); + assert_eq!(reader.bytes(), BUF); + assert_eq!(reader, native_reader(BUF)); + + let range = reader.range(2..8); + let buf_range = &BUF[2..8]; + assert_eq!(range.len(), buf_range.len()); + assert_eq!(range.bytes(), buf_range); + assert_ne!(range, native_reader(BUF)); + assert_eq!(range, native_reader(buf_range)); + + let range_from = range.range_from(1..); + let buf_range_from = &buf_range[1..]; + assert_eq!(range_from.len(), buf_range_from.len()); + assert_eq!(range_from.bytes(), buf_range_from); + assert_ne!(range_from, native_reader(BUF)); + assert_eq!(range_from, native_reader(buf_range_from)); + + let range_to = range_from.range_to(..4); + let buf_range_to = &buf_range_from[..4]; + assert_eq!(range_to.len(), buf_range_to.len()); + assert_eq!(range_to.bytes(), buf_range_to); + assert_ne!(range_to, native_reader(BUF)); + assert_eq!(range_to, native_reader(buf_range_to)); + } + + #[test] + fn find() { + let mut reader = native_reader(BUF); + reader.skip(2).unwrap(); + assert_eq!( + reader.find(5), + Ok(BUF[2..].iter().position(|x| *x == 5).unwrap()) + ); + } + + #[test] + fn indexing() { + let mut reader = native_reader(BUF); + reader.skip(2).unwrap(); + assert_eq!(reader[0], BUF[2]); + } + + #[test] + #[should_panic] + fn indexing_out_of_bounds() { + let mut reader = native_reader(BUF); + reader.skip(2).unwrap(); + let _ = reader[900]; + } + + #[test] + fn endian() { + let reader = native_reader(BUF); + assert_eq!(reader.endian(), NativeEndian); + } + + #[test] + fn empty() { + let mut reader = native_reader(BUF); + assert!(!reader.is_empty()); + reader.empty(); + assert!(reader.is_empty()); + assert!(reader.bytes().is_empty()); + } + + #[test] + fn truncate() { + let reader = native_reader(BUF); + let mut reader = reader.range(2..8); + reader.truncate(2).unwrap(); + assert_eq!(reader.bytes(), &BUF[2..4]); + } + + #[test] + fn offset_from() { + let reader = native_reader(BUF); + let sub = reader.range(2..8); + assert_eq!(sub.offset_from(&reader), 2); + } + + #[test] + fn skip() { + let mut reader = native_reader(BUF); + reader.skip(2).unwrap(); + assert_eq!(reader.bytes(), &BUF[2..]); + } + + #[test] + fn to_slice() { + assert_eq!( + native_reader(BUF).range(2..5).to_slice(), + Ok(Cow::from(&BUF[2..5])) + ); + } + + #[test] + fn to_string_ok() { + let buf = b"hello, world!"; + let reader = native_reader(&buf[..]); + let reader = reader.range_from(7..); + assert_eq!(reader.to_string(), Ok(Cow::from("world!"))); + } + + // The rocket emoji (🚀 = [0xf0, 0x9f, 0x9a, 0x80]) but rotated left by one + // to make it invalid UTF-8. + const BAD_UTF8: &[u8] = &[0x9f, 0x9a, 0x80, 0xf0]; + + #[test] + fn to_string_err() { + let reader = native_reader(BAD_UTF8); + assert!(reader.to_string().is_err()); + } + + #[test] + fn to_string_lossy() { + let reader = native_reader(BAD_UTF8); + assert_eq!(reader.to_string_lossy(), Ok(Cow::from("����"))); + } + + #[test] + fn read_u8_array() { + let mut reader = native_reader(BAD_UTF8); + reader.skip(1).unwrap(); + let arr: [u8; 2] = reader.read_u8_array().unwrap(); + assert_eq!(arr, &BAD_UTF8[1..3]); + assert_eq!(reader.bytes(), &BAD_UTF8[3..]); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/endian_slice.rs b/anneal/v2/vendor/gimli/src/read/endian_slice.rs new file mode 100644 index 0000000000..03351429ef --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/endian_slice.rs @@ -0,0 +1,360 @@ +//! Working with byte slices that have an associated endianity. + +#[cfg(feature = "read")] +use alloc::borrow::Cow; +#[cfg(feature = "read")] +use alloc::string::String; +use core::fmt; +use core::ops::{Deref, Range, RangeFrom, RangeTo}; +use core::str; + +use crate::endianity::Endianity; +use crate::read::{Error, Reader, ReaderOffsetId, Result}; + +/// A `&[u8]` slice with endianity metadata. +/// +/// This implements the `Reader` trait, which is used for all reading of DWARF sections. +#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EndianSlice<'input, Endian> +where + Endian: Endianity, +{ + slice: &'input [u8], + endian: Endian, +} + +impl<'input, Endian> EndianSlice<'input, Endian> +where + Endian: Endianity, +{ + /// Construct a new `EndianSlice` with the given slice and endianity. + #[inline] + pub fn new(slice: &'input [u8], endian: Endian) -> EndianSlice<'input, Endian> { + EndianSlice { slice, endian } + } + + /// Return a reference to the raw slice. + #[inline] + #[doc(hidden)] + #[deprecated(note = "Method renamed to EndianSlice::slice; use that instead.")] + pub fn buf(&self) -> &'input [u8] { + self.slice + } + + /// Return a reference to the raw slice. + #[inline] + pub fn slice(&self) -> &'input [u8] { + self.slice + } + + /// Split the slice in two at the given index, resulting in the tuple where + /// the first item has range [0, idx), and the second has range [idx, + /// len). Panics if the index is out of bounds. + #[inline] + pub fn split_at( + &self, + idx: usize, + ) -> (EndianSlice<'input, Endian>, EndianSlice<'input, Endian>) { + (self.range_to(..idx), self.range_from(idx..)) + } + + /// Find the first occurrence of a byte in the slice, and return its index. + #[inline] + pub fn find(&self, byte: u8) -> Option { + self.slice.iter().position(|ch| *ch == byte) + } + + /// Return the offset of the start of the slice relative to the start + /// of the given slice. + #[inline] + pub fn offset_from(&self, base: EndianSlice<'input, Endian>) -> usize { + let base_ptr = base.slice.as_ptr() as usize; + let ptr = self.slice.as_ptr() as usize; + debug_assert!(base_ptr <= ptr); + debug_assert!(ptr + self.slice.len() <= base_ptr + base.slice.len()); + ptr - base_ptr + } + + /// Converts the slice to a string using `str::from_utf8`. + /// + /// Returns an error if the slice contains invalid characters. + #[inline] + pub fn to_string(&self) -> Result<&'input str> { + str::from_utf8(self.slice).map_err(|_| Error::BadUtf8) + } + + /// Converts the slice to a string, including invalid characters, + /// using `String::from_utf8_lossy`. + #[cfg(feature = "read")] + #[inline] + pub fn to_string_lossy(&self) -> Cow<'input, str> { + String::from_utf8_lossy(self.slice) + } + + #[inline] + fn read_slice(&mut self, len: usize) -> Result<&'input [u8]> { + if self.slice.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + let val = &self.slice[..len]; + self.slice = &self.slice[len..]; + Ok(val) + } + } +} + +/// # Range Methods +/// +/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't +/// implement `Index>` to return a new `EndianSlice` the way we would +/// like to. Instead, we abandon fancy indexing operators and have these plain +/// old methods. +impl<'input, Endian> EndianSlice<'input, Endian> +where + Endian: Endianity, +{ + /// Take the given `start..end` range of the underlying slice and return a + /// new `EndianSlice`. + /// + /// ``` + /// use gimli::{EndianSlice, LittleEndian}; + /// + /// let slice = &[0x01, 0x02, 0x03, 0x04]; + /// let endian_slice = EndianSlice::new(slice, LittleEndian); + /// assert_eq!(endian_slice.range(1..3), + /// EndianSlice::new(&slice[1..3], LittleEndian)); + /// ``` + pub fn range(&self, idx: Range) -> EndianSlice<'input, Endian> { + EndianSlice { + slice: &self.slice[idx], + endian: self.endian, + } + } + + /// Take the given `start..` range of the underlying slice and return a new + /// `EndianSlice`. + /// + /// ``` + /// use gimli::{EndianSlice, LittleEndian}; + /// + /// let slice = &[0x01, 0x02, 0x03, 0x04]; + /// let endian_slice = EndianSlice::new(slice, LittleEndian); + /// assert_eq!(endian_slice.range_from(2..), + /// EndianSlice::new(&slice[2..], LittleEndian)); + /// ``` + pub fn range_from(&self, idx: RangeFrom) -> EndianSlice<'input, Endian> { + EndianSlice { + slice: &self.slice[idx], + endian: self.endian, + } + } + + /// Take the given `..end` range of the underlying slice and return a new + /// `EndianSlice`. + /// + /// ``` + /// use gimli::{EndianSlice, LittleEndian}; + /// + /// let slice = &[0x01, 0x02, 0x03, 0x04]; + /// let endian_slice = EndianSlice::new(slice, LittleEndian); + /// assert_eq!(endian_slice.range_to(..3), + /// EndianSlice::new(&slice[..3], LittleEndian)); + /// ``` + pub fn range_to(&self, idx: RangeTo) -> EndianSlice<'input, Endian> { + EndianSlice { + slice: &self.slice[idx], + endian: self.endian, + } + } +} + +impl<'input, Endian> Deref for EndianSlice<'input, Endian> +where + Endian: Endianity, +{ + type Target = [u8]; + fn deref(&self) -> &Self::Target { + self.slice + } +} + +impl<'input, Endian: Endianity> fmt::Debug for EndianSlice<'input, Endian> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> { + fmt.debug_tuple("EndianSlice") + .field(&self.endian) + .field(&DebugBytes(self.slice)) + .finish() + } +} + +struct DebugBytes<'input>(&'input [u8]); + +impl<'input> core::fmt::Debug for DebugBytes<'input> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> { + let mut list = fmt.debug_list(); + list.entries(self.0.iter().take(8).copied().map(DebugByte)); + if self.0.len() > 8 { + list.entry(&DebugLen(self.0.len())); + } + list.finish() + } +} + +struct DebugByte(u8); + +impl fmt::Debug for DebugByte { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "0x{:02x}", self.0) + } +} + +struct DebugLen(usize); + +impl fmt::Debug for DebugLen { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "...; {}", self.0) + } +} + +impl<'input, Endian> Reader for EndianSlice<'input, Endian> +where + Endian: Endianity, +{ + type Endian = Endian; + type Offset = usize; + + #[inline] + fn endian(&self) -> Endian { + self.endian + } + + #[inline] + fn len(&self) -> usize { + self.slice.len() + } + + #[inline] + fn is_empty(&self) -> bool { + self.slice.is_empty() + } + + #[inline] + fn empty(&mut self) { + self.slice = &[]; + } + + #[inline] + fn truncate(&mut self, len: usize) -> Result<()> { + if self.slice.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + self.slice = &self.slice[..len]; + Ok(()) + } + } + + #[inline] + fn offset_from(&self, base: &Self) -> usize { + self.offset_from(*base) + } + + #[inline] + fn offset_id(&self) -> ReaderOffsetId { + ReaderOffsetId(self.slice.as_ptr() as u64) + } + + #[inline] + fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option { + let id = id.0; + let self_id = self.slice.as_ptr() as u64; + let self_len = self.slice.len() as u64; + if id >= self_id && id <= self_id + self_len { + Some((id - self_id) as usize) + } else { + None + } + } + + #[inline] + fn find(&self, byte: u8) -> Result { + self.find(byte) + .ok_or_else(|| Error::UnexpectedEof(self.offset_id())) + } + + #[inline] + fn skip(&mut self, len: usize) -> Result<()> { + if self.slice.len() < len { + Err(Error::UnexpectedEof(self.offset_id())) + } else { + self.slice = &self.slice[len..]; + Ok(()) + } + } + + #[inline] + fn split(&mut self, len: usize) -> Result { + let slice = self.read_slice(len)?; + Ok(EndianSlice::new(slice, self.endian)) + } + + #[cfg(not(feature = "read"))] + fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed { + super::reader::seal_if_no_alloc::Sealed + } + + #[cfg(feature = "read")] + #[inline] + fn to_slice(&self) -> Result> { + Ok(self.slice.into()) + } + + #[cfg(feature = "read")] + #[inline] + fn to_string(&self) -> Result> { + match str::from_utf8(self.slice) { + Ok(s) => Ok(s.into()), + _ => Err(Error::BadUtf8), + } + } + + #[cfg(feature = "read")] + #[inline] + fn to_string_lossy(&self) -> Result> { + Ok(String::from_utf8_lossy(self.slice)) + } + + #[inline] + fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> { + let slice = self.read_slice(buf.len())?; + buf.copy_from_slice(slice); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::endianity::NativeEndian; + + #[test] + fn test_endian_slice_split_at() { + let endian = NativeEndian; + let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + let eb = EndianSlice::new(slice, endian); + assert_eq!( + eb.split_at(3), + ( + EndianSlice::new(&slice[..3], endian), + EndianSlice::new(&slice[3..], endian) + ) + ); + } + + #[test] + #[should_panic] + fn test_endian_slice_split_at_out_of_bounds() { + let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + let eb = EndianSlice::new(slice, NativeEndian); + eb.split_at(30); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/index.rs b/anneal/v2/vendor/gimli/src/read/index.rs new file mode 100644 index 0000000000..bd8e74bf1f --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/index.rs @@ -0,0 +1,631 @@ +use core::slice; + +use crate::common::SectionId; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section}; + +/// The data in the `.debug_cu_index` section of a `.dwp` file. +/// +/// This section contains the compilation unit index. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugCuIndex { + section: R, +} + +impl<'input, Endian> DebugCuIndex> +where + Endian: Endianity, +{ + /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index` + /// section. + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugCuIndex { + /// Create a `DebugCuIndex` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfPackageSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugCuIndex + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugCuIndex { + fn id() -> SectionId { + SectionId::DebugCuIndex + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugCuIndex { + fn from(section: R) -> Self { + DebugCuIndex { section } + } +} + +impl DebugCuIndex { + /// Parse the index header. + pub fn index(self) -> Result> { + UnitIndex::parse(self.section) + } +} + +/// The data in the `.debug_tu_index` section of a `.dwp` file. +/// +/// This section contains the type unit index. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugTuIndex { + section: R, +} + +impl<'input, Endian> DebugTuIndex> +where + Endian: Endianity, +{ + /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index` + /// section. + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugTuIndex { + /// Create a `DebugTuIndex` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfPackageSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTuIndex + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugTuIndex { + fn id() -> SectionId { + SectionId::DebugTuIndex + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugTuIndex { + fn from(section: R) -> Self { + DebugTuIndex { section } + } +} + +impl DebugTuIndex { + /// Parse the index header. + pub fn index(self) -> Result> { + UnitIndex::parse(self.section) + } +} + +const SECTION_COUNT_MAX: u8 = 8; + +/// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`. +#[derive(Debug, Clone)] +pub struct UnitIndex { + version: u16, + section_count: u32, + unit_count: u32, + slot_count: u32, + hash_ids: R, + hash_rows: R, + // Only `section_count` values are valid. + sections: [IndexSectionId; SECTION_COUNT_MAX as usize], + offsets: R, + sizes: R, +} + +impl UnitIndex { + fn parse(mut input: R) -> Result> { + if input.is_empty() { + return Ok(UnitIndex { + version: 0, + section_count: 0, + unit_count: 0, + slot_count: 0, + hash_ids: input.clone(), + hash_rows: input.clone(), + sections: [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize], + offsets: input.clone(), + sizes: input.clone(), + }); + } + + // GNU split-dwarf extension to DWARF 4 uses a 32-bit version, + // but DWARF 5 uses a 16-bit version followed by 16-bit padding. + let mut original_input = input.clone(); + let version; + if input.read_u32()? == 2 { + version = 2 + } else { + version = original_input.read_u16()?; + if version != 5 { + return Err(Error::UnknownVersion(version.into())); + } + } + + let section_count = input.read_u32()?; + let unit_count = input.read_u32()?; + let slot_count = input.read_u32()?; + if slot_count != 0 && (slot_count & (slot_count - 1) != 0 || slot_count <= unit_count) { + return Err(Error::InvalidIndexSlotCount); + } + + let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?; + let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?; + + let mut sections = [IndexSectionId::DebugAbbrev; SECTION_COUNT_MAX as usize]; + if section_count > SECTION_COUNT_MAX.into() { + return Err(Error::InvalidIndexSectionCount); + } + for i in 0..section_count { + let section = input.read_u32()?; + sections[i as usize] = if version == 2 { + match constants::DwSectV2(section) { + constants::DW_SECT_V2_INFO => IndexSectionId::DebugInfo, + constants::DW_SECT_V2_TYPES => IndexSectionId::DebugTypes, + constants::DW_SECT_V2_ABBREV => IndexSectionId::DebugAbbrev, + constants::DW_SECT_V2_LINE => IndexSectionId::DebugLine, + constants::DW_SECT_V2_LOC => IndexSectionId::DebugLoc, + constants::DW_SECT_V2_STR_OFFSETS => IndexSectionId::DebugStrOffsets, + constants::DW_SECT_V2_MACINFO => IndexSectionId::DebugMacinfo, + constants::DW_SECT_V2_MACRO => IndexSectionId::DebugMacro, + section => return Err(Error::UnknownIndexSectionV2(section)), + } + } else { + match constants::DwSect(section) { + constants::DW_SECT_INFO => IndexSectionId::DebugInfo, + constants::DW_SECT_ABBREV => IndexSectionId::DebugAbbrev, + constants::DW_SECT_LINE => IndexSectionId::DebugLine, + constants::DW_SECT_LOCLISTS => IndexSectionId::DebugLocLists, + constants::DW_SECT_STR_OFFSETS => IndexSectionId::DebugStrOffsets, + constants::DW_SECT_MACRO => IndexSectionId::DebugMacro, + constants::DW_SECT_RNGLISTS => IndexSectionId::DebugRngLists, + section => return Err(Error::UnknownIndexSection(section)), + } + }; + } + + let offsets = input.split(R::Offset::from_u64( + u64::from(unit_count) * u64::from(section_count) * 4, + )?)?; + let sizes = input.split(R::Offset::from_u64( + u64::from(unit_count) * u64::from(section_count) * 4, + )?)?; + + Ok(UnitIndex { + version, + section_count, + unit_count, + slot_count, + hash_ids, + hash_rows, + sections, + offsets, + sizes, + }) + } + + /// Find `id` in the index hash table, and return the row index. + /// + /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`, + /// or a type signature if this index is from `.debug_tu_index`. + pub fn find(&self, id: u64) -> Option { + if self.slot_count == 0 { + return None; + } + let mask = u64::from(self.slot_count - 1); + let mut hash1 = id & mask; + let hash2 = ((id >> 32) & mask) | 1; + for _ in 0..self.slot_count { + // The length of these arrays was validated in `UnitIndex::parse`. + let mut hash_ids = self.hash_ids.clone(); + hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?; + let hash_id = hash_ids.read_u64().ok()?; + if hash_id == id { + let mut hash_rows = self.hash_rows.clone(); + hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?; + let hash_row = hash_rows.read_u32().ok()?; + return Some(hash_row); + } + if hash_id == 0 { + return None; + } + hash1 = (hash1 + hash2) & mask; + } + None + } + + /// Return the section offsets and sizes for the given row index. + pub fn sections(&self, mut row: u32) -> Result> { + if row == 0 { + return Err(Error::InvalidIndexRow); + } + row -= 1; + if row >= self.unit_count { + return Err(Error::InvalidIndexRow); + } + let mut offsets = self.offsets.clone(); + offsets.skip(R::Offset::from_u64( + u64::from(row) * u64::from(self.section_count) * 4, + )?)?; + let mut sizes = self.sizes.clone(); + sizes.skip(R::Offset::from_u64( + u64::from(row) * u64::from(self.section_count) * 4, + )?)?; + Ok(UnitIndexSectionIterator { + sections: self.sections[..self.section_count as usize].iter(), + offsets, + sizes, + }) + } + + /// Return the version. + /// + /// Defaults to 0 for empty sections. + pub fn version(&self) -> u16 { + self.version + } + + /// Return the number of sections. + pub fn section_count(&self) -> u32 { + self.section_count + } + + /// Return the number of units. + pub fn unit_count(&self) -> u32 { + self.unit_count + } + + /// Return the number of slots. + pub fn slot_count(&self) -> u32 { + self.slot_count + } +} + +/// An iterator over the section offsets and sizes for a row in a `UnitIndex`. +#[derive(Debug, Clone)] +pub struct UnitIndexSectionIterator<'index, R: Reader> { + sections: slice::Iter<'index, IndexSectionId>, + offsets: R, + sizes: R, +} + +impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> { + type Item = UnitIndexSection; + + fn next(&mut self) -> Option { + let section = *self.sections.next()?; + // The length of these arrays was validated in `UnitIndex::parse`. + let offset = self.offsets.read_u32().ok()?; + let size = self.sizes.read_u32().ok()?; + Some(UnitIndexSection { + section, + offset, + size, + }) + } +} + +/// Information about a unit's contribution to a section in a `.dwp` file. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct UnitIndexSection { + /// The section kind. + pub section: IndexSectionId, + /// The base offset of the unit's contribution to the section. + pub offset: u32, + /// The size of the unit's contribution to the section. + pub size: u32, +} + +/// Section kinds which are permitted in a `.dwp` index. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum IndexSectionId { + /// The `.debug_abbrev.dwo` section. + DebugAbbrev, + /// The `.debug_info.dwo` section. + DebugInfo, + /// The `.debug_line.dwo` section. + DebugLine, + /// The `.debug_loc.dwo` section. + DebugLoc, + /// The `.debug_loclists.dwo` section. + DebugLocLists, + /// The `.debug_macinfo.dwo` section. + DebugMacinfo, + /// The `.debug_macro.dwo` section. + DebugMacro, + /// The `.debug_rnglists.dwo` section. + DebugRngLists, + /// The `.debug_str_offsets.dwo` section. + DebugStrOffsets, + /// The `.debug_types.dwo` section. + DebugTypes, +} + +impl IndexSectionId { + /// Returns the corresponding `SectionId`. + pub fn section_id(self) -> SectionId { + match self { + IndexSectionId::DebugAbbrev => SectionId::DebugAbbrev, + IndexSectionId::DebugInfo => SectionId::DebugInfo, + IndexSectionId::DebugLine => SectionId::DebugLine, + IndexSectionId::DebugLoc => SectionId::DebugLoc, + IndexSectionId::DebugLocLists => SectionId::DebugLocLists, + IndexSectionId::DebugMacro => SectionId::DebugMacro, + IndexSectionId::DebugMacinfo => SectionId::DebugMacinfo, + IndexSectionId::DebugRngLists => SectionId::DebugRngLists, + IndexSectionId::DebugStrOffsets => SectionId::DebugStrOffsets, + IndexSectionId::DebugTypes => SectionId::DebugTypes, + } + } + + /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file. + pub fn dwo_name(self) -> &'static str { + self.section_id().dwo_name().unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::endianity::BigEndian; + use test_assembler::{Endian, Section}; + + #[test] + fn test_empty() { + let buf = EndianSlice::new(&[], BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.version(), 0); + assert_eq!(index.unit_count(), 0); + assert_eq!(index.slot_count(), 0); + assert!(index.find(0).is_none()); + } + + #[test] + fn test_zero_slots() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D32(2).D32(0).D32(0).D32(0); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.version(), 2); + assert_eq!(index.unit_count(), 0); + assert_eq!(index.slot_count(), 0); + assert!(index.find(0).is_none()); + } + + #[test] + fn test_version_2() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D32(2).D32(0).D32(0).D32(1) + // Slots. + .D64(0).D32(0); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.version, 2); + } + + #[test] + fn test_version_5() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D16(5).D16(0).D32(0).D32(0).D32(1) + // Slots. + .D64(0).D32(0); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.version, 5); + } + + #[test] + fn test_version_5_invalid() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D32(5).D32(0).D32(0).D32(1) + // Slots. + .D64(0).D32(0); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + assert!(UnitIndex::parse(buf).is_err()); + } + + #[test] + fn test_version_2_sections() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D32(2).D32(8).D32(1).D32(2) + // Slots. + .D64(0).D64(0).D32(0).D32(0) + // Sections. + .D32(constants::DW_SECT_V2_INFO.0) + .D32(constants::DW_SECT_V2_TYPES.0) + .D32(constants::DW_SECT_V2_ABBREV.0) + .D32(constants::DW_SECT_V2_LINE.0) + .D32(constants::DW_SECT_V2_LOC.0) + .D32(constants::DW_SECT_V2_STR_OFFSETS.0) + .D32(constants::DW_SECT_V2_MACINFO.0) + .D32(constants::DW_SECT_V2_MACRO.0) + // Offsets. + .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18) + // Sizes. + .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.section_count, 8); + assert_eq!( + index.sections, + [ + IndexSectionId::DebugInfo, + IndexSectionId::DebugTypes, + IndexSectionId::DebugAbbrev, + IndexSectionId::DebugLine, + IndexSectionId::DebugLoc, + IndexSectionId::DebugStrOffsets, + IndexSectionId::DebugMacinfo, + IndexSectionId::DebugMacro, + ] + ); + #[rustfmt::skip] + let expect = [ + UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 }, + UnitIndexSection { section: IndexSectionId::DebugTypes, offset: 12, size: 22 }, + UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 13, size: 23 }, + UnitIndexSection { section: IndexSectionId::DebugLine, offset: 14, size: 24 }, + UnitIndexSection { section: IndexSectionId::DebugLoc, offset: 15, size: 25 }, + UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 16, size: 26 }, + UnitIndexSection { section: IndexSectionId::DebugMacinfo, offset: 17, size: 27 }, + UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 18, size: 28 }, + ]; + let mut sections = index.sections(1).unwrap(); + for section in &expect { + assert_eq!(*section, sections.next().unwrap()); + } + assert!(sections.next().is_none()); + } + + #[test] + fn test_version_5_sections() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D16(5).D16(0).D32(7).D32(1).D32(2) + // Slots. + .D64(0).D64(0).D32(0).D32(0) + // Sections. + .D32(constants::DW_SECT_INFO.0) + .D32(constants::DW_SECT_ABBREV.0) + .D32(constants::DW_SECT_LINE.0) + .D32(constants::DW_SECT_LOCLISTS.0) + .D32(constants::DW_SECT_STR_OFFSETS.0) + .D32(constants::DW_SECT_MACRO.0) + .D32(constants::DW_SECT_RNGLISTS.0) + // Offsets. + .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17) + // Sizes. + .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.section_count, 7); + assert_eq!( + index.sections[..7], + [ + IndexSectionId::DebugInfo, + IndexSectionId::DebugAbbrev, + IndexSectionId::DebugLine, + IndexSectionId::DebugLocLists, + IndexSectionId::DebugStrOffsets, + IndexSectionId::DebugMacro, + IndexSectionId::DebugRngLists, + ] + ); + #[rustfmt::skip] + let expect = [ + UnitIndexSection { section: IndexSectionId::DebugInfo, offset: 11, size: 21 }, + UnitIndexSection { section: IndexSectionId::DebugAbbrev, offset: 12, size: 22 }, + UnitIndexSection { section: IndexSectionId::DebugLine, offset: 13, size: 23 }, + UnitIndexSection { section: IndexSectionId::DebugLocLists, offset: 14, size: 24 }, + UnitIndexSection { section: IndexSectionId::DebugStrOffsets, offset: 15, size: 25 }, + UnitIndexSection { section: IndexSectionId::DebugMacro, offset: 16, size: 26 }, + UnitIndexSection { section: IndexSectionId::DebugRngLists, offset: 17, size: 27 }, + ]; + let mut sections = index.sections(1).unwrap(); + for section in &expect { + assert_eq!(*section, sections.next().unwrap()); + } + assert!(sections.next().is_none()); + + assert!(index.sections(0).is_err()); + assert!(index.sections(2).is_err()); + } + + #[test] + fn test_hash() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D16(5).D16(0).D32(2).D32(3).D32(4) + // Slots. + .D64(0xffff_fff2_ffff_fff1) + .D64(0xffff_fff0_ffff_fff1) + .D64(0xffff_fff1_ffff_fff1) + .D64(0) + .D32(3).D32(1).D32(2).D32(0) + // Sections. + .D32(constants::DW_SECT_INFO.0) + .D32(constants::DW_SECT_ABBREV.0) + // Offsets. + .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0) + // Sizes. + .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0); + let buf = section.get_contents().unwrap(); + let buf = EndianSlice::new(&buf, BigEndian); + let index = UnitIndex::parse(buf).unwrap(); + assert_eq!(index.version(), 5); + assert_eq!(index.slot_count(), 4); + assert_eq!(index.unit_count(), 3); + assert_eq!(index.section_count(), 2); + assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1)); + assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2)); + assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3)); + assert_eq!(index.find(0xffff_fff3_ffff_fff1), None); + } + + #[test] + fn test_cu_index() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D16(5).D16(0).D32(0).D32(0).D32(1) + // Slots. + .D64(0).D32(0); + let buf = section.get_contents().unwrap(); + let cu_index = DebugCuIndex::new(&buf, BigEndian); + let index = cu_index.index().unwrap(); + assert_eq!(index.version, 5); + } + + #[test] + fn test_tu_index() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Big) + // Header. + .D16(5).D16(0).D32(0).D32(0).D32(1) + // Slots. + .D64(0).D32(0); + let buf = section.get_contents().unwrap(); + let tu_index = DebugTuIndex::new(&buf, BigEndian); + let index = tu_index.index().unwrap(); + assert_eq!(index.version, 5); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/line.rs b/anneal/v2/vendor/gimli/src/read/line.rs new file mode 100644 index 0000000000..d2b6c66775 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/line.rs @@ -0,0 +1,3185 @@ +use alloc::vec::Vec; +use core::num::{NonZeroU64, Wrapping}; + +use crate::common::{ + DebugLineOffset, DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsIndex, Encoding, Format, + LineEncoding, SectionId, +}; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::{ + AttributeValue, EndianSlice, Error, Reader, ReaderAddress, ReaderOffset, Result, Section, +}; + +/// The `DebugLine` struct contains the source location to instruction mapping +/// found in the `.debug_line` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugLine { + debug_line_section: R, +} + +impl<'input, Endian> DebugLine> +where + Endian: Endianity, +{ + /// Construct a new `DebugLine` instance from the data in the `.debug_line` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_line` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugLine, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_line_section_somehow = || &buf; + /// let debug_line = DebugLine::new(read_debug_line_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_line_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_line_section, endian)) + } +} + +impl DebugLine { + /// Parse the line number program whose header is at the given `offset` in the + /// `.debug_line` section. + /// + /// The `address_size` must match the compilation unit that the lines apply to. + /// The `comp_dir` should be from the `DW_AT_comp_dir` attribute of the compilation + /// unit. The `comp_name` should be from the `DW_AT_name` attribute of the + /// compilation unit. + /// + /// ```rust,no_run + /// use gimli::{DebugLine, DebugLineOffset, IncompleteLineProgram, EndianSlice, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_line_section_somehow = || &buf; + /// let debug_line = DebugLine::new(read_debug_line_section_somehow(), LittleEndian); + /// + /// // In a real example, we'd grab the offset via a compilation unit + /// // entry's `DW_AT_stmt_list` attribute, and the address size from that + /// // unit directly. + /// let offset = DebugLineOffset(0); + /// let address_size = 8; + /// + /// let program = debug_line.program(offset, address_size, None, None) + /// .expect("should have found a header at that offset, and parsed it OK"); + /// ``` + pub fn program( + &self, + offset: DebugLineOffset, + address_size: u8, + comp_dir: Option, + comp_name: Option, + ) -> Result> { + let input = &mut self.debug_line_section.clone(); + input.skip(offset.0)?; + let header = LineProgramHeader::parse(input, offset, address_size, comp_dir, comp_name)?; + let program = IncompleteLineProgram { header }; + Ok(program) + } +} + +impl DebugLine { + /// Create a `DebugLine` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLine + where + F: FnMut(&'a T) -> R, + { + borrow(&self.debug_line_section).into() + } +} + +impl Section for DebugLine { + fn id() -> SectionId { + SectionId::DebugLine + } + + fn reader(&self) -> &R { + &self.debug_line_section + } +} + +impl From for DebugLine { + fn from(debug_line_section: R) -> Self { + DebugLine { debug_line_section } + } +} + +/// Deprecated. `LineNumberProgram` has been renamed to `LineProgram`. +#[deprecated(note = "LineNumberProgram has been renamed to LineProgram, use that instead.")] +pub type LineNumberProgram = dyn LineProgram; + +/// A `LineProgram` provides access to a `LineProgramHeader` and +/// a way to add files to the files table if necessary. Gimli consumers should +/// never need to use or see this trait. +pub trait LineProgram::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// Get a reference to the held `LineProgramHeader`. + fn header(&self) -> &LineProgramHeader; + /// Add a file to the file table if necessary. + fn add_file(&mut self, file: FileEntry); +} + +impl LineProgram for IncompleteLineProgram +where + R: Reader, + Offset: ReaderOffset, +{ + fn header(&self) -> &LineProgramHeader { + &self.header + } + fn add_file(&mut self, file: FileEntry) { + self.header.file_names.push(file); + } +} + +impl<'program, R, Offset> LineProgram for &'program CompleteLineProgram +where + R: Reader, + Offset: ReaderOffset, +{ + fn header(&self) -> &LineProgramHeader { + &self.header + } + fn add_file(&mut self, _: FileEntry) { + // Nop. Our file table is already complete. + } +} + +/// Deprecated. `StateMachine` has been renamed to `LineRows`. +#[deprecated(note = "StateMachine has been renamed to LineRows, use that instead.")] +pub type StateMachine = LineRows; + +/// Executes a `LineProgram` to iterate over the rows in the matrix of line number information. +/// +/// "The hypothetical machine used by a consumer of the line number information +/// to expand the byte-coded instruction stream into a matrix of line number +/// information." -- Section 6.2.1 +#[derive(Debug, Clone)] +pub struct LineRows::Offset> +where + Program: LineProgram, + R: Reader, + Offset: ReaderOffset, +{ + program: Program, + row: LineRow, + instructions: LineInstructions, +} + +type OneShotLineRows::Offset> = + LineRows, Offset>; + +type ResumedLineRows<'program, R, Offset = ::Offset> = + LineRows, Offset>; + +impl LineRows +where + Program: LineProgram, + R: Reader, + Offset: ReaderOffset, +{ + fn new(program: IncompleteLineProgram) -> OneShotLineRows { + let row = LineRow::new(program.header()); + let instructions = LineInstructions { + input: program.header().program_buf.clone(), + }; + LineRows { + program, + row, + instructions, + } + } + + fn resume<'program>( + program: &'program CompleteLineProgram, + sequence: &LineSequence, + ) -> ResumedLineRows<'program, R, Offset> { + let row = LineRow::new(program.header()); + let instructions = sequence.instructions.clone(); + LineRows { + program, + row, + instructions, + } + } + + /// Get a reference to the header for this state machine's line number + /// program. + #[inline] + pub fn header(&self) -> &LineProgramHeader { + self.program.header() + } + + /// Parse and execute the next instructions in the line number program until + /// another row in the line number matrix is computed. + /// + /// The freshly computed row is returned as `Ok(Some((header, row)))`. + /// If the matrix is complete, and there are no more new rows in the line + /// number matrix, then `Ok(None)` is returned. If there was an error parsing + /// an instruction, then `Err(e)` is returned. + /// + /// Unfortunately, the references mean that this cannot be a + /// `FallibleIterator`. + pub fn next_row(&mut self) -> Result, &LineRow)>> { + // Perform any reset that was required after copying the previous row. + self.row.reset(self.program.header()); + + loop { + // Split the borrow here, rather than calling `self.header()`. + match self.instructions.next_instruction(self.program.header()) { + Err(err) => return Err(err), + Ok(None) => return Ok(None), + Ok(Some(instruction)) => { + if self.row.execute(instruction, &mut self.program)? { + if self.row.tombstone { + // Perform any reset that was required for the tombstone row. + // Normally this is done when `next_row` is called again, but for + // tombstones we loop immediately. + self.row.reset(self.program.header()); + } else { + return Ok(Some((self.header(), &self.row))); + } + } + // Fall through, parse the next instruction, and see if that + // yields a row. + } + } + } + } +} + +/// Deprecated. `Opcode` has been renamed to `LineInstruction`. +#[deprecated(note = "Opcode has been renamed to LineInstruction, use that instead.")] +pub type Opcode = LineInstruction::Offset>; + +/// A parsed line number program instruction. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum LineInstruction::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// > ### 6.2.5.1 Special Opcodes + /// > + /// > Each ubyte special opcode has the following effect on the state machine: + /// > + /// > 1. Add a signed integer to the line register. + /// > + /// > 2. Modify the operation pointer by incrementing the address and + /// > op_index registers as described below. + /// > + /// > 3. Append a row to the matrix using the current values of the state + /// > machine registers. + /// > + /// > 4. Set the basic_block register to “false.” + /// > + /// > 5. Set the prologue_end register to “false.” + /// > + /// > 6. Set the epilogue_begin register to “false.” + /// > + /// > 7. Set the discriminator register to 0. + /// > + /// > All of the special opcodes do those same seven things; they differ from + /// > one another only in what values they add to the line, address and + /// > op_index registers. + Special(u8), + + /// "[`LineInstruction::Copy`] appends a row to the matrix using the current + /// values of the state machine registers. Then it sets the discriminator + /// register to 0, and sets the basic_block, prologue_end and epilogue_begin + /// registers to “false.”" + Copy, + + /// "The DW_LNS_advance_pc opcode takes a single unsigned LEB128 operand as + /// the operation advance and modifies the address and op_index registers + /// [the same as `LineInstruction::Special`]" + AdvancePc(u64), + + /// "The DW_LNS_advance_line opcode takes a single signed LEB128 operand and + /// adds that value to the line register of the state machine." + AdvanceLine(i64), + + /// "The DW_LNS_set_file opcode takes a single unsigned LEB128 operand and + /// stores it in the file register of the state machine." + SetFile(u64), + + /// "The DW_LNS_set_column opcode takes a single unsigned LEB128 operand and + /// stores it in the column register of the state machine." + SetColumn(u64), + + /// "The DW_LNS_negate_stmt opcode takes no operands. It sets the is_stmt + /// register of the state machine to the logical negation of its current + /// value." + NegateStatement, + + /// "The DW_LNS_set_basic_block opcode takes no operands. It sets the + /// basic_block register of the state machine to “true.”" + SetBasicBlock, + + /// > The DW_LNS_const_add_pc opcode takes no operands. It advances the + /// > address and op_index registers by the increments corresponding to + /// > special opcode 255. + /// > + /// > When the line number program needs to advance the address by a small + /// > amount, it can use a single special opcode, which occupies a single + /// > byte. When it needs to advance the address by up to twice the range of + /// > the last special opcode, it can use DW_LNS_const_add_pc followed by a + /// > special opcode, for a total of two bytes. Only if it needs to advance + /// > the address by more than twice that range will it need to use both + /// > DW_LNS_advance_pc and a special opcode, requiring three or more bytes. + ConstAddPc, + + /// > The DW_LNS_fixed_advance_pc opcode takes a single uhalf (unencoded) + /// > operand and adds it to the address register of the state machine and + /// > sets the op_index register to 0. This is the only standard opcode whose + /// > operand is not a variable length number. It also does not multiply the + /// > operand by the minimum_instruction_length field of the header. + FixedAddPc(u16), + + /// "[`LineInstruction::SetPrologueEnd`] sets the prologue_end register to “true”." + SetPrologueEnd, + + /// "[`LineInstruction::SetEpilogueBegin`] sets the epilogue_begin register to + /// “true”." + SetEpilogueBegin, + + /// "The DW_LNS_set_isa opcode takes a single unsigned LEB128 operand and + /// stores that value in the isa register of the state machine." + SetIsa(u64), + + /// An unknown standard opcode with zero operands. + UnknownStandard0(constants::DwLns), + + /// An unknown standard opcode with one operand. + UnknownStandard1(constants::DwLns, u64), + + /// An unknown standard opcode with multiple operands. + UnknownStandardN(constants::DwLns, R), + + /// > [`LineInstruction::EndSequence`] sets the end_sequence register of the state + /// > machine to “true” and appends a row to the matrix using the current + /// > values of the state-machine registers. Then it resets the registers to + /// > the initial values specified above (see Section 6.2.2). Every line + /// > number program sequence must end with a DW_LNE_end_sequence instruction + /// > which creates a row whose address is that of the byte after the last + /// > target machine instruction of the sequence. + EndSequence, + + /// > The DW_LNE_set_address opcode takes a single relocatable address as an + /// > operand. The size of the operand is the size of an address on the target + /// > machine. It sets the address register to the value given by the + /// > relocatable address and sets the op_index register to 0. + /// > + /// > All of the other line number program opcodes that affect the address + /// > register add a delta to it. This instruction stores a relocatable value + /// > into it instead. + SetAddress(u64), + + /// Defines a new source file in the line number program and appends it to + /// the line number program header's list of source files. + DefineFile(FileEntry), + + /// "The DW_LNE_set_discriminator opcode takes a single parameter, an + /// unsigned LEB128 integer. It sets the discriminator register to the new + /// value." + SetDiscriminator(u64), + + /// An unknown extended opcode and the slice of its unparsed operands. + UnknownExtended(constants::DwLne, R), +} + +impl LineInstruction +where + R: Reader, + Offset: ReaderOffset, +{ + fn parse<'header>( + header: &'header LineProgramHeader, + input: &mut R, + ) -> Result> + where + R: 'header, + { + let opcode = input.read_u8()?; + if opcode == 0 { + let length = input.read_uleb128().and_then(R::Offset::from_u64)?; + let mut instr_rest = input.split(length)?; + let opcode = instr_rest.read_u8()?; + + match constants::DwLne(opcode) { + constants::DW_LNE_end_sequence => Ok(LineInstruction::EndSequence), + + constants::DW_LNE_set_address => { + let address = instr_rest.read_address(header.address_size())?; + Ok(LineInstruction::SetAddress(address)) + } + + constants::DW_LNE_define_file => { + if header.version() <= 4 { + let path_name = instr_rest.read_null_terminated_slice()?; + let entry = FileEntry::parse(&mut instr_rest, path_name)?; + Ok(LineInstruction::DefineFile(entry)) + } else { + Ok(LineInstruction::UnknownExtended( + constants::DW_LNE_define_file, + instr_rest, + )) + } + } + + constants::DW_LNE_set_discriminator => { + let discriminator = instr_rest.read_uleb128()?; + Ok(LineInstruction::SetDiscriminator(discriminator)) + } + + otherwise => Ok(LineInstruction::UnknownExtended(otherwise, instr_rest)), + } + } else if opcode >= header.opcode_base { + Ok(LineInstruction::Special(opcode)) + } else { + match constants::DwLns(opcode) { + constants::DW_LNS_copy => Ok(LineInstruction::Copy), + + constants::DW_LNS_advance_pc => { + let advance = input.read_uleb128()?; + Ok(LineInstruction::AdvancePc(advance)) + } + + constants::DW_LNS_advance_line => { + let increment = input.read_sleb128()?; + Ok(LineInstruction::AdvanceLine(increment)) + } + + constants::DW_LNS_set_file => { + let file = input.read_uleb128()?; + Ok(LineInstruction::SetFile(file)) + } + + constants::DW_LNS_set_column => { + let column = input.read_uleb128()?; + Ok(LineInstruction::SetColumn(column)) + } + + constants::DW_LNS_negate_stmt => Ok(LineInstruction::NegateStatement), + + constants::DW_LNS_set_basic_block => Ok(LineInstruction::SetBasicBlock), + + constants::DW_LNS_const_add_pc => Ok(LineInstruction::ConstAddPc), + + constants::DW_LNS_fixed_advance_pc => { + let advance = input.read_u16()?; + Ok(LineInstruction::FixedAddPc(advance)) + } + + constants::DW_LNS_set_prologue_end => Ok(LineInstruction::SetPrologueEnd), + + constants::DW_LNS_set_epilogue_begin => Ok(LineInstruction::SetEpilogueBegin), + + constants::DW_LNS_set_isa => { + let isa = input.read_uleb128()?; + Ok(LineInstruction::SetIsa(isa)) + } + + otherwise => { + let mut opcode_lengths = header.standard_opcode_lengths().clone(); + opcode_lengths.skip(R::Offset::from_u8(opcode - 1))?; + let num_args = opcode_lengths.read_u8()? as usize; + match num_args { + 0 => Ok(LineInstruction::UnknownStandard0(otherwise)), + 1 => { + let arg = input.read_uleb128()?; + Ok(LineInstruction::UnknownStandard1(otherwise, arg)) + } + _ => { + let mut args = input.clone(); + for _ in 0..num_args { + input.read_uleb128()?; + } + let len = input.offset_from(&args); + args.truncate(len)?; + Ok(LineInstruction::UnknownStandardN(otherwise, args)) + } + } + } + } + } + } +} + +/// Deprecated. `OpcodesIter` has been renamed to `LineInstructions`. +#[deprecated(note = "OpcodesIter has been renamed to LineInstructions, use that instead.")] +pub type OpcodesIter = LineInstructions; + +/// An iterator yielding parsed instructions. +/// +/// See +/// [`LineProgramHeader::instructions`](./struct.LineProgramHeader.html#method.instructions) +/// for more details. +#[derive(Clone, Debug)] +pub struct LineInstructions { + input: R, +} + +impl LineInstructions { + fn remove_trailing(&self, other: &LineInstructions) -> Result> { + let offset = other.input.offset_from(&self.input); + let mut input = self.input.clone(); + input.truncate(offset)?; + Ok(LineInstructions { input }) + } +} + +impl LineInstructions { + /// Advance the iterator and return the next instruction. + /// + /// Returns the newly parsed instruction as `Ok(Some(instruction))`. Returns + /// `Ok(None)` when iteration is complete and all instructions have already been + /// parsed and yielded. If an error occurs while parsing the next attribute, + /// then this error is returned as `Err(e)`, and all subsequent calls return + /// `Ok(None)`. + /// + /// Unfortunately, the `header` parameter means that this cannot be a + /// `FallibleIterator`. + #[inline(always)] + pub fn next_instruction( + &mut self, + header: &LineProgramHeader, + ) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + match LineInstruction::parse(header, &mut self.input) { + Ok(instruction) => Ok(Some(instruction)), + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +/// Deprecated. `LineNumberRow` has been renamed to `LineRow`. +#[deprecated(note = "LineNumberRow has been renamed to LineRow, use that instead.")] +pub type LineNumberRow = LineRow; + +/// A row in the line number program's resulting matrix. +/// +/// Each row is a copy of the registers of the state machine, as defined in section 6.2.2. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct LineRow { + tombstone: bool, + address: u64, + op_index: Wrapping, + file: u64, + line: Wrapping, + column: u64, + is_stmt: bool, + basic_block: bool, + end_sequence: bool, + prologue_end: bool, + epilogue_begin: bool, + isa: u64, + discriminator: u64, +} + +impl LineRow { + /// Create a line number row in the initial state for the given program. + pub fn new(header: &LineProgramHeader) -> Self { + LineRow { + // "At the beginning of each sequence within a line number program, the + // state of the registers is:" -- Section 6.2.2 + tombstone: false, + address: 0, + op_index: Wrapping(0), + file: 1, + line: Wrapping(1), + column: 0, + // "determined by default_is_stmt in the line number program header" + is_stmt: header.line_encoding.default_is_stmt, + basic_block: false, + end_sequence: false, + prologue_end: false, + epilogue_begin: false, + // "The isa value 0 specifies that the instruction set is the + // architecturally determined default instruction set. This may be fixed + // by the ABI, or it may be specified by other means, for example, by + // the object file description." + isa: 0, + discriminator: 0, + } + } + + /// "The program-counter value corresponding to a machine instruction + /// generated by the compiler." + #[inline] + pub fn address(&self) -> u64 { + self.address + } + + /// > An unsigned integer representing the index of an operation within a VLIW + /// > instruction. The index of the first operation is 0. For non-VLIW + /// > architectures, this register will always be 0. + /// > + /// > The address and op_index registers, taken together, form an operation + /// > pointer that can reference any individual operation with the + /// > instruction stream. + #[inline] + pub fn op_index(&self) -> u64 { + self.op_index.0 + } + + /// "An unsigned integer indicating the identity of the source file + /// corresponding to a machine instruction." + #[inline] + pub fn file_index(&self) -> u64 { + self.file + } + + /// The source file corresponding to the current machine instruction. + #[inline] + pub fn file<'header, R: Reader>( + &self, + header: &'header LineProgramHeader, + ) -> Option<&'header FileEntry> { + header.file(self.file) + } + + /// "An unsigned integer indicating a source line number. Lines are numbered + /// beginning at 1. The compiler may emit the value 0 in cases where an + /// instruction cannot be attributed to any source line." + /// Line number values of 0 are represented as `None`. + #[inline] + pub fn line(&self) -> Option { + NonZeroU64::new(self.line.0) + } + + /// "An unsigned integer indicating a column number within a source + /// line. Columns are numbered beginning at 1. The value 0 is reserved to + /// indicate that a statement begins at the “left edge” of the line." + #[inline] + pub fn column(&self) -> ColumnType { + NonZeroU64::new(self.column) + .map(ColumnType::Column) + .unwrap_or(ColumnType::LeftEdge) + } + + /// "A boolean indicating that the current instruction is a recommended + /// breakpoint location. A recommended breakpoint location is intended to + /// “represent” a line, a statement and/or a semantically distinct subpart + /// of a statement." + #[inline] + pub fn is_stmt(&self) -> bool { + self.is_stmt + } + + /// "A boolean indicating that the current instruction is the beginning of a + /// basic block." + #[inline] + pub fn basic_block(&self) -> bool { + self.basic_block + } + + /// "A boolean indicating that the current address is that of the first byte + /// after the end of a sequence of target machine instructions. end_sequence + /// terminates a sequence of lines; therefore other information in the same + /// row is not meaningful." + #[inline] + pub fn end_sequence(&self) -> bool { + self.end_sequence + } + + /// "A boolean indicating that the current address is one (of possibly many) + /// where execution should be suspended for an entry breakpoint of a + /// function." + #[inline] + pub fn prologue_end(&self) -> bool { + self.prologue_end + } + + /// "A boolean indicating that the current address is one (of possibly many) + /// where execution should be suspended for an exit breakpoint of a + /// function." + #[inline] + pub fn epilogue_begin(&self) -> bool { + self.epilogue_begin + } + + /// Tag for the current instruction set architecture. + /// + /// > An unsigned integer whose value encodes the applicable instruction set + /// > architecture for the current instruction. + /// > + /// > The encoding of instruction sets should be shared by all users of a + /// > given architecture. It is recommended that this encoding be defined by + /// > the ABI authoring committee for each architecture. + #[inline] + pub fn isa(&self) -> u64 { + self.isa + } + + /// "An unsigned integer identifying the block to which the current + /// instruction belongs. Discriminator values are assigned arbitrarily by + /// the DWARF producer and serve to distinguish among multiple blocks that + /// may all be associated with the same source file, line, and column. Where + /// only one block exists for a given source position, the discriminator + /// value should be zero." + #[inline] + pub fn discriminator(&self) -> u64 { + self.discriminator + } + + /// Execute the given instruction, and return true if a new row in the + /// line number matrix needs to be generated. + /// + /// Unknown opcodes are treated as no-ops. + #[inline] + pub fn execute( + &mut self, + instruction: LineInstruction, + program: &mut Program, + ) -> Result + where + Program: LineProgram, + R: Reader, + { + Ok(match instruction { + LineInstruction::Special(opcode) => { + self.exec_special_opcode(opcode, program.header())?; + true + } + + LineInstruction::Copy => true, + + LineInstruction::AdvancePc(operation_advance) => { + self.apply_operation_advance(operation_advance, program.header())?; + false + } + + LineInstruction::AdvanceLine(line_increment) => { + self.apply_line_advance(line_increment); + false + } + + LineInstruction::SetFile(file) => { + self.file = file; + false + } + + LineInstruction::SetColumn(column) => { + self.column = column; + false + } + + LineInstruction::NegateStatement => { + self.is_stmt = !self.is_stmt; + false + } + + LineInstruction::SetBasicBlock => { + self.basic_block = true; + false + } + + LineInstruction::ConstAddPc => { + let adjusted = self.adjust_opcode(255, program.header()); + let operation_advance = adjusted / program.header().line_encoding.line_range; + self.apply_operation_advance(u64::from(operation_advance), program.header())?; + false + } + + LineInstruction::FixedAddPc(operand) => { + if !self.tombstone { + let address_size = program.header().address_size(); + self.address = self.address.add_sized(u64::from(operand), address_size)?; + self.op_index.0 = 0; + } + false + } + + LineInstruction::SetPrologueEnd => { + self.prologue_end = true; + false + } + + LineInstruction::SetEpilogueBegin => { + self.epilogue_begin = true; + false + } + + LineInstruction::SetIsa(isa) => { + self.isa = isa; + false + } + + LineInstruction::EndSequence => { + self.end_sequence = true; + true + } + + LineInstruction::SetAddress(address) => { + // If the address is a tombstone, then skip instructions until the next address. + // DWARF specifies a tombstone value of -1, but many linkers use 0. + // However, 0 may be a valid address, so we only skip that if we have previously + // seen a higher address. Additionally, gold may keep the relocation addend, + // so we treat all lower addresses as tombstones instead of just 0. + // This works because DWARF specifies that addresses are monotonically increasing + // within a sequence; the alternative is to return an error. + self.tombstone = address < self.address + || address >= u64::min_tombstone(program.header().encoding.address_size); + if !self.tombstone { + self.address = address; + self.op_index.0 = 0; + } + false + } + + LineInstruction::DefineFile(entry) => { + program.add_file(entry); + false + } + + LineInstruction::SetDiscriminator(discriminator) => { + self.discriminator = discriminator; + false + } + + // Compatibility with future opcodes. + LineInstruction::UnknownStandard0(_) + | LineInstruction::UnknownStandard1(_, _) + | LineInstruction::UnknownStandardN(_, _) + | LineInstruction::UnknownExtended(_, _) => false, + }) + } + + /// Perform any reset that was required after copying the previous row. + #[inline] + pub fn reset(&mut self, header: &LineProgramHeader) { + if self.end_sequence { + // Previous instruction was EndSequence, so reset everything + // as specified in Section 6.2.5.3. + *self = Self::new(header); + } else { + // Previous instruction was one of: + // - Special - specified in Section 6.2.5.1, steps 4-7 + // - Copy - specified in Section 6.2.5.2 + // The reset behaviour is the same in both cases. + self.discriminator = 0; + self.basic_block = false; + self.prologue_end = false; + self.epilogue_begin = false; + } + } + + /// Step 1 of section 6.2.5.1 + fn apply_line_advance(&mut self, line_increment: i64) { + if line_increment < 0 { + let decrement = -line_increment as u64; + if decrement <= self.line.0 { + self.line.0 -= decrement; + } else { + self.line.0 = 0; + } + } else { + self.line += Wrapping(line_increment as u64); + } + } + + /// Step 2 of section 6.2.5.1 + fn apply_operation_advance( + &mut self, + operation_advance: u64, + header: &LineProgramHeader, + ) -> Result<()> { + if self.tombstone { + return Ok(()); + } + + let operation_advance = Wrapping(operation_advance); + + let minimum_instruction_length = u64::from(header.line_encoding.minimum_instruction_length); + let minimum_instruction_length = Wrapping(minimum_instruction_length); + + let maximum_operations_per_instruction = + u64::from(header.line_encoding.maximum_operations_per_instruction); + let maximum_operations_per_instruction = Wrapping(maximum_operations_per_instruction); + + let address_advance = if maximum_operations_per_instruction.0 == 1 { + self.op_index.0 = 0; + minimum_instruction_length * operation_advance + } else { + let op_index_with_advance = self.op_index + operation_advance; + self.op_index = op_index_with_advance % maximum_operations_per_instruction; + minimum_instruction_length + * (op_index_with_advance / maximum_operations_per_instruction) + }; + self.address = self + .address + .add_sized(address_advance.0, header.address_size())?; + Ok(()) + } + + #[inline] + fn adjust_opcode(&self, opcode: u8, header: &LineProgramHeader) -> u8 { + opcode - header.opcode_base + } + + /// Section 6.2.5.1 + fn exec_special_opcode( + &mut self, + opcode: u8, + header: &LineProgramHeader, + ) -> Result<()> { + let adjusted_opcode = self.adjust_opcode(opcode, header); + + let line_range = header.line_encoding.line_range; + let line_advance = adjusted_opcode % line_range; + let operation_advance = adjusted_opcode / line_range; + + // Step 1 + let line_base = i64::from(header.line_encoding.line_base); + self.apply_line_advance(line_base + i64::from(line_advance)); + + // Step 2 + self.apply_operation_advance(u64::from(operation_advance), header)?; + Ok(()) + } +} + +/// The type of column that a row is referring to. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum ColumnType { + /// The `LeftEdge` means that the statement begins at the start of the new + /// line. + LeftEdge, + /// A column number, whose range begins at 1. + Column(NonZeroU64), +} + +/// Deprecated. `LineNumberSequence` has been renamed to `LineSequence`. +#[deprecated(note = "LineNumberSequence has been renamed to LineSequence, use that instead.")] +pub type LineNumberSequence = LineSequence; + +/// A sequence within a line number program. A sequence, as defined in section +/// 6.2.5 of the standard, is a linear subset of a line number program within +/// which addresses are monotonically increasing. +#[derive(Clone, Debug)] +pub struct LineSequence { + /// The first address that is covered by this sequence within the line number + /// program. + pub start: u64, + /// The first address that is *not* covered by this sequence within the line + /// number program. + pub end: u64, + instructions: LineInstructions, +} + +/// Deprecated. `LineNumberProgramHeader` has been renamed to `LineProgramHeader`. +#[deprecated( + note = "LineNumberProgramHeader has been renamed to LineProgramHeader, use that instead." +)] +pub type LineNumberProgramHeader = LineProgramHeader; + +/// A header for a line number program in the `.debug_line` section, as defined +/// in section 6.2.4 of the standard. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct LineProgramHeader::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + encoding: Encoding, + offset: DebugLineOffset, + unit_length: Offset, + + header_length: Offset, + + line_encoding: LineEncoding, + + /// "The number assigned to the first special opcode." + opcode_base: u8, + + /// "This array specifies the number of LEB128 operands for each of the + /// standard opcodes. The first element of the array corresponds to the + /// opcode whose value is 1, and the last element corresponds to the opcode + /// whose value is `opcode_base - 1`." + standard_opcode_lengths: R, + + /// "A sequence of directory entry format descriptions." + directory_entry_format: Vec, + + /// > Entries in this sequence describe each path that was searched for + /// > included source files in this compilation. (The paths include those + /// > directories specified explicitly by the user for the compiler to search + /// > and those the compiler searches without explicit direction.) Each path + /// > entry is either a full path name or is relative to the current directory + /// > of the compilation. + /// > + /// > The last entry is followed by a single null byte. + include_directories: Vec>, + + /// "A sequence of file entry format descriptions." + file_name_entry_format: Vec, + + /// "Entries in this sequence describe source files that contribute to the + /// line number information for this compilation unit or is used in other + /// contexts." + file_names: Vec>, + + /// The encoded line program instructions. + program_buf: R, + + /// The current directory of the compilation. + comp_dir: Option, + + /// The primary source file. + comp_file: Option>, +} + +impl LineProgramHeader +where + R: Reader, + Offset: ReaderOffset, +{ + /// Return the offset of the line number program header in the `.debug_line` section. + pub fn offset(&self) -> DebugLineOffset { + self.offset + } + + /// Return the length of the line number program and header, not including + /// the length of the encoded length itself. + pub fn unit_length(&self) -> R::Offset { + self.unit_length + } + + /// Return the encoding parameters for this header's line program. + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Get the version of this header's line program. + pub fn version(&self) -> u16 { + self.encoding.version + } + + /// Get the length of the encoded line number program header, not including + /// the length of the encoded length itself. + pub fn header_length(&self) -> R::Offset { + self.header_length + } + + /// Get the size in bytes of a target machine address. + pub fn address_size(&self) -> u8 { + self.encoding.address_size + } + + /// Whether this line program is encoded in 64- or 32-bit DWARF. + pub fn format(&self) -> Format { + self.encoding.format + } + + /// Get the line encoding parameters for this header's line program. + pub fn line_encoding(&self) -> LineEncoding { + self.line_encoding + } + + /// Get the minimum instruction length any instruction in this header's line + /// program may have. + pub fn minimum_instruction_length(&self) -> u8 { + self.line_encoding.minimum_instruction_length + } + + /// Get the maximum number of operations each instruction in this header's + /// line program may have. + pub fn maximum_operations_per_instruction(&self) -> u8 { + self.line_encoding.maximum_operations_per_instruction + } + + /// Get the default value of the `is_stmt` register for this header's line + /// program. + pub fn default_is_stmt(&self) -> bool { + self.line_encoding.default_is_stmt + } + + /// Get the line base for this header's line program. + pub fn line_base(&self) -> i8 { + self.line_encoding.line_base + } + + /// Get the line range for this header's line program. + pub fn line_range(&self) -> u8 { + self.line_encoding.line_range + } + + /// Get opcode base for this header's line program. + pub fn opcode_base(&self) -> u8 { + self.opcode_base + } + + /// An array of `u8` that specifies the number of LEB128 operands for + /// each of the standard opcodes. + pub fn standard_opcode_lengths(&self) -> &R { + &self.standard_opcode_lengths + } + + /// Get the format of a directory entry. + pub fn directory_entry_format(&self) -> &[FileEntryFormat] { + &self.directory_entry_format[..] + } + + /// Get the set of include directories for this header's line program. + /// + /// For DWARF version <= 4, the compilation's current directory is not included + /// in the return value, but is implicitly considered to be in the set per spec. + pub fn include_directories(&self) -> &[AttributeValue] { + &self.include_directories[..] + } + + /// The include directory with the given directory index. + /// + /// A directory index of 0 corresponds to the compilation unit directory. + pub fn directory(&self, directory: u64) -> Option> { + if self.encoding.version <= 4 { + if directory == 0 { + self.comp_dir.clone().map(AttributeValue::String) + } else { + let directory = directory as usize - 1; + self.include_directories.get(directory).cloned() + } + } else { + self.include_directories.get(directory as usize).cloned() + } + } + + /// Get the format of a file name entry. + pub fn file_name_entry_format(&self) -> &[FileEntryFormat] { + &self.file_name_entry_format[..] + } + + /// Return true if the file entries may have valid timestamps. + /// + /// Only returns false if we definitely know that all timestamp fields + /// are invalid. + pub fn file_has_timestamp(&self) -> bool { + self.encoding.version <= 4 + || self + .file_name_entry_format + .iter() + .any(|x| x.content_type == constants::DW_LNCT_timestamp) + } + + /// Return true if the file entries may have valid sizes. + /// + /// Only returns false if we definitely know that all size fields + /// are invalid. + pub fn file_has_size(&self) -> bool { + self.encoding.version <= 4 + || self + .file_name_entry_format + .iter() + .any(|x| x.content_type == constants::DW_LNCT_size) + } + + /// Return true if the file name entry format contains an MD5 field. + pub fn file_has_md5(&self) -> bool { + self.file_name_entry_format + .iter() + .any(|x| x.content_type == constants::DW_LNCT_MD5) + } + + /// Return true if the file name entry format contains a source field. + pub fn file_has_source(&self) -> bool { + self.file_name_entry_format + .iter() + .any(|x| x.content_type == constants::DW_LNCT_LLVM_source) + } + + /// Get the list of source files that appear in this header's line program. + pub fn file_names(&self) -> &[FileEntry] { + &self.file_names[..] + } + + /// The source file with the given file index. + /// + /// A file index of 0 corresponds to the compilation unit file. + /// Note that a file index of 0 is invalid for DWARF version <= 4, + /// but we support it anyway. + pub fn file(&self, file: u64) -> Option<&FileEntry> { + if self.encoding.version <= 4 { + if file == 0 { + self.comp_file.as_ref() + } else { + let file = file as usize - 1; + self.file_names.get(file) + } + } else { + self.file_names.get(file as usize) + } + } + + /// Get the raw, un-parsed `EndianSlice` containing this header's line number + /// program. + /// + /// ``` + /// # fn foo() { + /// use gimli::{LineProgramHeader, EndianSlice, NativeEndian}; + /// + /// fn get_line_number_program_header<'a>() -> LineProgramHeader> { + /// // Get a line number program header from some offset in a + /// // `.debug_line` section... + /// # unimplemented!() + /// } + /// + /// let header = get_line_number_program_header(); + /// let raw_program = header.raw_program_buf(); + /// println!("The length of the raw program in bytes is {}", raw_program.len()); + /// # } + /// ``` + pub fn raw_program_buf(&self) -> R { + self.program_buf.clone() + } + + /// Iterate over the instructions in this header's line number program, parsing + /// them as we go. + pub fn instructions(&self) -> LineInstructions { + LineInstructions { + input: self.program_buf.clone(), + } + } + + fn parse( + input: &mut R, + offset: DebugLineOffset, + mut address_size: u8, + mut comp_dir: Option, + comp_name: Option, + ) -> Result> { + let (unit_length, format) = input.read_initial_length()?; + let rest = &mut input.split(unit_length)?; + + let version = rest.read_u16()?; + if version < 2 || version > 5 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + if version >= 5 { + address_size = rest.read_address_size()?; + let segment_selector_size = rest.read_u8()?; + if segment_selector_size != 0 { + return Err(Error::UnsupportedSegmentSize); + } + } + + let encoding = Encoding { + format, + version, + address_size, + }; + + let header_length = rest.read_length(format)?; + + let mut program_buf = rest.clone(); + program_buf.skip(header_length)?; + rest.truncate(header_length)?; + + let minimum_instruction_length = rest.read_u8()?; + if minimum_instruction_length == 0 { + return Err(Error::MinimumInstructionLengthZero); + } + + // This field did not exist before DWARF 4, but is specified to be 1 for + // non-VLIW architectures, which makes it a no-op. + let maximum_operations_per_instruction = if version >= 4 { rest.read_u8()? } else { 1 }; + if maximum_operations_per_instruction == 0 { + return Err(Error::MaximumOperationsPerInstructionZero); + } + + let default_is_stmt = rest.read_u8()? != 0; + let line_base = rest.read_i8()?; + let line_range = rest.read_u8()?; + if line_range == 0 { + return Err(Error::LineRangeZero); + } + let line_encoding = LineEncoding { + minimum_instruction_length, + maximum_operations_per_instruction, + default_is_stmt, + line_base, + line_range, + }; + + let opcode_base = rest.read_u8()?; + if opcode_base == 0 { + return Err(Error::OpcodeBaseZero); + } + + let standard_opcode_count = R::Offset::from_u8(opcode_base - 1); + let standard_opcode_lengths = rest.split(standard_opcode_count)?; + + let directory_entry_format; + let mut include_directories = Vec::new(); + if version <= 4 { + directory_entry_format = Vec::new(); + loop { + let directory = rest.read_null_terminated_slice()?; + if directory.is_empty() { + break; + } + include_directories.push(AttributeValue::String(directory)); + } + } else { + comp_dir = None; + directory_entry_format = FileEntryFormat::parse(rest)?; + let count = rest.read_uleb128()?; + for _ in 0..count { + include_directories.push(parse_directory_v5( + rest, + encoding, + &directory_entry_format, + )?); + } + } + + let comp_file; + let file_name_entry_format; + let mut file_names = Vec::new(); + if version <= 4 { + comp_file = comp_name.map(|name| FileEntry { + path_name: AttributeValue::String(name), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }); + + file_name_entry_format = Vec::new(); + loop { + let path_name = rest.read_null_terminated_slice()?; + if path_name.is_empty() { + break; + } + file_names.push(FileEntry::parse(rest, path_name)?); + } + } else { + comp_file = None; + file_name_entry_format = FileEntryFormat::parse(rest)?; + let count = rest.read_uleb128()?; + for _ in 0..count { + file_names.push(parse_file_v5(rest, encoding, &file_name_entry_format)?); + } + } + + let header = LineProgramHeader { + encoding, + offset, + unit_length, + header_length, + line_encoding, + opcode_base, + standard_opcode_lengths, + directory_entry_format, + include_directories, + file_name_entry_format, + file_names, + program_buf, + comp_dir, + comp_file, + }; + Ok(header) + } +} + +/// Deprecated. `IncompleteLineNumberProgram` has been renamed to `IncompleteLineProgram`. +#[deprecated( + note = "IncompleteLineNumberProgram has been renamed to IncompleteLineProgram, use that instead." +)] +pub type IncompleteLineNumberProgram = IncompleteLineProgram; + +/// A line number program that has not been run to completion. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct IncompleteLineProgram::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + header: LineProgramHeader, +} + +impl IncompleteLineProgram +where + R: Reader, + Offset: ReaderOffset, +{ + /// Retrieve the `LineProgramHeader` for this program. + pub fn header(&self) -> &LineProgramHeader { + &self.header + } + + /// Construct a new `LineRows` for executing this program to iterate + /// over rows in the line information matrix. + pub fn rows(self) -> OneShotLineRows { + OneShotLineRows::new(self) + } + + /// Execute the line number program, completing the `IncompleteLineProgram` + /// into a `CompleteLineProgram` and producing an array of sequences within + /// the line number program that can later be used with + /// `CompleteLineProgram::resume_from`. + /// + /// ``` + /// # fn foo() { + /// use gimli::{IncompleteLineProgram, EndianSlice, NativeEndian}; + /// + /// fn get_line_number_program<'a>() -> IncompleteLineProgram> { + /// // Get a line number program from some offset in a + /// // `.debug_line` section... + /// # unimplemented!() + /// } + /// + /// let program = get_line_number_program(); + /// let (program, sequences) = program.sequences().unwrap(); + /// println!("There are {} sequences in this line number program", sequences.len()); + /// # } + /// ``` + #[allow(clippy::type_complexity)] + pub fn sequences(self) -> Result<(CompleteLineProgram, Vec>)> { + let mut sequences = Vec::new(); + let mut rows = self.rows(); + let mut instructions = rows.instructions.clone(); + let mut sequence_start_addr = None; + loop { + let sequence_end_addr; + if rows.next_row()?.is_none() { + break; + } + + let row = &rows.row; + if row.end_sequence() { + sequence_end_addr = row.address(); + } else if sequence_start_addr.is_none() { + sequence_start_addr = Some(row.address()); + continue; + } else { + continue; + } + + // We just finished a sequence. + sequences.push(LineSequence { + // In theory one could have multiple DW_LNE_end_sequence instructions + // in a row. + start: sequence_start_addr.unwrap_or(0), + end: sequence_end_addr, + instructions: instructions.remove_trailing(&rows.instructions)?, + }); + sequence_start_addr = None; + instructions = rows.instructions.clone(); + } + + let program = CompleteLineProgram { + header: rows.program.header, + }; + Ok((program, sequences)) + } +} + +/// Deprecated. `CompleteLineNumberProgram` has been renamed to `CompleteLineProgram`. +#[deprecated( + note = "CompleteLineNumberProgram has been renamed to CompleteLineProgram, use that instead." +)] +pub type CompleteLineNumberProgram = CompleteLineProgram; + +/// A line number program that has previously been run to completion. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CompleteLineProgram::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + header: LineProgramHeader, +} + +impl CompleteLineProgram +where + R: Reader, + Offset: ReaderOffset, +{ + /// Retrieve the `LineProgramHeader` for this program. + pub fn header(&self) -> &LineProgramHeader { + &self.header + } + + /// Construct a new `LineRows` for executing the subset of the line + /// number program identified by 'sequence' and generating the line information + /// matrix. + /// + /// ``` + /// # fn foo() { + /// use gimli::{IncompleteLineProgram, EndianSlice, NativeEndian}; + /// + /// fn get_line_number_program<'a>() -> IncompleteLineProgram> { + /// // Get a line number program from some offset in a + /// // `.debug_line` section... + /// # unimplemented!() + /// } + /// + /// let program = get_line_number_program(); + /// let (program, sequences) = program.sequences().unwrap(); + /// for sequence in &sequences { + /// let mut sm = program.resume_from(sequence); + /// } + /// # } + /// ``` + pub fn resume_from<'program>( + &'program self, + sequence: &LineSequence, + ) -> ResumedLineRows<'program, R, Offset> { + ResumedLineRows::resume(self, sequence) + } +} + +/// An entry in the `LineProgramHeader`'s `file_names` set. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct FileEntry::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + path_name: AttributeValue, + directory_index: u64, + timestamp: u64, + size: u64, + md5: [u8; 16], + source: Option>, +} + +impl FileEntry +where + R: Reader, + Offset: ReaderOffset, +{ + // version 2-4 + fn parse(input: &mut R, path_name: R) -> Result> { + let directory_index = input.read_uleb128()?; + let timestamp = input.read_uleb128()?; + let size = input.read_uleb128()?; + + let entry = FileEntry { + path_name: AttributeValue::String(path_name), + directory_index, + timestamp, + size, + md5: [0; 16], + source: None, + }; + + Ok(entry) + } + + /// > A slice containing the full or relative path name of + /// > a source file. If the entry contains a file name or a relative path + /// > name, the file is located relative to either the compilation directory + /// > (as specified by the DW_AT_comp_dir attribute given in the compilation + /// > unit) or one of the directories in the include_directories section. + pub fn path_name(&self) -> AttributeValue { + self.path_name.clone() + } + + /// > An unsigned LEB128 number representing the directory index of the + /// > directory in which the file was found. + /// > + /// > ... + /// > + /// > The directory index represents an entry in the include_directories + /// > section of the line number program header. The index is 0 if the file + /// > was found in the current directory of the compilation, 1 if it was found + /// > in the first directory in the include_directories section, and so + /// > on. The directory index is ignored for file names that represent full + /// > path names. + pub fn directory_index(&self) -> u64 { + self.directory_index + } + + /// Get this file's directory. + /// + /// A directory index of 0 corresponds to the compilation unit directory. + pub fn directory(&self, header: &LineProgramHeader) -> Option> { + header.directory(self.directory_index) + } + + /// The implementation-defined time of last modification of the file, + /// or 0 if not available. + pub fn timestamp(&self) -> u64 { + self.timestamp + } + + /// "An unsigned LEB128 number representing the time of last modification of + /// the file, or 0 if not available." + // Terminology changed in DWARF version 5. + #[doc(hidden)] + pub fn last_modification(&self) -> u64 { + self.timestamp + } + + /// The size of the file in bytes, or 0 if not available. + pub fn size(&self) -> u64 { + self.size + } + + /// "An unsigned LEB128 number representing the length in bytes of the file, + /// or 0 if not available." + // Terminology changed in DWARF version 5. + #[doc(hidden)] + pub fn length(&self) -> u64 { + self.size + } + + /// A 16-byte MD5 digest of the file contents. + /// + /// Only valid if `LineProgramHeader::file_has_md5` returns `true`. + pub fn md5(&self) -> &[u8; 16] { + &self.md5 + } + + /// The source code of this file. (UTF-8 source text string with "\n" line + /// endings). + /// + /// Note: For DWARF v5 files this may return an empty attribute that + /// indicates that no source code is available, which this function + /// represents as `Some()`. + pub fn source(&self) -> Option> { + self.source.clone() + } +} + +/// The format of a component of an include directory or file name entry. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct FileEntryFormat { + /// The type of information that is represented by the component. + pub content_type: constants::DwLnct, + + /// The encoding form of the component value. + pub form: constants::DwForm, +} + +impl FileEntryFormat { + fn parse(input: &mut R) -> Result> { + let format_count = input.read_u8()? as usize; + let mut format = Vec::with_capacity(format_count); + let mut path_count = 0; + for _ in 0..format_count { + let content_type = input.read_uleb128()?; + let content_type = if content_type > u64::from(u16::MAX) { + constants::DwLnct(u16::MAX) + } else { + constants::DwLnct(content_type as u16) + }; + if content_type == constants::DW_LNCT_path { + path_count += 1; + } + + let form = constants::DwForm(input.read_uleb128_u16()?); + + format.push(FileEntryFormat { content_type, form }); + } + if path_count != 1 { + return Err(Error::MissingFileEntryFormatPath); + } + Ok(format) + } +} + +fn parse_directory_v5( + input: &mut R, + encoding: Encoding, + formats: &[FileEntryFormat], +) -> Result> { + let mut path_name = None; + + for format in formats { + let value = parse_attribute(input, encoding, format.form)?; + if format.content_type == constants::DW_LNCT_path { + path_name = Some(value); + } + } + + Ok(path_name.unwrap()) +} + +fn parse_file_v5( + input: &mut R, + encoding: Encoding, + formats: &[FileEntryFormat], +) -> Result> { + let mut path_name = None; + let mut directory_index = 0; + let mut timestamp = 0; + let mut size = 0; + let mut md5 = [0; 16]; + let mut source = None; + + for format in formats { + let value = parse_attribute(input, encoding, format.form)?; + match format.content_type { + constants::DW_LNCT_path => path_name = Some(value), + constants::DW_LNCT_directory_index => { + if let Some(value) = value.udata_value() { + directory_index = value; + } + } + constants::DW_LNCT_timestamp => { + if let Some(value) = value.udata_value() { + timestamp = value; + } + } + constants::DW_LNCT_size => { + if let Some(value) = value.udata_value() { + size = value; + } + } + constants::DW_LNCT_MD5 => { + if let AttributeValue::Block(mut value) = value { + if value.len().into_u64() == 16 { + md5 = value.read_u8_array()?; + } + } + } + constants::DW_LNCT_LLVM_source => { + source = Some(value); + } + // Ignore unknown content types. + _ => {} + } + } + + Ok(FileEntry { + path_name: path_name.unwrap(), + directory_index, + timestamp, + size, + md5, + source, + }) +} + +// TODO: this should be shared with unit::parse_attribute(), but that is hard to do. +fn parse_attribute( + input: &mut R, + encoding: Encoding, + form: constants::DwForm, +) -> Result> { + Ok(match form { + constants::DW_FORM_block1 => { + let len = input.read_u8().map(R::Offset::from_u8)?; + let block = input.split(len)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block2 => { + let len = input.read_u16().map(R::Offset::from_u16)?; + let block = input.split(len)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block4 => { + let len = input.read_u32().map(R::Offset::from_u32)?; + let block = input.split(len)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block => { + let len = input.read_uleb128().and_then(R::Offset::from_u64)?; + let block = input.split(len)?; + AttributeValue::Block(block) + } + constants::DW_FORM_data1 => { + let data = input.read_u8()?; + AttributeValue::Data1(data) + } + constants::DW_FORM_data2 => { + let data = input.read_u16()?; + AttributeValue::Data2(data) + } + constants::DW_FORM_data4 => { + let data = input.read_u32()?; + AttributeValue::Data4(data) + } + constants::DW_FORM_data8 => { + let data = input.read_u64()?; + AttributeValue::Data8(data) + } + constants::DW_FORM_data16 => { + let block = input.split(R::Offset::from_u8(16))?; + AttributeValue::Block(block) + } + constants::DW_FORM_udata => { + let data = input.read_uleb128()?; + AttributeValue::Udata(data) + } + constants::DW_FORM_sdata => { + let data = input.read_sleb128()?; + AttributeValue::Sdata(data) + } + constants::DW_FORM_flag => { + let present = input.read_u8()?; + AttributeValue::Flag(present != 0) + } + constants::DW_FORM_sec_offset => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::SecOffset(offset) + } + constants::DW_FORM_string => { + let string = input.read_null_terminated_slice()?; + AttributeValue::String(string) + } + constants::DW_FORM_strp => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugStrRef(DebugStrOffset(offset)) + } + constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugStrRefSup(DebugStrOffset(offset)) + } + constants::DW_FORM_line_strp => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset)) + } + constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => { + let index = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx1 => { + let index = input.read_u8().map(R::Offset::from_u8)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx2 => { + let index = input.read_u16().map(R::Offset::from_u16)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx3 => { + let index = input.read_uint(3).and_then(R::Offset::from_u64)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx4 => { + let index = input.read_u32().map(R::Offset::from_u32)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + _ => { + return Err(Error::UnknownForm(form)); + } + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::constants; + use crate::endianity::LittleEndian; + use crate::read::{EndianSlice, Error}; + use crate::test_util::GimliSectionMethods; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_parse_debug_line_32_ok() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 62. + 0x3e, 0x00, 0x00, 0x00, + // Version. + 0x04, 0x00, + // Header length = 40. + 0x28, 0x00, 0x00, 0x00, + // Minimum instruction length. + 0x01, + // Maximum operations per byte. + 0x01, + // Default is_stmt. + 0x01, + // Line base. + 0x00, + // Line range. + 0x01, + // Opcode base. + 0x03, + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + 0x01, 0x02, + // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0' + 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00, + // File names + // foo.rs + 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00, + 0x00, + 0x00, + 0x00, + // bar.h + 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00, + 0x01, + 0x00, + 0x00, + // End file names. + 0x00, + + // Dummy line program data. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next line program. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + let comp_dir = EndianSlice::new(b"/comp_dir", LittleEndian); + let comp_name = EndianSlice::new(b"/comp_name", LittleEndian); + + let header = + LineProgramHeader::parse(rest, DebugLineOffset(0), 4, Some(comp_dir), Some(comp_name)) + .expect("should parse header ok"); + + assert_eq!( + *rest, + EndianSlice::new(&buf[buf.len() - 16..], LittleEndian) + ); + + assert_eq!(header.offset, DebugLineOffset(0)); + assert_eq!(header.version(), 4); + assert_eq!(header.minimum_instruction_length(), 1); + assert_eq!(header.maximum_operations_per_instruction(), 1); + assert!(header.default_is_stmt()); + assert_eq!(header.line_base(), 0); + assert_eq!(header.line_range(), 1); + assert_eq!(header.opcode_base(), 3); + assert_eq!(header.directory(0), Some(AttributeValue::String(comp_dir))); + assert_eq!( + header.file(0).unwrap().path_name, + AttributeValue::String(comp_name) + ); + + let expected_lengths = [1, 2]; + assert_eq!(header.standard_opcode_lengths().slice(), &expected_lengths); + + let expected_include_directories = [ + AttributeValue::String(EndianSlice::new(b"/inc", LittleEndian)), + AttributeValue::String(EndianSlice::new(b"/inc2", LittleEndian)), + ]; + assert_eq!(header.include_directories(), &expected_include_directories); + + let expected_file_names = [ + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"foo.rs", LittleEndian)), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }, + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"bar.h", LittleEndian)), + directory_index: 1, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }, + ]; + assert_eq!(header.file_names(), &expected_file_names); + } + + #[test] + fn test_parse_debug_line_header_length_too_short() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 62. + 0x3e, 0x00, 0x00, 0x00, + // Version. + 0x04, 0x00, + // Header length = 20. TOO SHORT!!! + 0x15, 0x00, 0x00, 0x00, + // Minimum instruction length. + 0x01, + // Maximum operations per byte. + 0x01, + // Default is_stmt. + 0x01, + // Line base. + 0x00, + // Line range. + 0x01, + // Opcode base. + 0x03, + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + 0x01, 0x02, + // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0' + 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00, + // File names + // foo.rs + 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00, + 0x00, + 0x00, + 0x00, + // bar.h + 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00, + 0x01, + 0x00, + 0x00, + // End file names. + 0x00, + + // Dummy line program data. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next line program. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let input = &mut EndianSlice::new(&buf, LittleEndian); + + match LineProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_parse_debug_line_unit_length_too_short() { + #[rustfmt::skip] + let buf = [ + // 32-bit length = 40. TOO SHORT!!! + 0x28, 0x00, 0x00, 0x00, + // Version. + 0x04, 0x00, + // Header length = 40. + 0x28, 0x00, 0x00, 0x00, + // Minimum instruction length. + 0x01, + // Maximum operations per byte. + 0x01, + // Default is_stmt. + 0x01, + // Line base. + 0x00, + // Line range. + 0x01, + // Opcode base. + 0x03, + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + 0x01, 0x02, + // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0' + 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00, + // File names + // foo.rs + 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00, + 0x00, + 0x00, + 0x00, + // bar.h + 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00, + 0x01, + 0x00, + 0x00, + // End file names. + 0x00, + + // Dummy line program data. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // Dummy next line program. + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let input = &mut EndianSlice::new(&buf, LittleEndian); + + match LineProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + const OPCODE_BASE: u8 = 13; + const STANDARD_OPCODE_LENGTHS: &[u8] = &[0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1]; + + fn make_test_header( + buf: EndianSlice<'_, LittleEndian>, + ) -> LineProgramHeader> { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 8, + }; + let line_encoding = LineEncoding { + line_base: -3, + line_range: 12, + ..Default::default() + }; + LineProgramHeader { + encoding, + offset: DebugLineOffset(0), + unit_length: 1, + header_length: 1, + line_encoding, + opcode_base: OPCODE_BASE, + standard_opcode_lengths: EndianSlice::new(STANDARD_OPCODE_LENGTHS, LittleEndian), + file_names: vec![ + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"foo.c", LittleEndian)), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }, + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"bar.rs", LittleEndian)), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }, + ], + include_directories: vec![], + directory_entry_format: vec![], + file_name_entry_format: vec![], + program_buf: buf, + comp_dir: None, + comp_file: None, + } + } + + fn make_test_program( + buf: EndianSlice<'_, LittleEndian>, + ) -> IncompleteLineProgram> { + IncompleteLineProgram { + header: make_test_header(buf), + } + } + + #[test] + fn test_parse_special_opcodes() { + for i in OPCODE_BASE..u8::MAX { + let input = [i, 0, 0, 0]; + let input = EndianSlice::new(&input, LittleEndian); + let header = make_test_header(input); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!(*rest, *input.range_from(1..)); + assert_eq!(opcode, LineInstruction::Special(i)); + } + } + + #[test] + fn test_parse_standard_opcodes() { + fn test( + raw: constants::DwLns, + operands: Operands, + expected: LineInstruction>, + ) where + Operands: AsRef<[u8]>, + { + let mut input = Vec::new(); + input.push(raw.0); + input.extend_from_slice(operands.as_ref()); + + let expected_rest = [0, 1, 2, 3, 4]; + input.extend_from_slice(&expected_rest); + + let input = EndianSlice::new(&input, LittleEndian); + let header = make_test_header(input); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!(opcode, expected); + assert_eq!(*rest, expected_rest); + } + + test(constants::DW_LNS_copy, [], LineInstruction::Copy); + test( + constants::DW_LNS_advance_pc, + [42], + LineInstruction::AdvancePc(42), + ); + test( + constants::DW_LNS_advance_line, + [9], + LineInstruction::AdvanceLine(9), + ); + test(constants::DW_LNS_set_file, [7], LineInstruction::SetFile(7)); + test( + constants::DW_LNS_set_column, + [1], + LineInstruction::SetColumn(1), + ); + test( + constants::DW_LNS_negate_stmt, + [], + LineInstruction::NegateStatement, + ); + test( + constants::DW_LNS_set_basic_block, + [], + LineInstruction::SetBasicBlock, + ); + test( + constants::DW_LNS_const_add_pc, + [], + LineInstruction::ConstAddPc, + ); + test( + constants::DW_LNS_fixed_advance_pc, + [42, 0], + LineInstruction::FixedAddPc(42), + ); + test( + constants::DW_LNS_set_prologue_end, + [], + LineInstruction::SetPrologueEnd, + ); + test( + constants::DW_LNS_set_isa, + [57 + 0x80, 100], + LineInstruction::SetIsa(12857), + ); + } + + #[test] + fn test_parse_unknown_standard_opcode_no_args() { + let input = [OPCODE_BASE, 1, 2, 3]; + let input = EndianSlice::new(&input, LittleEndian); + let mut standard_opcode_lengths = Vec::new(); + let mut header = make_test_header(input); + standard_opcode_lengths.extend(header.standard_opcode_lengths.slice()); + standard_opcode_lengths.push(0); + header.opcode_base += 1; + header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!( + opcode, + LineInstruction::UnknownStandard0(constants::DwLns(OPCODE_BASE)) + ); + assert_eq!(*rest, *input.range_from(1..)); + } + + #[test] + fn test_parse_unknown_standard_opcode_one_arg() { + let input = [OPCODE_BASE, 1, 2, 3]; + let input = EndianSlice::new(&input, LittleEndian); + let mut standard_opcode_lengths = Vec::new(); + let mut header = make_test_header(input); + standard_opcode_lengths.extend(header.standard_opcode_lengths.slice()); + standard_opcode_lengths.push(1); + header.opcode_base += 1; + header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!( + opcode, + LineInstruction::UnknownStandard1(constants::DwLns(OPCODE_BASE), 1) + ); + assert_eq!(*rest, *input.range_from(2..)); + } + + #[test] + fn test_parse_unknown_standard_opcode_many_args() { + let input = [OPCODE_BASE, 1, 2, 3]; + let input = EndianSlice::new(&input, LittleEndian); + let args = input.range_from(1..); + let mut standard_opcode_lengths = Vec::new(); + let mut header = make_test_header(input); + standard_opcode_lengths.extend(header.standard_opcode_lengths.slice()); + standard_opcode_lengths.push(3); + header.opcode_base += 1; + header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!( + opcode, + LineInstruction::UnknownStandardN(constants::DwLns(OPCODE_BASE), args) + ); + assert_eq!(*rest, []); + } + + #[test] + fn test_parse_extended_opcodes() { + fn test( + raw: constants::DwLne, + operands: Operands, + expected: LineInstruction>, + ) where + Operands: AsRef<[u8]>, + { + let mut input = Vec::new(); + input.push(0); + + let operands = operands.as_ref(); + input.push(1 + operands.len() as u8); + + input.push(raw.0); + input.extend_from_slice(operands); + + let expected_rest = [0, 1, 2, 3, 4]; + input.extend_from_slice(&expected_rest); + + let input = EndianSlice::new(&input, LittleEndian); + let header = make_test_header(input); + + let mut rest = input; + let opcode = + LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK"); + + assert_eq!(opcode, expected); + assert_eq!(*rest, expected_rest); + } + + test( + constants::DW_LNE_end_sequence, + [], + LineInstruction::EndSequence, + ); + test( + constants::DW_LNE_set_address, + [1, 2, 3, 4, 5, 6, 7, 8], + LineInstruction::SetAddress(578_437_695_752_307_201), + ); + test( + constants::DW_LNE_set_discriminator, + [42], + LineInstruction::SetDiscriminator(42), + ); + + let mut file = Vec::new(); + // "foo.c" + let path_name = [b'f', b'o', b'o', b'.', b'c', 0]; + file.extend_from_slice(&path_name); + // Directory index. + file.push(0); + // Last modification of file. + file.push(1); + // Size of file. + file.push(2); + + test( + constants::DW_LNE_define_file, + file, + LineInstruction::DefineFile(FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"foo.c", LittleEndian)), + directory_index: 0, + timestamp: 1, + size: 2, + md5: [0; 16], + source: None, + }), + ); + + // Unknown extended opcode. + let operands = [1, 2, 3, 4, 5, 6]; + let opcode = constants::DwLne(99); + test( + opcode, + operands, + LineInstruction::UnknownExtended(opcode, EndianSlice::new(&operands, LittleEndian)), + ); + } + + #[test] + fn test_file_entry_directory() { + let path_name = [b'f', b'o', b'o', b'.', b'r', b's', 0]; + + let mut file = FileEntry { + path_name: AttributeValue::String(EndianSlice::new(&path_name, LittleEndian)), + directory_index: 1, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }; + + let mut header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let dir = AttributeValue::String(EndianSlice::new(b"dir", LittleEndian)); + header.include_directories.push(dir); + + assert_eq!(file.directory(&header), Some(dir)); + + // Now test the compilation's current directory. + file.directory_index = 0; + assert_eq!(file.directory(&header), None); + } + + fn assert_exec_opcode<'input>( + header: LineProgramHeader>, + mut registers: LineRow, + opcode: LineInstruction>, + expected_registers: LineRow, + expect_new_row: bool, + ) { + let mut program = IncompleteLineProgram { header }; + let is_new_row = registers.execute(opcode, &mut program); + + assert_eq!(is_new_row, Ok(expect_new_row)); + assert_eq!(registers, expected_registers); + } + + #[test] + fn test_exec_special_noop() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::Special(16); + let expected_registers = initial_registers; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_negative_line_advance() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.line.0 = 10; + + let opcode = LineInstruction::Special(13); + + let mut expected_registers = initial_registers; + expected_registers.line.0 -= 3; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_positive_line_advance() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let initial_registers = LineRow::new(&header); + + let opcode = LineInstruction::Special(19); + + let mut expected_registers = initial_registers; + expected_registers.line.0 += 3; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_positive_address_advance() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let initial_registers = LineRow::new(&header); + + let opcode = LineInstruction::Special(52); + + let mut expected_registers = initial_registers; + expected_registers.address += 3; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_positive_address_and_line_advance() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let initial_registers = LineRow::new(&header); + + let opcode = LineInstruction::Special(55); + + let mut expected_registers = initial_registers; + expected_registers.address += 3; + expected_registers.line.0 += 3; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_positive_address_and_negative_line_advance() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.line.0 = 10; + + let opcode = LineInstruction::Special(49); + + let mut expected_registers = initial_registers; + expected_registers.address += 3; + expected_registers.line.0 -= 3; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_special_line_underflow() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.line.0 = 2; + + // -3 line advance. + let opcode = LineInstruction::Special(13); + + let mut expected_registers = initial_registers; + // Clamp at 0. No idea if this is the best way to handle this situation + // or not... + expected_registers.line.0 = 0; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_copy() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.address = 1337; + initial_registers.line.0 = 42; + + let opcode = LineInstruction::Copy; + + let expected_registers = initial_registers; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_advance_pc() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::AdvancePc(42); + + let mut expected_registers = initial_registers; + expected_registers.address += 42; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_advance_pc_overflow_32() { + let mut header = make_test_header(EndianSlice::new(&[], LittleEndian)); + header.encoding.address_size = 4; + let mut registers = LineRow::new(&header); + registers.address = u32::MAX.into(); + let opcode = LineInstruction::AdvancePc(42); + let mut program = IncompleteLineProgram { header }; + let result = registers.execute(opcode, &mut program); + assert_eq!(result, Err(Error::AddressOverflow)); + } + + #[test] + fn test_exec_advance_pc_overflow_64() { + let mut header = make_test_header(EndianSlice::new(&[], LittleEndian)); + header.encoding.address_size = 8; + let mut registers = LineRow::new(&header); + registers.address = u64::MAX; + let opcode = LineInstruction::AdvancePc(42); + let mut program = IncompleteLineProgram { header }; + let result = registers.execute(opcode, &mut program); + assert_eq!(result, Err(Error::AddressOverflow)); + } + + #[test] + fn test_exec_advance_line() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::AdvanceLine(42); + + let mut expected_registers = initial_registers; + expected_registers.line.0 += 42; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_advance_line_overflow() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let opcode = LineInstruction::AdvanceLine(42); + + let mut initial_registers = LineRow::new(&header); + initial_registers.line.0 = u64::MAX; + + let mut expected_registers = initial_registers; + expected_registers.line.0 = 41; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_set_file_in_bounds() { + for file_idx in 1..3 { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetFile(file_idx); + + let mut expected_registers = initial_registers; + expected_registers.file = file_idx; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + } + + #[test] + fn test_exec_set_file_out_of_bounds() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetFile(100); + + // The spec doesn't say anything about rejecting input programs + // that set the file register out of bounds of the actual number + // of files that have been defined. Instead, we cross our + // fingers and hope that one gets defined before + // `LineRow::file` gets called and handle the error at + // that time if need be. + let mut expected_registers = initial_registers; + expected_registers.file = 100; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_file_entry_file_index_out_of_bounds() { + // These indices are 1-based, so 0 is invalid. 100 is way more than the + // number of files defined in the header. + let out_of_bounds_indices = [0, 100]; + + for file_idx in &out_of_bounds_indices[..] { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let mut row = LineRow::new(&header); + + row.file = *file_idx; + + assert_eq!(row.file(&header), None); + } + } + + #[test] + fn test_file_entry_file_index_in_bounds() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let mut row = LineRow::new(&header); + + row.file = 2; + + assert_eq!(row.file(&header), Some(&header.file_names()[1])); + } + + #[test] + fn test_exec_set_column() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetColumn(42); + + let mut expected_registers = initial_registers; + expected_registers.column = 42; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_negate_statement() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::NegateStatement; + + let mut expected_registers = initial_registers; + expected_registers.is_stmt = !initial_registers.is_stmt; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_set_basic_block() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.basic_block = false; + + let opcode = LineInstruction::SetBasicBlock; + + let mut expected_registers = initial_registers; + expected_registers.basic_block = true; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_const_add_pc() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::ConstAddPc; + + let mut expected_registers = initial_registers; + expected_registers.address += 20; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_const_add_pc_overflow() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let mut registers = LineRow::new(&header); + registers.address = u64::MAX; + let opcode = LineInstruction::ConstAddPc; + let mut program = IncompleteLineProgram { header }; + let result = registers.execute(opcode, &mut program); + assert_eq!(result, Err(Error::AddressOverflow)); + } + + #[test] + fn test_exec_fixed_add_pc() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.op_index.0 = 1; + + let opcode = LineInstruction::FixedAddPc(10); + + let mut expected_registers = initial_registers; + expected_registers.address += 10; + expected_registers.op_index.0 = 0; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_fixed_add_pc_overflow() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let mut registers = LineRow::new(&header); + registers.address = u64::MAX; + registers.op_index.0 = 1; + let opcode = LineInstruction::FixedAddPc(10); + let mut program = IncompleteLineProgram { header }; + let result = registers.execute(opcode, &mut program); + assert_eq!(result, Err(Error::AddressOverflow)); + } + + #[test] + fn test_exec_set_prologue_end() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + + let mut initial_registers = LineRow::new(&header); + initial_registers.prologue_end = false; + + let opcode = LineInstruction::SetPrologueEnd; + + let mut expected_registers = initial_registers; + expected_registers.prologue_end = true; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_set_isa() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetIsa(1993); + + let mut expected_registers = initial_registers; + expected_registers.isa = 1993; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_unknown_standard_0() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::UnknownStandard0(constants::DwLns(111)); + let expected_registers = initial_registers; + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_unknown_standard_1() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::UnknownStandard1(constants::DwLns(111), 2); + let expected_registers = initial_registers; + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_unknown_standard_n() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::UnknownStandardN( + constants::DwLns(111), + EndianSlice::new(&[2, 2, 2], LittleEndian), + ); + let expected_registers = initial_registers; + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_end_sequence() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::EndSequence; + + let mut expected_registers = initial_registers; + expected_registers.end_sequence = true; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, true); + } + + #[test] + fn test_exec_set_address() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetAddress(3030); + + let mut expected_registers = initial_registers; + expected_registers.address = 3030; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_set_address_tombstone() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetAddress(!0); + + let mut expected_registers = initial_registers; + expected_registers.tombstone = true; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_set_address_backwards() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let mut initial_registers = LineRow::new(&header); + initial_registers.address = 1; + let opcode = LineInstruction::SetAddress(0); + + let mut expected_registers = initial_registers; + expected_registers.tombstone = true; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_define_file() { + let mut program = make_test_program(EndianSlice::new(&[], LittleEndian)); + let mut row = LineRow::new(program.header()); + + let file = FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"test.cpp", LittleEndian)), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [0; 16], + source: None, + }; + + let opcode = LineInstruction::DefineFile(file); + let is_new_row = row.execute(opcode, &mut program).unwrap(); + + assert!(!is_new_row); + assert_eq!(Some(&file), program.header().file_names.last()); + } + + #[test] + fn test_exec_set_discriminator() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::SetDiscriminator(9); + + let mut expected_registers = initial_registers; + expected_registers.discriminator = 9; + + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + #[test] + fn test_exec_unknown_extended() { + let header = make_test_header(EndianSlice::new(&[], LittleEndian)); + let initial_registers = LineRow::new(&header); + let opcode = LineInstruction::UnknownExtended( + constants::DwLne(74), + EndianSlice::new(&[], LittleEndian), + ); + let expected_registers = initial_registers; + assert_exec_opcode(header, initial_registers, opcode, expected_registers, false); + } + + /// Ensure that `LineRows` is covariant wrt R. + /// This only needs to compile. + #[allow(dead_code, unreachable_code, unused_variables)] + #[allow(clippy::diverging_sub_expression)] + fn test_line_rows_variance<'a, 'b>(_: &'a [u8], _: &'b [u8]) + where + 'a: 'b, + { + let a: &OneShotLineRows> = unimplemented!(); + let _: &OneShotLineRows> = a; + } + + #[test] + fn test_parse_debug_line_v5_ok() { + let expected_lengths = &[1, 2]; + let expected_program = &[0, 1, 2, 3, 4]; + let expected_rest = &[5, 6, 7, 8, 9]; + let expected_include_directories = [ + AttributeValue::String(EndianSlice::new(b"dir1", LittleEndian)), + AttributeValue::String(EndianSlice::new(b"dir2", LittleEndian)), + ]; + let expected_file_names = [ + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"file1", LittleEndian)), + directory_index: 0, + timestamp: 0, + size: 0, + md5: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + source: Some(AttributeValue::String(EndianSlice::new( + b"foobar", + LittleEndian, + ))), + }, + FileEntry { + path_name: AttributeValue::String(EndianSlice::new(b"file2", LittleEndian)), + directory_index: 1, + timestamp: 0, + size: 0, + md5: [ + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + ], + source: Some(AttributeValue::String(EndianSlice::new( + b"quux", + LittleEndian, + ))), + }, + ]; + + for format in [Format::Dwarf32, Format::Dwarf64] { + let length = Label::new(); + let header_length = Label::new(); + let start = Label::new(); + let header_start = Label::new(); + let end = Label::new(); + let header_end = Label::new(); + let section = Section::with_endian(Endian::Little) + .initial_length(format, &length, &start) + .D16(5) + // Address size. + .D8(4) + // Segment selector size. + .D8(0) + .word_label(format.word_size(), &header_length) + .mark(&header_start) + // Minimum instruction length. + .D8(1) + // Maximum operations per byte. + .D8(1) + // Default is_stmt. + .D8(1) + // Line base. + .D8(0) + // Line range. + .D8(1) + // Opcode base. + .D8(expected_lengths.len() as u8 + 1) + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + .append_bytes(expected_lengths) + // Directory entry format count. + .D8(1) + .uleb(constants::DW_LNCT_path.0 as u64) + .uleb(constants::DW_FORM_string.0 as u64) + // Directory count. + .D8(2) + .append_bytes(b"dir1\0") + .append_bytes(b"dir2\0") + // File entry format count. + .D8(4) + .uleb(constants::DW_LNCT_path.0 as u64) + .uleb(constants::DW_FORM_string.0 as u64) + .uleb(constants::DW_LNCT_directory_index.0 as u64) + .uleb(constants::DW_FORM_data1.0 as u64) + .uleb(constants::DW_LNCT_MD5.0 as u64) + .uleb(constants::DW_FORM_data16.0 as u64) + .uleb(constants::DW_LNCT_LLVM_source.0 as u64) + .uleb(constants::DW_FORM_string.0 as u64) + // File count. + .D8(2) + .append_bytes(b"file1\0") + .D8(0) + .append_bytes(&expected_file_names[0].md5) + .append_bytes(b"foobar\0") + .append_bytes(b"file2\0") + .D8(1) + .append_bytes(&expected_file_names[1].md5) + .append_bytes(b"quux\0") + .mark(&header_end) + // Dummy line program data. + .append_bytes(expected_program) + .mark(&end) + // Dummy trailing data. + .append_bytes(expected_rest); + length.set_const((&end - &start) as u64); + header_length.set_const((&header_end - &header_start) as u64); + let section = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(§ion, LittleEndian); + + let header = LineProgramHeader::parse(input, DebugLineOffset(0), 0, None, None) + .expect("should parse header ok"); + + assert_eq!(header.raw_program_buf().slice(), expected_program); + assert_eq!(input.slice(), expected_rest); + + assert_eq!(header.offset, DebugLineOffset(0)); + assert_eq!(header.version(), 5); + assert_eq!(header.address_size(), 4); + assert_eq!(header.minimum_instruction_length(), 1); + assert_eq!(header.maximum_operations_per_instruction(), 1); + assert!(header.default_is_stmt()); + assert_eq!(header.line_base(), 0); + assert_eq!(header.line_range(), 1); + assert_eq!(header.opcode_base(), expected_lengths.len() as u8 + 1); + assert_eq!(header.standard_opcode_lengths().slice(), expected_lengths); + assert_eq!( + header.directory_entry_format(), + &[FileEntryFormat { + content_type: constants::DW_LNCT_path, + form: constants::DW_FORM_string, + }] + ); + assert_eq!(header.include_directories(), expected_include_directories); + assert_eq!(header.directory(0), Some(expected_include_directories[0])); + assert_eq!( + header.file_name_entry_format(), + &[ + FileEntryFormat { + content_type: constants::DW_LNCT_path, + form: constants::DW_FORM_string, + }, + FileEntryFormat { + content_type: constants::DW_LNCT_directory_index, + form: constants::DW_FORM_data1, + }, + FileEntryFormat { + content_type: constants::DW_LNCT_MD5, + form: constants::DW_FORM_data16, + }, + FileEntryFormat { + content_type: constants::DW_LNCT_LLVM_source, + form: constants::DW_FORM_string, + } + ] + ); + assert_eq!(header.file_names(), expected_file_names); + assert_eq!(header.file(0), Some(&expected_file_names[0])); + } + } + + #[test] + fn test_sequences() { + #[rustfmt::skip] + let buf = [ + // 32-bit length + 94, 0x00, 0x00, 0x00, + // Version. + 0x04, 0x00, + // Header length = 40. + 0x28, 0x00, 0x00, 0x00, + // Minimum instruction length. + 0x01, + // Maximum operations per byte. + 0x01, + // Default is_stmt. + 0x01, + // Line base. + 0x00, + // Line range. + 0x01, + // Opcode base. + 0x03, + // Standard opcode lengths for opcodes 1 .. opcode base - 1. + 0x01, 0x02, + // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0' + 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00, + // File names + // foo.rs + 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00, + 0x00, + 0x00, + 0x00, + // bar.h + 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00, + 0x01, + 0x00, + 0x00, + // End file names. + 0x00, + + 0, 5, constants::DW_LNE_set_address.0, 1, 0, 0, 0, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + + // Tombstone + 0, 5, constants::DW_LNE_set_address.0, 0xff, 0xff, 0xff, 0xff, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + + 0, 5, constants::DW_LNE_set_address.0, 11, 0, 0, 0, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 1, + constants::DW_LNS_copy.0, + constants::DW_LNS_advance_pc.0, 2, + 0, 1, constants::DW_LNE_end_sequence.0, + ]; + assert_eq!(buf[0] as usize, buf.len() - 4); + + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + let header = LineProgramHeader::parse(rest, DebugLineOffset(0), 4, None, None) + .expect("should parse header ok"); + let program = IncompleteLineProgram { header }; + + let sequences = program.sequences().unwrap().1; + assert_eq!(sequences.len(), 2); + assert_eq!(sequences[0].start, 1); + assert_eq!(sequences[0].end, 4); + assert_eq!(sequences[1].start, 11); + assert_eq!(sequences[1].end, 14); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/lists.rs b/anneal/v2/vendor/gimli/src/read/lists.rs new file mode 100644 index 0000000000..bb41901ddc --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/lists.rs @@ -0,0 +1,68 @@ +use crate::common::{Encoding, Format}; +use crate::read::{Error, Reader, Result}; + +#[derive(Debug, Clone, Copy)] +pub(crate) struct ListsHeader { + encoding: Encoding, + #[allow(dead_code)] + offset_entry_count: u32, +} + +impl Default for ListsHeader { + fn default() -> Self { + ListsHeader { + encoding: Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 0, + }, + offset_entry_count: 0, + } + } +} + +impl ListsHeader { + /// Return the serialized size of the table header. + #[allow(dead_code)] + #[inline] + fn size(self) -> u8 { + // initial_length + version + address_size + segment_selector_size + offset_entry_count + ListsHeader::size_for_encoding(self.encoding) + } + + /// Return the serialized size of the table header. + #[inline] + pub(crate) fn size_for_encoding(encoding: Encoding) -> u8 { + // initial_length + version + address_size + segment_selector_size + offset_entry_count + encoding.format.initial_length_size() + 2 + 1 + 1 + 4 + } +} + +// TODO: add an iterator over headers in the appropriate sections section +#[allow(dead_code)] +fn parse_header(input: &mut R) -> Result { + let (length, format) = input.read_initial_length()?; + input.truncate(length)?; + + let version = input.read_u16()?; + if version != 5 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + let address_size = input.read_address_size()?; + let segment_selector_size = input.read_u8()?; + if segment_selector_size != 0 { + return Err(Error::UnsupportedSegmentSize); + } + let offset_entry_count = input.read_u32()?; + + let encoding = Encoding { + format, + version, + address_size, + }; + Ok(ListsHeader { + encoding, + offset_entry_count, + }) +} diff --git a/anneal/v2/vendor/gimli/src/read/loclists.rs b/anneal/v2/vendor/gimli/src/read/loclists.rs new file mode 100644 index 0000000000..0efca02943 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/loclists.rs @@ -0,0 +1,1126 @@ +use crate::common::{ + DebugAddrBase, DebugAddrIndex, DebugLocListsBase, DebugLocListsIndex, DwarfFileType, Encoding, + LocationListsOffset, SectionId, +}; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::{ + lists::ListsHeader, DebugAddr, EndianSlice, Error, Expression, Range, RawRange, Reader, + ReaderAddress, ReaderOffset, ReaderOffsetId, Result, Section, +}; + +/// The raw contents of the `.debug_loc` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugLoc { + pub(crate) section: R, +} + +impl<'input, Endian> DebugLoc> +where + Endian: Endianity, +{ + /// Construct a new `DebugLoc` instance from the data in the `.debug_loc` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_loc` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugLoc, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_loc_section_somehow = || &buf; + /// let debug_loc = DebugLoc::new(read_debug_loc_section_somehow(), LittleEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugLoc { + /// Create a `DebugLoc` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLoc + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugLoc { + fn id() -> SectionId { + SectionId::DebugLoc + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugLoc { + fn from(section: R) -> Self { + DebugLoc { section } + } +} + +/// The `DebugLocLists` struct represents the DWARF data +/// found in the `.debug_loclists` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugLocLists { + section: R, +} + +impl<'input, Endian> DebugLocLists> +where + Endian: Endianity, +{ + /// Construct a new `DebugLocLists` instance from the data in the `.debug_loclists` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_loclists` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugLocLists, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_loclists_section_somehow = || &buf; + /// let debug_loclists = DebugLocLists::new(read_debug_loclists_section_somehow(), LittleEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugLocLists { + /// Create a `DebugLocLists` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLocLists + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugLocLists { + fn id() -> SectionId { + SectionId::DebugLocLists + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugLocLists { + fn from(section: R) -> Self { + DebugLocLists { section } + } +} + +pub(crate) type LocListsHeader = ListsHeader; + +impl DebugLocListsBase +where + Offset: ReaderOffset, +{ + /// Returns a `DebugLocListsBase` with the default value of DW_AT_loclists_base + /// for the given `Encoding` and `DwarfFileType`. + pub fn default_for_encoding_and_file( + encoding: Encoding, + file_type: DwarfFileType, + ) -> DebugLocListsBase { + if encoding.version >= 5 && file_type == DwarfFileType::Dwo { + // In .dwo files, the compiler omits the DW_AT_loclists_base attribute (because there is + // only a single unit in the file) but we must skip past the header, which the attribute + // would normally do for us. + DebugLocListsBase(Offset::from_u8(LocListsHeader::size_for_encoding(encoding))) + } else { + DebugLocListsBase(Offset::from_u8(0)) + } + } +} + +/// The DWARF data found in `.debug_loc` and `.debug_loclists` sections. +#[derive(Debug, Default, Clone, Copy)] +pub struct LocationLists { + debug_loc: DebugLoc, + debug_loclists: DebugLocLists, +} + +impl LocationLists { + /// Construct a new `LocationLists` instance from the data in the `.debug_loc` and + /// `.debug_loclists` sections. + pub fn new(debug_loc: DebugLoc, debug_loclists: DebugLocLists) -> LocationLists { + LocationLists { + debug_loc, + debug_loclists, + } + } +} + +impl LocationLists { + /// Create a `LocationLists` that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `Dwarf::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> LocationLists + where + F: FnMut(&'a T) -> R, + { + LocationLists { + debug_loc: borrow(&self.debug_loc.section).into(), + debug_loclists: borrow(&self.debug_loclists.section).into(), + } + } +} + +impl LocationLists { + /// Iterate over the `LocationListEntry`s starting at the given offset. + /// + /// The `unit_encoding` must match the compilation unit that the + /// offset was contained in. + /// + /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the + /// `DW_TAG_compile_unit` entry for the compilation unit that contains this location + /// list. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn locations( + &self, + offset: LocationListsOffset, + unit_encoding: Encoding, + base_address: u64, + debug_addr: &DebugAddr, + debug_addr_base: DebugAddrBase, + ) -> Result> { + Ok(LocListIter::new( + self.raw_locations(offset, unit_encoding)?, + base_address, + debug_addr.clone(), + debug_addr_base, + )) + } + + /// Similar to `locations`, but with special handling for .dwo files. + /// This should only been used when this `LocationLists` was loaded from a + /// .dwo file. + pub fn locations_dwo( + &self, + offset: LocationListsOffset, + unit_encoding: Encoding, + base_address: u64, + debug_addr: &DebugAddr, + debug_addr_base: DebugAddrBase, + ) -> Result> { + Ok(LocListIter::new( + self.raw_locations_dwo(offset, unit_encoding)?, + base_address, + debug_addr.clone(), + debug_addr_base, + )) + } + + /// Iterate over the raw `LocationListEntry`s starting at the given offset. + /// + /// The `unit_encoding` must match the compilation unit that the + /// offset was contained in. + /// + /// This iterator does not perform any processing of the location entries, + /// such as handling base addresses. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn raw_locations( + &self, + offset: LocationListsOffset, + unit_encoding: Encoding, + ) -> Result> { + let (mut input, format) = if unit_encoding.version <= 4 { + (self.debug_loc.section.clone(), LocListsFormat::Bare) + } else { + (self.debug_loclists.section.clone(), LocListsFormat::Lle) + }; + input.skip(offset.0)?; + Ok(RawLocListIter::new(input, unit_encoding, format)) + } + + /// Similar to `raw_locations`, but with special handling for .dwo files. + /// This should only been used when this `LocationLists` was loaded from a + /// .dwo file. + pub fn raw_locations_dwo( + &self, + offset: LocationListsOffset, + unit_encoding: Encoding, + ) -> Result> { + let mut input = if unit_encoding.version <= 4 { + // In the GNU split dwarf extension the locations are present in the + // .debug_loc section but are encoded with the DW_LLE values used + // for the DWARF 5 .debug_loclists section. + self.debug_loc.section.clone() + } else { + self.debug_loclists.section.clone() + }; + input.skip(offset.0)?; + Ok(RawLocListIter::new( + input, + unit_encoding, + LocListsFormat::Lle, + )) + } + + /// Returns the `.debug_loclists` offset at the given `base` and `index`. + /// + /// The `base` must be the `DW_AT_loclists_base` value from the compilation unit DIE. + /// This is an offset that points to the first entry following the header. + /// + /// The `index` is the value of a `DW_FORM_loclistx` attribute. + pub fn get_offset( + &self, + unit_encoding: Encoding, + base: DebugLocListsBase, + index: DebugLocListsIndex, + ) -> Result> { + let format = unit_encoding.format; + let input = &mut self.debug_loclists.section.clone(); + input.skip(base.0)?; + input.skip(R::Offset::from_u64( + index.0.into_u64() * u64::from(format.word_size()), + )?)?; + input + .read_offset(format) + .map(|x| LocationListsOffset(base.0 + x)) + } + + /// Call `Reader::lookup_offset_id` for each section, and return the first match. + pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> { + self.debug_loc + .lookup_offset_id(id) + .or_else(|| self.debug_loclists.lookup_offset_id(id)) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum LocListsFormat { + /// The bare location list format used before DWARF 5. + Bare, + /// The DW_LLE encoded range list format used in DWARF 5 and the non-standard GNU + /// split dwarf extension. + Lle, +} + +/// A raw iterator over a location list. +/// +/// This iterator does not perform any processing of the location entries, +/// such as handling base addresses. +#[derive(Debug)] +pub struct RawLocListIter { + input: R, + encoding: Encoding, + format: LocListsFormat, +} + +/// A raw entry in .debug_loclists. +#[derive(Clone, Debug)] +pub enum RawLocListEntry { + /// A location from DWARF version <= 4. + AddressOrOffsetPair { + /// Start of range. May be an address or an offset. + begin: u64, + /// End of range. May be an address or an offset. + end: u64, + /// expression + data: Expression, + }, + /// DW_LLE_base_address + BaseAddress { + /// base address + addr: u64, + }, + /// DW_LLE_base_addressx + BaseAddressx { + /// base address + addr: DebugAddrIndex, + }, + /// DW_LLE_startx_endx + StartxEndx { + /// start of range + begin: DebugAddrIndex, + /// end of range + end: DebugAddrIndex, + /// expression + data: Expression, + }, + /// DW_LLE_startx_length + StartxLength { + /// start of range + begin: DebugAddrIndex, + /// length of range + length: u64, + /// expression + data: Expression, + }, + /// DW_LLE_offset_pair + OffsetPair { + /// start of range + begin: u64, + /// end of range + end: u64, + /// expression + data: Expression, + }, + /// DW_LLE_default_location + DefaultLocation { + /// expression + data: Expression, + }, + /// DW_LLE_start_end + StartEnd { + /// start of range + begin: u64, + /// end of range + end: u64, + /// expression + data: Expression, + }, + /// DW_LLE_start_length + StartLength { + /// start of range + begin: u64, + /// length of range + length: u64, + /// expression + data: Expression, + }, +} + +fn parse_data(input: &mut R, encoding: Encoding) -> Result> { + if encoding.version >= 5 { + let len = R::Offset::from_u64(input.read_uleb128()?)?; + Ok(Expression(input.split(len)?)) + } else { + // In the GNU split-dwarf extension this is a fixed 2 byte value. + let len = R::Offset::from_u16(input.read_u16()?); + Ok(Expression(input.split(len)?)) + } +} + +impl RawLocListEntry { + /// Parse a location list entry from `.debug_loclists` + fn parse(input: &mut R, encoding: Encoding, format: LocListsFormat) -> Result> { + Ok(match format { + LocListsFormat::Bare => { + let range = RawRange::parse(input, encoding.address_size)?; + if range.is_end() { + None + } else if range.is_base_address(encoding.address_size) { + Some(RawLocListEntry::BaseAddress { addr: range.end }) + } else { + let len = R::Offset::from_u16(input.read_u16()?); + let data = Expression(input.split(len)?); + Some(RawLocListEntry::AddressOrOffsetPair { + begin: range.begin, + end: range.end, + data, + }) + } + } + LocListsFormat::Lle => match constants::DwLle(input.read_u8()?) { + constants::DW_LLE_end_of_list => None, + constants::DW_LLE_base_addressx => Some(RawLocListEntry::BaseAddressx { + addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + }), + constants::DW_LLE_startx_endx => Some(RawLocListEntry::StartxEndx { + begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + data: parse_data(input, encoding)?, + }), + constants::DW_LLE_startx_length => Some(RawLocListEntry::StartxLength { + begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + length: if encoding.version >= 5 { + input.read_uleb128()? + } else { + // In the GNU split-dwarf extension this is a fixed 4 byte value. + input.read_u32()? as u64 + }, + data: parse_data(input, encoding)?, + }), + constants::DW_LLE_offset_pair => Some(RawLocListEntry::OffsetPair { + begin: input.read_uleb128()?, + end: input.read_uleb128()?, + data: parse_data(input, encoding)?, + }), + constants::DW_LLE_default_location => Some(RawLocListEntry::DefaultLocation { + data: parse_data(input, encoding)?, + }), + constants::DW_LLE_base_address => Some(RawLocListEntry::BaseAddress { + addr: input.read_address(encoding.address_size)?, + }), + constants::DW_LLE_start_end => Some(RawLocListEntry::StartEnd { + begin: input.read_address(encoding.address_size)?, + end: input.read_address(encoding.address_size)?, + data: parse_data(input, encoding)?, + }), + constants::DW_LLE_start_length => Some(RawLocListEntry::StartLength { + begin: input.read_address(encoding.address_size)?, + length: input.read_uleb128()?, + data: parse_data(input, encoding)?, + }), + entry => { + return Err(Error::UnknownLocListsEntry(entry)); + } + }, + }) + } +} + +impl RawLocListIter { + /// Construct a `RawLocListIter`. + fn new(input: R, encoding: Encoding, format: LocListsFormat) -> RawLocListIter { + RawLocListIter { + input, + encoding, + format, + } + } + + /// Advance the iterator to the next location. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + match RawLocListEntry::parse(&mut self.input, self.encoding, self.format) { + Ok(entry) => { + if entry.is_none() { + self.input.empty(); + } + Ok(entry) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for RawLocListIter { + type Item = RawLocListEntry; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + RawLocListIter::next(self) + } +} + +/// An iterator over a location list. +/// +/// This iterator internally handles processing of base address selection entries +/// and list end entries. Thus, it only returns location entries that are valid +/// and already adjusted for the base address. +#[derive(Debug)] +pub struct LocListIter { + raw: RawLocListIter, + base_address: u64, + debug_addr: DebugAddr, + debug_addr_base: DebugAddrBase, +} + +impl LocListIter { + /// Construct a `LocListIter`. + fn new( + raw: RawLocListIter, + base_address: u64, + debug_addr: DebugAddr, + debug_addr_base: DebugAddrBase, + ) -> LocListIter { + LocListIter { + raw, + base_address, + debug_addr, + debug_addr_base, + } + } + + #[inline] + fn get_address(&self, index: DebugAddrIndex) -> Result { + self.debug_addr + .get_address(self.raw.encoding.address_size, self.debug_addr_base, index) + } + + /// Advance the iterator to the next location. + pub fn next(&mut self) -> Result>> { + loop { + let raw_loc = match self.raw.next()? { + Some(loc) => loc, + None => return Ok(None), + }; + + let loc = self.convert_raw(raw_loc)?; + if loc.is_some() { + return Ok(loc); + } + } + } + + /// Return the next raw location. + /// + /// The raw location should be passed to `convert_raw`. + #[doc(hidden)] + pub fn next_raw(&mut self) -> Result>> { + self.raw.next() + } + + /// Convert a raw location into a location, and update the state of the iterator. + /// + /// The raw location should have been obtained from `next_raw`. + #[doc(hidden)] + pub fn convert_raw( + &mut self, + raw_loc: RawLocListEntry, + ) -> Result>> { + let address_size = self.raw.encoding.address_size; + + let (range, data) = match raw_loc { + RawLocListEntry::BaseAddress { addr } => { + self.base_address = addr; + return Ok(None); + } + RawLocListEntry::BaseAddressx { addr } => { + self.base_address = self.get_address(addr)?; + return Ok(None); + } + RawLocListEntry::StartxEndx { begin, end, data } => { + let begin = self.get_address(begin)?; + let end = self.get_address(end)?; + (Range { begin, end }, data) + } + RawLocListEntry::StartxLength { + begin, + length, + data, + } => { + let begin = self.get_address(begin)?; + let end = begin.wrapping_add_sized(length, address_size); + (Range { begin, end }, data) + } + RawLocListEntry::DefaultLocation { data } => ( + Range { + begin: 0, + end: u64::MAX, + }, + data, + ), + RawLocListEntry::AddressOrOffsetPair { begin, end, data } + | RawLocListEntry::OffsetPair { begin, end, data } => { + // Skip tombstone entries (see below). + if self.base_address >= u64::min_tombstone(address_size) { + return Ok(None); + } + let mut range = Range { begin, end }; + range.add_base_address(self.base_address, address_size); + (range, data) + } + RawLocListEntry::StartEnd { begin, end, data } => (Range { begin, end }, data), + RawLocListEntry::StartLength { + begin, + length, + data, + } => { + let end = begin.wrapping_add_sized(length, address_size); + (Range { begin, end }, data) + } + }; + + // Skip tombstone entries. + // + // DWARF specifies a tombstone value of -1 or -2, but many linkers use 0 or 1. + // However, 0/1 may be a valid address, so we can't always reliably skip them. + // One case where we can skip them is for address pairs, where both values are + // replaced by tombstones and thus `begin` equals `end`. Since these entries + // are empty, it's safe to skip them even if they aren't tombstones. + // + // In addition to skipping tombstone entries, we also skip invalid entries + // where `begin` is greater than `end`. This can occur due to compiler bugs. + if range.begin >= u64::min_tombstone(address_size) || range.begin >= range.end { + return Ok(None); + } + + Ok(Some(LocationListEntry { range, data })) + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for LocListIter { + type Item = LocationListEntry; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + LocListIter::next(self) + } +} + +/// A location list entry from the `.debug_loc` or `.debug_loclists` sections. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocationListEntry { + /// The address range that this location is valid for. + pub range: Range, + + /// The data containing a single location description. + pub data: Expression, +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::common::Format; + use crate::constants::*; + use crate::endianity::LittleEndian; + use crate::read::{EndianSlice, Range}; + use crate::test_util::GimliSectionMethods; + use alloc::vec::Vec; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_loclists() { + let format = Format::Dwarf32; + for size in [4, 8] { + let tombstone = u64::ones_sized(size); + let tombstone_0 = 0; + let encoding = Encoding { + format, + version: 5, + address_size: size, + }; + + let section = Section::with_endian(Endian::Little) + .word(size, 0x0300_0000) + .word(size, 0x0301_0300) + .word(size, 0x0301_0400) + .word(size, 0x0301_0500) + .word(size, tombstone) + .word(size, 0x0301_0600) + .word(size, tombstone_0); + let buf = section.get_contents().unwrap(); + let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .initial_length(format, &length, &start) + .L16(encoding.version) + .L8(encoding.address_size) + .L8(0) + .L32(0) + .mark(&first); + + let mut expected_locations = Vec::new(); + let mut expect_location = |begin, end, data| { + expected_locations.push(LocationListEntry { + range: Range { begin, end }, + data: Expression(EndianSlice::new(data, LittleEndian)), + }); + }; + + // An offset pair using the unit base address. + section = section.L8(DW_LLE_offset_pair.0).uleb(0x10200).uleb(0x10300); + section = section.uleb(4).L32(2); + expect_location(0x0101_0200, 0x0101_0300, &[2, 0, 0, 0]); + + section = section.L8(DW_LLE_base_address.0).word(size, 0x0200_0000); + section = section.L8(DW_LLE_offset_pair.0).uleb(0x10400).uleb(0x10500); + section = section.uleb(4).L32(3); + expect_location(0x0201_0400, 0x0201_0500, &[3, 0, 0, 0]); + + section = section + .L8(DW_LLE_start_end.0) + .word(size, 0x201_0a00) + .word(size, 0x201_0b00); + section = section.uleb(4).L32(6); + expect_location(0x0201_0a00, 0x0201_0b00, &[6, 0, 0, 0]); + + section = section + .L8(DW_LLE_start_length.0) + .word(size, 0x201_0c00) + .uleb(0x100); + section = section.uleb(4).L32(7); + expect_location(0x0201_0c00, 0x0201_0d00, &[7, 0, 0, 0]); + + // An offset pair that starts at 0. + section = section.L8(DW_LLE_base_address.0).word(size, 0); + section = section.L8(DW_LLE_offset_pair.0).uleb(0).uleb(1); + section = section.uleb(4).L32(8); + expect_location(0, 1, &[8, 0, 0, 0]); + + // An offset pair that ends at -1. + section = section.L8(DW_LLE_base_address.0).word(size, 0); + section = section.L8(DW_LLE_offset_pair.0).uleb(0).uleb(tombstone); + section = section.uleb(4).L32(9); + expect_location(0, tombstone, &[9, 0, 0, 0]); + + section = section.L8(DW_LLE_default_location.0).uleb(4).L32(10); + expect_location(0, u64::MAX, &[10, 0, 0, 0]); + + section = section.L8(DW_LLE_base_addressx.0).uleb(0); + section = section.L8(DW_LLE_offset_pair.0).uleb(0x10100).uleb(0x10200); + section = section.uleb(4).L32(11); + expect_location(0x0301_0100, 0x0301_0200, &[11, 0, 0, 0]); + + section = section.L8(DW_LLE_startx_endx.0).uleb(1).uleb(2); + section = section.uleb(4).L32(12); + expect_location(0x0301_0300, 0x0301_0400, &[12, 0, 0, 0]); + + section = section.L8(DW_LLE_startx_length.0).uleb(3).uleb(0x100); + section = section.uleb(4).L32(13); + expect_location(0x0301_0500, 0x0301_0600, &[13, 0, 0, 0]); + + // Tombstone entries, all of which should be ignored. + section = section.L8(DW_LLE_base_addressx.0).uleb(4); + section = section.L8(DW_LLE_offset_pair.0).uleb(0x11100).uleb(0x11200); + section = section.uleb(4).L32(20); + + section = section.L8(DW_LLE_base_address.0).word(size, tombstone); + section = section.L8(DW_LLE_offset_pair.0).uleb(0x11300).uleb(0x11400); + section = section.uleb(4).L32(21); + + section = section.L8(DW_LLE_startx_endx.0).uleb(4).uleb(5); + section = section.uleb(4).L32(22); + section = section.L8(DW_LLE_startx_length.0).uleb(4).uleb(0x100); + section = section.uleb(4).L32(23); + section = section + .L8(DW_LLE_start_end.0) + .word(size, tombstone) + .word(size, 0x201_1500); + section = section.uleb(4).L32(24); + section = section + .L8(DW_LLE_start_length.0) + .word(size, tombstone) + .uleb(0x100); + section = section.uleb(4).L32(25); + + // Ignore some instances of 0 for tombstone. + section = section.L8(DW_LLE_startx_endx.0).uleb(6).uleb(6); + section = section.uleb(4).L32(30); + section = section + .L8(DW_LLE_start_end.0) + .word(size, tombstone_0) + .word(size, tombstone_0); + section = section.uleb(4).L32(31); + + // Ignore empty ranges. + section = section.L8(DW_LLE_base_address.0).word(size, 0); + section = section.L8(DW_LLE_offset_pair.0).uleb(0).uleb(0); + section = section.uleb(4).L32(41); + section = section.L8(DW_LLE_base_address.0).word(size, 0x10000); + section = section.L8(DW_LLE_offset_pair.0).uleb(0x1234).uleb(0x1234); + section = section.uleb(4).L32(42); + + // A valid range after the tombstones. + section = section + .L8(DW_LLE_start_end.0) + .word(size, 0x201_1600) + .word(size, 0x201_1700); + section = section.uleb(4).L32(100); + expect_location(0x0201_1600, 0x0201_1700, &[100, 0, 0, 0]); + + section = section.L8(DW_LLE_end_of_list.0); + section = section.mark(&end); + // Some extra data. + section = section.word(size, 0x1234_5678); + length.set_const((&end - &start) as u64); + + let offset = LocationListsOffset((&first - §ion.start()) as usize); + let buf = section.get_contents().unwrap(); + let debug_loc = DebugLoc::new(&[], LittleEndian); + let debug_loclists = DebugLocLists::new(&buf, LittleEndian); + let loclists = LocationLists::new(debug_loc, debug_loclists); + let mut locations = loclists + .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) + .unwrap(); + + for expected_location in expected_locations { + let location = locations.next(); + assert_eq!( + location, + Ok(Some(expected_location)), + "read {:x?}, expect {:x?}", + location, + expected_location + ); + } + assert_eq!(locations.next(), Ok(None)); + } + } + + #[test] + fn test_location_list() { + for size in [4, 8] { + let base = u64::ones_sized(size); + let tombstone = u64::ones_sized(size) - 1; + let start = Label::new(); + let first = Label::new(); + let mut section = Section::with_endian(Endian::Little) + // A location before the offset. + .mark(&start) + .word(size, 0x10000) + .word(size, 0x10100) + .L16(4) + .L32(1) + .mark(&first); + + let mut expected_locations = Vec::new(); + let mut expect_location = |begin, end, data| { + expected_locations.push(LocationListEntry { + range: Range { begin, end }, + data: Expression(EndianSlice::new(data, LittleEndian)), + }); + }; + + // A normal location. + section = section.word(size, 0x10200).word(size, 0x10300); + section = section.L16(4).L32(2); + expect_location(0x0101_0200, 0x0101_0300, &[2, 0, 0, 0]); + // A base address selection followed by a normal location. + section = section.word(size, base).word(size, 0x0200_0000); + section = section.word(size, 0x10400).word(size, 0x10500); + section = section.L16(4).L32(3); + expect_location(0x0201_0400, 0x0201_0500, &[3, 0, 0, 0]); + // An empty location range followed by a normal location. + section = section.word(size, 0x10600).word(size, 0x10600); + section = section.L16(4).L32(4); + section = section.word(size, 0x10800).word(size, 0x10900); + section = section.L16(4).L32(5); + expect_location(0x0201_0800, 0x0201_0900, &[5, 0, 0, 0]); + // A location range that starts at 0. + section = section.word(size, base).word(size, 0); + section = section.word(size, 0).word(size, 1); + section = section.L16(4).L32(6); + expect_location(0, 1, &[6, 0, 0, 0]); + // A location range that ends at -1. + section = section.word(size, base).word(size, 0); + section = section.word(size, 0).word(size, base); + section = section.L16(4).L32(7); + expect_location(0, base, &[7, 0, 0, 0]); + // A normal location with tombstone. + section = section.word(size, tombstone).word(size, tombstone); + section = section.L16(4).L32(8); + // A base address selection with tombstone followed by a normal location. + section = section.word(size, base).word(size, tombstone); + section = section.word(size, 0x10a00).word(size, 0x10b00); + section = section.L16(4).L32(9); + // A location list end. + section = section.word(size, 0).word(size, 0); + // Some extra data. + section = section.word(size, 0x1234_5678); + + let buf = section.get_contents().unwrap(); + let debug_loc = DebugLoc::new(&buf, LittleEndian); + let debug_loclists = DebugLocLists::new(&[], LittleEndian); + let loclists = LocationLists::new(debug_loc, debug_loclists); + let offset = LocationListsOffset((&first - &start) as usize); + let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: size, + }; + let mut locations = loclists + .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) + .unwrap(); + + for expected_location in expected_locations { + let location = locations.next(); + assert_eq!( + location, + Ok(Some(expected_location)), + "read {:x?}, expect {:x?}", + location, + expected_location + ); + } + assert_eq!(locations.next(), Ok(None)); + + // An offset at the end of buf. + let mut locations = loclists + .locations( + LocationListsOffset(buf.len()), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(locations.next(), Ok(None)); + } + } + + #[test] + fn test_locations_invalid() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + // An invalid location range. + .L32(0x20000).L32(0x10000).L16(4).L32(1) + // An invalid range after wrapping. + .L32(0x20000).L32(0xff01_0000).L16(4).L32(2); + + let buf = section.get_contents().unwrap(); + let debug_loc = DebugLoc::new(&buf, LittleEndian); + let debug_loclists = DebugLocLists::new(&[], LittleEndian); + let loclists = LocationLists::new(debug_loc, debug_loclists); + let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + + // An invalid location range. + let mut locations = loclists + .locations( + LocationListsOffset(0x0), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(locations.next(), Ok(None)); + + // An invalid location range after wrapping. + let mut locations = loclists + .locations( + LocationListsOffset(14), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(locations.next(), Ok(None)); + + // An invalid offset. + match loclists.locations( + LocationListsOffset(buf.len() + 1), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_get_offset() { + for format in [Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version: 5, + address_size: 4, + }; + + let zero = Label::new(); + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .mark(&zero) + .initial_length(format, &length, &start) + .D16(encoding.version) + .D8(encoding.address_size) + .D8(0) + .D32(20) + .mark(&first); + for i in 0..20 { + section = section.word(format.word_size(), 1000 + i); + } + section = section.mark(&end); + length.set_const((&end - &start) as u64); + let section = section.get_contents().unwrap(); + + let debug_loc = DebugLoc::from(EndianSlice::new(&[], LittleEndian)); + let debug_loclists = DebugLocLists::from(EndianSlice::new(§ion, LittleEndian)); + let locations = LocationLists::new(debug_loc, debug_loclists); + + let base = DebugLocListsBase((&first - &zero) as usize); + assert_eq!( + locations.get_offset(encoding, base, DebugLocListsIndex(0)), + Ok(LocationListsOffset(base.0 + 1000)) + ); + assert_eq!( + locations.get_offset(encoding, base, DebugLocListsIndex(19)), + Ok(LocationListsOffset(base.0 + 1019)) + ); + } + } + + #[test] + fn test_loclists_gnu_v4_split_dwarf() { + #[rustfmt::skip] + let buf = [ + 0x03, // DW_LLE_startx_length + 0x00, // ULEB encoded b7 + 0x08, 0x00, 0x00, 0x00, // Fixed 4 byte length of 8 + 0x03, 0x00, // Fixed two byte length of the location + 0x11, 0x00, // DW_OP_constu 0 + 0x9f, // DW_OP_stack_value + // Padding data + //0x99, 0x99, 0x99, 0x99 + ]; + let data_buf = [0x11, 0x00, 0x9f]; + let expected_data = EndianSlice::new(&data_buf, LittleEndian); + let debug_loc = DebugLoc::new(&buf, LittleEndian); + let debug_loclists = DebugLocLists::new(&[], LittleEndian); + let loclists = LocationLists::new(debug_loc, debug_loclists); + let debug_addr = + &DebugAddr::from(EndianSlice::new(&[0x01, 0x02, 0x03, 0x04], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + + // An invalid location range. + let mut locations = loclists + .locations_dwo( + LocationListsOffset(0x0), + encoding, + 0, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!( + locations.next(), + Ok(Some(LocationListEntry { + range: Range { + begin: 0x0403_0201, + end: 0x0403_0209 + }, + data: Expression(expected_data), + })) + ); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/lookup.rs b/anneal/v2/vendor/gimli/src/read/lookup.rs new file mode 100644 index 0000000000..1d082f24f4 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/lookup.rs @@ -0,0 +1,202 @@ +use core::marker::PhantomData; + +use crate::common::{DebugInfoOffset, Format}; +use crate::read::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset}; + +// The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have +// similar structures. They consist of a header with metadata and an offset into the +// .debug_info section for the entire compilation unit, and a series +// of following entries that list addresses (for .debug_aranges) or names +// (for .debug_pubnames and .debug_pubtypes) that are covered. +// +// Because these three tables all have similar structures, we abstract out some of +// the parsing mechanics. + +pub trait LookupParser { + /// The type of the produced header. + type Header; + /// The type of the produced entry. + type Entry; + + /// Parse a header from `input`. Returns a tuple of `input` sliced to contain just the entries + /// corresponding to this header (without the header itself), and the parsed representation of + /// the header itself. + fn parse_header(input: &mut R) -> Result<(R, Self::Header)>; + + /// Parse a single entry from `input`. Returns either a parsed representation of the entry + /// or None if `input` is exhausted. + fn parse_entry(input: &mut R, header: &Self::Header) -> Result>; +} + +#[derive(Clone, Debug)] +pub struct DebugLookup +where + R: Reader, + Parser: LookupParser, +{ + input_buffer: R, + phantom: PhantomData, +} + +impl From for DebugLookup +where + R: Reader, + Parser: LookupParser, +{ + fn from(input_buffer: R) -> Self { + DebugLookup { + input_buffer, + phantom: PhantomData, + } + } +} + +impl DebugLookup +where + R: Reader, + Parser: LookupParser, +{ + pub fn items(&self) -> LookupEntryIter { + LookupEntryIter { + current_set: None, + remaining_input: self.input_buffer.clone(), + } + } + + pub fn reader(&self) -> &R { + &self.input_buffer + } +} + +#[derive(Clone, Debug)] +pub struct LookupEntryIter +where + R: Reader, + Parser: LookupParser, +{ + current_set: Option<(R, Parser::Header)>, // Only none at the very beginning and end. + remaining_input: R, +} + +impl LookupEntryIter +where + R: Reader, + Parser: LookupParser, +{ + /// Advance the iterator and return the next entry. + /// + /// Returns the newly parsed entry as `Ok(Some(Parser::Entry))`. Returns + /// `Ok(None)` when iteration is complete and all entries have already been + /// parsed and yielded. If an error occurs while parsing the next entry, + /// then this error is returned as `Err(e)`, and all subsequent calls return + /// `Ok(None)`. + /// + /// Can be [used with `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn next(&mut self) -> Result> { + loop { + if let Some((ref mut input, ref header)) = self.current_set { + if !input.is_empty() { + match Parser::parse_entry(input, header) { + Ok(Some(entry)) => return Ok(Some(entry)), + Ok(None) => {} + Err(e) => { + input.empty(); + self.remaining_input.empty(); + return Err(e); + } + } + } + } + if self.remaining_input.is_empty() { + self.current_set = None; + return Ok(None); + } + match Parser::parse_header(&mut self.remaining_input) { + Ok(set) => { + self.current_set = Some(set); + } + Err(e) => { + self.current_set = None; + self.remaining_input.empty(); + return Err(e); + } + } + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PubStuffHeader { + format: Format, + length: T, + version: u16, + unit_offset: DebugInfoOffset, + unit_length: T, +} + +pub trait PubStuffEntry { + fn new( + die_offset: UnitOffset, + name: R, + unit_header_offset: DebugInfoOffset, + ) -> Self; +} + +#[derive(Clone, Debug)] +pub struct PubStuffParser +where + R: Reader, + Entry: PubStuffEntry, +{ + // This struct is never instantiated. + phantom: PhantomData<(R, Entry)>, +} + +impl LookupParser for PubStuffParser +where + R: Reader, + Entry: PubStuffEntry, +{ + type Header = PubStuffHeader; + type Entry = Entry; + + /// Parse an pubthings set header. Returns a tuple of the + /// pubthings to be parsed for this set, and the newly created PubThingHeader struct. + fn parse_header(input: &mut R) -> Result<(R, Self::Header)> { + let (length, format) = input.read_initial_length()?; + let mut rest = input.split(length)?; + + let version = rest.read_u16()?; + if version != 2 { + return Err(Error::UnknownVersion(u64::from(version))); + } + + let unit_offset = parse_debug_info_offset(&mut rest, format)?; + let unit_length = rest.read_length(format)?; + + let header = PubStuffHeader { + format, + length, + version, + unit_offset, + unit_length, + }; + Ok((rest, header)) + } + + /// Parse a single pubthing. Return `None` for the null pubthing, `Some` for an actual pubthing. + fn parse_entry(input: &mut R, header: &Self::Header) -> Result> { + let offset = input.read_offset(header.format)?; + if offset.into_u64() == 0 { + input.empty(); + Ok(None) + } else { + let name = input.read_null_terminated_slice()?; + Ok(Some(Self::Entry::new( + UnitOffset(offset), + name, + header.unit_offset, + ))) + } + } +} diff --git a/anneal/v2/vendor/gimli/src/read/macros.rs b/anneal/v2/vendor/gimli/src/read/macros.rs new file mode 100644 index 0000000000..b723abca33 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/macros.rs @@ -0,0 +1,872 @@ +use crate::common::{DebugMacinfoOffset, SectionId}; +use crate::endianity::Endianity; +use crate::read::{EndianSlice, Reader, ReaderOffset, Section, UnitRef}; +use crate::{ + constants, DebugLineOffset, DebugMacroOffset, DebugStrOffset, DebugStrOffsetsIndex, DwMacinfo, + DwMacro, Error, Format, Result, +}; + +/// The raw contents of the `.debug_macinfo` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugMacinfo { + pub(crate) section: R, +} + +impl<'input, Endian> DebugMacinfo> +where + Endian: Endianity, +{ + /// Construct a new `DebugMacinfo` instance from the data in the `.debug_macinfo` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_macinfo` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugMacinfo, LittleEndian}; + /// + /// # let buf = [1, 0, 95, 95, 83, 84, 68, 67, 95, 95, 32, 49, 0]; + /// # let read_section_somehow = || &buf; + /// let debug_str = DebugMacinfo::new(read_section_somehow(), LittleEndian); + /// ``` + pub fn new(macinfo_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(macinfo_section, endian)) + } +} + +impl DebugMacinfo { + /// Look up a macro reference the `.debug_macinfo` section by DebugMacinfoOffset. + /// + /// A macinfo offset points to a list of macro information entries in the `.debug_macinfo` section. + /// To handle this, the function returns an iterator. + /// + /// ``` + /// use gimli::{DebugMacinfo, DebugMacinfoOffset, LittleEndian}; + /// + /// # fn main() -> Result<(), gimli::Error> { + /// # let buf = [1, 0, 95, 95, 83, 84, 68, 67, 95, 95, 32, 49, 0, 0]; + /// # let offset = DebugMacinfoOffset(0); + /// # let read_section_somehow = || &buf; + /// # let debug_macinfo_offset_somehow = || offset; + /// let debug_macinfo = DebugMacinfo::new(read_section_somehow(), LittleEndian); + /// let mut iter = debug_macinfo.get_macinfo(debug_macinfo_offset_somehow())?; + /// while let Some(macinfo) = iter.next()? { + /// println!("Found macro info {:?}", macinfo); + /// } + /// # Ok(()) } + /// ``` + pub fn get_macinfo(&self, offset: DebugMacinfoOffset) -> Result> { + let mut input = self.section.clone(); + input.skip(offset.0)?; + Ok(MacroIter { + input, + format: Format::Dwarf32, + is_macro: false, + }) + } +} + +impl DebugMacinfo { + /// Create a `DebugMacinfo` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugMacinfo + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugMacinfo { + fn id() -> SectionId { + SectionId::DebugMacinfo + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugMacinfo { + fn from(macinfo_section: R) -> Self { + DebugMacinfo { + section: macinfo_section, + } + } +} + +/// The raw contents of the `.debug_macro` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugMacro { + pub(crate) section: R, +} + +impl<'input, Endian> DebugMacro> +where + Endian: Endianity, +{ + /// Construct a new `DebugMacro` instance from the data in the `.debug_macro` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_macro` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugMacro, LittleEndian}; + /// + /// # let buf = [1, 0, 95, 95, 83, 84, 68, 67, 95, 95, 32, 49, 0]; + /// # let read_section_somehow = || &buf; + /// let debug_str = DebugMacro::new(read_section_somehow(), LittleEndian); + /// ``` + pub fn new(macro_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(macro_section, endian)) + } +} + +impl DebugMacro { + /// Look up a macro reference the `.debug_macinfo` section by DebugMacroOffset. + /// + /// A macinfo offset points to a list of macro information entries in the `.debug_macinfo` section. + /// To handle this, the function returns an iterator. + /// + /// ``` + /// use gimli::{DebugMacro, DebugMacroOffset, LittleEndian}; + /// + /// # fn main() -> Result<(), gimli::Error> { + /// # let buf = [0x05, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x5f, 0x53, 0x54, 0x44, 0x43, 0x5f, 0x5f, 0x20, 0x31, 0x00, 0x00]; + /// # let offset = DebugMacroOffset(0); + /// # let read_section_somehow = || &buf; + /// # let debug_macro_offset_somehow = || offset; + /// let debug_macro = DebugMacro::new(read_section_somehow(), LittleEndian); + /// let mut iter = debug_macro.get_macros(debug_macro_offset_somehow())?; + /// while let Some(cur_macro) = iter.next()? { + /// println!("Found macro info {:?}", cur_macro); + /// } + /// # Ok(()) } + /// ``` + pub fn get_macros(&self, offset: DebugMacroOffset) -> Result> { + let mut input = self.section.clone(); + input.skip(offset.0)?; + let header = MacroUnitHeader::parse(&mut input)?; + Ok(MacroIter { + input, + format: header.format(), + is_macro: true, + }) + } +} + +impl DebugMacro { + /// Create a `DebugMacro` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugMacro + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugMacro { + fn id() -> SectionId { + SectionId::DebugMacro + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugMacro { + fn from(macro_section: R) -> Self { + DebugMacro { + section: macro_section, + } + } +} + +#[derive(Debug, Clone)] +struct MacroUnitHeader { + /// The version of the macro unit header. At the moment only version 5 is defined. + _version: u16, + flags: u8, + _debug_line_offset: DebugLineOffset, +} + +impl MacroUnitHeader { + const OFFSET_SIZE_FLAG: u8 = 0b0000_0001; + const DEBUG_LINE_OFFSET_FLAG: u8 = 0b0000_0010; + const OPCODE_OPERANDS_TABLE_FLAG: u8 = 0b0000_0100; + + fn parse(input: &mut R) -> Result { + let version = input.read_u16()?; + let flags = input.read_u8()?; + let format = if flags & Self::OFFSET_SIZE_FLAG == 0 { + Format::Dwarf32 + } else { + Format::Dwarf64 + }; + let _debug_line_offset = if flags & Self::DEBUG_LINE_OFFSET_FLAG != 0 { + DebugLineOffset(input.read_offset(format)?) + } else { + DebugLineOffset(R::Offset::from_u64(0)?) + }; + // if the opcode operands table flag is set, there is a table in the header which currently isn't parsed + if flags & Self::OPCODE_OPERANDS_TABLE_FLAG != 0 { + return Err(Error::UnsupportedOpcodeOperandsTable); + } + Ok(MacroUnitHeader { + _version: version, + flags, + _debug_line_offset, + }) + } + + fn format(&self) -> Format { + if self.flags & Self::OFFSET_SIZE_FLAG == 0 { + Format::Dwarf32 + } else { + Format::Dwarf64 + } + } +} + +/// A string in a macro entry. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MacroString::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// The string is directly embedded in the macro entry + Direct(R), + /// The macro refers to a string in the `.debug_str` section using a `DebugStrOffset`. + StringPointer(DebugStrOffset), + /// The macro contains an index into an array in the `.debug_str_offsets` + /// section, which refers to a string in the `.debug_str` section. + IndirectStringPointer(DebugStrOffsetsIndex), + /// The macro refers to a string in the `.debug_str` section in the supplementary object file + Supplementary(DebugStrOffset), +} + +impl MacroString { + /// Get the string slice from the macro entry. + pub fn string(&self, unit: UnitRef<'_, R>) -> Result { + match self { + MacroString::Direct(s) => Ok(s.clone()), + MacroString::StringPointer(offset) => unit.string(*offset), + MacroString::IndirectStringPointer(index) => { + let str_offset = unit.string_offset(*index)?; + unit.string(str_offset) + } + MacroString::Supplementary(offset) => unit.sup_string(*offset), + } + } +} + +/// an Entry in the `.debug_macro` section. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MacroEntry::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// A macro definition. + Define { + /// The line number where the macro is defined. + line: u64, + /// The text of the macro: The name of the macro followed immediately by any formal + /// parameters including the surrounding parentheses, followed by the macro definition. + text: MacroString, + }, + /// A macro undefinition. + Undef { + /// The line number where the macro is undefined. + line: u64, + /// The name of the macro without the definition. + name: MacroString, + }, + /// The start of a file. + StartFile { + /// Line number of the source file on which the inclusion macro directive occurred. + line: u64, + /// An index into the line number table of the compilation unit. + file: u64, + }, + /// The end of the current included file. + EndFile, + /// import a macro unit + Import { + /// offset of the macro unit in the `.debug_macro` section + offset: DebugMacroOffset, + }, + /// import a macro unit from the supplementary object file + ImportSup { + /// offset of the macro unit in the `.debug_macro` section of the supplementary object file + offset: DebugMacroOffset, + }, + /// A vendor-specific extension. + VendorExt { + /// A numeric constant, whose meaning is vendor specific. + numeric: u64, + /// A string whose meaning is vendor specific. + string: R, + }, +} + +/// Iterator over the entries in the `.debug_macro` section. +#[derive(Clone, Debug)] +pub struct MacroIter { + input: R, + format: Format, + is_macro: bool, +} + +impl MacroIter { + /// Advance the iterator to the next entry in the `.debug_macro` section. + pub fn next(&mut self) -> Result>> { + // DW_MACINFO_* and DW_MACRO_* have the same values, so we can use the same parsing logic. + let macro_type = DwMacro(self.input.read_u8()?); + match macro_type { + DwMacro(0) => { + self.input.empty(); + Ok(None) + } + constants::DW_MACRO_define => { + let line = self.input.read_uleb128()?; + let text = self.input.read_null_terminated_slice()?; + Ok(Some(MacroEntry::Define { + line, + text: MacroString::Direct(text), + })) + } + constants::DW_MACRO_undef => { + let line = self.input.read_uleb128()?; + let name = self.input.read_null_terminated_slice()?; + Ok(Some(MacroEntry::Undef { + line, + name: MacroString::Direct(name), + })) + } + constants::DW_MACRO_start_file => { + let line = self.input.read_uleb128()?; + let file = self.input.read_uleb128()?; + Ok(Some(MacroEntry::StartFile { line, file })) + } + constants::DW_MACRO_end_file => Ok(Some(MacroEntry::EndFile)), + constants::DW_MACRO_define_strp if self.is_macro => { + let line = self.input.read_uleb128()?; + let text_offset = DebugStrOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::Define { + line, + text: MacroString::StringPointer(text_offset), + })) + } + constants::DW_MACRO_undef_strp if self.is_macro => { + let line = self.input.read_uleb128()?; + let name_offset = DebugStrOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::Undef { + line, + name: MacroString::StringPointer(name_offset), + })) + } + constants::DW_MACRO_import if self.is_macro => { + let offset = DebugMacroOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::Import { offset })) + } + constants::DW_MACRO_define_sup if self.is_macro => { + let line = self.input.read_uleb128()?; + let text_offset = DebugStrOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::Define { + line, + text: MacroString::Supplementary(text_offset), + })) + } + constants::DW_MACRO_undef_sup if self.is_macro => { + let line = self.input.read_uleb128()?; + let name_offset = DebugStrOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::Undef { + line, + name: MacroString::Supplementary(name_offset), + })) + } + constants::DW_MACRO_import_sup if self.is_macro => { + let offset = DebugMacroOffset(self.input.read_offset(self.format)?); + Ok(Some(MacroEntry::ImportSup { offset })) + } + constants::DW_MACRO_define_strx if self.is_macro => { + let line = self.input.read_uleb128()?; + let index = self.input.read_uleb128().and_then(R::Offset::from_u64)?; + let text_index = DebugStrOffsetsIndex(index); + Ok(Some(MacroEntry::Define { + line, + text: MacroString::IndirectStringPointer(text_index), + })) + } + constants::DW_MACRO_undef_strx if self.is_macro => { + let line = self.input.read_uleb128()?; + let index = self.input.read_uleb128().and_then(R::Offset::from_u64)?; + let name_index = DebugStrOffsetsIndex(index); + Ok(Some(MacroEntry::Undef { + line, + name: MacroString::IndirectStringPointer(name_index), + })) + } + _ => { + if self.is_macro { + self.input.empty(); + Err(Error::InvalidMacroType(macro_type)) + } else if macro_type.0 == constants::DW_MACINFO_vendor_ext.0 { + let numeric = self.input.read_uleb128()?; + let string = self.input.read_null_terminated_slice()?; + Ok(Some(MacroEntry::VendorExt { numeric, string })) + } else { + self.input.empty(); + Err(Error::InvalidMacinfoType(DwMacinfo(macro_type.0))) + } + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for MacroIter { + type Item = MacroEntry; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Error> { + MacroIter::next(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{test_util::GimliSectionMethods, DebugStr, LittleEndian}; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_get_macinfo() { + let position = Label::new(); + + // Create a test section with some macinfo entries + let section = Section::with_endian(Endian::Little) + .set_start_const(0) + .mark(&position) + .D8(crate::DW_MACINFO_define.0) + .uleb(0) // line number: 0 - defined on the compiler command line + .append_bytes(b"__STDC__ 1\0") + .D8(crate::DW_MACINFO_define.0) + .uleb(1) // line number: 1 - defined in the source file + .append_bytes(b"__GNUC__ 1\0") + .D8(crate::DW_MACINFO_undef.0) + .uleb(2) // line number: 2 - undefined in the source file + .append_bytes(b"__GNUC__\0") + .D8(crate::DW_MACINFO_start_file.0) + .uleb(3) // line number: 3 - start of file + .uleb(4) // file number index: 4 - index into the line number table + .D8(crate::DW_MACINFO_end_file.0) // end of file + .D8(crate::DW_MACINFO_vendor_ext.0) + .uleb(5) // numeric constant: 5 - vendor specific + .append_bytes(b"foo\0") + .D8(0); // end of unit + + // Create a DebugMacinfo instance from the section + let section = section.get_contents().unwrap(); + let debug_macinfo = DebugMacinfo::from(EndianSlice::new(§ion, LittleEndian)); + + let offset = position.value().unwrap() as usize; + + let mut iter = debug_macinfo + .get_macinfo(DebugMacinfoOffset(offset)) + .unwrap(); + + // Test getting macinfo entries + let entry = iter.next().unwrap().unwrap(); + assert!( + matches!(entry, MacroEntry::Define { line: 0, text: MacroString::Direct(text) } if text.slice() == b"__STDC__ 1") + ); + + let entry = iter.next().unwrap().unwrap(); + assert!( + matches!(entry, MacroEntry::Define { line: 1, text: MacroString::Direct(text) } if text.slice() == b"__GNUC__ 1") + ); + + let entry = iter.next().unwrap().unwrap(); + assert!( + matches!(entry, MacroEntry::Undef { line: 2, name: MacroString::Direct(name) } if name.slice() == b"__GNUC__") + ); + + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 4 })); + + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + + let entry = iter.next().unwrap().unwrap(); + assert!( + matches!(entry, MacroEntry::VendorExt { numeric: 5, string } if string.slice() == b"foo") + ); + + assert_eq!(iter.next(), Ok(None)); + } + + #[test] + fn get_macros_1() { + let position = Label::new(); + + // The test data is originally from the DWARF v5 standard, appendix D.16 + // 1) Figure D.71, simple DWARF encoding + let section = Section::with_endian(Endian::Little) + .set_start_const(0) + .mark(&position) + .D16(5) // Dwarf version + .D8(0b0000_0010) // Flags: offset_size = 0 (32-bit), debug_line_offset = 1, opcode_operands_table = 0 + .D32(0) // debug line offset + .D8(crate::DW_MACRO_start_file.0) // start file: "a.c" + .uleb(0) // line number + .uleb(0) // file number + .D8(crate::DW_MACRO_start_file.0) // start file: "a.h" + .uleb(1) // line number + .uleb(1) // file number + .D8(crate::DW_MACRO_define.0) // define + .uleb(1) // line number + .append_bytes(b"LONGER_MACRO 1\0") // macro name + .D8(crate::DW_MACRO_define.0) // define + .uleb(2) // line number + .append_bytes(b"B 2\0") // macro name + .D8(crate::DW_MACRO_start_file.0) // start file: "b.h" + .uleb(3) // line number + .uleb(2) // file number + .D8(crate::DW_MACRO_undef.0) // undef + .uleb(1) // line number + .append_bytes(b"B\0") // macro name + .D8(crate::DW_MACRO_define.0) // define + .uleb(2) // line number + .append_bytes(b"D 3\0") // macro name + .D8(crate::DW_MACRO_define.0) // define + .uleb(3) // line number + .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") // macro name + .D8(crate::DW_MACRO_end_file.0) // end file: "b.h" -> "a.h" + .D8(crate::DW_MACRO_define.0) // define + .uleb(4) // line number + .append_bytes(b"B 3\0") // macro name + .D8(crate::DW_MACRO_end_file.0) // end file: "a.h" -> "a.c" + .D8(crate::DW_MACRO_define.0) // define + .uleb(2) // line number + .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") // macro name + .D8(crate::DW_MACRO_start_file.0) // start file: "b.h" + .uleb(3) // line number + .uleb(2) // file number + .D8(crate::DW_MACRO_undef.0) // undef + .uleb(1) // line number + .append_bytes(b"B\0") // macro name + .D8(crate::DW_MACRO_define.0) // define + .uleb(2) // line number + .append_bytes(b"D 3\0") // macro name + .D8(crate::DW_MACRO_define.0) // define + .uleb(3) // line number + .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") // macro name + .D8(crate::DW_MACRO_end_file.0) // end file: "b.h" -> "a.c" + .D8(crate::DW_MACRO_end_file.0) // end file: "a.c" -> "" + .D8(0); // end of unit + + // Create a DebugMacro instance from the section + let section = section.get_contents().unwrap(); + let debug_macro = DebugMacro::from(EndianSlice::new(§ion, LittleEndian)); + + let offset = position.value().unwrap() as usize; + + let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap(); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 1, text: MacroString::Direct(text) + } if text.slice() == b"LONGER_MACRO 1" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"B 2" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Undef { + line: 1, name: MacroString::Direct(name) + } if name.slice() == b"B" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"D 3" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 3, text: MacroString::Direct(text) + } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 4, text: MacroString::Direct(text) + } if text.slice() == b"B 3" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Undef { + line: 1, name: MacroString::Direct(name) + } if name.slice() == b"B" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"D 3" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 3, text: MacroString::Direct(text) + } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + assert_eq!(iter.next(), Ok(None)); + } + + #[test] + fn get_macros_2() { + let str_0 = Label::new(); + let str_1 = Label::new(); + let macro_unit_0 = Label::new(); + let macro_unit_1 = Label::new(); + let macro_unit_2 = Label::new(); + + // The test data is originally from the DWARF v5 standard, appendix D.16 + // 2) Figure D.72, shareable DWARF encoding + let str_section = Section::with_endian(Endian::Little) + .set_start_const(0) + .mark(&str_0) + .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") // macro name + .mark(&str_1) + .append_bytes(b"LONGER_MACRO 1\0"); // macro name + + let macro_section = Section::with_endian(Endian::Little) + .set_start_const(0) + //--------------------unit 0---------------------- + .mark(¯o_unit_0) // start of unit 0 + .D16(5) // Dwarf version + .D8(0b0000_0010) // Flags: offset_size = 0 (32-bit), debug_line_offset = 1, opcode_operands_table = 0 + .D32(0) // debug line offset + .D8(crate::DW_MACRO_start_file.0) // start file: "a.c" + .uleb(0) // line number + .uleb(0) // file number + .D8(crate::DW_MACRO_start_file.0) // start file: "a.h" + .uleb(1) // line number + .uleb(1) // file number + .D8(crate::DW_MACRO_import.0) // import unit 1 + .L32(macro_unit_1.clone()) // debug line offset to unit 1 + .D8(crate::DW_MACRO_start_file.0) // start file: "b.h" + .uleb(3) // line number + .uleb(2) // file number + .D8(crate::DW_MACRO_import.0) // import unit 2 + .L32(macro_unit_2.clone()) // debug line offset to unit 2 + .D8(crate::DW_MACRO_end_file.0) // end file: "b.h" -> "a.h" + .D8(crate::DW_MACRO_define.0) // define + .uleb(4) // line number + .append_bytes(b"B 3\0") // macro name + .D8(crate::DW_MACRO_end_file.0) // end file: "a.h" -> "a.c" + .D8(crate::DW_MACRO_define_strp.0) // define: "FUNCTION_LIKE_MACRO(x) 4+x" + .uleb(2) // line number + .D32(0) // macro name offset in the string table + .D8(crate::DW_MACRO_start_file.0) // start file: "b.h" + .uleb(3) // line number + .uleb(2) // file number + .D8(crate::DW_MACRO_import.0) // import unit 2 + .L32(¯o_unit_2) // debug line offset to unit 2 + .D8(crate::DW_MACRO_end_file.0) // end file: "b.h" -> "a.c" + .D8(crate::DW_MACRO_end_file.0) // end file: "a.c" -> "" + .D8(0) + //--------------------unit 1---------------------- + .mark(¯o_unit_1) // start of unit 1 + .D16(5) // Dwarf version + .D8(0b0000_0000) // Flags: offset_size = 0 (32-bit), debug_line_offset = 0, opcode_operands_table = 0 + .D8(crate::DW_MACRO_define_strp.0) // define strp: "LONGER_MACRO 1" + .uleb(1) // line number + .L32(str_0.clone()) // macro name offset in the string table + .D8(crate::DW_MACRO_define.0) // define: "B 2" + .uleb(2) // line number + .append_bytes(b"B 2\0") // macro name + .D8(0) // end of unit + //---------------------unit 2--------------------- + .mark(¯o_unit_2) // start of unit 2 + .D16(5) // Dwarf version + .D8(0b0000_0000) // Flags: offset_size = 0 (32-bit), debug_line_offset = 0, opcode_operands_table = 0 + .D8(crate::DW_MACRO_undef.0) // undef: "B" + .uleb(1) // line number + .append_bytes(b"B\0") // macro name + .D8(crate::DW_MACRO_define.0) // define: "D 3" + .uleb(2) // line number + .append_bytes(b"D 3\0") // macro name + .D8(crate::DW_MACRO_define_strp.0) // define strp: "FUNCTION_LIKE_MACRO(x) 4+x" + .uleb(2) // line number + .L32(str_1.clone()) // macro name offset in the string table + .D8(0); // end of unit + + // Create a DebugMacro instance from the section + let str_section = str_section.get_contents().unwrap(); + let debug_str = DebugStr::from(EndianSlice::new(&str_section, LittleEndian)); + + // Create a DebugMacro instance from the section + let macro_section = macro_section.get_contents().unwrap(); + let debug_macro = DebugMacro::from(EndianSlice::new(¯o_section, LittleEndian)); + + // check the content of macro unit 0 + let offset = macro_unit_0.value().unwrap() as usize; + let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap(); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Import { offset } if offset.0 == macro_unit_1.value().unwrap() as usize + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 4, text: MacroString::Direct(text) + } if text.slice() == b"B 3" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::StringPointer(text_offset) + } if text_offset.0 == str_0.value().unwrap() as usize + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 })); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!(entry, MacroEntry::EndFile)); + assert_eq!(iter.next(), Ok(None)); + + // check the content of macro unit 1 + let offset = macro_unit_1.value().unwrap() as usize; + let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap(); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 1, text: MacroString::StringPointer(text_offset) + } if text_offset.0 == str_0.value().unwrap() as usize + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"B 2" + )); + assert_eq!(iter.next(), Ok(None)); + + // check the content of macro unit 2 + let offset = macro_unit_2.value().unwrap() as usize; + let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap(); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Undef { + line: 1, name: MacroString::Direct(name) + } if name.slice() == b"B" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::Direct(text) + } if text.slice() == b"D 3" + )); + let entry = iter.next().unwrap().unwrap(); + assert!(matches!( + entry, + MacroEntry::Define { + line: 2, text: MacroString::StringPointer(text_offset) + } if text_offset.0 == str_1.value().unwrap() as usize + )); + assert_eq!(iter.next(), Ok(None)); + + // check the content of the string table + let text_offset = DebugStrOffset(str_0.value().unwrap() as usize); + assert_eq!( + debug_str.get_str(text_offset).unwrap().slice(), + b"FUNCTION_LIKE_MACRO(x) 4+x" + ); + let text_offset = DebugStrOffset(str_1.value().unwrap() as usize); + assert_eq!( + debug_str.get_str(text_offset).unwrap().slice(), + b"LONGER_MACRO 1" + ); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/mod.rs b/anneal/v2/vendor/gimli/src/read/mod.rs new file mode 100644 index 0000000000..0aaa7664bf --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/mod.rs @@ -0,0 +1,868 @@ +//! Read DWARF debugging information. +//! +//! * [Example Usage](#example-usage) +//! * [API Structure](#api-structure) +//! * [Using with `FallibleIterator`](#using-with-fallibleiterator) +//! +//! ## Example Usage +//! +//! Print out all of the functions in the debuggee program: +//! +//! ```rust,no_run +//! # fn example() -> Result<(), gimli::Error> { +//! # type R = gimli::EndianSlice<'static, gimli::LittleEndian>; +//! # let get_file_section_reader = |name| -> Result { unimplemented!() }; +//! # let get_sup_file_section_reader = |name| -> Result { unimplemented!() }; +//! // Read the DWARF sections with whatever object loader you're using. +//! // These closures should return a `Reader` instance (e.g. `EndianSlice`). +//! let loader = |section: gimli::SectionId| { get_file_section_reader(section.name()) }; +//! let sup_loader = |section: gimli::SectionId| { get_sup_file_section_reader(section.name()) }; +//! let mut dwarf = gimli::Dwarf::load(loader)?; +//! dwarf.load_sup(sup_loader)?; +//! +//! // Iterate over all compilation units. +//! let mut iter = dwarf.units(); +//! while let Some(header) = iter.next()? { +//! // Parse the abbreviations and other information for this compilation unit. +//! let unit = dwarf.unit(header)?; +//! +//! // Iterate over all of this compilation unit's entries. +//! let mut entries = unit.entries(); +//! while let Some((_, entry)) = entries.next_dfs()? { +//! // If we find an entry for a function, print it. +//! if entry.tag() == gimli::DW_TAG_subprogram { +//! println!("Found a function: {:?}", entry); +//! } +//! } +//! } +//! # unreachable!() +//! # } +//! ``` +//! +//! Full example programs: +//! +//! * [A simple `.debug_info` parser](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/simple.rs) +//! +//! * [A simple `.debug_line` parser](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/simple_line.rs) +//! +//! * [A `dwarfdump` +//! clone](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarfdump.rs) +//! +//! * [An `addr2line` clone](https://github.com/gimli-rs/addr2line) +//! +//! * [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into +//! code generation by making debugging information readable +//! +//! * [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the +//! compilers used to create each compilation unit within a shared library or +//! executable (via `DW_AT_producer`) +//! +//! * [`dwarf-validate`](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarf-validate.rs), +//! a program to validate the integrity of some DWARF and its references +//! between sections and compilation units. +//! +//! ## API Structure +//! +//! * Basic familiarity with DWARF is assumed. +//! +//! * The [`Dwarf`](./struct.Dwarf.html) type contains the commonly used DWARF +//! sections. It has methods that simplify access to debugging data that spans +//! multiple sections. Use of this type is optional, but recommended. +//! +//! * The [`DwarfPackage`](./struct.Dwarf.html) type contains the DWARF +//! package (DWP) sections. It has methods to find a DWARF object (DWO) +//! within the package. +//! +//! * Each section gets its own type. Consider these types the entry points to +//! the library: +//! +//! * [`DebugAbbrev`](./struct.DebugAbbrev.html): The `.debug_abbrev` section. +//! +//! * [`DebugAddr`](./struct.DebugAddr.html): The `.debug_addr` section. +//! +//! * [`DebugAranges`](./struct.DebugAranges.html): The `.debug_aranges` +//! section. +//! +//! * [`DebugFrame`](./struct.DebugFrame.html): The `.debug_frame` section. +//! +//! * [`DebugInfo`](./struct.DebugInfo.html): The `.debug_info` section. +//! +//! * [`DebugLine`](./struct.DebugLine.html): The `.debug_line` section. +//! +//! * [`DebugLineStr`](./struct.DebugLineStr.html): The `.debug_line_str` section. +//! +//! * [`DebugLoc`](./struct.DebugLoc.html): The `.debug_loc` section. +//! +//! * [`DebugLocLists`](./struct.DebugLocLists.html): The `.debug_loclists` section. +//! +//! * [`DebugPubNames`](./struct.DebugPubNames.html): The `.debug_pubnames` +//! section. +//! +//! * [`DebugPubTypes`](./struct.DebugPubTypes.html): The `.debug_pubtypes` +//! section. +//! +//! * [`DebugRanges`](./struct.DebugRanges.html): The `.debug_ranges` section. +//! +//! * [`DebugRngLists`](./struct.DebugRngLists.html): The `.debug_rnglists` section. +//! +//! * [`DebugStr`](./struct.DebugStr.html): The `.debug_str` section. +//! +//! * [`DebugStrOffsets`](./struct.DebugStrOffsets.html): The `.debug_str_offsets` section. +//! +//! * [`DebugTypes`](./struct.DebugTypes.html): The `.debug_types` section. +//! +//! * [`DebugCuIndex`](./struct.DebugCuIndex.html): The `.debug_cu_index` section. +//! +//! * [`DebugTuIndex`](./struct.DebugTuIndex.html): The `.debug_tu_index` section. +//! +//! * [`EhFrame`](./struct.EhFrame.html): The `.eh_frame` section. +//! +//! * [`EhFrameHdr`](./struct.EhFrameHdr.html): The `.eh_frame_hdr` section. +//! +//! * Each section type exposes methods for accessing the debugging data encoded +//! in that section. For example, the [`DebugInfo`](./struct.DebugInfo.html) +//! struct has the [`units`](./struct.DebugInfo.html#method.units) method for +//! iterating over the compilation units defined within it. +//! +//! * Offsets into a section are strongly typed: an offset into `.debug_info` is +//! the [`DebugInfoOffset`](./struct.DebugInfoOffset.html) type. It cannot be +//! used to index into the [`DebugLine`](./struct.DebugLine.html) type because +//! `DebugLine` represents the `.debug_line` section. There are similar types +//! for offsets relative to a compilation unit rather than a section. +//! +//! ## Using with `FallibleIterator` +//! +//! The standard library's `Iterator` trait and related APIs do not play well +//! with iterators where the `next` operation is fallible. One can make the +//! `Iterator`'s associated `Item` type be a `Result`, however the +//! provided methods cannot gracefully handle the case when an `Err` is +//! returned. +//! +//! This situation led to the +//! [`fallible-iterator`](https://crates.io/crates/fallible-iterator) crate's +//! existence. You can read more of the rationale for its existence in its +//! docs. The crate provides the helpers you have come to expect (eg `map`, +//! `filter`, etc) for iterators that can fail. +//! +//! `gimli`'s many lazy parsing iterators are a perfect match for the +//! `fallible-iterator` crate's `FallibleIterator` trait because parsing is not +//! done eagerly. Parse errors later in the input might only be discovered after +//! having iterated through many items. +//! +//! To use `gimli` iterators with `FallibleIterator`, import the crate and trait +//! into your code: +//! +//! ``` +//! # #[cfg(feature = "fallible-iterator")] +//! # fn foo() { +//! // Use the `FallibleIterator` trait so its methods are in scope! +//! use fallible_iterator::FallibleIterator; +//! use gimli::{DebugAranges, EndianSlice, LittleEndian}; +//! +//! fn find_sum_of_address_range_lengths(aranges: DebugAranges>) +//! -> gimli::Result +//! { +//! // `DebugAranges::headers` returns a `FallibleIterator`! +//! aranges.headers() +//! // `flat_map` is provided by `FallibleIterator`! +//! .flat_map(|header| Ok(header.entries())) +//! // `map` is provided by `FallibleIterator`! +//! .map(|arange| Ok(arange.length())) +//! // `fold` is provided by `FallibleIterator`! +//! .fold(0, |sum, len| Ok(sum + len)) +//! } +//! # } +//! # fn main() {} +//! ``` + +use core::fmt::{self, Debug}; +use core::result; +#[cfg(feature = "std")] +use std::{error, io}; + +use crate::common::{Register, SectionId}; +use crate::constants; + +mod util; +pub use util::*; + +mod addr; +pub use self::addr::*; + +mod cfi; +pub use self::cfi::*; + +#[cfg(feature = "read")] +mod dwarf; +#[cfg(feature = "read")] +pub use self::dwarf::*; + +mod endian_slice; +pub use self::endian_slice::*; + +#[cfg(feature = "endian-reader")] +mod endian_reader; +#[cfg(feature = "endian-reader")] +pub use self::endian_reader::*; + +mod reader; +pub use self::reader::*; + +mod relocate; +pub use self::relocate::*; + +#[cfg(feature = "read")] +mod abbrev; +#[cfg(feature = "read")] +pub use self::abbrev::*; + +mod aranges; +pub use self::aranges::*; + +mod index; +pub use self::index::*; + +#[cfg(feature = "read")] +mod line; +#[cfg(feature = "read")] +pub use self::line::*; + +mod lists; + +mod loclists; +pub use self::loclists::*; + +#[cfg(feature = "read")] +mod lookup; + +#[cfg(feature = "read")] +mod macros; +#[cfg(feature = "read")] +pub use self::macros::*; + +mod op; +pub use self::op::*; + +#[cfg(feature = "read")] +mod pubnames; +#[cfg(feature = "read")] +pub use self::pubnames::*; + +#[cfg(feature = "read")] +mod pubtypes; +#[cfg(feature = "read")] +pub use self::pubtypes::*; + +mod rnglists; +pub use self::rnglists::*; + +mod str; +pub use self::str::*; + +/// An offset into the current compilation or type unit. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub struct UnitOffset(pub T); + +#[cfg(feature = "read")] +mod unit; +#[cfg(feature = "read")] +pub use self::unit::*; + +mod value; +pub use self::value::*; + +/// Indicates that storage should be allocated on heap. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct StoreOnHeap; + +/// `EndianBuf` has been renamed to `EndianSlice`. For ease of upgrading across +/// `gimli` versions, we export this type alias. +#[deprecated(note = "EndianBuf has been renamed to EndianSlice, use that instead.")] +pub type EndianBuf<'input, Endian> = EndianSlice<'input, Endian>; + +/// An error that occurred when parsing. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// An I/O error occurred while reading. + Io, + /// Found a PC relative pointer, but the section base is undefined. + PcRelativePointerButSectionBaseIsUndefined, + /// Found a `.text` relative pointer, but the `.text` base is undefined. + TextRelativePointerButTextBaseIsUndefined, + /// Found a data relative pointer, but the data base is undefined. + DataRelativePointerButDataBaseIsUndefined, + /// Found a function relative pointer in a context that does not have a + /// function base. + FuncRelativePointerInBadContext, + /// Cannot parse a pointer with a `DW_EH_PE_omit` encoding. + CannotParseOmitPointerEncoding, + /// An error parsing an unsigned LEB128 value. + BadUnsignedLeb128, + /// An error parsing a signed LEB128 value. + BadSignedLeb128, + /// An abbreviation declared that its tag is zero, but zero is reserved for + /// null records. + AbbreviationTagZero, + /// An attribute specification declared that its form is zero, but zero is + /// reserved for null records. + AttributeFormZero, + /// The abbreviation's has-children byte was not one of + /// `DW_CHILDREN_{yes,no}`. + BadHasChildren, + /// The specified length is impossible. + BadLength, + /// Found an unknown `DW_FORM_*` type. + UnknownForm(constants::DwForm), + /// Expected a zero, found something else. + ExpectedZero, + /// Found an abbreviation code that has already been used. + DuplicateAbbreviationCode, + /// Found a duplicate arange. + DuplicateArange, + /// Found an unknown reserved length value. + UnknownReservedLength, + /// Found an unknown DWARF version. + UnknownVersion(u64), + /// Found a record with an unknown abbreviation code. + UnknownAbbreviation(u64), + /// Hit the end of input before it was expected. + UnexpectedEof(ReaderOffsetId), + /// Read a null entry before it was expected. + UnexpectedNull, + /// Found an unknown standard opcode. + UnknownStandardOpcode(constants::DwLns), + /// Found an unknown extended opcode. + UnknownExtendedOpcode(constants::DwLne), + /// Found an unknown location-lists format. + UnknownLocListsEntry(constants::DwLle), + /// Found an unknown range-lists format. + UnknownRangeListsEntry(constants::DwRle), + /// The specified address size is not supported. + UnsupportedAddressSize(u8), + /// The specified offset size is not supported. + UnsupportedOffsetSize(u8), + /// The specified field size is not supported. + UnsupportedFieldSize(u8), + /// The minimum instruction length must not be zero. + MinimumInstructionLengthZero, + /// The maximum operations per instruction must not be zero. + MaximumOperationsPerInstructionZero, + /// The line range must not be zero. + LineRangeZero, + /// The opcode base must not be zero. + OpcodeBaseZero, + /// Found an invalid UTF-8 string. + BadUtf8, + /// Expected to find the CIE ID, but found something else. + NotCieId, + /// Expected to find a pointer to a CIE, but found the CIE ID instead. + NotCiePointer, + /// Expected to find a pointer to an FDE, but found a CIE instead. + NotFdePointer, + /// Invalid branch target for a DW_OP_bra or DW_OP_skip. + BadBranchTarget(u64), + /// DW_OP_push_object_address used but no address passed in. + InvalidPushObjectAddress, + /// Not enough items on the stack when evaluating an expression. + NotEnoughStackItems, + /// Too many iterations to compute the expression. + TooManyIterations, + /// An unrecognized operation was found while parsing a DWARF + /// expression. + InvalidExpression(constants::DwOp), + /// An unsupported operation was found while evaluating a DWARF expression. + UnsupportedEvaluation, + /// The expression had a piece followed by an expression + /// terminator without a piece. + InvalidPiece, + /// An expression-terminating operation was followed by something + /// other than the end of the expression or a piece operation. + InvalidExpressionTerminator(u64), + /// Division or modulus by zero when evaluating an expression. + DivisionByZero, + /// An expression operation used mismatching types. + TypeMismatch, + /// An expression operation required an integral type but saw a + /// floating point type. + IntegralTypeRequired, + /// An expression operation used types that are not supported. + UnsupportedTypeOperation, + /// The shift value in an expression must be a non-negative integer. + InvalidShiftExpression, + /// The size of a deref expression must not be larger than the size of an address. + InvalidDerefSize(u8), + /// An unknown DW_CFA_* instruction. + UnknownCallFrameInstruction(constants::DwCfa), + /// The end of an address range was before the beginning. + InvalidAddressRange, + /// An address calculation overflowed. + /// + /// This is returned in cases where the address is expected to be + /// larger than a previous address, but the calculation overflowed. + AddressOverflow, + /// Encountered a call frame instruction in a context in which it is not + /// valid. + CfiInstructionInInvalidContext, + /// When evaluating call frame instructions, found a `DW_CFA_restore_state` + /// stack pop instruction, but the stack was empty, and had nothing to pop. + PopWithEmptyStack, + /// Do not have unwind info for the given address. + NoUnwindInfoForAddress, + /// An offset value was larger than the maximum supported value. + UnsupportedOffset, + /// The given pointer encoding is either unknown or invalid. + UnknownPointerEncoding(constants::DwEhPe), + /// Did not find an entry at the given offset. + NoEntryAtGivenOffset, + /// The given offset is out of bounds. + OffsetOutOfBounds, + /// Found an unknown CFI augmentation. + UnknownAugmentation, + /// We do not support the given pointer encoding yet. + UnsupportedPointerEncoding, + /// Registers larger than `u16` are not supported. + UnsupportedRegister(u64), + /// The CFI program defined more register rules than we have storage for. + TooManyRegisterRules, + /// Attempted to push onto the CFI or evaluation stack, but it was already + /// at full capacity. + StackFull, + /// The `.eh_frame_hdr` binary search table claims to be variable-length encoded, + /// which makes binary search impossible. + VariableLengthSearchTable, + /// The `DW_UT_*` value for this unit is not supported yet. + UnsupportedUnitType, + /// Ranges using AddressIndex are not supported yet. + UnsupportedAddressIndex, + /// Nonzero segment selector sizes aren't supported yet. + UnsupportedSegmentSize, + /// A compilation unit or type unit is missing its top level DIE. + MissingUnitDie, + /// A DIE attribute used an unsupported form. + UnsupportedAttributeForm, + /// Missing DW_LNCT_path in file entry format. + MissingFileEntryFormatPath, + /// Expected an attribute value to be a string form. + ExpectedStringAttributeValue, + /// `DW_FORM_implicit_const` used in an invalid context. + InvalidImplicitConst, + /// Invalid section count in `.dwp` index. + InvalidIndexSectionCount, + /// Invalid slot count in `.dwp` index. + InvalidIndexSlotCount, + /// Invalid hash row in `.dwp` index. + InvalidIndexRow, + /// Unknown section type in `.dwp` index. + UnknownIndexSection(constants::DwSect), + /// Unknown section type in version 2 `.dwp` index. + UnknownIndexSectionV2(constants::DwSectV2), + /// Invalid macinfo type in `.debug_macinfo`. + InvalidMacinfoType(constants::DwMacinfo), + /// Invalid macro type in `.debug_macro`. + InvalidMacroType(constants::DwMacro), + /// The optional `opcode_operands_table` in `.debug_macro` is currently not supported. + UnsupportedOpcodeOperandsTable, +} + +impl fmt::Display for Error { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> ::core::result::Result<(), fmt::Error> { + write!(f, "{}", self.description()) + } +} + +impl Error { + /// A short description of the error. + pub fn description(&self) -> &str { + match *self { + Error::Io => "An I/O error occurred while reading.", + Error::PcRelativePointerButSectionBaseIsUndefined => { + "Found a PC relative pointer, but the section base is undefined." + } + Error::TextRelativePointerButTextBaseIsUndefined => { + "Found a `.text` relative pointer, but the `.text` base is undefined." + } + Error::DataRelativePointerButDataBaseIsUndefined => { + "Found a data relative pointer, but the data base is undefined." + } + Error::FuncRelativePointerInBadContext => { + "Found a function relative pointer in a context that does not have a function base." + } + Error::CannotParseOmitPointerEncoding => { + "Cannot parse a pointer with a `DW_EH_PE_omit` encoding." + } + Error::BadUnsignedLeb128 => "An error parsing an unsigned LEB128 value", + Error::BadSignedLeb128 => "An error parsing a signed LEB128 value", + Error::AbbreviationTagZero => { + "An abbreviation declared that its tag is zero, + but zero is reserved for null records" + } + Error::AttributeFormZero => { + "An attribute specification declared that its form is zero, + but zero is reserved for null records" + } + Error::BadHasChildren => { + "The abbreviation's has-children byte was not one of + `DW_CHILDREN_{yes,no}`" + } + Error::BadLength => "The specified length is impossible", + Error::UnknownForm(_) => "Found an unknown `DW_FORM_*` type", + Error::ExpectedZero => "Expected a zero, found something else", + Error::DuplicateAbbreviationCode => { + "Found an abbreviation code that has already been used" + } + Error::DuplicateArange => "Found a duplicate arange", + Error::UnknownReservedLength => "Found an unknown reserved length value", + Error::UnknownVersion(_) => "Found an unknown DWARF version", + Error::UnknownAbbreviation(_) => "Found a record with an unknown abbreviation code", + Error::UnexpectedEof(_) => "Hit the end of input before it was expected", + Error::UnexpectedNull => "Read a null entry before it was expected.", + Error::UnknownStandardOpcode(_) => "Found an unknown standard opcode", + Error::UnknownExtendedOpcode(_) => "Found an unknown extended opcode", + Error::UnknownLocListsEntry(_) => "Found an unknown location lists entry", + Error::UnknownRangeListsEntry(_) => "Found an unknown range lists entry", + Error::UnsupportedAddressSize(_) => "The specified address size is not supported", + Error::UnsupportedOffsetSize(_) => "The specified offset size is not supported", + Error::UnsupportedFieldSize(_) => "The specified field size is not supported", + Error::MinimumInstructionLengthZero => { + "The minimum instruction length must not be zero." + } + Error::MaximumOperationsPerInstructionZero => { + "The maximum operations per instruction must not be zero." + } + Error::LineRangeZero => "The line range must not be zero.", + Error::OpcodeBaseZero => "The opcode base must not be zero.", + Error::BadUtf8 => "Found an invalid UTF-8 string.", + Error::NotCieId => "Expected to find the CIE ID, but found something else.", + Error::NotCiePointer => "Expected to find a CIE pointer, but found the CIE ID instead.", + Error::NotFdePointer => { + "Expected to find an FDE pointer, but found a CIE pointer instead." + } + Error::BadBranchTarget(_) => "Invalid branch target in DWARF expression", + Error::InvalidPushObjectAddress => { + "DW_OP_push_object_address used but no object address given" + } + Error::NotEnoughStackItems => "Not enough items on stack when evaluating expression", + Error::TooManyIterations => "Too many iterations to evaluate DWARF expression", + Error::InvalidExpression(_) => "Invalid opcode in DWARF expression", + Error::UnsupportedEvaluation => "Unsupported operation when evaluating expression", + Error::InvalidPiece => { + "DWARF expression has piece followed by non-piece expression at end" + } + Error::InvalidExpressionTerminator(_) => "Expected DW_OP_piece or DW_OP_bit_piece", + Error::DivisionByZero => "Division or modulus by zero when evaluating expression", + Error::TypeMismatch => "Type mismatch when evaluating expression", + Error::IntegralTypeRequired => "Integral type expected when evaluating expression", + Error::UnsupportedTypeOperation => { + "An expression operation used types that are not supported" + } + Error::InvalidShiftExpression => { + "The shift value in an expression must be a non-negative integer." + } + Error::InvalidDerefSize(_) => { + "The size of a deref expression must not be larger than the size of an address." + } + Error::UnknownCallFrameInstruction(_) => "An unknown DW_CFA_* instruction", + Error::InvalidAddressRange => { + "The end of an address range must not be before the beginning." + } + Error::AddressOverflow => "An address calculation overflowed.", + Error::CfiInstructionInInvalidContext => { + "Encountered a call frame instruction in a context in which it is not valid." + } + Error::PopWithEmptyStack => { + "When evaluating call frame instructions, found a `DW_CFA_restore_state` stack pop \ + instruction, but the stack was empty, and had nothing to pop." + } + Error::NoUnwindInfoForAddress => "Do not have unwind info for the given address.", + Error::UnsupportedOffset => { + "An offset value was larger than the maximum supported value." + } + Error::UnknownPointerEncoding(_) => { + "The given pointer encoding is either unknown or invalid." + } + Error::NoEntryAtGivenOffset => "Did not find an entry at the given offset.", + Error::OffsetOutOfBounds => "The given offset is out of bounds.", + Error::UnknownAugmentation => "Found an unknown CFI augmentation.", + Error::UnsupportedPointerEncoding => { + "We do not support the given pointer encoding yet." + } + Error::UnsupportedRegister(_) => "Registers larger than `u16` are not supported.", + Error::TooManyRegisterRules => { + "The CFI program defined more register rules than we have storage for." + } + Error::StackFull => { + "Attempted to push onto the CFI stack, but it was already at full capacity." + } + Error::VariableLengthSearchTable => { + "The `.eh_frame_hdr` binary search table claims to be variable-length encoded, \ + which makes binary search impossible." + } + Error::UnsupportedUnitType => "The `DW_UT_*` value for this unit is not supported yet", + Error::UnsupportedAddressIndex => "Ranges involving AddressIndex are not supported yet", + Error::UnsupportedSegmentSize => "Nonzero segment size not supported yet", + Error::MissingUnitDie => { + "A compilation unit or type unit is missing its top level DIE." + } + Error::UnsupportedAttributeForm => "A DIE attribute used an unsupported form.", + Error::MissingFileEntryFormatPath => "Missing DW_LNCT_path in file entry format.", + Error::ExpectedStringAttributeValue => { + "Expected an attribute value to be a string form." + } + Error::InvalidImplicitConst => "DW_FORM_implicit_const used in an invalid context.", + Error::InvalidIndexSectionCount => "Invalid section count in `.dwp` index.", + Error::InvalidIndexSlotCount => "Invalid slot count in `.dwp` index.", + Error::InvalidIndexRow => "Invalid hash row in `.dwp` index.", + Error::UnknownIndexSection(_) => "Unknown section type in `.dwp` index.", + Error::UnknownIndexSectionV2(_) => "Unknown section type in version 2 `.dwp` index.", + Error::InvalidMacinfoType(_) => "Invalid macinfo type in `.debug_macinfo`.", + Error::InvalidMacroType(_) => "Invalid macro type in `.debug_macro`.", + Error::UnsupportedOpcodeOperandsTable => { + "The optional `opcode_operands_table` in `.debug_macro` is currently not supported." + } + } + } +} + +#[cfg(feature = "std")] +impl error::Error for Error {} + +#[cfg(feature = "std")] +impl From for Error { + fn from(_: io::Error) -> Self { + Error::Io + } +} + +/// The result of a parse. +pub type Result = result::Result; + +/// A convenience trait for loading DWARF sections from object files. To be +/// used like: +/// +/// ``` +/// use gimli::{DebugInfo, EndianSlice, LittleEndian, Reader, Section}; +/// +/// let buf = [0x00, 0x01, 0x02, 0x03]; +/// let reader = EndianSlice::new(&buf, LittleEndian); +/// let loader = |name| -> Result<_, ()> { Ok(reader) }; +/// +/// let debug_info: DebugInfo<_> = Section::load(loader).unwrap(); +/// ``` +pub trait Section: From { + /// Returns the section id for this type. + fn id() -> SectionId; + + /// Returns the ELF section name for this type. + fn section_name() -> &'static str { + Self::id().name() + } + + /// Returns the ELF section name (if any) for this type when used in a dwo + /// file. + fn dwo_section_name() -> Option<&'static str> { + Self::id().dwo_name() + } + + /// Returns the XCOFF section name (if any) for this type when used in a XCOFF + /// file. + fn xcoff_section_name() -> Option<&'static str> { + Self::id().xcoff_name() + } + + /// Try to load the section using the given loader function. + fn load(f: F) -> core::result::Result + where + F: FnOnce(SectionId) -> core::result::Result, + { + f(Self::id()).map(From::from) + } + + /// Returns the `Reader` for this section. + fn reader(&self) -> &R + where + R: Reader; + + /// Returns the subrange of the section that is the contribution of + /// a unit in a `.dwp` file. + fn dwp_range(&self, offset: u32, size: u32) -> Result + where + R: Reader, + { + let mut data = self.reader().clone(); + data.skip(R::Offset::from_u32(offset))?; + data.truncate(R::Offset::from_u32(size))?; + Ok(data.into()) + } + + /// Returns the `Reader` for this section. + fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> + where + R: Reader, + { + self.reader() + .lookup_offset_id(id) + .map(|offset| (Self::id(), offset)) + } +} + +impl Register { + pub(crate) fn from_u64(x: u64) -> Result { + let y = x as u16; + if u64::from(y) == x { + Ok(Register(y)) + } else { + Err(Error::UnsupportedRegister(x)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::common::Format; + use crate::endianity::LittleEndian; + use test_assembler::{Endian, Section}; + + #[test] + fn test_parse_initial_length_32_ok() { + let section = Section::with_endian(Endian::Little).L32(0x7856_3412); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_initial_length() { + Ok((length, format)) => { + assert_eq!(input.len(), 0); + assert_eq!(format, Format::Dwarf32); + assert_eq!(0x7856_3412, length); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_parse_initial_length_64_ok() { + let section = Section::with_endian(Endian::Little) + // Dwarf_64_INITIAL_UNIT_LENGTH + .L32(0xffff_ffff) + // Actual length + .L64(0xffde_bc9a_7856_3412); + let buf = section.get_contents().unwrap(); + let input = &mut EndianSlice::new(&buf, LittleEndian); + + #[cfg(target_pointer_width = "64")] + match input.read_initial_length() { + Ok((length, format)) => { + assert_eq!(input.len(), 0); + assert_eq!(format, Format::Dwarf64); + assert_eq!(0xffde_bc9a_7856_3412, length); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + + #[cfg(target_pointer_width = "32")] + match input.read_initial_length() { + Err(Error::UnsupportedOffset) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_initial_length_unknown_reserved_value() { + let section = Section::with_endian(Endian::Little).L32(0xffff_fffe); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_initial_length() { + Err(Error::UnknownReservedLength) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_initial_length_incomplete() { + let buf = [0xff, 0xff, 0xff]; // Need at least 4 bytes. + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_initial_length() { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_initial_length_64_incomplete() { + let section = Section::with_endian(Endian::Little) + // Dwarf_64_INITIAL_UNIT_LENGTH + .L32(0xffff_ffff) + // Actual length is not long enough. + .L32(0x7856_3412); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_initial_length() { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_offset_32() { + let section = Section::with_endian(Endian::Little).L32(0x0123_4567); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_offset(Format::Dwarf32) { + Ok(val) => { + assert_eq!(input.len(), 0); + assert_eq!(val, 0x0123_4567); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_offset_64_small() { + let section = Section::with_endian(Endian::Little).L64(0x0123_4567); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_offset(Format::Dwarf64) { + Ok(val) => { + assert_eq!(input.len(), 0); + assert_eq!(val, 0x0123_4567); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_offset_64_large() { + let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_offset(Format::Dwarf64) { + Ok(val) => { + assert_eq!(input.len(), 0); + assert_eq!(val, 0x0123_4567_89ab_cdef); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + #[cfg(target_pointer_width = "32")] + fn test_parse_offset_64_large() { + let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef); + let buf = section.get_contents().unwrap(); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + match input.read_offset(Format::Dwarf64) { + Err(Error::UnsupportedOffset) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } +} diff --git a/anneal/v2/vendor/gimli/src/read/op.rs b/anneal/v2/vendor/gimli/src/read/op.rs new file mode 100644 index 0000000000..0f9261a059 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/op.rs @@ -0,0 +1,4182 @@ +//! Functions for parsing and evaluating DWARF expressions. + +#[cfg(feature = "read")] +use alloc::vec::Vec; +use core::mem; + +use super::util::{ArrayLike, ArrayVec}; +use crate::common::{DebugAddrIndex, DebugInfoOffset, Encoding, Register}; +use crate::constants; +use crate::read::{Error, Reader, ReaderOffset, Result, StoreOnHeap, UnitOffset, Value, ValueType}; + +/// A reference to a DIE, either relative to the current CU or +/// relative to the section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DieReference { + /// A CU-relative reference. + UnitRef(UnitOffset), + /// A section-relative reference. + DebugInfoRef(DebugInfoOffset), +} + +/// A single decoded DWARF expression operation. +/// +/// DWARF expression evaluation is done in two parts: first the raw +/// bytes of the next part of the expression are decoded; and then the +/// decoded operation is evaluated. This approach lets other +/// consumers inspect the DWARF expression without reimplementing the +/// decoding operation. +/// +/// Multiple DWARF opcodes may decode into a single `Operation`. For +/// example, both `DW_OP_deref` and `DW_OP_xderef` are represented +/// using `Operation::Deref`. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Operation::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// Dereference the topmost value of the stack. + Deref { + /// The DIE of the base type or 0 to indicate the generic type + base_type: UnitOffset, + /// The size of the data to dereference. + size: u8, + /// True if the dereference operation takes an address space + /// argument from the stack; false otherwise. + space: bool, + }, + /// Drop an item from the stack. + Drop, + /// Pick an item from the stack and push it on top of the stack. + /// This operation handles `DW_OP_pick`, `DW_OP_dup`, and + /// `DW_OP_over`. + Pick { + /// The index, from the top of the stack, of the item to copy. + index: u8, + }, + /// Swap the top two stack items. + Swap, + /// Rotate the top three stack items. + Rot, + /// Take the absolute value of the top of the stack. + Abs, + /// Bitwise `and` of the top two values on the stack. + And, + /// Divide the top two values on the stack. + Div, + /// Subtract the top two values on the stack. + Minus, + /// Modulus of the top two values on the stack. + Mod, + /// Multiply the top two values on the stack. + Mul, + /// Negate the top of the stack. + Neg, + /// Bitwise `not` of the top of the stack. + Not, + /// Bitwise `or` of the top two values on the stack. + Or, + /// Add the top two values on the stack. + Plus, + /// Add a constant to the topmost value on the stack. + PlusConstant { + /// The value to add. + value: u64, + }, + /// Logical left shift of the 2nd value on the stack by the number + /// of bits given by the topmost value on the stack. + Shl, + /// Right shift of the 2nd value on the stack by the number of + /// bits given by the topmost value on the stack. + Shr, + /// Arithmetic left shift of the 2nd value on the stack by the + /// number of bits given by the topmost value on the stack. + Shra, + /// Bitwise `xor` of the top two values on the stack. + Xor, + /// Branch to the target location if the top of stack is nonzero. + Bra { + /// The relative offset to the target bytecode. + target: i16, + }, + /// Compare the top two stack values for equality. + Eq, + /// Compare the top two stack values using `>=`. + Ge, + /// Compare the top two stack values using `>`. + Gt, + /// Compare the top two stack values using `<=`. + Le, + /// Compare the top two stack values using `<`. + Lt, + /// Compare the top two stack values using `!=`. + Ne, + /// Unconditional branch to the target location. + Skip { + /// The relative offset to the target bytecode. + target: i16, + }, + /// Push an unsigned constant value on the stack. This handles multiple + /// DWARF opcodes. + UnsignedConstant { + /// The value to push. + value: u64, + }, + /// Push a signed constant value on the stack. This handles multiple + /// DWARF opcodes. + SignedConstant { + /// The value to push. + value: i64, + }, + /// Indicate that this piece's location is in the given register. + /// + /// Completes the piece or expression. + Register { + /// The register number. + register: Register, + }, + /// Find the value of the given register, add the offset, and then + /// push the resulting sum on the stack. + RegisterOffset { + /// The register number. + register: Register, + /// The offset to add. + offset: i64, + /// The DIE of the base type or 0 to indicate the generic type + base_type: UnitOffset, + }, + /// Compute the frame base (using `DW_AT_frame_base`), add the + /// given offset, and then push the resulting sum on the stack. + FrameOffset { + /// The offset to add. + offset: i64, + }, + /// No operation. + Nop, + /// Push the object address on the stack. + PushObjectAddress, + /// Evaluate a DWARF expression as a subroutine. The expression + /// comes from the `DW_AT_location` attribute of the indicated + /// DIE. + Call { + /// The DIE to use. + offset: DieReference, + }, + /// Compute the address of a thread-local variable and push it on + /// the stack. + TLS, + /// Compute the call frame CFA and push it on the stack. + CallFrameCFA, + /// Terminate a piece. + Piece { + /// The size of this piece in bits. + size_in_bits: u64, + /// The bit offset of this piece. If `None`, then this piece + /// was specified using `DW_OP_piece` and should start at the + /// next byte boundary. + bit_offset: Option, + }, + /// The object has no location, but has a known constant value. + /// + /// Represents `DW_OP_implicit_value`. + /// Completes the piece or expression. + ImplicitValue { + /// The implicit value to use. + data: R, + }, + /// The object has no location, but its value is at the top of the stack. + /// + /// Represents `DW_OP_stack_value`. + /// Completes the piece or expression. + StackValue, + /// The object is a pointer to a value which has no actual location, + /// such as an implicit value or a stack value. + /// + /// Represents `DW_OP_implicit_pointer`. + /// Completes the piece or expression. + ImplicitPointer { + /// The `.debug_info` offset of the value that this is an implicit pointer into. + value: DebugInfoOffset, + /// The byte offset into the value that the implicit pointer points to. + byte_offset: i64, + }, + /// Evaluate an expression at the entry to the current subprogram, and push it on the stack. + /// + /// Represents `DW_OP_entry_value`. + EntryValue { + /// The expression to be evaluated. + expression: R, + }, + /// This represents a parameter that was optimized out. + /// + /// The offset points to the definition of the parameter, and is + /// matched to the `DW_TAG_GNU_call_site_parameter` in the caller that also + /// points to the same definition of the parameter. + /// + /// Represents `DW_OP_GNU_parameter_ref`. + ParameterRef { + /// The DIE to use. + offset: UnitOffset, + }, + /// Relocate the address if needed, and push it on the stack. + /// + /// Represents `DW_OP_addr`. + Address { + /// The offset to add. + address: u64, + }, + /// Read the address at the given index in `.debug_addr, relocate the address if needed, + /// and push it on the stack. + /// + /// Represents `DW_OP_addrx`. + AddressIndex { + /// The index of the address in `.debug_addr`. + index: DebugAddrIndex, + }, + /// Read the address at the given index in `.debug_addr, and push it on the stack. + /// Do not relocate the address. + /// + /// Represents `DW_OP_constx`. + ConstantIndex { + /// The index of the address in `.debug_addr`. + index: DebugAddrIndex, + }, + /// Interpret the value bytes as a constant of a given type, and push it on the stack. + /// + /// Represents `DW_OP_const_type`. + TypedLiteral { + /// The DIE of the base type. + base_type: UnitOffset, + /// The value bytes. + value: R, + }, + /// Pop the top stack entry, convert it to a different type, and push it on the stack. + /// + /// Represents `DW_OP_convert`. + Convert { + /// The DIE of the base type. + base_type: UnitOffset, + }, + /// Pop the top stack entry, reinterpret the bits in its value as a different type, + /// and push it on the stack. + /// + /// Represents `DW_OP_reinterpret`. + Reinterpret { + /// The DIE of the base type. + base_type: UnitOffset, + }, + /// The index of a local in the currently executing function. + /// + /// Represents `DW_OP_WASM_location 0x00`. + /// Completes the piece or expression. + WasmLocal { + /// The index of the local. + index: u32, + }, + /// The index of a global. + /// + /// Represents `DW_OP_WASM_location 0x01` or `DW_OP_WASM_location 0x03`. + /// Completes the piece or expression. + WasmGlobal { + /// The index of the global. + index: u32, + }, + /// The index of an item on the operand stack. + /// + /// Represents `DW_OP_WASM_location 0x02`. + /// Completes the piece or expression. + WasmStack { + /// The index of the stack item. 0 is the bottom of the operand stack. + index: u32, + }, +} + +#[derive(Debug)] +enum OperationEvaluationResult { + Piece, + Incomplete, + Complete { location: Location }, + Waiting(EvaluationWaiting, EvaluationResult), +} + +/// A single location of a piece of the result of a DWARF expression. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Location::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// The piece is empty. Ordinarily this means the piece has been + /// optimized away. + Empty, + /// The piece is found in a register. + Register { + /// The register number. + register: Register, + }, + /// The piece is found in memory. + Address { + /// The address. + address: u64, + }, + /// The piece has no location but its value is known. + Value { + /// The value. + value: Value, + }, + /// The piece is represented by some constant bytes. + Bytes { + /// The value. + value: R, + }, + /// The piece is a pointer to a value which has no actual location. + ImplicitPointer { + /// The `.debug_info` offset of the value that this is an implicit pointer into. + value: DebugInfoOffset, + /// The byte offset into the value that the implicit pointer points to. + byte_offset: i64, + }, +} + +impl Location +where + R: Reader, + Offset: ReaderOffset, +{ + /// Return true if the piece is empty. + pub fn is_empty(&self) -> bool { + matches!(*self, Location::Empty) + } +} + +/// The description of a single piece of the result of a DWARF +/// expression. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Piece::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// If given, the size of the piece in bits. If `None`, there + /// must be only one piece whose size is all of the object. + pub size_in_bits: Option, + /// If given, the bit offset of the piece within the location. + /// If the location is a `Location::Register` or `Location::Value`, + /// then this offset is from the least significant bit end of + /// the register or value. + /// If the location is a `Location::Address` then the offset uses + /// the bit numbering and direction conventions of the language + /// and target system. + /// + /// If `None`, the piece starts at the location. If the + /// location is a register whose size is larger than the piece, + /// then placement within the register is defined by the ABI. + pub bit_offset: Option, + /// Where this piece is to be found. + pub location: Location, +} + +// A helper function to handle branch offsets. +fn compute_pc(pc: &R, bytecode: &R, offset: i16) -> Result { + let pc_offset = pc.offset_from(bytecode); + let new_pc_offset = pc_offset.wrapping_add(R::Offset::from_i16(offset)); + if new_pc_offset > bytecode.len() { + Err(Error::BadBranchTarget(new_pc_offset.into_u64())) + } else { + let mut new_pc = bytecode.clone(); + new_pc.skip(new_pc_offset)?; + Ok(new_pc) + } +} + +fn generic_type() -> UnitOffset { + UnitOffset(O::from_u64(0).unwrap()) +} + +impl Operation +where + R: Reader, + Offset: ReaderOffset, +{ + /// Parse a single DWARF expression operation. + /// + /// This is useful when examining a DWARF expression for reasons other + /// than direct evaluation. + /// + /// `bytes` points to a the operation to decode. It should point into + /// the same array as `bytecode`, which should be the entire + /// expression. + pub fn parse(bytes: &mut R, encoding: Encoding) -> Result> { + let opcode = bytes.read_u8()?; + let name = constants::DwOp(opcode); + match name { + constants::DW_OP_addr => { + let address = bytes.read_address(encoding.address_size)?; + Ok(Operation::Address { address }) + } + constants::DW_OP_deref => Ok(Operation::Deref { + base_type: generic_type(), + size: encoding.address_size, + space: false, + }), + constants::DW_OP_const1u => { + let value = bytes.read_u8()?; + Ok(Operation::UnsignedConstant { + value: u64::from(value), + }) + } + constants::DW_OP_const1s => { + let value = bytes.read_i8()?; + Ok(Operation::SignedConstant { + value: i64::from(value), + }) + } + constants::DW_OP_const2u => { + let value = bytes.read_u16()?; + Ok(Operation::UnsignedConstant { + value: u64::from(value), + }) + } + constants::DW_OP_const2s => { + let value = bytes.read_i16()?; + Ok(Operation::SignedConstant { + value: i64::from(value), + }) + } + constants::DW_OP_const4u => { + let value = bytes.read_u32()?; + Ok(Operation::UnsignedConstant { + value: u64::from(value), + }) + } + constants::DW_OP_const4s => { + let value = bytes.read_i32()?; + Ok(Operation::SignedConstant { + value: i64::from(value), + }) + } + constants::DW_OP_const8u => { + let value = bytes.read_u64()?; + Ok(Operation::UnsignedConstant { value }) + } + constants::DW_OP_const8s => { + let value = bytes.read_i64()?; + Ok(Operation::SignedConstant { value }) + } + constants::DW_OP_constu => { + let value = bytes.read_uleb128()?; + Ok(Operation::UnsignedConstant { value }) + } + constants::DW_OP_consts => { + let value = bytes.read_sleb128()?; + Ok(Operation::SignedConstant { value }) + } + constants::DW_OP_dup => Ok(Operation::Pick { index: 0 }), + constants::DW_OP_drop => Ok(Operation::Drop), + constants::DW_OP_over => Ok(Operation::Pick { index: 1 }), + constants::DW_OP_pick => { + let value = bytes.read_u8()?; + Ok(Operation::Pick { index: value }) + } + constants::DW_OP_swap => Ok(Operation::Swap), + constants::DW_OP_rot => Ok(Operation::Rot), + constants::DW_OP_xderef => Ok(Operation::Deref { + base_type: generic_type(), + size: encoding.address_size, + space: true, + }), + constants::DW_OP_abs => Ok(Operation::Abs), + constants::DW_OP_and => Ok(Operation::And), + constants::DW_OP_div => Ok(Operation::Div), + constants::DW_OP_minus => Ok(Operation::Minus), + constants::DW_OP_mod => Ok(Operation::Mod), + constants::DW_OP_mul => Ok(Operation::Mul), + constants::DW_OP_neg => Ok(Operation::Neg), + constants::DW_OP_not => Ok(Operation::Not), + constants::DW_OP_or => Ok(Operation::Or), + constants::DW_OP_plus => Ok(Operation::Plus), + constants::DW_OP_plus_uconst => { + let value = bytes.read_uleb128()?; + Ok(Operation::PlusConstant { value }) + } + constants::DW_OP_shl => Ok(Operation::Shl), + constants::DW_OP_shr => Ok(Operation::Shr), + constants::DW_OP_shra => Ok(Operation::Shra), + constants::DW_OP_xor => Ok(Operation::Xor), + constants::DW_OP_bra => { + let target = bytes.read_i16()?; + Ok(Operation::Bra { target }) + } + constants::DW_OP_eq => Ok(Operation::Eq), + constants::DW_OP_ge => Ok(Operation::Ge), + constants::DW_OP_gt => Ok(Operation::Gt), + constants::DW_OP_le => Ok(Operation::Le), + constants::DW_OP_lt => Ok(Operation::Lt), + constants::DW_OP_ne => Ok(Operation::Ne), + constants::DW_OP_skip => { + let target = bytes.read_i16()?; + Ok(Operation::Skip { target }) + } + constants::DW_OP_lit0 + | constants::DW_OP_lit1 + | constants::DW_OP_lit2 + | constants::DW_OP_lit3 + | constants::DW_OP_lit4 + | constants::DW_OP_lit5 + | constants::DW_OP_lit6 + | constants::DW_OP_lit7 + | constants::DW_OP_lit8 + | constants::DW_OP_lit9 + | constants::DW_OP_lit10 + | constants::DW_OP_lit11 + | constants::DW_OP_lit12 + | constants::DW_OP_lit13 + | constants::DW_OP_lit14 + | constants::DW_OP_lit15 + | constants::DW_OP_lit16 + | constants::DW_OP_lit17 + | constants::DW_OP_lit18 + | constants::DW_OP_lit19 + | constants::DW_OP_lit20 + | constants::DW_OP_lit21 + | constants::DW_OP_lit22 + | constants::DW_OP_lit23 + | constants::DW_OP_lit24 + | constants::DW_OP_lit25 + | constants::DW_OP_lit26 + | constants::DW_OP_lit27 + | constants::DW_OP_lit28 + | constants::DW_OP_lit29 + | constants::DW_OP_lit30 + | constants::DW_OP_lit31 => Ok(Operation::UnsignedConstant { + value: (opcode - constants::DW_OP_lit0.0).into(), + }), + constants::DW_OP_reg0 + | constants::DW_OP_reg1 + | constants::DW_OP_reg2 + | constants::DW_OP_reg3 + | constants::DW_OP_reg4 + | constants::DW_OP_reg5 + | constants::DW_OP_reg6 + | constants::DW_OP_reg7 + | constants::DW_OP_reg8 + | constants::DW_OP_reg9 + | constants::DW_OP_reg10 + | constants::DW_OP_reg11 + | constants::DW_OP_reg12 + | constants::DW_OP_reg13 + | constants::DW_OP_reg14 + | constants::DW_OP_reg15 + | constants::DW_OP_reg16 + | constants::DW_OP_reg17 + | constants::DW_OP_reg18 + | constants::DW_OP_reg19 + | constants::DW_OP_reg20 + | constants::DW_OP_reg21 + | constants::DW_OP_reg22 + | constants::DW_OP_reg23 + | constants::DW_OP_reg24 + | constants::DW_OP_reg25 + | constants::DW_OP_reg26 + | constants::DW_OP_reg27 + | constants::DW_OP_reg28 + | constants::DW_OP_reg29 + | constants::DW_OP_reg30 + | constants::DW_OP_reg31 => Ok(Operation::Register { + register: Register((opcode - constants::DW_OP_reg0.0).into()), + }), + constants::DW_OP_breg0 + | constants::DW_OP_breg1 + | constants::DW_OP_breg2 + | constants::DW_OP_breg3 + | constants::DW_OP_breg4 + | constants::DW_OP_breg5 + | constants::DW_OP_breg6 + | constants::DW_OP_breg7 + | constants::DW_OP_breg8 + | constants::DW_OP_breg9 + | constants::DW_OP_breg10 + | constants::DW_OP_breg11 + | constants::DW_OP_breg12 + | constants::DW_OP_breg13 + | constants::DW_OP_breg14 + | constants::DW_OP_breg15 + | constants::DW_OP_breg16 + | constants::DW_OP_breg17 + | constants::DW_OP_breg18 + | constants::DW_OP_breg19 + | constants::DW_OP_breg20 + | constants::DW_OP_breg21 + | constants::DW_OP_breg22 + | constants::DW_OP_breg23 + | constants::DW_OP_breg24 + | constants::DW_OP_breg25 + | constants::DW_OP_breg26 + | constants::DW_OP_breg27 + | constants::DW_OP_breg28 + | constants::DW_OP_breg29 + | constants::DW_OP_breg30 + | constants::DW_OP_breg31 => { + let value = bytes.read_sleb128()?; + Ok(Operation::RegisterOffset { + register: Register((opcode - constants::DW_OP_breg0.0).into()), + offset: value, + base_type: generic_type(), + }) + } + constants::DW_OP_regx => { + let register = bytes.read_uleb128().and_then(Register::from_u64)?; + Ok(Operation::Register { register }) + } + constants::DW_OP_fbreg => { + let value = bytes.read_sleb128()?; + Ok(Operation::FrameOffset { offset: value }) + } + constants::DW_OP_bregx => { + let register = bytes.read_uleb128().and_then(Register::from_u64)?; + let offset = bytes.read_sleb128()?; + Ok(Operation::RegisterOffset { + register, + offset, + base_type: generic_type(), + }) + } + constants::DW_OP_piece => { + let size = bytes.read_uleb128()?; + Ok(Operation::Piece { + size_in_bits: 8 * size, + bit_offset: None, + }) + } + constants::DW_OP_deref_size => { + let size = bytes.read_u8()?; + Ok(Operation::Deref { + base_type: generic_type(), + size, + space: false, + }) + } + constants::DW_OP_xderef_size => { + let size = bytes.read_u8()?; + Ok(Operation::Deref { + base_type: generic_type(), + size, + space: true, + }) + } + constants::DW_OP_nop => Ok(Operation::Nop), + constants::DW_OP_push_object_address => Ok(Operation::PushObjectAddress), + constants::DW_OP_call2 => { + let value = bytes.read_u16().map(R::Offset::from_u16)?; + Ok(Operation::Call { + offset: DieReference::UnitRef(UnitOffset(value)), + }) + } + constants::DW_OP_call4 => { + let value = bytes.read_u32().map(R::Offset::from_u32)?; + Ok(Operation::Call { + offset: DieReference::UnitRef(UnitOffset(value)), + }) + } + constants::DW_OP_call_ref => { + let value = bytes.read_offset(encoding.format)?; + Ok(Operation::Call { + offset: DieReference::DebugInfoRef(DebugInfoOffset(value)), + }) + } + constants::DW_OP_form_tls_address | constants::DW_OP_GNU_push_tls_address => { + Ok(Operation::TLS) + } + constants::DW_OP_call_frame_cfa => Ok(Operation::CallFrameCFA), + constants::DW_OP_bit_piece => { + let size = bytes.read_uleb128()?; + let offset = bytes.read_uleb128()?; + Ok(Operation::Piece { + size_in_bits: size, + bit_offset: Some(offset), + }) + } + constants::DW_OP_implicit_value => { + let len = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + let data = bytes.split(len)?; + Ok(Operation::ImplicitValue { data }) + } + constants::DW_OP_stack_value => Ok(Operation::StackValue), + constants::DW_OP_implicit_pointer | constants::DW_OP_GNU_implicit_pointer => { + let value = if encoding.version == 2 { + bytes + .read_address(encoding.address_size) + .and_then(Offset::from_u64)? + } else { + bytes.read_offset(encoding.format)? + }; + let byte_offset = bytes.read_sleb128()?; + Ok(Operation::ImplicitPointer { + value: DebugInfoOffset(value), + byte_offset, + }) + } + constants::DW_OP_addrx | constants::DW_OP_GNU_addr_index => { + let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::AddressIndex { + index: DebugAddrIndex(index), + }) + } + constants::DW_OP_constx | constants::DW_OP_GNU_const_index => { + let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::ConstantIndex { + index: DebugAddrIndex(index), + }) + } + constants::DW_OP_entry_value | constants::DW_OP_GNU_entry_value => { + let len = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + let expression = bytes.split(len)?; + Ok(Operation::EntryValue { expression }) + } + constants::DW_OP_GNU_parameter_ref => { + let value = bytes.read_u32().map(R::Offset::from_u32)?; + Ok(Operation::ParameterRef { + offset: UnitOffset(value), + }) + } + constants::DW_OP_const_type | constants::DW_OP_GNU_const_type => { + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + let len = bytes.read_u8()?; + let value = bytes.split(R::Offset::from_u8(len))?; + Ok(Operation::TypedLiteral { + base_type: UnitOffset(base_type), + value, + }) + } + constants::DW_OP_regval_type | constants::DW_OP_GNU_regval_type => { + let register = bytes.read_uleb128().and_then(Register::from_u64)?; + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::RegisterOffset { + register, + offset: 0, + base_type: UnitOffset(base_type), + }) + } + constants::DW_OP_deref_type | constants::DW_OP_GNU_deref_type => { + let size = bytes.read_u8()?; + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::Deref { + base_type: UnitOffset(base_type), + size, + space: false, + }) + } + constants::DW_OP_xderef_type => { + let size = bytes.read_u8()?; + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::Deref { + base_type: UnitOffset(base_type), + size, + space: true, + }) + } + constants::DW_OP_convert | constants::DW_OP_GNU_convert => { + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::Convert { + base_type: UnitOffset(base_type), + }) + } + constants::DW_OP_reinterpret | constants::DW_OP_GNU_reinterpret => { + let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?; + Ok(Operation::Reinterpret { + base_type: UnitOffset(base_type), + }) + } + constants::DW_OP_WASM_location => match bytes.read_u8()? { + 0x0 => { + let index = bytes.read_uleb128_u32()?; + Ok(Operation::WasmLocal { index }) + } + 0x1 => { + let index = bytes.read_uleb128_u32()?; + Ok(Operation::WasmGlobal { index }) + } + 0x2 => { + let index = bytes.read_uleb128_u32()?; + Ok(Operation::WasmStack { index }) + } + 0x3 => { + let index = bytes.read_u32()?; + Ok(Operation::WasmGlobal { index }) + } + _ => Err(Error::InvalidExpression(name)), + }, + _ => Err(Error::InvalidExpression(name)), + } + } +} + +#[derive(Debug)] +enum EvaluationState { + Start(Option), + Ready, + Error(Error), + Complete, + Waiting(EvaluationWaiting), +} + +#[derive(Debug)] +enum EvaluationWaiting { + Memory, + Register { offset: i64 }, + FrameBase { offset: i64 }, + Tls, + Cfa, + AtLocation, + EntryValue, + ParameterRef, + RelocatedAddress, + IndexedAddress, + TypedLiteral { value: R }, + Convert, + Reinterpret, +} + +/// The state of an `Evaluation` after evaluating a DWARF expression. +/// The evaluation is either `Complete`, or it requires more data +/// to continue, as described by the variant. +#[derive(Debug, PartialEq)] +pub enum EvaluationResult { + /// The `Evaluation` is complete, and `Evaluation::result()` can be called. + Complete, + /// The `Evaluation` needs a value from memory to proceed further. Once the + /// caller determines what value to provide it should resume the `Evaluation` + /// by calling `Evaluation::resume_with_memory`. + RequiresMemory { + /// The address of the value required. + address: u64, + /// The size of the value required. This is guaranteed to be at most the + /// word size of the target architecture. + size: u8, + /// If not `None`, a target-specific address space value. + space: Option, + /// The DIE of the base type or 0 to indicate the generic type + base_type: UnitOffset, + }, + /// The `Evaluation` needs a value from a register to proceed further. Once + /// the caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_register`. + RequiresRegister { + /// The register number. + register: Register, + /// The DIE of the base type or 0 to indicate the generic type + base_type: UnitOffset, + }, + /// The `Evaluation` needs the frame base address to proceed further. Once + /// the caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_frame_base`. The frame + /// base address is the address produced by the location description in the + /// `DW_AT_frame_base` attribute of the current function. + RequiresFrameBase, + /// The `Evaluation` needs a value from TLS to proceed further. Once the + /// caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_tls`. + RequiresTls(u64), + /// The `Evaluation` needs the CFA to proceed further. Once the caller + /// determines what value to provide it should resume the `Evaluation` by + /// calling `Evaluation::resume_with_call_frame_cfa`. + RequiresCallFrameCfa, + /// The `Evaluation` needs the DWARF expression at the given location to + /// proceed further. Once the caller determines what value to provide it + /// should resume the `Evaluation` by calling + /// `Evaluation::resume_with_at_location`. + RequiresAtLocation(DieReference), + /// The `Evaluation` needs the value produced by evaluating a DWARF + /// expression at the entry point of the current subprogram. Once the + /// caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_entry_value`. + RequiresEntryValue(Expression), + /// The `Evaluation` needs the value of the parameter at the given location + /// in the current function's caller. Once the caller determines what value + /// to provide it should resume the `Evaluation` by calling + /// `Evaluation::resume_with_parameter_ref`. + RequiresParameterRef(UnitOffset), + /// The `Evaluation` needs an address to be relocated to proceed further. + /// Once the caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_relocated_address`. + RequiresRelocatedAddress(u64), + /// The `Evaluation` needs an address from the `.debug_addr` section. + /// This address may also need to be relocated. + /// Once the caller determines what value to provide it should resume the + /// `Evaluation` by calling `Evaluation::resume_with_indexed_address`. + RequiresIndexedAddress { + /// The index of the address in the `.debug_addr` section, + /// relative to the `DW_AT_addr_base` of the compilation unit. + index: DebugAddrIndex, + /// Whether the address also needs to be relocated. + relocate: bool, + }, + /// The `Evaluation` needs the `ValueType` for the base type DIE at + /// the give unit offset. Once the caller determines what value to provide it + /// should resume the `Evaluation` by calling + /// `Evaluation::resume_with_base_type`. + RequiresBaseType(UnitOffset), +} + +/// The bytecode for a DWARF expression or location description. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Expression(pub R); + +impl Expression { + /// Create an evaluation for this expression. + /// + /// The `encoding` is determined by the + /// [`CompilationUnitHeader`](struct.CompilationUnitHeader.html) or + /// [`TypeUnitHeader`](struct.TypeUnitHeader.html) that this expression + /// relates to. + /// + /// # Examples + /// ```rust,no_run + /// use gimli::Expression; + /// # let endian = gimli::LittleEndian; + /// # let debug_info = gimli::DebugInfo::from(gimli::EndianSlice::new(&[], endian)); + /// # let unit = debug_info.units().next().unwrap().unwrap(); + /// # let bytecode = gimli::EndianSlice::new(&[], endian); + /// let expression = gimli::Expression(bytecode); + /// let mut eval = expression.evaluation(unit.encoding()); + /// let mut result = eval.evaluate().unwrap(); + /// ``` + #[cfg(feature = "read")] + #[inline] + pub fn evaluation(self, encoding: Encoding) -> Evaluation { + Evaluation::new(self.0, encoding) + } + + /// Return an iterator for the operations in the expression. + pub fn operations(self, encoding: Encoding) -> OperationIter { + OperationIter { + input: self.0, + encoding, + } + } +} + +/// An iterator for the operations in an expression. +#[derive(Debug, Clone, Copy)] +pub struct OperationIter { + input: R, + encoding: Encoding, +} + +impl OperationIter { + /// Read the next operation in an expression. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + match Operation::parse(&mut self.input, self.encoding) { + Ok(op) => Ok(Some(op)), + Err(e) => { + self.input.empty(); + Err(e) + } + } + } + + /// Return the current byte offset of the iterator. + pub fn offset_from(&self, expression: &Expression) -> R::Offset { + self.input.offset_from(&expression.0) + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for OperationIter { + type Item = Operation; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + OperationIter::next(self) + } +} + +/// Specification of what storage should be used for [`Evaluation`]. +/// +#[cfg_attr( + feature = "read", + doc = " +Normally you would only need to use [`StoreOnHeap`], which places the stacks and the results +on the heap using [`Vec`]. This is the default storage type parameter for [`Evaluation`]. +" +)] +/// +/// If you need to avoid [`Evaluation`] from allocating memory, e.g. for signal safety, +/// you can provide you own storage specification: +/// ```rust,no_run +/// # use gimli::*; +/// # let bytecode = EndianSlice::new(&[], LittleEndian); +/// # let encoding = unimplemented!(); +/// # let get_register_value = |_, _| Value::Generic(42); +/// # let get_frame_base = || 0xdeadbeef; +/// # +/// struct StoreOnStack; +/// +/// impl EvaluationStorage for StoreOnStack { +/// type Stack = [Value; 64]; +/// type ExpressionStack = [(R, R); 4]; +/// type Result = [Piece; 1]; +/// } +/// +/// let mut eval = Evaluation::<_, StoreOnStack>::new_in(bytecode, encoding); +/// let mut result = eval.evaluate().unwrap(); +/// while result != EvaluationResult::Complete { +/// match result { +/// EvaluationResult::RequiresRegister { register, base_type } => { +/// let value = get_register_value(register, base_type); +/// result = eval.resume_with_register(value).unwrap(); +/// }, +/// EvaluationResult::RequiresFrameBase => { +/// let frame_base = get_frame_base(); +/// result = eval.resume_with_frame_base(frame_base).unwrap(); +/// }, +/// _ => unimplemented!(), +/// }; +/// } +/// +/// let result = eval.as_result(); +/// println!("{:?}", result); +/// ``` +pub trait EvaluationStorage { + /// The storage used for the evaluation stack. + type Stack: ArrayLike; + /// The storage used for the expression stack. + type ExpressionStack: ArrayLike; + /// The storage used for the results. + type Result: ArrayLike>; +} + +#[cfg(feature = "read")] +impl EvaluationStorage for StoreOnHeap { + type Stack = Vec; + type ExpressionStack = Vec<(R, R)>; + type Result = Vec>; +} + +/// A DWARF expression evaluator. +/// +/// # Usage +/// A DWARF expression may require additional data to produce a final result, +/// such as the value of a register or a memory location. Once initial setup +/// is complete (i.e. `set_initial_value()`, `set_object_address()`) the +/// consumer calls the `evaluate()` method. That returns an `EvaluationResult`, +/// which is either `EvaluationResult::Complete` or a value indicating what +/// data is needed to resume the `Evaluation`. The consumer is responsible for +/// producing that data and resuming the computation with the correct method, +/// as documented for `EvaluationResult`. Only once an `EvaluationResult::Complete` +/// is returned can the consumer call `result()`. +/// +/// This design allows the consumer of `Evaluation` to decide how and when to +/// produce the required data and resume the computation. The `Evaluation` can +/// be driven synchronously (as shown below) or by some asynchronous mechanism +/// such as futures. +/// +/// # Examples +/// ```rust,no_run +/// use gimli::{Evaluation, EvaluationResult, Expression}; +/// # let bytecode = gimli::EndianSlice::new(&[], gimli::LittleEndian); +/// # let encoding = unimplemented!(); +/// # let get_register_value = |_, _| gimli::Value::Generic(42); +/// # let get_frame_base = || 0xdeadbeef; +/// +/// let mut eval = Evaluation::new(bytecode, encoding); +/// let mut result = eval.evaluate().unwrap(); +/// while result != EvaluationResult::Complete { +/// match result { +/// EvaluationResult::RequiresRegister { register, base_type } => { +/// let value = get_register_value(register, base_type); +/// result = eval.resume_with_register(value).unwrap(); +/// }, +/// EvaluationResult::RequiresFrameBase => { +/// let frame_base = get_frame_base(); +/// result = eval.resume_with_frame_base(frame_base).unwrap(); +/// }, +/// _ => unimplemented!(), +/// }; +/// } +/// +/// let result = eval.result(); +/// println!("{:?}", result); +/// ``` +#[derive(Debug)] +pub struct Evaluation = StoreOnHeap> { + bytecode: R, + encoding: Encoding, + object_address: Option, + max_iterations: Option, + iteration: u32, + state: EvaluationState, + + // Stack operations are done on word-sized values. We do all + // operations on 64-bit values, and then mask the results + // appropriately when popping. + addr_mask: u64, + + // The stack. + stack: ArrayVec, + + // The next operation to decode and evaluate. + pc: R, + + // If we see a DW_OP_call* operation, the previous PC and bytecode + // is stored here while evaluating the subroutine. + expression_stack: ArrayVec, + + value_result: Option, + result: ArrayVec, +} + +#[cfg(feature = "read")] +impl Evaluation { + /// Create a new DWARF expression evaluator. + /// + /// The new evaluator is created without an initial value, without + /// an object address, and without a maximum number of iterations. + pub fn new(bytecode: R, encoding: Encoding) -> Self { + Self::new_in(bytecode, encoding) + } + + /// Get the result of this `Evaluation`. + /// + /// # Panics + /// Panics if this `Evaluation` has not been driven to completion. + pub fn result(self) -> Vec> { + match self.state { + EvaluationState::Complete => self.result.into_vec(), + _ => { + panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed") + } + } + } +} + +impl> Evaluation { + /// Create a new DWARF expression evaluator. + /// + /// The new evaluator is created without an initial value, without + /// an object address, and without a maximum number of iterations. + pub fn new_in(bytecode: R, encoding: Encoding) -> Self { + let pc = bytecode.clone(); + Evaluation { + bytecode, + encoding, + object_address: None, + max_iterations: None, + iteration: 0, + state: EvaluationState::Start(None), + addr_mask: if encoding.address_size == 8 { + !0u64 + } else { + (1 << (8 * u64::from(encoding.address_size))) - 1 + }, + stack: Default::default(), + expression_stack: Default::default(), + pc, + value_result: None, + result: Default::default(), + } + } + + /// Set an initial value to be pushed on the DWARF expression + /// evaluator's stack. This can be used in cases like + /// `DW_AT_vtable_elem_location`, which require a value on the + /// stack before evaluation commences. If no initial value is + /// set, and the expression uses an opcode requiring the initial + /// value, then evaluation will fail with an error. + /// + /// # Panics + /// Panics if `set_initial_value()` has already been called, or if + /// `evaluate()` has already been called. + pub fn set_initial_value(&mut self, value: u64) { + match self.state { + EvaluationState::Start(None) => { + self.state = EvaluationState::Start(Some(value)); + } + _ => panic!( + "`Evaluation::set_initial_value` was called twice, or after evaluation began." + ), + }; + } + + /// Set the enclosing object's address, as used by + /// `DW_OP_push_object_address`. If no object address is set, and + /// the expression uses an opcode requiring the object address, + /// then evaluation will fail with an error. + pub fn set_object_address(&mut self, value: u64) { + self.object_address = Some(value); + } + + /// Set the maximum number of iterations to be allowed by the + /// expression evaluator. + /// + /// An iteration corresponds approximately to the evaluation of a + /// single operation in an expression ("approximately" because the + /// implementation may allow two such operations in some cases). + /// The default is not to have a maximum; once set, it's not + /// possible to go back to this default state. This value can be + /// set to avoid denial of service attacks by bad DWARF bytecode. + pub fn set_max_iterations(&mut self, value: u32) { + self.max_iterations = Some(value); + } + + fn pop(&mut self) -> Result { + match self.stack.pop() { + Some(value) => Ok(value), + None => Err(Error::NotEnoughStackItems), + } + } + + fn push(&mut self, value: Value) -> Result<()> { + self.stack.try_push(value).map_err(|_| Error::StackFull) + } + + fn evaluate_one_operation(&mut self) -> Result> { + let operation = Operation::parse(&mut self.pc, self.encoding)?; + + match operation { + Operation::Deref { + base_type, + size, + space, + } => { + if size > self.encoding.address_size { + return Err(Error::InvalidDerefSize(size)); + } + let entry = self.pop()?; + let addr = entry.to_u64(self.addr_mask)?; + let addr_space = if space { + let entry = self.pop()?; + let value = entry.to_u64(self.addr_mask)?; + Some(value) + } else { + None + }; + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Memory, + EvaluationResult::RequiresMemory { + address: addr, + size, + space: addr_space, + base_type, + }, + )); + } + + Operation::Drop => { + self.pop()?; + } + Operation::Pick { index } => { + let len = self.stack.len(); + let index = index as usize; + if index >= len { + return Err(Error::NotEnoughStackItems); + } + let value = self.stack[len - index - 1]; + self.push(value)?; + } + Operation::Swap => { + let top = self.pop()?; + let next = self.pop()?; + self.push(top)?; + self.push(next)?; + } + Operation::Rot => { + let one = self.pop()?; + let two = self.pop()?; + let three = self.pop()?; + self.push(one)?; + self.push(three)?; + self.push(two)?; + } + + Operation::Abs => { + let value = self.pop()?; + let result = value.abs(self.addr_mask)?; + self.push(result)?; + } + Operation::And => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.and(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Div => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.div(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Minus => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.sub(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Mod => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.rem(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Mul => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.mul(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Neg => { + let v = self.pop()?; + let result = v.neg(self.addr_mask)?; + self.push(result)?; + } + Operation::Not => { + let value = self.pop()?; + let result = value.not(self.addr_mask)?; + self.push(result)?; + } + Operation::Or => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.or(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Plus => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.add(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::PlusConstant { value } => { + let lhs = self.pop()?; + let rhs = Value::from_u64(lhs.value_type(), value)?; + let result = lhs.add(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Shl => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.shl(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Shr => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.shr(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Shra => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.shra(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Xor => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.xor(rhs, self.addr_mask)?; + self.push(result)?; + } + + Operation::Bra { target } => { + let entry = self.pop()?; + let v = entry.to_u64(self.addr_mask)?; + if v != 0 { + self.pc = compute_pc(&self.pc, &self.bytecode, target)?; + } + } + + Operation::Eq => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.eq(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Ge => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.ge(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Gt => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.gt(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Le => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.le(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Lt => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.lt(rhs, self.addr_mask)?; + self.push(result)?; + } + Operation::Ne => { + let rhs = self.pop()?; + let lhs = self.pop()?; + let result = lhs.ne(rhs, self.addr_mask)?; + self.push(result)?; + } + + Operation::Skip { target } => { + self.pc = compute_pc(&self.pc, &self.bytecode, target)?; + } + + Operation::UnsignedConstant { value } => { + self.push(Value::Generic(value))?; + } + + Operation::SignedConstant { value } => { + self.push(Value::Generic(value as u64))?; + } + + Operation::RegisterOffset { + register, + offset, + base_type, + } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Register { offset }, + EvaluationResult::RequiresRegister { + register, + base_type, + }, + )); + } + + Operation::FrameOffset { offset } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::FrameBase { offset }, + EvaluationResult::RequiresFrameBase, + )); + } + + Operation::Nop => {} + + Operation::PushObjectAddress => { + if let Some(value) = self.object_address { + self.push(Value::Generic(value))?; + } else { + return Err(Error::InvalidPushObjectAddress); + } + } + + Operation::Call { offset } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::AtLocation, + EvaluationResult::RequiresAtLocation(offset), + )); + } + + Operation::TLS => { + let entry = self.pop()?; + let index = entry.to_u64(self.addr_mask)?; + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Tls, + EvaluationResult::RequiresTls(index), + )); + } + + Operation::CallFrameCFA => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Cfa, + EvaluationResult::RequiresCallFrameCfa, + )); + } + + Operation::Register { register } => { + let location = Location::Register { register }; + return Ok(OperationEvaluationResult::Complete { location }); + } + + Operation::ImplicitValue { ref data } => { + let location = Location::Bytes { + value: data.clone(), + }; + return Ok(OperationEvaluationResult::Complete { location }); + } + + Operation::StackValue => { + let value = self.pop()?; + let location = Location::Value { value }; + return Ok(OperationEvaluationResult::Complete { location }); + } + + Operation::ImplicitPointer { value, byte_offset } => { + let location = Location::ImplicitPointer { value, byte_offset }; + return Ok(OperationEvaluationResult::Complete { location }); + } + + Operation::EntryValue { ref expression } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::EntryValue, + EvaluationResult::RequiresEntryValue(Expression(expression.clone())), + )); + } + + Operation::ParameterRef { offset } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::ParameterRef, + EvaluationResult::RequiresParameterRef(offset), + )); + } + + Operation::Address { address } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::RelocatedAddress, + EvaluationResult::RequiresRelocatedAddress(address), + )); + } + + Operation::AddressIndex { index } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::IndexedAddress, + EvaluationResult::RequiresIndexedAddress { + index, + relocate: true, + }, + )); + } + + Operation::ConstantIndex { index } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::IndexedAddress, + EvaluationResult::RequiresIndexedAddress { + index, + relocate: false, + }, + )); + } + + Operation::Piece { + size_in_bits, + bit_offset, + } => { + let location = if self.stack.is_empty() { + Location::Empty + } else { + let entry = self.pop()?; + let address = entry.to_u64(self.addr_mask)?; + Location::Address { address } + }; + self.result + .try_push(Piece { + size_in_bits: Some(size_in_bits), + bit_offset, + location, + }) + .map_err(|_| Error::StackFull)?; + return Ok(OperationEvaluationResult::Piece); + } + + Operation::TypedLiteral { base_type, value } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::TypedLiteral { value }, + EvaluationResult::RequiresBaseType(base_type), + )); + } + Operation::Convert { base_type } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Convert, + EvaluationResult::RequiresBaseType(base_type), + )); + } + Operation::Reinterpret { base_type } => { + return Ok(OperationEvaluationResult::Waiting( + EvaluationWaiting::Reinterpret, + EvaluationResult::RequiresBaseType(base_type), + )); + } + Operation::WasmLocal { .. } + | Operation::WasmGlobal { .. } + | Operation::WasmStack { .. } => { + return Err(Error::UnsupportedEvaluation); + } + } + + Ok(OperationEvaluationResult::Incomplete) + } + + /// Get the result if this is an evaluation for a value. + /// + /// Returns `None` if the evaluation contained operations that are only + /// valid for location descriptions. + /// + /// # Panics + /// Panics if this `Evaluation` has not been driven to completion. + pub fn value_result(&self) -> Option { + match self.state { + EvaluationState::Complete => self.value_result, + _ => { + panic!("Called `Evaluation::value_result` on an `Evaluation` that has not been completed") + } + } + } + + /// Get the result of this `Evaluation`. + /// + /// # Panics + /// Panics if this `Evaluation` has not been driven to completion. + pub fn as_result(&self) -> &[Piece] { + match self.state { + EvaluationState::Complete => &self.result, + _ => { + panic!( + "Called `Evaluation::as_result` on an `Evaluation` that has not been completed" + ) + } + } + } + + /// Evaluate a DWARF expression. This method should only ever be called + /// once. If the returned `EvaluationResult` is not + /// `EvaluationResult::Complete`, the caller should provide the required + /// value and resume the evaluation by calling the appropriate resume_with + /// method on `Evaluation`. + pub fn evaluate(&mut self) -> Result> { + match self.state { + EvaluationState::Start(initial_value) => { + if let Some(value) = initial_value { + self.push(Value::Generic(value))?; + } + self.state = EvaluationState::Ready; + } + EvaluationState::Ready => {} + EvaluationState::Error(err) => return Err(err), + EvaluationState::Complete => return Ok(EvaluationResult::Complete), + EvaluationState::Waiting(_) => panic!(), + }; + + match self.evaluate_internal() { + Ok(r) => Ok(r), + Err(e) => { + self.state = EvaluationState::Error(e); + Err(e) + } + } + } + + /// Resume the `Evaluation` with the provided memory `value`. This will apply + /// the provided memory value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresMemory`. + pub fn resume_with_memory(&mut self, value: Value) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::Memory) => { + self.push(value)?; + } + _ => panic!( + "Called `Evaluation::resume_with_memory` without a preceding `EvaluationResult::RequiresMemory`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `register` value. This will apply + /// the provided register value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresRegister`. + pub fn resume_with_register(&mut self, value: Value) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::Register { offset }) => { + let offset = Value::from_u64(value.value_type(), offset as u64)?; + let value = value.add(offset, self.addr_mask)?; + self.push(value)?; + } + _ => panic!( + "Called `Evaluation::resume_with_register` without a preceding `EvaluationResult::RequiresRegister`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `frame_base`. This will + /// apply the provided frame base value to the evaluation and continue + /// evaluating opcodes until the evaluation is completed, reaches an error, + /// or needs more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresFrameBase`. + pub fn resume_with_frame_base(&mut self, frame_base: u64) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::FrameBase { offset }) => { + self.push(Value::Generic(frame_base.wrapping_add(offset as u64)))?; + } + _ => panic!( + "Called `Evaluation::resume_with_frame_base` without a preceding `EvaluationResult::RequiresFrameBase`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `value`. This will apply + /// the provided TLS value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresTls`. + pub fn resume_with_tls(&mut self, value: u64) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::Tls) => { + self.push(Value::Generic(value))?; + } + _ => panic!( + "Called `Evaluation::resume_with_tls` without a preceding `EvaluationResult::RequiresTls`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `cfa`. This will + /// apply the provided CFA value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresCallFrameCfa`. + pub fn resume_with_call_frame_cfa(&mut self, cfa: u64) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::Cfa) => { + self.push(Value::Generic(cfa))?; + } + _ => panic!( + "Called `Evaluation::resume_with_call_frame_cfa` without a preceding `EvaluationResult::RequiresCallFrameCfa`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `bytes`. This will + /// continue processing the evaluation with the new expression provided + /// until the evaluation is completed, reaches an error, or needs more + /// information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresAtLocation`. + pub fn resume_with_at_location(&mut self, mut bytes: R) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::AtLocation) => { + if !bytes.is_empty() { + let mut pc = bytes.clone(); + mem::swap(&mut pc, &mut self.pc); + mem::swap(&mut bytes, &mut self.bytecode); + self.expression_stack.try_push((pc, bytes)).map_err(|_| Error::StackFull)?; + } + } + _ => panic!( + "Called `Evaluation::resume_with_at_location` without a precedeing `EvaluationResult::RequiresAtLocation`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `entry_value`. This will + /// apply the provided entry value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresEntryValue`. + pub fn resume_with_entry_value(&mut self, entry_value: Value) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::EntryValue) => { + self.push(entry_value)?; + } + _ => panic!( + "Called `Evaluation::resume_with_entry_value` without a preceding `EvaluationResult::RequiresEntryValue`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `parameter_value`. This will + /// apply the provided parameter value to the evaluation and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresParameterRef`. + pub fn resume_with_parameter_ref( + &mut self, + parameter_value: u64, + ) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::ParameterRef) => { + self.push(Value::Generic(parameter_value))?; + } + _ => panic!( + "Called `Evaluation::resume_with_parameter_ref` without a preceding `EvaluationResult::RequiresParameterRef`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided relocated `address`. This will use the + /// provided relocated address for the operation that required it, and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with + /// `EvaluationResult::RequiresRelocatedAddress`. + pub fn resume_with_relocated_address(&mut self, address: u64) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::RelocatedAddress) => { + self.push(Value::Generic(address))?; + } + _ => panic!( + "Called `Evaluation::resume_with_relocated_address` without a preceding `EvaluationResult::RequiresRelocatedAddress`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided indexed `address`. This will use the + /// provided indexed address for the operation that required it, and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with + /// `EvaluationResult::RequiresIndexedAddress`. + pub fn resume_with_indexed_address(&mut self, address: u64) -> Result> { + match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::IndexedAddress) => { + self.push(Value::Generic(address))?; + } + _ => panic!( + "Called `Evaluation::resume_with_indexed_address` without a preceding `EvaluationResult::RequiresIndexedAddress`" + ), + }; + + self.evaluate_internal() + } + + /// Resume the `Evaluation` with the provided `base_type`. This will use the + /// provided base type for the operation that required it, and continue evaluating + /// opcodes until the evaluation is completed, reaches an error, or needs + /// more information again. + /// + /// # Panics + /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresBaseType`. + pub fn resume_with_base_type(&mut self, base_type: ValueType) -> Result> { + let value = match self.state { + EvaluationState::Error(err) => return Err(err), + EvaluationState::Waiting(EvaluationWaiting::TypedLiteral { ref value }) => { + Value::parse(base_type, value.clone())? + } + EvaluationState::Waiting(EvaluationWaiting::Convert) => { + let entry = self.pop()?; + entry.convert(base_type, self.addr_mask)? + } + EvaluationState::Waiting(EvaluationWaiting::Reinterpret) => { + let entry = self.pop()?; + entry.reinterpret(base_type, self.addr_mask)? + } + _ => panic!( + "Called `Evaluation::resume_with_base_type` without a preceding `EvaluationResult::RequiresBaseType`" + ), + }; + self.push(value)?; + self.evaluate_internal() + } + + fn end_of_expression(&mut self) -> bool { + while self.pc.is_empty() { + match self.expression_stack.pop() { + Some((newpc, newbytes)) => { + self.pc = newpc; + self.bytecode = newbytes; + } + None => return true, + } + } + false + } + + fn evaluate_internal(&mut self) -> Result> { + while !self.end_of_expression() { + self.iteration += 1; + if let Some(max_iterations) = self.max_iterations { + if self.iteration > max_iterations { + return Err(Error::TooManyIterations); + } + } + + let op_result = self.evaluate_one_operation()?; + match op_result { + OperationEvaluationResult::Piece => {} + OperationEvaluationResult::Incomplete => { + if self.end_of_expression() && !self.result.is_empty() { + // We saw a piece earlier and then some + // unterminated piece. It's not clear this is + // well-defined. + return Err(Error::InvalidPiece); + } + } + OperationEvaluationResult::Complete { location } => { + if self.end_of_expression() { + if !self.result.is_empty() { + // We saw a piece earlier and then some + // unterminated piece. It's not clear this is + // well-defined. + return Err(Error::InvalidPiece); + } + self.result + .try_push(Piece { + size_in_bits: None, + bit_offset: None, + location, + }) + .map_err(|_| Error::StackFull)?; + } else { + // If there are more operations, then the next operation must + // be a Piece. + match Operation::parse(&mut self.pc, self.encoding)? { + Operation::Piece { + size_in_bits, + bit_offset, + } => { + self.result + .try_push(Piece { + size_in_bits: Some(size_in_bits), + bit_offset, + location, + }) + .map_err(|_| Error::StackFull)?; + } + _ => { + let value = + self.bytecode.len().into_u64() - self.pc.len().into_u64() - 1; + return Err(Error::InvalidExpressionTerminator(value)); + } + } + } + } + OperationEvaluationResult::Waiting(waiting, result) => { + self.state = EvaluationState::Waiting(waiting); + return Ok(result); + } + } + } + + // If no pieces have been seen, use the stack top as the + // result. + if self.result.is_empty() { + let entry = self.pop()?; + self.value_result = Some(entry); + let addr = entry.to_u64(self.addr_mask)?; + self.result + .try_push(Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Address { address: addr }, + }) + .map_err(|_| Error::StackFull)?; + } + + self.state = EvaluationState::Complete; + Ok(EvaluationResult::Complete) + } +} + +#[cfg(test)] +// Tests require leb128::write. +#[cfg(feature = "write")] +mod tests { + use super::*; + use crate::common::Format; + use crate::constants; + use crate::endianity::LittleEndian; + use crate::leb128; + use crate::read::{EndianSlice, Error, Result, UnitOffset}; + use crate::test_util::GimliSectionMethods; + use test_assembler::{Endian, Section}; + + fn encoding4() -> Encoding { + Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + } + } + + fn encoding8() -> Encoding { + Encoding { + format: Format::Dwarf64, + version: 4, + address_size: 8, + } + } + + #[test] + fn test_compute_pc() { + // Contents don't matter for this test, just length. + let bytes = [0, 1, 2, 3, 4]; + let bytecode = &bytes[..]; + let ebuf = &EndianSlice::new(bytecode, LittleEndian); + + assert_eq!(compute_pc(ebuf, ebuf, 0), Ok(*ebuf)); + assert_eq!( + compute_pc(ebuf, ebuf, -1), + Err(Error::BadBranchTarget(usize::MAX as u64)) + ); + assert_eq!(compute_pc(ebuf, ebuf, 5), Ok(ebuf.range_from(5..))); + assert_eq!( + compute_pc(&ebuf.range_from(3..), ebuf, -2), + Ok(ebuf.range_from(1..)) + ); + assert_eq!( + compute_pc(&ebuf.range_from(2..), ebuf, 2), + Ok(ebuf.range_from(4..)) + ); + } + + fn check_op_parse_simple<'input>( + input: &'input [u8], + expect: &Operation>, + encoding: Encoding, + ) { + let buf = EndianSlice::new(input, LittleEndian); + let mut pc = buf; + let value = Operation::parse(&mut pc, encoding); + match value { + Ok(val) => { + assert_eq!(val, *expect); + assert_eq!(pc.len(), 0); + } + _ => panic!("Unexpected result"), + } + } + + fn check_op_parse_eof(input: &[u8], encoding: Encoding) { + let buf = EndianSlice::new(input, LittleEndian); + let mut pc = buf; + match Operation::parse(&mut pc, encoding) { + Err(Error::UnexpectedEof(id)) => { + assert!(buf.lookup_offset_id(id).is_some()); + } + + _ => panic!("Unexpected result"), + } + } + + fn check_op_parse( + input: F, + expect: &Operation>, + encoding: Encoding, + ) where + F: Fn(Section) -> Section, + { + let input = input(Section::with_endian(Endian::Little)) + .get_contents() + .unwrap(); + for i in 1..input.len() { + check_op_parse_eof(&input[..i], encoding); + } + check_op_parse_simple(&input, expect, encoding); + } + + #[test] + fn test_op_parse_onebyte() { + // Doesn't matter for this test. + let encoding = encoding4(); + + // Test all single-byte opcodes. + #[rustfmt::skip] + let inputs = [ + ( + constants::DW_OP_deref, + Operation::Deref { + base_type: generic_type(), + size: encoding.address_size, + space: false, + }, + ), + (constants::DW_OP_dup, Operation::Pick { index: 0 }), + (constants::DW_OP_drop, Operation::Drop), + (constants::DW_OP_over, Operation::Pick { index: 1 }), + (constants::DW_OP_swap, Operation::Swap), + (constants::DW_OP_rot, Operation::Rot), + ( + constants::DW_OP_xderef, + Operation::Deref { + base_type: generic_type(), + size: encoding.address_size, + space: true, + }, + ), + (constants::DW_OP_abs, Operation::Abs), + (constants::DW_OP_and, Operation::And), + (constants::DW_OP_div, Operation::Div), + (constants::DW_OP_minus, Operation::Minus), + (constants::DW_OP_mod, Operation::Mod), + (constants::DW_OP_mul, Operation::Mul), + (constants::DW_OP_neg, Operation::Neg), + (constants::DW_OP_not, Operation::Not), + (constants::DW_OP_or, Operation::Or), + (constants::DW_OP_plus, Operation::Plus), + (constants::DW_OP_shl, Operation::Shl), + (constants::DW_OP_shr, Operation::Shr), + (constants::DW_OP_shra, Operation::Shra), + (constants::DW_OP_xor, Operation::Xor), + (constants::DW_OP_eq, Operation::Eq), + (constants::DW_OP_ge, Operation::Ge), + (constants::DW_OP_gt, Operation::Gt), + (constants::DW_OP_le, Operation::Le), + (constants::DW_OP_lt, Operation::Lt), + (constants::DW_OP_ne, Operation::Ne), + (constants::DW_OP_lit0, Operation::UnsignedConstant { value: 0 }), + (constants::DW_OP_lit1, Operation::UnsignedConstant { value: 1 }), + (constants::DW_OP_lit2, Operation::UnsignedConstant { value: 2 }), + (constants::DW_OP_lit3, Operation::UnsignedConstant { value: 3 }), + (constants::DW_OP_lit4, Operation::UnsignedConstant { value: 4 }), + (constants::DW_OP_lit5, Operation::UnsignedConstant { value: 5 }), + (constants::DW_OP_lit6, Operation::UnsignedConstant { value: 6 }), + (constants::DW_OP_lit7, Operation::UnsignedConstant { value: 7 }), + (constants::DW_OP_lit8, Operation::UnsignedConstant { value: 8 }), + (constants::DW_OP_lit9, Operation::UnsignedConstant { value: 9 }), + (constants::DW_OP_lit10, Operation::UnsignedConstant { value: 10 }), + (constants::DW_OP_lit11, Operation::UnsignedConstant { value: 11 }), + (constants::DW_OP_lit12, Operation::UnsignedConstant { value: 12 }), + (constants::DW_OP_lit13, Operation::UnsignedConstant { value: 13 }), + (constants::DW_OP_lit14, Operation::UnsignedConstant { value: 14 }), + (constants::DW_OP_lit15, Operation::UnsignedConstant { value: 15 }), + (constants::DW_OP_lit16, Operation::UnsignedConstant { value: 16 }), + (constants::DW_OP_lit17, Operation::UnsignedConstant { value: 17 }), + (constants::DW_OP_lit18, Operation::UnsignedConstant { value: 18 }), + (constants::DW_OP_lit19, Operation::UnsignedConstant { value: 19 }), + (constants::DW_OP_lit20, Operation::UnsignedConstant { value: 20 }), + (constants::DW_OP_lit21, Operation::UnsignedConstant { value: 21 }), + (constants::DW_OP_lit22, Operation::UnsignedConstant { value: 22 }), + (constants::DW_OP_lit23, Operation::UnsignedConstant { value: 23 }), + (constants::DW_OP_lit24, Operation::UnsignedConstant { value: 24 }), + (constants::DW_OP_lit25, Operation::UnsignedConstant { value: 25 }), + (constants::DW_OP_lit26, Operation::UnsignedConstant { value: 26 }), + (constants::DW_OP_lit27, Operation::UnsignedConstant { value: 27 }), + (constants::DW_OP_lit28, Operation::UnsignedConstant { value: 28 }), + (constants::DW_OP_lit29, Operation::UnsignedConstant { value: 29 }), + (constants::DW_OP_lit30, Operation::UnsignedConstant { value: 30 }), + (constants::DW_OP_lit31, Operation::UnsignedConstant { value: 31 }), + (constants::DW_OP_reg0, Operation::Register { register: Register(0) }), + (constants::DW_OP_reg1, Operation::Register { register: Register(1) }), + (constants::DW_OP_reg2, Operation::Register { register: Register(2) }), + (constants::DW_OP_reg3, Operation::Register { register: Register(3) }), + (constants::DW_OP_reg4, Operation::Register { register: Register(4) }), + (constants::DW_OP_reg5, Operation::Register { register: Register(5) }), + (constants::DW_OP_reg6, Operation::Register { register: Register(6) }), + (constants::DW_OP_reg7, Operation::Register { register: Register(7) }), + (constants::DW_OP_reg8, Operation::Register { register: Register(8) }), + (constants::DW_OP_reg9, Operation::Register { register: Register(9) }), + (constants::DW_OP_reg10, Operation::Register { register: Register(10) }), + (constants::DW_OP_reg11, Operation::Register { register: Register(11) }), + (constants::DW_OP_reg12, Operation::Register { register: Register(12) }), + (constants::DW_OP_reg13, Operation::Register { register: Register(13) }), + (constants::DW_OP_reg14, Operation::Register { register: Register(14) }), + (constants::DW_OP_reg15, Operation::Register { register: Register(15) }), + (constants::DW_OP_reg16, Operation::Register { register: Register(16) }), + (constants::DW_OP_reg17, Operation::Register { register: Register(17) }), + (constants::DW_OP_reg18, Operation::Register { register: Register(18) }), + (constants::DW_OP_reg19, Operation::Register { register: Register(19) }), + (constants::DW_OP_reg20, Operation::Register { register: Register(20) }), + (constants::DW_OP_reg21, Operation::Register { register: Register(21) }), + (constants::DW_OP_reg22, Operation::Register { register: Register(22) }), + (constants::DW_OP_reg23, Operation::Register { register: Register(23) }), + (constants::DW_OP_reg24, Operation::Register { register: Register(24) }), + (constants::DW_OP_reg25, Operation::Register { register: Register(25) }), + (constants::DW_OP_reg26, Operation::Register { register: Register(26) }), + (constants::DW_OP_reg27, Operation::Register { register: Register(27) }), + (constants::DW_OP_reg28, Operation::Register { register: Register(28) }), + (constants::DW_OP_reg29, Operation::Register { register: Register(29) }), + (constants::DW_OP_reg30, Operation::Register { register: Register(30) }), + (constants::DW_OP_reg31, Operation::Register { register: Register(31) }), + (constants::DW_OP_nop, Operation::Nop), + (constants::DW_OP_push_object_address, Operation::PushObjectAddress), + (constants::DW_OP_form_tls_address, Operation::TLS), + (constants::DW_OP_GNU_push_tls_address, Operation::TLS), + (constants::DW_OP_call_frame_cfa, Operation::CallFrameCFA), + (constants::DW_OP_stack_value, Operation::StackValue), + ]; + + let input = []; + check_op_parse_eof(&input[..], encoding); + + for item in inputs.iter() { + let (opcode, ref result) = *item; + check_op_parse(|s| s.D8(opcode.0), result, encoding); + } + } + + #[test] + fn test_op_parse_twobyte() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let inputs = [ + ( + constants::DW_OP_const1u, + 23, + Operation::UnsignedConstant { value: 23 }, + ), + ( + constants::DW_OP_const1s, + (-23i8) as u8, + Operation::SignedConstant { value: -23 }, + ), + (constants::DW_OP_pick, 7, Operation::Pick { index: 7 }), + ( + constants::DW_OP_deref_size, + 19, + Operation::Deref { + base_type: generic_type(), + size: 19, + space: false, + }, + ), + ( + constants::DW_OP_xderef_size, + 19, + Operation::Deref { + base_type: generic_type(), + size: 19, + space: true, + }, + ), + ]; + + for item in inputs.iter() { + let (opcode, arg, ref result) = *item; + check_op_parse(|s| s.D8(opcode.0).D8(arg), result, encoding); + } + } + + #[test] + fn test_op_parse_threebyte() { + // Doesn't matter for this test. + let encoding = encoding4(); + + // While bra and skip are 3-byte opcodes, they aren't tested here, + // but rather specially in their own function. + let inputs = [ + ( + constants::DW_OP_const2u, + 23, + Operation::UnsignedConstant { value: 23 }, + ), + ( + constants::DW_OP_const2s, + (-23i16) as u16, + Operation::SignedConstant { value: -23 }, + ), + ( + constants::DW_OP_call2, + 1138, + Operation::Call { + offset: DieReference::UnitRef(UnitOffset(1138)), + }, + ), + ( + constants::DW_OP_bra, + (-23i16) as u16, + Operation::Bra { target: -23 }, + ), + ( + constants::DW_OP_skip, + (-23i16) as u16, + Operation::Skip { target: -23 }, + ), + ]; + + for item in inputs.iter() { + let (opcode, arg, ref result) = *item; + check_op_parse(|s| s.D8(opcode.0).L16(arg), result, encoding); + } + } + + #[test] + fn test_op_parse_fivebyte() { + // There are some tests here that depend on address size. + let encoding = encoding4(); + + let inputs = [ + ( + constants::DW_OP_addr, + 0x1234_5678, + Operation::Address { + address: 0x1234_5678, + }, + ), + ( + constants::DW_OP_const4u, + 0x1234_5678, + Operation::UnsignedConstant { value: 0x1234_5678 }, + ), + ( + constants::DW_OP_const4s, + (-23i32) as u32, + Operation::SignedConstant { value: -23 }, + ), + ( + constants::DW_OP_call4, + 0x1234_5678, + Operation::Call { + offset: DieReference::UnitRef(UnitOffset(0x1234_5678)), + }, + ), + ( + constants::DW_OP_call_ref, + 0x1234_5678, + Operation::Call { + offset: DieReference::DebugInfoRef(DebugInfoOffset(0x1234_5678)), + }, + ), + ]; + + for item in inputs.iter() { + let (op, arg, ref expect) = *item; + check_op_parse(|s| s.D8(op.0).L32(arg), expect, encoding); + } + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_op_parse_ninebyte() { + // There are some tests here that depend on address size. + let encoding = encoding8(); + + let inputs = [ + ( + constants::DW_OP_addr, + 0x1234_5678_1234_5678, + Operation::Address { + address: 0x1234_5678_1234_5678, + }, + ), + ( + constants::DW_OP_const8u, + 0x1234_5678_1234_5678, + Operation::UnsignedConstant { + value: 0x1234_5678_1234_5678, + }, + ), + ( + constants::DW_OP_const8s, + (-23i64) as u64, + Operation::SignedConstant { value: -23 }, + ), + ( + constants::DW_OP_call_ref, + 0x1234_5678_1234_5678, + Operation::Call { + offset: DieReference::DebugInfoRef(DebugInfoOffset(0x1234_5678_1234_5678)), + }, + ), + ]; + + for item in inputs.iter() { + let (op, arg, ref expect) = *item; + check_op_parse(|s| s.D8(op.0).L64(arg), expect, encoding); + } + } + + #[test] + fn test_op_parse_sleb() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let values = [ + -1i64, + 0, + 1, + 0x100, + 0x1eee_eeee, + 0x7fff_ffff_ffff_ffff, + -0x100, + -0x1eee_eeee, + -0x7fff_ffff_ffff_ffff, + ]; + for value in values.iter() { + let mut inputs = vec![ + ( + constants::DW_OP_consts.0, + Operation::SignedConstant { value: *value }, + ), + ( + constants::DW_OP_fbreg.0, + Operation::FrameOffset { offset: *value }, + ), + ]; + + for i in 0..32 { + inputs.push(( + constants::DW_OP_breg0.0 + i, + Operation::RegisterOffset { + register: Register(i.into()), + offset: *value, + base_type: UnitOffset(0), + }, + )); + } + + for item in inputs.iter() { + let (op, ref expect) = *item; + check_op_parse(|s| s.D8(op).sleb(*value), expect, encoding); + } + } + } + + #[test] + fn test_op_parse_uleb() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let values = [ + 0, + 1, + 0x100, + (!0u16).into(), + 0x1eee_eeee, + 0x7fff_ffff_ffff_ffff, + !0u64, + ]; + for value in values.iter() { + let mut inputs = vec![ + ( + constants::DW_OP_constu, + Operation::UnsignedConstant { value: *value }, + ), + ( + constants::DW_OP_plus_uconst, + Operation::PlusConstant { value: *value }, + ), + ]; + + if *value <= (!0u16).into() { + inputs.push(( + constants::DW_OP_regx, + Operation::Register { + register: Register::from_u64(*value).unwrap(), + }, + )); + } + + if *value <= (!0u32).into() { + inputs.extend(&[ + ( + constants::DW_OP_addrx, + Operation::AddressIndex { + index: DebugAddrIndex(*value as usize), + }, + ), + ( + constants::DW_OP_constx, + Operation::ConstantIndex { + index: DebugAddrIndex(*value as usize), + }, + ), + ]); + } + + // FIXME + if *value < !0u64 / 8 { + inputs.push(( + constants::DW_OP_piece, + Operation::Piece { + size_in_bits: 8 * value, + bit_offset: None, + }, + )); + } + + for item in inputs.iter() { + let (op, ref expect) = *item; + let input = Section::with_endian(Endian::Little) + .D8(op.0) + .uleb(*value) + .get_contents() + .unwrap(); + check_op_parse_simple(&input, expect, encoding); + } + } + } + + #[test] + fn test_op_parse_bregx() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let uvalues = [0, 1, 0x100, !0u16]; + let svalues = [ + -1i64, + 0, + 1, + 0x100, + 0x1eee_eeee, + 0x7fff_ffff_ffff_ffff, + -0x100, + -0x1eee_eeee, + -0x7fff_ffff_ffff_ffff, + ]; + + for v1 in uvalues.iter() { + for v2 in svalues.iter() { + check_op_parse( + |s| s.D8(constants::DW_OP_bregx.0).uleb((*v1).into()).sleb(*v2), + &Operation::RegisterOffset { + register: Register(*v1), + offset: *v2, + base_type: UnitOffset(0), + }, + encoding, + ); + } + } + } + + #[test] + fn test_op_parse_bit_piece() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let values = [0, 1, 0x100, 0x1eee_eeee, 0x7fff_ffff_ffff_ffff, !0u64]; + + for v1 in values.iter() { + for v2 in values.iter() { + let input = Section::with_endian(Endian::Little) + .D8(constants::DW_OP_bit_piece.0) + .uleb(*v1) + .uleb(*v2) + .get_contents() + .unwrap(); + check_op_parse_simple( + &input, + &Operation::Piece { + size_in_bits: *v1, + bit_offset: Some(*v2), + }, + encoding, + ); + } + } + } + + #[test] + fn test_op_parse_implicit_value() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let data = b"hello"; + + check_op_parse( + |s| { + s.D8(constants::DW_OP_implicit_value.0) + .uleb(data.len() as u64) + .append_bytes(&data[..]) + }, + &Operation::ImplicitValue { + data: EndianSlice::new(&data[..], LittleEndian), + }, + encoding, + ); + } + + #[test] + fn test_op_parse_const_type() { + // Doesn't matter for this test. + let encoding = encoding4(); + + let data = b"hello"; + + check_op_parse( + |s| { + s.D8(constants::DW_OP_const_type.0) + .uleb(100) + .D8(data.len() as u8) + .append_bytes(&data[..]) + }, + &Operation::TypedLiteral { + base_type: UnitOffset(100), + value: EndianSlice::new(&data[..], LittleEndian), + }, + encoding, + ); + check_op_parse( + |s| { + s.D8(constants::DW_OP_GNU_const_type.0) + .uleb(100) + .D8(data.len() as u8) + .append_bytes(&data[..]) + }, + &Operation::TypedLiteral { + base_type: UnitOffset(100), + value: EndianSlice::new(&data[..], LittleEndian), + }, + encoding, + ); + } + + #[test] + fn test_op_parse_regval_type() { + // Doesn't matter for this test. + let encoding = encoding4(); + + check_op_parse( + |s| s.D8(constants::DW_OP_regval_type.0).uleb(1).uleb(100), + &Operation::RegisterOffset { + register: Register(1), + offset: 0, + base_type: UnitOffset(100), + }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_GNU_regval_type.0).uleb(1).uleb(100), + &Operation::RegisterOffset { + register: Register(1), + offset: 0, + base_type: UnitOffset(100), + }, + encoding, + ); + } + + #[test] + fn test_op_parse_deref_type() { + // Doesn't matter for this test. + let encoding = encoding4(); + + check_op_parse( + |s| s.D8(constants::DW_OP_deref_type.0).D8(8).uleb(100), + &Operation::Deref { + base_type: UnitOffset(100), + size: 8, + space: false, + }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_GNU_deref_type.0).D8(8).uleb(100), + &Operation::Deref { + base_type: UnitOffset(100), + size: 8, + space: false, + }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_xderef_type.0).D8(8).uleb(100), + &Operation::Deref { + base_type: UnitOffset(100), + size: 8, + space: true, + }, + encoding, + ); + } + + #[test] + fn test_op_convert() { + // Doesn't matter for this test. + let encoding = encoding4(); + + check_op_parse( + |s| s.D8(constants::DW_OP_convert.0).uleb(100), + &Operation::Convert { + base_type: UnitOffset(100), + }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_GNU_convert.0).uleb(100), + &Operation::Convert { + base_type: UnitOffset(100), + }, + encoding, + ); + } + + #[test] + fn test_op_reinterpret() { + // Doesn't matter for this test. + let encoding = encoding4(); + + check_op_parse( + |s| s.D8(constants::DW_OP_reinterpret.0).uleb(100), + &Operation::Reinterpret { + base_type: UnitOffset(100), + }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_GNU_reinterpret.0).uleb(100), + &Operation::Reinterpret { + base_type: UnitOffset(100), + }, + encoding, + ); + } + + #[test] + fn test_op_parse_implicit_pointer() { + for op in &[ + constants::DW_OP_implicit_pointer, + constants::DW_OP_GNU_implicit_pointer, + ] { + check_op_parse( + |s| s.D8(op.0).D32(0x1234_5678).sleb(0x123), + &Operation::ImplicitPointer { + value: DebugInfoOffset(0x1234_5678), + byte_offset: 0x123, + }, + encoding4(), + ); + + check_op_parse( + |s| s.D8(op.0).D64(0x1234_5678).sleb(0x123), + &Operation::ImplicitPointer { + value: DebugInfoOffset(0x1234_5678), + byte_offset: 0x123, + }, + encoding8(), + ); + + check_op_parse( + |s| s.D8(op.0).D64(0x1234_5678).sleb(0x123), + &Operation::ImplicitPointer { + value: DebugInfoOffset(0x1234_5678), + byte_offset: 0x123, + }, + Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 8, + }, + ) + } + } + + #[test] + fn test_op_parse_entry_value() { + for op in &[ + constants::DW_OP_entry_value, + constants::DW_OP_GNU_entry_value, + ] { + let data = b"hello"; + check_op_parse( + |s| s.D8(op.0).uleb(data.len() as u64).append_bytes(&data[..]), + &Operation::EntryValue { + expression: EndianSlice::new(&data[..], LittleEndian), + }, + encoding4(), + ); + } + } + + #[test] + fn test_op_parse_gnu_parameter_ref() { + check_op_parse( + |s| s.D8(constants::DW_OP_GNU_parameter_ref.0).D32(0x1234_5678), + &Operation::ParameterRef { + offset: UnitOffset(0x1234_5678), + }, + encoding4(), + ) + } + + #[test] + fn test_op_wasm() { + // Doesn't matter for this test. + let encoding = encoding4(); + + check_op_parse( + |s| s.D8(constants::DW_OP_WASM_location.0).D8(0).uleb(1000), + &Operation::WasmLocal { index: 1000 }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_WASM_location.0).D8(1).uleb(1000), + &Operation::WasmGlobal { index: 1000 }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_WASM_location.0).D8(2).uleb(1000), + &Operation::WasmStack { index: 1000 }, + encoding, + ); + check_op_parse( + |s| s.D8(constants::DW_OP_WASM_location.0).D8(3).D32(1000), + &Operation::WasmGlobal { index: 1000 }, + encoding, + ); + } + + enum AssemblerEntry { + Op(constants::DwOp), + Mark(u8), + Branch(u8), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + Uleb(u64), + Sleb(u64), + } + + fn assemble(entries: &[AssemblerEntry]) -> Vec { + let mut result = Vec::new(); + + struct Marker(Option, Vec); + + let mut markers = Vec::new(); + for _ in 0..256 { + markers.push(Marker(None, Vec::new())); + } + + fn write(stack: &mut [u8], index: usize, mut num: u64, nbytes: u8) { + for i in 0..nbytes as usize { + stack[index + i] = (num & 0xff) as u8; + num >>= 8; + } + } + + fn push(stack: &mut Vec, num: u64, nbytes: u8) { + let index = stack.len(); + for _ in 0..nbytes { + stack.push(0); + } + write(stack, index, num, nbytes); + } + + for item in entries { + match *item { + AssemblerEntry::Op(op) => result.push(op.0), + AssemblerEntry::Mark(num) => { + assert!(markers[num as usize].0.is_none()); + markers[num as usize].0 = Some(result.len()); + } + AssemblerEntry::Branch(num) => { + markers[num as usize].1.push(result.len()); + push(&mut result, 0, 2); + } + AssemblerEntry::U8(num) => result.push(num), + AssemblerEntry::U16(num) => push(&mut result, u64::from(num), 2), + AssemblerEntry::U32(num) => push(&mut result, u64::from(num), 4), + AssemblerEntry::U64(num) => push(&mut result, num, 8), + AssemblerEntry::Uleb(num) => { + leb128::write::unsigned(&mut result, num).unwrap(); + } + AssemblerEntry::Sleb(num) => { + leb128::write::signed(&mut result, num as i64).unwrap(); + } + } + } + + // Update all the branches. + for marker in markers { + if let Some(offset) = marker.0 { + for branch_offset in marker.1 { + let delta = offset.wrapping_sub(branch_offset + 2) as u64; + write(&mut result, branch_offset, delta, 2); + } + } + } + + result + } + + fn check_eval_with_args( + program: &[AssemblerEntry], + expect: Result<&[Piece>]>, + encoding: Encoding, + object_address: Option, + initial_value: Option, + max_iterations: Option, + f: F, + ) where + for<'a> F: Fn( + &mut Evaluation>, + EvaluationResult>, + ) -> Result>>, + { + let bytes = assemble(program); + let bytes = EndianSlice::new(&bytes, LittleEndian); + + let mut eval = Evaluation::new(bytes, encoding); + + if let Some(val) = object_address { + eval.set_object_address(val); + } + if let Some(val) = initial_value { + eval.set_initial_value(val); + } + if let Some(val) = max_iterations { + eval.set_max_iterations(val); + } + + let result = match eval.evaluate() { + Err(e) => Err(e), + Ok(r) => f(&mut eval, r), + }; + + match (result, expect) { + (Ok(EvaluationResult::Complete), Ok(pieces)) => { + let vec = eval.result(); + assert_eq!(vec.len(), pieces.len()); + for i in 0..pieces.len() { + assert_eq!(vec[i], pieces[i]); + } + } + (Err(f1), Err(f2)) => { + assert_eq!(f1, f2); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + fn check_eval( + program: &[AssemblerEntry], + expect: Result<&[Piece>]>, + encoding: Encoding, + ) { + check_eval_with_args(program, expect, encoding, None, None, None, |_, result| { + Ok(result) + }); + } + + #[test] + fn test_eval_arith() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Indices of marks in the assembly. + let done = 0; + let fail = 1; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_const1u), U8(23), + Op(DW_OP_const1s), U8((-23i8) as u8), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const2u), U16(23), + Op(DW_OP_const2s), U16((-23i16) as u16), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4u), U32(0x1111_2222), + Op(DW_OP_const4s), U32((-0x1111_2222i32) as u32), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + // Plus should overflow. + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1u), U8(1), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_plus_uconst), Uleb(1), + Op(DW_OP_bra), Branch(fail), + + // Minus should underflow. + Op(DW_OP_const1s), U8(0), + Op(DW_OP_const1u), U8(1), + Op(DW_OP_minus), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_abs), + Op(DW_OP_const1u), U8(1), + Op(DW_OP_minus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4u), U32(0xf078_fffe), + Op(DW_OP_const4u), U32(0x0f87_0001), + Op(DW_OP_and), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4u), U32(0xf078_fffe), + Op(DW_OP_const4u), U32(0xf000_00fe), + Op(DW_OP_and), + Op(DW_OP_const4u), U32(0xf000_00fe), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + // Division is signed. + Op(DW_OP_const1s), U8(0xfe), + Op(DW_OP_const1s), U8(2), + Op(DW_OP_div), + Op(DW_OP_plus_uconst), Uleb(1), + Op(DW_OP_bra), Branch(fail), + + // Mod is unsigned. + Op(DW_OP_const1s), U8(0xfd), + Op(DW_OP_const1s), U8(2), + Op(DW_OP_mod), + Op(DW_OP_neg), + Op(DW_OP_plus_uconst), Uleb(1), + Op(DW_OP_bra), Branch(fail), + + // Overflow is defined for multiplication. + Op(DW_OP_const4u), U32(0x8000_0001), + Op(DW_OP_lit2), + Op(DW_OP_mul), + Op(DW_OP_lit2), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4u), U32(0xf0f0_f0f0), + Op(DW_OP_const4u), U32(0xf0f0_f0f0), + Op(DW_OP_xor), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4u), U32(0xf0f0_f0f0), + Op(DW_OP_const4u), U32(0x0f0f_0f0f), + Op(DW_OP_or), + Op(DW_OP_not), + Op(DW_OP_bra), Branch(fail), + + // In 32 bit mode, values are truncated. + Op(DW_OP_const8u), U64(0xffff_ffff_0000_0000), + Op(DW_OP_lit2), + Op(DW_OP_div), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1u), U8(0xff), + Op(DW_OP_lit1), + Op(DW_OP_shl), + Op(DW_OP_const2u), U16(0x1fe), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1u), U8(0xff), + Op(DW_OP_const1u), U8(50), + Op(DW_OP_shl), + Op(DW_OP_bra), Branch(fail), + + // Absurd shift. + Op(DW_OP_const1u), U8(0xff), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_shl), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_lit1), + Op(DW_OP_shr), + Op(DW_OP_const4u), U32(0x7fff_ffff), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1u), U8(0xff), + Op(DW_OP_shr), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_lit1), + Op(DW_OP_shra), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1u), U8(0xff), + Op(DW_OP_shra), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + // Success. + Op(DW_OP_lit0), + Op(DW_OP_nop), + Op(DW_OP_skip), Branch(done), + + Mark(fail), + Op(DW_OP_lit1), + + Mark(done), + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0), + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + } + + #[test] + fn test_eval_arith64() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Indices of marks in the assembly. + let done = 0; + let fail = 1; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_const8u), U64(0x1111_2222_3333_4444), + Op(DW_OP_const8s), U64((-0x1111_2222_3333_4444i64) as u64), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_constu), Uleb(0x1111_2222_3333_4444), + Op(DW_OP_consts), Sleb((-0x1111_2222_3333_4444i64) as u64), + Op(DW_OP_plus), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit1), + Op(DW_OP_plus_uconst), Uleb(!0u64), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit1), + Op(DW_OP_neg), + Op(DW_OP_not), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const8u), U64(0x8000_0000_0000_0000), + Op(DW_OP_const1u), U8(63), + Op(DW_OP_shr), + Op(DW_OP_lit1), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const8u), U64(0x8000_0000_0000_0000), + Op(DW_OP_const1u), U8(62), + Op(DW_OP_shra), + Op(DW_OP_plus_uconst), Uleb(2), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit1), + Op(DW_OP_const1u), U8(63), + Op(DW_OP_shl), + Op(DW_OP_const8u), U64(0x8000_0000_0000_0000), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + // Success. + Op(DW_OP_lit0), + Op(DW_OP_nop), + Op(DW_OP_skip), Branch(done), + + Mark(fail), + Op(DW_OP_lit1), + + Mark(done), + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0), + }, + }]; + + check_eval(&program, Ok(&result), encoding8()); + } + + #[test] + fn test_eval_compare() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Indices of marks in the assembly. + let done = 0; + let fail = 1; + + #[rustfmt::skip] + let program = [ + // Comparisons are signed. + Op(DW_OP_const1s), U8(1), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_lt), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1s), U8(1), + Op(DW_OP_gt), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(1), + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_le), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1s), U8(1), + Op(DW_OP_ge), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const1s), U8(0xff), + Op(DW_OP_const1s), U8(1), + Op(DW_OP_eq), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_const4s), U32(1), + Op(DW_OP_const1s), U8(1), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + // Success. + Op(DW_OP_lit0), + Op(DW_OP_nop), + Op(DW_OP_skip), Branch(done), + + Mark(fail), + Op(DW_OP_lit1), + + Mark(done), + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0), + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + } + + #[test] + fn test_eval_stack() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_lit17), // -- 17 + Op(DW_OP_dup), // -- 17 17 + Op(DW_OP_over), // -- 17 17 17 + Op(DW_OP_minus), // -- 17 0 + Op(DW_OP_swap), // -- 0 17 + Op(DW_OP_dup), // -- 0 17 17 + Op(DW_OP_plus_uconst), Uleb(1), // -- 0 17 18 + Op(DW_OP_rot), // -- 18 0 17 + Op(DW_OP_pick), U8(2), // -- 18 0 17 18 + Op(DW_OP_pick), U8(3), // -- 18 0 17 18 18 + Op(DW_OP_minus), // -- 18 0 17 0 + Op(DW_OP_drop), // -- 18 0 17 + Op(DW_OP_swap), // -- 18 17 0 + Op(DW_OP_drop), // -- 18 17 + Op(DW_OP_minus), // -- 1 + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(1), + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + } + + #[test] + fn test_eval_lit_and_reg() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + let mut program = Vec::new(); + program.push(Op(DW_OP_lit0)); + for i in 0..32 { + program.push(Op(DwOp(DW_OP_lit0.0 + i))); + program.push(Op(DwOp(DW_OP_breg0.0 + i))); + program.push(Sleb(u64::from(i))); + program.push(Op(DW_OP_plus)); + program.push(Op(DW_OP_plus)); + } + + program.push(Op(DW_OP_bregx)); + program.push(Uleb(0x1234)); + program.push(Sleb(0x1234)); + program.push(Op(DW_OP_plus)); + + program.push(Op(DW_OP_stack_value)); + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(496), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, mut result| { + while result != EvaluationResult::Complete { + result = eval.resume_with_register(match result { + EvaluationResult::RequiresRegister { + register, + base_type, + } => { + assert_eq!(base_type, UnitOffset(0)); + Value::Generic(u64::from(register.0).wrapping_neg()) + } + _ => panic!(), + })?; + } + Ok(result) + }, + ); + } + + #[test] + fn test_eval_memory() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Indices of marks in the assembly. + let done = 0; + let fail = 1; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_deref), + Op(DW_OP_const4u), U32(0xffff_fffc), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_deref_size), U8(2), + Op(DW_OP_const4u), U32(0xfffc), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit1), + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_xderef), + Op(DW_OP_const4u), U32(0xffff_fffd), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit1), + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_xderef_size), U8(2), + Op(DW_OP_const4u), U32(0xfffd), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit17), + Op(DW_OP_form_tls_address), + Op(DW_OP_constu), Uleb(!17), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_lit17), + Op(DW_OP_GNU_push_tls_address), + Op(DW_OP_constu), Uleb(!17), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_addrx), Uleb(0x10), + Op(DW_OP_deref), + Op(DW_OP_const4u), U32(0x4040), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + Op(DW_OP_constx), Uleb(17), + Op(DW_OP_form_tls_address), + Op(DW_OP_constu), Uleb(!27), + Op(DW_OP_ne), + Op(DW_OP_bra), Branch(fail), + + // Success. + Op(DW_OP_lit0), + Op(DW_OP_nop), + Op(DW_OP_skip), Branch(done), + + Mark(fail), + Op(DW_OP_lit1), + + Mark(done), + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, mut result| { + while result != EvaluationResult::Complete { + result = match result { + EvaluationResult::RequiresMemory { + address, + size, + space, + base_type, + } => { + assert_eq!(base_type, UnitOffset(0)); + let mut v = address << 2; + if let Some(value) = space { + v += value; + } + v &= (1u64 << (8 * size)) - 1; + eval.resume_with_memory(Value::Generic(v))? + } + EvaluationResult::RequiresTls(slot) => eval.resume_with_tls(!slot)?, + EvaluationResult::RequiresRelocatedAddress(address) => { + eval.resume_with_relocated_address(address)? + } + EvaluationResult::RequiresIndexedAddress { index, relocate } => { + if relocate { + eval.resume_with_indexed_address(0x1000 + index.0 as u64)? + } else { + eval.resume_with_indexed_address(10 + index.0 as u64)? + } + } + _ => panic!(), + }; + } + + Ok(result) + }, + ); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_deref_size), U8(8), + ]; + check_eval_with_args( + &program, + Err(Error::InvalidDerefSize(8)), + encoding4(), + None, + None, + None, + |eval, mut result| { + while result != EvaluationResult::Complete { + result = match result { + EvaluationResult::RequiresMemory { + address, + size, + space, + base_type, + } => { + assert_eq!(base_type, UnitOffset(0)); + let mut v = address << 2; + if let Some(value) = space { + v += value; + } + v &= (1u64 << (8 * size)) - 1; + eval.resume_with_memory(Value::Generic(v))? + } + EvaluationResult::RequiresRelocatedAddress(address) => { + eval.resume_with_relocated_address(address)? + } + _ => panic!("Unexpected result: {:?}", result), + }; + } + + Ok(result) + }, + ); + } + + #[test] + fn test_eval_register() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + for i in 0..32 { + #[rustfmt::skip] + let program = [ + Op(DwOp(DW_OP_reg0.0 + i)), + // Included only in the "bad" run. + Op(DW_OP_lit23), + ]; + let ok_result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Register { + register: Register(i.into()), + }, + }]; + + check_eval(&program[..1], Ok(&ok_result), encoding4()); + + check_eval( + &program, + Err(Error::InvalidExpressionTerminator(1)), + encoding4(), + ); + } + + #[rustfmt::skip] + let program = [ + Op(DW_OP_regx), Uleb(0x1234) + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Register { + register: Register(0x1234), + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + } + + #[test] + fn test_eval_context() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Test `frame_base` and `call_frame_cfa` callbacks. + #[rustfmt::skip] + let program = [ + Op(DW_OP_fbreg), Sleb((-8i8) as u64), + Op(DW_OP_call_frame_cfa), + Op(DW_OP_plus), + Op(DW_OP_neg), + Op(DW_OP_stack_value) + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(9), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding8(), + None, + None, + None, + |eval, result| { + match result { + EvaluationResult::RequiresFrameBase => {} + _ => panic!(), + }; + match eval.resume_with_frame_base(0x0123_4567_89ab_cdef)? { + EvaluationResult::RequiresCallFrameCfa => {} + _ => panic!(), + }; + eval.resume_with_call_frame_cfa(0xfedc_ba98_7654_3210) + }, + ); + + // Test `evaluate_entry_value` callback. + #[rustfmt::skip] + let program = [ + Op(DW_OP_entry_value), Uleb(8), U64(0x1234_5678), + Op(DW_OP_stack_value) + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0x1234_5678), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding8(), + None, + None, + None, + |eval, result| { + let entry_value = match result { + EvaluationResult::RequiresEntryValue(mut expression) => { + expression.0.read_u64()? + } + _ => panic!(), + }; + eval.resume_with_entry_value(Value::Generic(entry_value)) + }, + ); + + // Test missing `object_address` field. + #[rustfmt::skip] + let program = [ + Op(DW_OP_push_object_address), + ]; + + check_eval_with_args( + &program, + Err(Error::InvalidPushObjectAddress), + encoding4(), + None, + None, + None, + |_, _| panic!(), + ); + + // Test `object_address` field. + #[rustfmt::skip] + let program = [ + Op(DW_OP_push_object_address), + Op(DW_OP_stack_value), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(0xff), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding8(), + Some(0xff), + None, + None, + |_, result| Ok(result), + ); + + // Test `initial_value` field. + #[rustfmt::skip] + let program = [ + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Address { + address: 0x1234_5678, + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding8(), + None, + Some(0x1234_5678), + None, + |_, result| Ok(result), + ); + } + + #[test] + fn test_eval_empty_stack() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_stack_value) + ]; + + check_eval(&program, Err(Error::NotEnoughStackItems), encoding4()); + } + + #[test] + fn test_eval_call() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + #[rustfmt::skip] + let program = [ + Op(DW_OP_lit23), + Op(DW_OP_call2), U16(0x7755), + Op(DW_OP_call4), U32(0x7755_aaee), + Op(DW_OP_call_ref), U32(0x7755_aaee), + Op(DW_OP_stack_value) + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(23), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, result| { + let buf = EndianSlice::new(&[], LittleEndian); + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf)?; + + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf)?; + + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf) + }, + ); + + // DW_OP_lit2 DW_OP_mul + const SUBR: &[u8] = &[0x32, 0x1e]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { + value: Value::Generic(184), + }, + }]; + + check_eval_with_args( + &program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, result| { + let buf = EndianSlice::new(SUBR, LittleEndian); + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf)?; + + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf)?; + + match result { + EvaluationResult::RequiresAtLocation(_) => {} + _ => panic!(), + }; + + eval.resume_with_at_location(buf) + }, + ); + } + + #[test] + fn test_eval_pieces() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + // Example from DWARF 2.6.1.3. + #[rustfmt::skip] + let program = [ + Op(DW_OP_reg3), + Op(DW_OP_piece), Uleb(4), + Op(DW_OP_reg4), + Op(DW_OP_piece), Uleb(2), + ]; + + let result = [ + Piece { + size_in_bits: Some(32), + bit_offset: None, + location: Location::Register { + register: Register(3), + }, + }, + Piece { + size_in_bits: Some(16), + bit_offset: None, + location: Location::Register { + register: Register(4), + }, + }, + ]; + + check_eval(&program, Ok(&result), encoding4()); + + // Example from DWARF 2.6.1.3 (but hacked since dealing with fbreg + // in the tests is a pain). + #[rustfmt::skip] + let program = [ + Op(DW_OP_reg0), + Op(DW_OP_piece), Uleb(4), + Op(DW_OP_piece), Uleb(4), + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_piece), Uleb(4), + ]; + + let result = [ + Piece { + size_in_bits: Some(32), + bit_offset: None, + location: Location::Register { + register: Register(0), + }, + }, + Piece { + size_in_bits: Some(32), + bit_offset: None, + location: Location::Empty, + }, + Piece { + size_in_bits: Some(32), + bit_offset: None, + location: Location::Address { + address: 0x7fff_ffff, + }, + }, + ]; + + check_eval_with_args( + &program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, mut result| { + while result != EvaluationResult::Complete { + result = match result { + EvaluationResult::RequiresRelocatedAddress(address) => { + eval.resume_with_relocated_address(address)? + } + _ => panic!(), + }; + } + + Ok(result) + }, + ); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_implicit_value), Uleb(5), + U8(23), U8(24), U8(25), U8(26), U8(0), + ]; + + const BYTES: &[u8] = &[23, 24, 25, 26, 0]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Bytes { + value: EndianSlice::new(BYTES, LittleEndian), + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_lit7), + Op(DW_OP_stack_value), + Op(DW_OP_bit_piece), Uleb(5), Uleb(0), + Op(DW_OP_bit_piece), Uleb(3), Uleb(0), + ]; + + let result = [ + Piece { + size_in_bits: Some(5), + bit_offset: Some(0), + location: Location::Value { + value: Value::Generic(7), + }, + }, + Piece { + size_in_bits: Some(3), + bit_offset: Some(0), + location: Location::Empty, + }, + ]; + + check_eval(&program, Ok(&result), encoding4()); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_lit7), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Address { address: 7 }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_implicit_pointer), U32(0x1234_5678), Sleb(0x123), + ]; + + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::ImplicitPointer { + value: DebugInfoOffset(0x1234_5678), + byte_offset: 0x123, + }, + }]; + + check_eval(&program, Ok(&result), encoding4()); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_reg3), + Op(DW_OP_piece), Uleb(4), + Op(DW_OP_reg4), + ]; + + check_eval(&program, Err(Error::InvalidPiece), encoding4()); + + #[rustfmt::skip] + let program = [ + Op(DW_OP_reg3), + Op(DW_OP_piece), Uleb(4), + Op(DW_OP_lit0), + ]; + + check_eval(&program, Err(Error::InvalidPiece), encoding4()); + } + + #[test] + fn test_eval_max_iterations() { + // It's nice if an operation and its arguments can fit on a single + // line in the test program. + use self::AssemblerEntry::*; + use crate::constants::*; + + #[rustfmt::skip] + let program = [ + Mark(1), + Op(DW_OP_skip), Branch(1), + ]; + + check_eval_with_args( + &program, + Err(Error::TooManyIterations), + encoding4(), + None, + None, + Some(150), + |_, _| panic!(), + ); + } + + #[test] + fn test_eval_typed_stack() { + use self::AssemblerEntry::*; + use crate::constants::*; + + let base_types = [ + ValueType::Generic, + ValueType::U16, + ValueType::U32, + ValueType::F32, + ]; + + // TODO: convert, reinterpret + #[rustfmt::skip] + let tests = [ + ( + &[ + Op(DW_OP_const_type), Uleb(1), U8(2), U16(0x1234), + Op(DW_OP_stack_value), + ][..], + Value::U16(0x1234), + ), + ( + &[ + Op(DW_OP_regval_type), Uleb(0x1234), Uleb(1), + Op(DW_OP_stack_value), + ][..], + Value::U16(0x2340), + ), + ( + &[ + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_deref_type), U8(2), Uleb(1), + Op(DW_OP_stack_value), + ][..], + Value::U16(0xfff0), + ), + ( + &[ + Op(DW_OP_lit1), + Op(DW_OP_addr), U32(0x7fff_ffff), + Op(DW_OP_xderef_type), U8(2), Uleb(1), + Op(DW_OP_stack_value), + ][..], + Value::U16(0xfff1), + ), + ( + &[ + Op(DW_OP_const_type), Uleb(1), U8(2), U16(0x1234), + Op(DW_OP_convert), Uleb(2), + Op(DW_OP_stack_value), + ][..], + Value::U32(0x1234), + ), + ( + &[ + Op(DW_OP_const_type), Uleb(2), U8(4), U32(0x3f80_0000), + Op(DW_OP_reinterpret), Uleb(3), + Op(DW_OP_stack_value), + ][..], + Value::F32(1.0), + ), + ]; + for &(program, value) in &tests { + let result = [Piece { + size_in_bits: None, + bit_offset: None, + location: Location::Value { value }, + }]; + + check_eval_with_args( + program, + Ok(&result), + encoding4(), + None, + None, + None, + |eval, mut result| { + while result != EvaluationResult::Complete { + result = match result { + EvaluationResult::RequiresMemory { + address, + size, + space, + base_type, + } => { + let mut v = address << 4; + if let Some(value) = space { + v += value; + } + v &= (1u64 << (8 * size)) - 1; + let v = Value::from_u64(base_types[base_type.0], v)?; + eval.resume_with_memory(v)? + } + EvaluationResult::RequiresRegister { + register, + base_type, + } => { + let v = Value::from_u64( + base_types[base_type.0], + u64::from(register.0) << 4, + )?; + eval.resume_with_register(v)? + } + EvaluationResult::RequiresBaseType(offset) => { + eval.resume_with_base_type(base_types[offset.0])? + } + EvaluationResult::RequiresRelocatedAddress(address) => { + eval.resume_with_relocated_address(address)? + } + _ => panic!("Unexpected result {:?}", result), + } + } + Ok(result) + }, + ); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/read/pubnames.rs b/anneal/v2/vendor/gimli/src/read/pubnames.rs new file mode 100644 index 0000000000..e8b7e55286 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/pubnames.rs @@ -0,0 +1,141 @@ +use crate::common::{DebugInfoOffset, SectionId}; +use crate::endianity::Endianity; +use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser}; +use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset}; + +/// A single parsed pubname. +#[derive(Debug, Clone)] +pub struct PubNamesEntry { + unit_header_offset: DebugInfoOffset, + die_offset: UnitOffset, + name: R, +} + +impl PubNamesEntry { + /// Returns the name this entry refers to. + pub fn name(&self) -> &R { + &self.name + } + + /// Returns the offset into the .debug_info section for the header of the compilation unit + /// which contains this name. + pub fn unit_header_offset(&self) -> DebugInfoOffset { + self.unit_header_offset + } + + /// Returns the offset into the compilation unit for the debugging information entry which + /// has this name. + pub fn die_offset(&self) -> UnitOffset { + self.die_offset + } +} + +impl PubStuffEntry for PubNamesEntry { + fn new( + die_offset: UnitOffset, + name: R, + unit_header_offset: DebugInfoOffset, + ) -> Self { + PubNamesEntry { + unit_header_offset, + die_offset, + name, + } + } +} + +/// The `DebugPubNames` struct represents the DWARF public names information +/// found in the `.debug_pubnames` section. +#[derive(Debug, Clone)] +pub struct DebugPubNames(DebugLookup>>); + +impl<'input, Endian> DebugPubNames> +where + Endian: Endianity, +{ + /// Construct a new `DebugPubNames` instance from the data in the `.debug_pubnames` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_pubnames` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugPubNames, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_pubnames_section_somehow = || &buf; + /// let debug_pubnames = + /// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_pubnames_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_pubnames_section, endian)) + } +} + +impl DebugPubNames { + /// Iterate the pubnames in the `.debug_pubnames` section. + /// + /// ``` + /// use gimli::{DebugPubNames, EndianSlice, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_pubnames_section_somehow = || &buf; + /// let debug_pubnames = + /// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian); + /// + /// let mut iter = debug_pubnames.items(); + /// while let Some(pubname) = iter.next().unwrap() { + /// println!("pubname {} found!", pubname.name().to_string_lossy()); + /// } + /// ``` + pub fn items(&self) -> PubNamesEntryIter { + PubNamesEntryIter(self.0.items()) + } +} + +impl Section for DebugPubNames { + fn id() -> SectionId { + SectionId::DebugPubNames + } + + fn reader(&self) -> &R { + self.0.reader() + } +} + +impl From for DebugPubNames { + fn from(debug_pubnames_section: R) -> Self { + DebugPubNames(DebugLookup::from(debug_pubnames_section)) + } +} + +/// An iterator over the pubnames from a `.debug_pubnames` section. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Debug, Clone)] +pub struct PubNamesEntryIter(LookupEntryIter>>); + +impl PubNamesEntryIter { + /// Advance the iterator and return the next pubname. + /// + /// Returns the newly parsed pubname as `Ok(Some(pubname))`. Returns + /// `Ok(None)` when iteration is complete and all pubnames have already been + /// parsed and yielded. If an error occurs while parsing the next pubname, + /// then this error is returned as `Err(e)`, and all subsequent calls return + /// `Ok(None)`. + pub fn next(&mut self) -> Result>> { + self.0.next() + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for PubNamesEntryIter { + type Item = PubNamesEntry; + type Error = crate::read::Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + self.0.next() + } +} diff --git a/anneal/v2/vendor/gimli/src/read/pubtypes.rs b/anneal/v2/vendor/gimli/src/read/pubtypes.rs new file mode 100644 index 0000000000..6723b42228 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/pubtypes.rs @@ -0,0 +1,141 @@ +use crate::common::{DebugInfoOffset, SectionId}; +use crate::endianity::Endianity; +use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser}; +use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset}; + +/// A single parsed pubtype. +#[derive(Debug, Clone)] +pub struct PubTypesEntry { + unit_header_offset: DebugInfoOffset, + die_offset: UnitOffset, + name: R, +} + +impl PubTypesEntry { + /// Returns the name of the type this entry refers to. + pub fn name(&self) -> &R { + &self.name + } + + /// Returns the offset into the .debug_info section for the header of the compilation unit + /// which contains the type with this name. + pub fn unit_header_offset(&self) -> DebugInfoOffset { + self.unit_header_offset + } + + /// Returns the offset into the compilation unit for the debugging information entry which + /// the type with this name. + pub fn die_offset(&self) -> UnitOffset { + self.die_offset + } +} + +impl PubStuffEntry for PubTypesEntry { + fn new( + die_offset: UnitOffset, + name: R, + unit_header_offset: DebugInfoOffset, + ) -> Self { + PubTypesEntry { + unit_header_offset, + die_offset, + name, + } + } +} + +/// The `DebugPubTypes` struct represents the DWARF public types information +/// found in the `.debug_info` section. +#[derive(Debug, Clone)] +pub struct DebugPubTypes(DebugLookup>>); + +impl<'input, Endian> DebugPubTypes> +where + Endian: Endianity, +{ + /// Construct a new `DebugPubTypes` instance from the data in the `.debug_pubtypes` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_pubtypes` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugPubTypes, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_pubtypes_somehow = || &buf; + /// let debug_pubtypes = + /// DebugPubTypes::new(read_debug_pubtypes_somehow(), LittleEndian); + /// ``` + pub fn new(debug_pubtypes_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_pubtypes_section, endian)) + } +} + +impl DebugPubTypes { + /// Iterate the pubtypes in the `.debug_pubtypes` section. + /// + /// ``` + /// use gimli::{DebugPubTypes, EndianSlice, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_pubtypes_section_somehow = || &buf; + /// let debug_pubtypes = + /// DebugPubTypes::new(read_debug_pubtypes_section_somehow(), LittleEndian); + /// + /// let mut iter = debug_pubtypes.items(); + /// while let Some(pubtype) = iter.next().unwrap() { + /// println!("pubtype {} found!", pubtype.name().to_string_lossy()); + /// } + /// ``` + pub fn items(&self) -> PubTypesEntryIter { + PubTypesEntryIter(self.0.items()) + } +} + +impl Section for DebugPubTypes { + fn id() -> SectionId { + SectionId::DebugPubTypes + } + + fn reader(&self) -> &R { + self.0.reader() + } +} + +impl From for DebugPubTypes { + fn from(debug_pubtypes_section: R) -> Self { + DebugPubTypes(DebugLookup::from(debug_pubtypes_section)) + } +} + +/// An iterator over the pubtypes from a `.debug_pubtypes` section. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Debug, Clone)] +pub struct PubTypesEntryIter(LookupEntryIter>>); + +impl PubTypesEntryIter { + /// Advance the iterator and return the next pubtype. + /// + /// Returns the newly parsed pubtype as `Ok(Some(pubtype))`. Returns + /// `Ok(None)` when iteration is complete and all pubtypes have already been + /// parsed and yielded. If an error occurs while parsing the next pubtype, + /// then this error is returned as `Err(e)`, and all subsequent calls return + /// `Ok(None)`. + pub fn next(&mut self) -> Result>> { + self.0.next() + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for PubTypesEntryIter { + type Item = PubTypesEntry; + type Error = crate::read::Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + self.0.next() + } +} diff --git a/anneal/v2/vendor/gimli/src/read/reader.rs b/anneal/v2/vendor/gimli/src/read/reader.rs new file mode 100644 index 0000000000..1e3148f854 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/reader.rs @@ -0,0 +1,594 @@ +#[cfg(feature = "read")] +use alloc::borrow::Cow; +use core::convert::TryInto; +use core::fmt::Debug; +use core::hash::Hash; +use core::ops::{Add, AddAssign, Sub}; + +use crate::common::Format; +use crate::endianity::Endianity; +use crate::leb128; +use crate::read::{Error, Result}; + +/// An identifier for an offset within a section reader. +/// +/// This is used for error reporting. The meaning of this value is specific to +/// each reader implementation. The values should be chosen to be unique amongst +/// all readers. If values are not unique then errors may point to the wrong reader. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ReaderOffsetId(pub u64); + +/// A trait for offsets with a DWARF section. +/// +/// This allows consumers to choose a size that is appropriate for their address space. +pub trait ReaderOffset: + Debug + Copy + Eq + Ord + Hash + Add + AddAssign + Sub +{ + /// Convert a u8 to an offset. + fn from_u8(offset: u8) -> Self; + + /// Convert a u16 to an offset. + fn from_u16(offset: u16) -> Self; + + /// Convert an i16 to an offset. + fn from_i16(offset: i16) -> Self; + + /// Convert a u32 to an offset. + fn from_u32(offset: u32) -> Self; + + /// Convert a u64 to an offset. + /// + /// Returns `Error::UnsupportedOffset` if the value is too large. + fn from_u64(offset: u64) -> Result; + + /// Convert an offset to a u64. + fn into_u64(self) -> u64; + + /// Wrapping (modular) addition. Computes `self + other`. + fn wrapping_add(self, other: Self) -> Self; + + /// Checked subtraction. Computes `self - other`. + fn checked_sub(self, other: Self) -> Option; +} + +impl ReaderOffset for u64 { + #[inline] + fn from_u8(offset: u8) -> Self { + u64::from(offset) + } + + #[inline] + fn from_u16(offset: u16) -> Self { + u64::from(offset) + } + + #[inline] + fn from_i16(offset: i16) -> Self { + offset as u64 + } + + #[inline] + fn from_u32(offset: u32) -> Self { + u64::from(offset) + } + + #[inline] + fn from_u64(offset: u64) -> Result { + Ok(offset) + } + + #[inline] + fn into_u64(self) -> u64 { + self + } + + #[inline] + fn wrapping_add(self, other: Self) -> Self { + self.wrapping_add(other) + } + + #[inline] + fn checked_sub(self, other: Self) -> Option { + self.checked_sub(other) + } +} + +impl ReaderOffset for u32 { + #[inline] + fn from_u8(offset: u8) -> Self { + u32::from(offset) + } + + #[inline] + fn from_u16(offset: u16) -> Self { + u32::from(offset) + } + + #[inline] + fn from_i16(offset: i16) -> Self { + offset as u32 + } + + #[inline] + fn from_u32(offset: u32) -> Self { + offset + } + + #[inline] + fn from_u64(offset64: u64) -> Result { + let offset = offset64 as u32; + if u64::from(offset) == offset64 { + Ok(offset) + } else { + Err(Error::UnsupportedOffset) + } + } + + #[inline] + fn into_u64(self) -> u64 { + u64::from(self) + } + + #[inline] + fn wrapping_add(self, other: Self) -> Self { + self.wrapping_add(other) + } + + #[inline] + fn checked_sub(self, other: Self) -> Option { + self.checked_sub(other) + } +} + +impl ReaderOffset for usize { + #[inline] + fn from_u8(offset: u8) -> Self { + offset as usize + } + + #[inline] + fn from_u16(offset: u16) -> Self { + offset as usize + } + + #[inline] + fn from_i16(offset: i16) -> Self { + offset as usize + } + + #[inline] + fn from_u32(offset: u32) -> Self { + offset as usize + } + + #[inline] + fn from_u64(offset64: u64) -> Result { + let offset = offset64 as usize; + if offset as u64 == offset64 { + Ok(offset) + } else { + Err(Error::UnsupportedOffset) + } + } + + #[inline] + fn into_u64(self) -> u64 { + self as u64 + } + + #[inline] + fn wrapping_add(self, other: Self) -> Self { + self.wrapping_add(other) + } + + #[inline] + fn checked_sub(self, other: Self) -> Option { + self.checked_sub(other) + } +} + +/// A trait for addresses within a DWARF section. +/// +/// Currently this is a simple extension trait for `u64`, but it may be expanded +/// in the future to support user-defined address types. +pub(crate) trait ReaderAddress: Sized { + /// Add a length to an address of the given size. + /// + /// Returns an error for overflow. + fn add_sized(self, length: u64, size: u8) -> Result; + + /// Add a length to an address of the given size. + /// + /// Wraps the result to the size of the address to allow for the possibility + /// that the length is a negative value. + fn wrapping_add_sized(self, length: u64, size: u8) -> Self; + + /// The all-zeros value of an address. + fn zeros() -> Self; + + /// The all-ones value of an address of the given size. + fn ones_sized(size: u8) -> Self; + + /// Return the minimum value for a tombstone address. + /// + /// A variety of values may be used as tombstones in DWARF data. DWARF 6 specifies a + /// tombstone value of -1, and this is compatible with most sections in earlier DWARF + /// versions. However, for .debug_loc and .debug_ranges in DWARF 4 and earlier, the + /// tombstone value is -2, because -1 already has a special meaning. -2 has also been + /// seen in .debug_line, possibly from a proprietary fork of lld. + /// + /// So this function returns -2 (cast to an unsigned value), and callers can consider + /// addresses greater than or equal to this value to be tombstones. + /// + /// Prior to the use of -1 or -2 for tombstones, it was common to use 0 or 1. + /// Additionally, gold may leave the relocation addend in place. These values are not + /// handled by this function, so callers will need to handle them separately if they + /// want to. + fn min_tombstone(size: u8) -> Self { + Self::zeros().wrapping_add_sized(-2i64 as u64, size) + } +} + +impl ReaderAddress for u64 { + #[inline] + fn add_sized(self, length: u64, size: u8) -> Result { + let address = self.checked_add(length).ok_or(Error::AddressOverflow)?; + let mask = Self::ones_sized(size); + if address & !mask != 0 { + return Err(Error::AddressOverflow); + } + Ok(address) + } + + #[inline] + fn wrapping_add_sized(self, length: u64, size: u8) -> Self { + let mask = Self::ones_sized(size); + self.wrapping_add(length) & mask + } + + #[inline] + fn zeros() -> Self { + 0 + } + + #[inline] + fn ones_sized(size: u8) -> Self { + !0 >> (64 - size * 8) + } +} + +#[cfg(not(feature = "read"))] +pub(crate) mod seal_if_no_alloc { + #[derive(Debug)] + pub struct Sealed; +} + +/// A trait for reading the data from a DWARF section. +/// +/// All read operations advance the section offset of the reader +/// unless specified otherwise. +/// +/// ## Choosing a `Reader` Implementation +/// +/// `gimli` comes with a few different `Reader` implementations and lets you +/// choose the one that is right for your use case. A `Reader` is essentially a +/// view into the raw bytes that make up some DWARF, but this view might borrow +/// the underlying data or use reference counting ownership, and it might be +/// thread safe or not. +/// +/// | Implementation | Ownership | Thread Safe | Notes | +/// |:------------------|:------------------|:------------|:------| +/// | [`EndianSlice`](./struct.EndianSlice.html) | Borrowed | Yes | Fastest, but requires that all of your code work with borrows. | +/// | [`EndianRcSlice`](./struct.EndianRcSlice.html) | Reference counted | No | Shared ownership via reference counting, which alleviates the borrow restrictions of `EndianSlice` but imposes reference counting increments and decrements. Cannot be sent across threads, because the reference count is not atomic. | +/// | [`EndianArcSlice`](./struct.EndianArcSlice.html) | Reference counted | Yes | The same as `EndianRcSlice`, but uses atomic reference counting, and therefore reference counting operations are slower but `EndianArcSlice`s may be sent across threads. | +/// | [`EndianReader`](./struct.EndianReader.html) | Same as `T` | Same as `T` | Escape hatch for easily defining your own type of `Reader`. | +pub trait Reader: Debug + Clone { + /// The endianity of bytes that are read. + type Endian: Endianity; + + /// The type used for offsets and lengths. + type Offset: ReaderOffset; + + /// Return the endianity of bytes that are read. + fn endian(&self) -> Self::Endian; + + /// Return the number of bytes remaining. + fn len(&self) -> Self::Offset; + + /// Set the number of bytes remaining to zero. + fn empty(&mut self); + + /// Set the number of bytes remaining to the specified length. + fn truncate(&mut self, len: Self::Offset) -> Result<()>; + + /// Return the offset of this reader's data relative to the start of + /// the given base reader's data. + /// + /// May panic if this reader's data is not contained within the given + /// base reader's data. + fn offset_from(&self, base: &Self) -> Self::Offset; + + /// Return an identifier for the current reader offset. + fn offset_id(&self) -> ReaderOffsetId; + + /// Return the offset corresponding to the given `id` if + /// it is associated with this reader. + fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option; + + /// Find the index of the first occurrence of the given byte. + /// The offset of the reader is not changed. + fn find(&self, byte: u8) -> Result; + + /// Discard the specified number of bytes. + fn skip(&mut self, len: Self::Offset) -> Result<()>; + + /// Split a reader in two. + /// + /// A new reader is returned that can be used to read the next + /// `len` bytes, and `self` is advanced so that it reads the remainder. + fn split(&mut self, len: Self::Offset) -> Result; + + /// This trait cannot be implemented if "read" feature is not enabled. + /// + /// `Reader` trait has a few methods that depend on `alloc` crate. + /// Disallowing `Reader` trait implementation prevents a crate that only depends on + /// "read-core" from being broken if another crate depending on `gimli` enables + /// "read" feature. + #[cfg(not(feature = "read"))] + fn cannot_implement() -> seal_if_no_alloc::Sealed; + + /// Return all remaining data as a clone-on-write slice. + /// + /// The slice will be borrowed where possible, but some readers may + /// always return an owned vector. + /// + /// Does not advance the reader. + #[cfg(feature = "read")] + fn to_slice(&self) -> Result>; + + /// Convert all remaining data to a clone-on-write string. + /// + /// The string will be borrowed where possible, but some readers may + /// always return an owned string. + /// + /// Does not advance the reader. + /// + /// Returns an error if the data contains invalid characters. + #[cfg(feature = "read")] + fn to_string(&self) -> Result>; + + /// Convert all remaining data to a clone-on-write string, including invalid characters. + /// + /// The string will be borrowed where possible, but some readers may + /// always return an owned string. + /// + /// Does not advance the reader. + #[cfg(feature = "read")] + fn to_string_lossy(&self) -> Result>; + + /// Read exactly `buf.len()` bytes into `buf`. + fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>; + + /// Read a u8 array. + #[inline] + fn read_u8_array(&mut self) -> Result + where + A: Sized + Default + AsMut<[u8]>, + { + let mut val = Default::default(); + self.read_slice(>::as_mut(&mut val))?; + Ok(val) + } + + /// Return true if the number of bytes remaining is zero. + #[inline] + fn is_empty(&self) -> bool { + self.len() == Self::Offset::from_u8(0) + } + + /// Read a u8. + #[inline] + fn read_u8(&mut self) -> Result { + let a: [u8; 1] = self.read_u8_array()?; + Ok(a[0]) + } + + /// Read an i8. + #[inline] + fn read_i8(&mut self) -> Result { + let a: [u8; 1] = self.read_u8_array()?; + Ok(a[0] as i8) + } + + /// Read a u16. + #[inline] + fn read_u16(&mut self) -> Result { + let a: [u8; 2] = self.read_u8_array()?; + Ok(self.endian().read_u16(&a)) + } + + /// Read an i16. + #[inline] + fn read_i16(&mut self) -> Result { + let a: [u8; 2] = self.read_u8_array()?; + Ok(self.endian().read_i16(&a)) + } + + /// Read a u32. + #[inline] + fn read_u32(&mut self) -> Result { + let a: [u8; 4] = self.read_u8_array()?; + Ok(self.endian().read_u32(&a)) + } + + /// Read an i32. + #[inline] + fn read_i32(&mut self) -> Result { + let a: [u8; 4] = self.read_u8_array()?; + Ok(self.endian().read_i32(&a)) + } + + /// Read a u64. + #[inline] + fn read_u64(&mut self) -> Result { + let a: [u8; 8] = self.read_u8_array()?; + Ok(self.endian().read_u64(&a)) + } + + /// Read an i64. + #[inline] + fn read_i64(&mut self) -> Result { + let a: [u8; 8] = self.read_u8_array()?; + Ok(self.endian().read_i64(&a)) + } + + /// Read a f32. + #[inline] + fn read_f32(&mut self) -> Result { + let a: [u8; 4] = self.read_u8_array()?; + Ok(self.endian().read_f32(&a)) + } + + /// Read a f64. + #[inline] + fn read_f64(&mut self) -> Result { + let a: [u8; 8] = self.read_u8_array()?; + Ok(self.endian().read_f64(&a)) + } + + /// Read an unsigned n-bytes integer u64. + /// + /// # Panics + /// + /// Panics when nbytes < 1 or nbytes > 8 + #[inline] + fn read_uint(&mut self, n: usize) -> Result { + let mut buf = [0; 8]; + self.read_slice(&mut buf[..n])?; + Ok(self.endian().read_uint(&buf[..n])) + } + + /// Read a null-terminated slice, and return it (excluding the null). + fn read_null_terminated_slice(&mut self) -> Result { + let idx = self.find(0)?; + let val = self.split(idx)?; + self.skip(Self::Offset::from_u8(1))?; + Ok(val) + } + + /// Skip a LEB128 encoded integer. + fn skip_leb128(&mut self) -> Result<()> { + leb128::read::skip(self) + } + + /// Read an unsigned LEB128 encoded integer. + fn read_uleb128(&mut self) -> Result { + leb128::read::unsigned(self) + } + + /// Read an unsigned LEB128 encoded u32. + fn read_uleb128_u32(&mut self) -> Result { + leb128::read::unsigned(self)? + .try_into() + .map_err(|_| Error::BadUnsignedLeb128) + } + + /// Read an unsigned LEB128 encoded u16. + fn read_uleb128_u16(&mut self) -> Result { + leb128::read::u16(self) + } + + /// Read a signed LEB128 encoded integer. + fn read_sleb128(&mut self) -> Result { + leb128::read::signed(self) + } + + /// Read an initial length field. + /// + /// This field is encoded as either a 32-bit length or + /// a 64-bit length, and the returned `Format` indicates which. + fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> { + const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0; + const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff; + + let val = self.read_u32()?; + if val < MAX_DWARF_32_UNIT_LENGTH { + Ok((Self::Offset::from_u32(val), Format::Dwarf32)) + } else if val == DWARF_64_INITIAL_UNIT_LENGTH { + let val = self.read_u64().and_then(Self::Offset::from_u64)?; + Ok((val, Format::Dwarf64)) + } else { + Err(Error::UnknownReservedLength) + } + } + + /// Read a byte and validate it as an address size. + fn read_address_size(&mut self) -> Result { + let size = self.read_u8()?; + match size { + 1 | 2 | 4 | 8 => Ok(size), + _ => Err(Error::UnsupportedAddressSize(size)), + } + } + + /// Read an address-sized integer, and return it as a `u64`. + fn read_address(&mut self, address_size: u8) -> Result { + match address_size { + 1 => self.read_u8().map(u64::from), + 2 => self.read_u16().map(u64::from), + 4 => self.read_u32().map(u64::from), + 8 => self.read_u64(), + otherwise => Err(Error::UnsupportedAddressSize(otherwise)), + } + } + + /// Parse a word-sized integer according to the DWARF format. + /// + /// These are always used to encode section offsets or lengths, + /// and so have a type of `Self::Offset`. + fn read_word(&mut self, format: Format) -> Result { + match format { + Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32), + Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64), + } + } + + /// Parse a word-sized section length according to the DWARF format. + #[inline] + fn read_length(&mut self, format: Format) -> Result { + self.read_word(format) + } + + /// Parse a word-sized section offset according to the DWARF format. + #[inline] + fn read_offset(&mut self, format: Format) -> Result { + self.read_word(format) + } + + /// Parse a section offset of the given size. + /// + /// This is used for `DW_FORM_ref_addr` values in DWARF version 2. + fn read_sized_offset(&mut self, size: u8) -> Result { + match size { + 1 => self.read_u8().map(u64::from), + 2 => self.read_u16().map(u64::from), + 4 => self.read_u32().map(u64::from), + 8 => self.read_u64(), + otherwise => Err(Error::UnsupportedOffsetSize(otherwise)), + } + .and_then(Self::Offset::from_u64) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_min_tombstone() { + assert_eq!(u64::min_tombstone(1), 0xfe); + assert_eq!(u64::min_tombstone(2), 0xfffe); + assert_eq!(u64::min_tombstone(4), 0xffff_fffe); + assert_eq!(u64::min_tombstone(8), 0xffff_ffff_ffff_fffe); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/relocate.rs b/anneal/v2/vendor/gimli/src/read/relocate.rs new file mode 100644 index 0000000000..d26c2bf8cb --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/relocate.rs @@ -0,0 +1,153 @@ +#[cfg(feature = "read")] +use alloc::borrow::Cow; +use core::fmt::Debug; + +use crate::common::Format; +use crate::read::{Reader, ReaderOffset, ReaderOffsetId, Result}; + +/// Trait for relocating addresses and offsets while reading a section. +pub trait Relocate { + /// Relocate an address which was read from the given section offset. + fn relocate_address(&self, offset: T, value: u64) -> Result; + + /// Relocate a value which was read from the given section offset. + fn relocate_offset(&self, offset: T, value: T) -> Result; +} + +/// A `Reader` which applies relocations to addresses and offsets. +/// +/// This is useful for reading sections which contain relocations, +/// such as those in a relocatable object file. +/// It is generally not used for reading sections in an executable file. +#[derive(Debug, Clone)] +pub struct RelocateReader, T: Relocate> { + section: R, + reader: R, + relocate: T, +} + +impl RelocateReader +where + R: Reader, + T: Relocate, +{ + /// Create a new `RelocateReader` which applies relocations to the given section reader. + pub fn new(section: R, relocate: T) -> Self { + let reader = section.clone(); + Self { + section, + reader, + relocate, + } + } +} + +impl Reader for RelocateReader +where + R: Reader, + T: Relocate + Debug + Clone, +{ + type Endian = R::Endian; + type Offset = R::Offset; + + fn read_address(&mut self, address_size: u8) -> Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_address(address_size)?; + self.relocate.relocate_address(offset, value) + } + + fn read_offset(&mut self, format: Format) -> Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_offset(format)?; + self.relocate.relocate_offset(offset, value) + } + + fn read_sized_offset(&mut self, size: u8) -> Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_sized_offset(size)?; + self.relocate.relocate_offset(offset, value) + } + + #[inline] + fn split(&mut self, len: Self::Offset) -> Result { + let mut other = self.clone(); + other.reader.truncate(len)?; + self.reader.skip(len)?; + Ok(other) + } + + // All remaining methods simply delegate to `self.reader`. + + #[inline] + fn endian(&self) -> Self::Endian { + self.reader.endian() + } + + #[inline] + fn len(&self) -> Self::Offset { + self.reader.len() + } + + #[inline] + fn empty(&mut self) { + self.reader.empty() + } + + #[inline] + fn truncate(&mut self, len: Self::Offset) -> Result<()> { + self.reader.truncate(len) + } + + #[inline] + fn offset_from(&self, base: &Self) -> Self::Offset { + self.reader.offset_from(&base.reader) + } + + #[inline] + fn offset_id(&self) -> ReaderOffsetId { + self.reader.offset_id() + } + + #[inline] + fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option { + self.reader.lookup_offset_id(id) + } + + #[inline] + fn find(&self, byte: u8) -> Result { + self.reader.find(byte) + } + + #[inline] + fn skip(&mut self, len: Self::Offset) -> Result<()> { + self.reader.skip(len) + } + + #[cfg(not(feature = "read"))] + fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed { + super::reader::seal_if_no_alloc::Sealed + } + + #[cfg(feature = "read")] + #[inline] + fn to_slice(&self) -> Result> { + self.reader.to_slice() + } + + #[cfg(feature = "read")] + #[inline] + fn to_string(&self) -> Result> { + self.reader.to_string() + } + + #[cfg(feature = "read")] + #[inline] + fn to_string_lossy(&self) -> Result> { + self.reader.to_string_lossy() + } + + #[inline] + fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> { + self.reader.read_slice(buf) + } +} diff --git a/anneal/v2/vendor/gimli/src/read/rnglists.rs b/anneal/v2/vendor/gimli/src/read/rnglists.rs new file mode 100644 index 0000000000..dba8019cb2 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/rnglists.rs @@ -0,0 +1,1044 @@ +use crate::common::{ + DebugAddrBase, DebugAddrIndex, DebugRngListsBase, DebugRngListsIndex, DwarfFileType, Encoding, + RangeListsOffset, SectionId, +}; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::{ + lists::ListsHeader, DebugAddr, EndianSlice, Error, Reader, ReaderAddress, ReaderOffset, + ReaderOffsetId, Result, Section, +}; + +/// The raw contents of the `.debug_ranges` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugRanges { + pub(crate) section: R, +} + +impl<'input, Endian> DebugRanges> +where + Endian: Endianity, +{ + /// Construct a new `DebugRanges` instance from the data in the `.debug_ranges` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_ranges` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugRanges, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_ranges_section_somehow = || &buf; + /// let debug_ranges = DebugRanges::new(read_debug_ranges_section_somehow(), LittleEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugRanges { + /// Create a `DebugRanges` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRanges + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugRanges { + fn id() -> SectionId { + SectionId::DebugRanges + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugRanges { + fn from(section: R) -> Self { + DebugRanges { section } + } +} + +/// The `DebugRngLists` struct represents the contents of the +/// `.debug_rnglists` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugRngLists { + section: R, +} + +impl<'input, Endian> DebugRngLists> +where + Endian: Endianity, +{ + /// Construct a new `DebugRngLists` instance from the data in the + /// `.debug_rnglists` section. + /// + /// It is the caller's responsibility to read the `.debug_rnglists` + /// section and present it as a `&[u8]` slice. That means using some ELF + /// loader on Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugRngLists, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_rnglists_section_somehow = || &buf; + /// let debug_rnglists = + /// DebugRngLists::new(read_debug_rnglists_section_somehow(), LittleEndian); + /// ``` + pub fn new(section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(section, endian)) + } +} + +impl DebugRngLists { + /// Create a `DebugRngLists` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRngLists + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugRngLists { + fn id() -> SectionId { + SectionId::DebugRngLists + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugRngLists { + fn from(section: R) -> Self { + DebugRngLists { section } + } +} + +#[allow(unused)] +pub(crate) type RngListsHeader = ListsHeader; + +impl DebugRngListsBase +where + Offset: ReaderOffset, +{ + /// Returns a `DebugRngListsBase` with the default value of DW_AT_rnglists_base + /// for the given `Encoding` and `DwarfFileType`. + pub fn default_for_encoding_and_file( + encoding: Encoding, + file_type: DwarfFileType, + ) -> DebugRngListsBase { + if encoding.version >= 5 && file_type == DwarfFileType::Dwo { + // In .dwo files, the compiler omits the DW_AT_rnglists_base attribute (because there is + // only a single unit in the file) but we must skip past the header, which the attribute + // would normally do for us. + DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding))) + } else { + DebugRngListsBase(Offset::from_u8(0)) + } + } +} + +/// The DWARF data found in `.debug_ranges` and `.debug_rnglists` sections. +#[derive(Debug, Default, Clone, Copy)] +pub struct RangeLists { + debug_ranges: DebugRanges, + debug_rnglists: DebugRngLists, +} + +impl RangeLists { + /// Construct a new `RangeLists` instance from the data in the `.debug_ranges` and + /// `.debug_rnglists` sections. + pub fn new(debug_ranges: DebugRanges, debug_rnglists: DebugRngLists) -> RangeLists { + RangeLists { + debug_ranges, + debug_rnglists, + } + } + + /// Return the `.debug_ranges` section. + pub fn debug_ranges(&self) -> &DebugRanges { + &self.debug_ranges + } + + /// Replace the `.debug_ranges` section. + /// + /// This is useful for `.dwo` files when using the GNU split-dwarf extension to DWARF 4. + pub fn set_debug_ranges(&mut self, debug_ranges: DebugRanges) { + self.debug_ranges = debug_ranges; + } + + /// Return the `.debug_rnglists` section. + pub fn debug_rnglists(&self) -> &DebugRngLists { + &self.debug_rnglists + } +} + +impl RangeLists { + /// Create a `RangeLists` that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `Dwarf::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists + where + F: FnMut(&'a T) -> R, + { + RangeLists { + debug_ranges: borrow(&self.debug_ranges.section).into(), + debug_rnglists: borrow(&self.debug_rnglists.section).into(), + } + } +} + +impl RangeLists { + /// Iterate over the `Range` list entries starting at the given offset. + /// + /// The `unit_version` and `address_size` must match the compilation unit that the + /// offset was contained in. + /// + /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the + /// `DW_TAG_compile_unit` entry for the compilation unit that contains this range list. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn ranges( + &self, + offset: RangeListsOffset, + unit_encoding: Encoding, + base_address: u64, + debug_addr: &DebugAddr, + debug_addr_base: DebugAddrBase, + ) -> Result> { + Ok(RngListIter::new( + self.raw_ranges(offset, unit_encoding)?, + base_address, + debug_addr.clone(), + debug_addr_base, + )) + } + + /// Iterate over the `RawRngListEntry`ies starting at the given offset. + /// + /// The `unit_encoding` must match the compilation unit that the + /// offset was contained in. + /// + /// This iterator does not perform any processing of the range entries, + /// such as handling base addresses. + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn raw_ranges( + &self, + offset: RangeListsOffset, + unit_encoding: Encoding, + ) -> Result> { + let (mut input, format) = if unit_encoding.version <= 4 { + (self.debug_ranges.section.clone(), RangeListsFormat::Bare) + } else { + (self.debug_rnglists.section.clone(), RangeListsFormat::Rle) + }; + input.skip(offset.0)?; + Ok(RawRngListIter::new(input, unit_encoding, format)) + } + + /// Returns the `.debug_rnglists` offset at the given `base` and `index`. + /// + /// The `base` must be the `DW_AT_rnglists_base` value from the compilation unit DIE. + /// This is an offset that points to the first entry following the header. + /// + /// The `index` is the value of a `DW_FORM_rnglistx` attribute. + /// + /// The `unit_encoding` must match the compilation unit that the + /// index was contained in. + pub fn get_offset( + &self, + unit_encoding: Encoding, + base: DebugRngListsBase, + index: DebugRngListsIndex, + ) -> Result> { + let format = unit_encoding.format; + let input = &mut self.debug_rnglists.section.clone(); + input.skip(base.0)?; + input.skip(R::Offset::from_u64( + index.0.into_u64() * u64::from(format.word_size()), + )?)?; + input + .read_offset(format) + .map(|x| RangeListsOffset(base.0 + x)) + } + + /// Call `Reader::lookup_offset_id` for each section, and return the first match. + pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> { + self.debug_ranges + .lookup_offset_id(id) + .or_else(|| self.debug_rnglists.lookup_offset_id(id)) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum RangeListsFormat { + /// The bare range list format used before DWARF 5. + Bare, + /// The DW_RLE encoded range list format used in DWARF 5. + Rle, +} + +/// A raw iterator over an address range list. +/// +/// This iterator does not perform any processing of the range entries, +/// such as handling base addresses. +#[derive(Debug)] +pub struct RawRngListIter { + input: R, + encoding: Encoding, + format: RangeListsFormat, +} + +/// A raw entry in .debug_rnglists +#[derive(Clone, Debug)] +pub enum RawRngListEntry { + /// A range from DWARF version <= 4. + AddressOrOffsetPair { + /// Start of range. May be an address or an offset. + begin: u64, + /// End of range. May be an address or an offset. + end: u64, + }, + /// DW_RLE_base_address + BaseAddress { + /// base address + addr: u64, + }, + /// DW_RLE_base_addressx + BaseAddressx { + /// base address + addr: DebugAddrIndex, + }, + /// DW_RLE_startx_endx + StartxEndx { + /// start of range + begin: DebugAddrIndex, + /// end of range + end: DebugAddrIndex, + }, + /// DW_RLE_startx_length + StartxLength { + /// start of range + begin: DebugAddrIndex, + /// length of range + length: u64, + }, + /// DW_RLE_offset_pair + OffsetPair { + /// start of range + begin: u64, + /// end of range + end: u64, + }, + /// DW_RLE_start_end + StartEnd { + /// start of range + begin: u64, + /// end of range + end: u64, + }, + /// DW_RLE_start_length + StartLength { + /// start of range + begin: u64, + /// length of range + length: u64, + }, +} + +impl RawRngListEntry { + /// Parse a range entry from `.debug_rnglists` + fn parse>( + input: &mut R, + encoding: Encoding, + format: RangeListsFormat, + ) -> Result> { + Ok(match format { + RangeListsFormat::Bare => { + let range = RawRange::parse(input, encoding.address_size)?; + if range.is_end() { + None + } else if range.is_base_address(encoding.address_size) { + Some(RawRngListEntry::BaseAddress { addr: range.end }) + } else { + Some(RawRngListEntry::AddressOrOffsetPair { + begin: range.begin, + end: range.end, + }) + } + } + RangeListsFormat::Rle => match constants::DwRle(input.read_u8()?) { + constants::DW_RLE_end_of_list => None, + constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx { + addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + }), + constants::DW_RLE_startx_endx => Some(RawRngListEntry::StartxEndx { + begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + }), + constants::DW_RLE_startx_length => Some(RawRngListEntry::StartxLength { + begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?), + length: input.read_uleb128()?, + }), + constants::DW_RLE_offset_pair => Some(RawRngListEntry::OffsetPair { + begin: input.read_uleb128()?, + end: input.read_uleb128()?, + }), + constants::DW_RLE_base_address => Some(RawRngListEntry::BaseAddress { + addr: input.read_address(encoding.address_size)?, + }), + constants::DW_RLE_start_end => Some(RawRngListEntry::StartEnd { + begin: input.read_address(encoding.address_size)?, + end: input.read_address(encoding.address_size)?, + }), + constants::DW_RLE_start_length => Some(RawRngListEntry::StartLength { + begin: input.read_address(encoding.address_size)?, + length: input.read_uleb128()?, + }), + entry => { + return Err(Error::UnknownRangeListsEntry(entry)); + } + }, + }) + } +} + +impl RawRngListIter { + /// Construct a `RawRngListIter`. + fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter { + RawRngListIter { + input, + encoding, + format, + } + } + + /// Advance the iterator to the next range. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + return Ok(None); + } + + match RawRngListEntry::parse(&mut self.input, self.encoding, self.format) { + Ok(range) => { + if range.is_none() { + self.input.empty(); + } + Ok(range) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for RawRngListIter { + type Item = RawRngListEntry; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + RawRngListIter::next(self) + } +} + +/// An iterator over an address range list. +/// +/// This iterator internally handles processing of base addresses and different +/// entry types. Thus, it only returns range entries that are valid +/// and already adjusted for the base address. +#[derive(Debug)] +pub struct RngListIter { + raw: RawRngListIter, + base_address: u64, + debug_addr: DebugAddr, + debug_addr_base: DebugAddrBase, +} + +impl RngListIter { + /// Construct a `RngListIter`. + fn new( + raw: RawRngListIter, + base_address: u64, + debug_addr: DebugAddr, + debug_addr_base: DebugAddrBase, + ) -> RngListIter { + RngListIter { + raw, + base_address, + debug_addr, + debug_addr_base, + } + } + + #[inline] + fn get_address(&self, index: DebugAddrIndex) -> Result { + self.debug_addr + .get_address(self.raw.encoding.address_size, self.debug_addr_base, index) + } + + /// Advance the iterator to the next range. + pub fn next(&mut self) -> Result> { + loop { + let raw_range = match self.raw.next()? { + Some(range) => range, + None => return Ok(None), + }; + + let range = self.convert_raw(raw_range)?; + if range.is_some() { + return Ok(range); + } + } + } + + /// Return the next raw range. + /// + /// The raw range should be passed to `convert_range`. + #[doc(hidden)] + pub fn next_raw(&mut self) -> Result>> { + self.raw.next() + } + + /// Convert a raw range into a range, and update the state of the iterator. + /// + /// The raw range should have been obtained from `next_raw`. + #[doc(hidden)] + pub fn convert_raw(&mut self, raw_range: RawRngListEntry) -> Result> { + let address_size = self.raw.encoding.address_size; + + let range = match raw_range { + RawRngListEntry::BaseAddress { addr } => { + self.base_address = addr; + return Ok(None); + } + RawRngListEntry::BaseAddressx { addr } => { + self.base_address = self.get_address(addr)?; + return Ok(None); + } + RawRngListEntry::StartxEndx { begin, end } => { + let begin = self.get_address(begin)?; + let end = self.get_address(end)?; + Range { begin, end } + } + RawRngListEntry::StartxLength { begin, length } => { + let begin = self.get_address(begin)?; + let end = begin.wrapping_add_sized(length, address_size); + Range { begin, end } + } + RawRngListEntry::AddressOrOffsetPair { begin, end } + | RawRngListEntry::OffsetPair { begin, end } => { + // Skip tombstone entries (see below). + if self.base_address >= u64::min_tombstone(address_size) { + return Ok(None); + } + let mut range = Range { begin, end }; + range.add_base_address(self.base_address, address_size); + range + } + RawRngListEntry::StartEnd { begin, end } => Range { begin, end }, + RawRngListEntry::StartLength { begin, length } => { + let end = begin.wrapping_add_sized(length, address_size); + Range { begin, end } + } + }; + + // Skip tombstone entries. + // + // DWARF specifies a tombstone value of -1 or -2, but many linkers use 0 or 1. + // However, 0/1 may be a valid address, so we can't always reliably skip them. + // One case where we can skip them is for address pairs, where both values are + // replaced by tombstones and thus `begin` equals `end`. Since these entries + // are empty, it's safe to skip them even if they aren't tombstones. + // + // In addition to skipping tombstone entries, we also skip invalid entries + // where `begin` is greater than `end`. This can occur due to compiler bugs. + if range.begin >= u64::min_tombstone(address_size) || range.begin >= range.end { + return Ok(None); + } + + Ok(Some(range)) + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for RngListIter { + type Item = Range; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + RngListIter::next(self) + } +} + +/// A raw address range from the `.debug_ranges` section. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct RawRange { + /// The beginning address of the range. + pub begin: u64, + + /// The first address past the end of the range. + pub end: u64, +} + +impl RawRange { + /// Check if this is a range end entry. + #[inline] + pub fn is_end(&self) -> bool { + self.begin == 0 && self.end == 0 + } + + /// Check if this is a base address selection entry. + /// + /// A base address selection entry changes the base address that subsequent + /// range entries are relative to. + #[inline] + pub fn is_base_address(&self, address_size: u8) -> bool { + self.begin == !0 >> (64 - address_size * 8) + } + + /// Parse an address range entry from `.debug_ranges` or `.debug_loc`. + #[inline] + pub fn parse(input: &mut R, address_size: u8) -> Result { + let begin = input.read_address(address_size)?; + let end = input.read_address(address_size)?; + let range = RawRange { begin, end }; + Ok(range) + } +} + +/// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Range { + /// The beginning address of the range. + pub begin: u64, + + /// The first address past the end of the range. + pub end: u64, +} + +impl Range { + /// Add a base address to this range. + #[inline] + pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) { + self.begin = base_address.wrapping_add_sized(self.begin, address_size); + self.end = base_address.wrapping_add_sized(self.end, address_size); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::common::Format; + use crate::constants::*; + use crate::endianity::LittleEndian; + use crate::test_util::GimliSectionMethods; + use alloc::vec::Vec; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_rnglists() { + let format = Format::Dwarf32; + for size in [4, 8] { + let tombstone = u64::ones_sized(size); + let tombstone_0 = 0; + let encoding = Encoding { + format, + version: 5, + address_size: size, + }; + let section = Section::with_endian(Endian::Little) + .word(size, 0x0300_0000) + .word(size, 0x0301_0300) + .word(size, 0x0301_0400) + .word(size, 0x0301_0500) + .word(size, tombstone) + .word(size, 0x0301_0600) + .word(size, tombstone_0); + let buf = section.get_contents().unwrap(); + let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .initial_length(format, &length, &start) + .L16(encoding.version) + .L8(encoding.address_size) + .L8(0) + .L32(0) + .mark(&first); + + let mut expected_ranges = Vec::new(); + let mut expect_range = |begin, end| { + expected_ranges.push(Range { begin, end }); + }; + + // An offset pair using the unit base address. + section = section.L8(DW_RLE_offset_pair.0).uleb(0x10200).uleb(0x10300); + expect_range(0x0101_0200, 0x0101_0300); + + section = section.L8(DW_RLE_base_address.0).word(size, 0x0200_0000); + section = section.L8(DW_RLE_offset_pair.0).uleb(0x10400).uleb(0x10500); + expect_range(0x0201_0400, 0x0201_0500); + + section = section + .L8(DW_RLE_start_end.0) + .word(size, 0x201_0a00) + .word(size, 0x201_0b00); + expect_range(0x0201_0a00, 0x0201_0b00); + + section = section + .L8(DW_RLE_start_length.0) + .word(size, 0x201_0c00) + .uleb(0x100); + expect_range(0x0201_0c00, 0x0201_0d00); + + // An offset pair that starts at 0. + section = section.L8(DW_RLE_base_address.0).word(size, 0); + section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(1); + expect_range(0, 1); + + // An offset pair that ends at -1. + section = section.L8(DW_RLE_base_address.0).word(size, 0); + section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(tombstone); + expect_range(0, tombstone); + + section = section.L8(DW_RLE_base_addressx.0).uleb(0); + section = section.L8(DW_RLE_offset_pair.0).uleb(0x10100).uleb(0x10200); + expect_range(0x0301_0100, 0x0301_0200); + + section = section.L8(DW_RLE_startx_endx.0).uleb(1).uleb(2); + expect_range(0x0301_0300, 0x0301_0400); + + section = section.L8(DW_RLE_startx_length.0).uleb(3).uleb(0x100); + expect_range(0x0301_0500, 0x0301_0600); + + // Tombstone entries, all of which should be ignored. + section = section.L8(DW_RLE_base_addressx.0).uleb(4); + section = section.L8(DW_RLE_offset_pair.0).uleb(0x11100).uleb(0x11200); + + section = section.L8(DW_RLE_base_address.0).word(size, tombstone); + section = section.L8(DW_RLE_offset_pair.0).uleb(0x11300).uleb(0x11400); + + section = section.L8(DW_RLE_startx_endx.0).uleb(4).uleb(5); + section = section.L8(DW_RLE_startx_length.0).uleb(4).uleb(0x100); + section = section + .L8(DW_RLE_start_end.0) + .word(size, tombstone) + .word(size, 0x201_1500); + section = section + .L8(DW_RLE_start_length.0) + .word(size, tombstone) + .uleb(0x100); + + // Ignore some instances of 0 for tombstone. + section = section.L8(DW_RLE_startx_endx.0).uleb(6).uleb(6); + section = section + .L8(DW_RLE_start_end.0) + .word(size, tombstone_0) + .word(size, tombstone_0); + + // Ignore empty ranges. + section = section.L8(DW_RLE_base_address.0).word(size, 0); + section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(0); + section = section.L8(DW_RLE_base_address.0).word(size, 0x10000); + section = section.L8(DW_RLE_offset_pair.0).uleb(0x1234).uleb(0x1234); + + // A valid range after the tombstones. + section = section + .L8(DW_RLE_start_end.0) + .word(size, 0x201_1600) + .word(size, 0x201_1700); + expect_range(0x0201_1600, 0x0201_1700); + + section = section.L8(DW_RLE_end_of_list.0); + section = section.mark(&end); + // Some extra data. + section = section.word(size, 0x1234_5678); + length.set_const((&end - &start) as u64); + + let offset = RangeListsOffset((&first - §ion.start()) as usize); + let buf = section.get_contents().unwrap(); + let debug_ranges = DebugRanges::new(&[], LittleEndian); + let debug_rnglists = DebugRngLists::new(&buf, LittleEndian); + let rnglists = RangeLists::new(debug_ranges, debug_rnglists); + let mut ranges = rnglists + .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) + .unwrap(); + + for expected_range in expected_ranges { + let range = ranges.next(); + assert_eq!( + range, + Ok(Some(expected_range)), + "read {:x?}, expect {:x?}", + range, + expected_range + ); + } + assert_eq!(ranges.next(), Ok(None)); + + // An offset at the end of buf. + let mut ranges = rnglists + .ranges( + RangeListsOffset(buf.len()), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(ranges.next(), Ok(None)); + } + } + + #[test] + fn test_raw_range() { + let range = RawRange { + begin: 0, + end: 0xffff_ffff, + }; + assert!(!range.is_end()); + assert!(!range.is_base_address(4)); + assert!(!range.is_base_address(8)); + + let range = RawRange { begin: 0, end: 0 }; + assert!(range.is_end()); + assert!(!range.is_base_address(4)); + assert!(!range.is_base_address(8)); + + let range = RawRange { + begin: 0xffff_ffff, + end: 0, + }; + assert!(!range.is_end()); + assert!(range.is_base_address(4)); + assert!(!range.is_base_address(8)); + + let range = RawRange { + begin: 0xffff_ffff_ffff_ffff, + end: 0, + }; + assert!(!range.is_end()); + assert!(!range.is_base_address(4)); + assert!(range.is_base_address(8)); + } + + #[test] + fn test_ranges() { + for size in [4, 8] { + let base = u64::ones_sized(size); + let tombstone = u64::ones_sized(size) - 1; + let start = Label::new(); + let first = Label::new(); + let mut section = Section::with_endian(Endian::Little) + // A range before the offset. + .mark(&start) + .word(size, 0x10000) + .word(size, 0x10100) + .mark(&first); + + let mut expected_ranges = Vec::new(); + let mut expect_range = |begin, end| { + expected_ranges.push(Range { begin, end }); + }; + + // A normal range. + section = section.word(size, 0x10200).word(size, 0x10300); + expect_range(0x0101_0200, 0x0101_0300); + // A base address selection followed by a normal range. + section = section.word(size, base).word(size, 0x0200_0000); + section = section.word(size, 0x10400).word(size, 0x10500); + expect_range(0x0201_0400, 0x0201_0500); + // An empty range followed by a normal range. + section = section.word(size, 0x10600).word(size, 0x10600); + section = section.word(size, 0x10800).word(size, 0x10900); + expect_range(0x0201_0800, 0x0201_0900); + // A range that starts at 0. + section = section.word(size, base).word(size, 0); + section = section.word(size, 0).word(size, 1); + expect_range(0, 1); + // A range that ends at -1. + section = section.word(size, base).word(size, 0); + section = section.word(size, 0).word(size, base); + expect_range(0, base); + // A normal range with tombstone. + section = section.word(size, tombstone).word(size, tombstone); + // A base address selection with tombstone followed by a normal range. + section = section.word(size, base).word(size, tombstone); + section = section.word(size, 0x10a00).word(size, 0x10b00); + // A range end. + section = section.word(size, 0).word(size, 0); + // Some extra data. + section = section.word(size, 0x1234_5678); + + let buf = section.get_contents().unwrap(); + let debug_ranges = DebugRanges::new(&buf, LittleEndian); + let debug_rnglists = DebugRngLists::new(&[], LittleEndian); + let rnglists = RangeLists::new(debug_ranges, debug_rnglists); + let offset = RangeListsOffset((&first - &start) as usize); + let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: size, + }; + let mut ranges = rnglists + .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base) + .unwrap(); + + for expected_range in expected_ranges { + let range = ranges.next(); + assert_eq!( + range, + Ok(Some(expected_range)), + "read {:x?}, expect {:x?}", + range, + expected_range + ); + } + assert_eq!(ranges.next(), Ok(None)); + + // An offset at the end of buf. + let mut ranges = rnglists + .ranges( + RangeListsOffset(buf.len()), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(ranges.next(), Ok(None)); + } + } + + #[test] + fn test_ranges_invalid() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + // An invalid range. + .L32(0x20000).L32(0x10000) + // An invalid range after wrapping. + .L32(0x20000).L32(0xff01_0000); + + let buf = section.get_contents().unwrap(); + let debug_ranges = DebugRanges::new(&buf, LittleEndian); + let debug_rnglists = DebugRngLists::new(&[], LittleEndian); + let rnglists = RangeLists::new(debug_ranges, debug_rnglists); + let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian)); + let debug_addr_base = DebugAddrBase(0); + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + + // An invalid range. + let mut ranges = rnglists + .ranges( + RangeListsOffset(0x0), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(ranges.next(), Ok(None)); + + // An invalid range after wrapping. + let mut ranges = rnglists + .ranges( + RangeListsOffset(0x8), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) + .unwrap(); + assert_eq!(ranges.next(), Ok(None)); + + // An invalid offset. + match rnglists.ranges( + RangeListsOffset(buf.len() + 1), + encoding, + 0x0100_0000, + debug_addr, + debug_addr_base, + ) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_get_offset() { + for format in [Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version: 5, + address_size: 4, + }; + + let zero = Label::new(); + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .mark(&zero) + .initial_length(format, &length, &start) + .D16(encoding.version) + .D8(encoding.address_size) + .D8(0) + .D32(20) + .mark(&first); + for i in 0..20 { + section = section.word(format.word_size(), 1000 + i); + } + section = section.mark(&end); + length.set_const((&end - &start) as u64); + let section = section.get_contents().unwrap(); + + let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian)); + let debug_rnglists = DebugRngLists::from(EndianSlice::new(§ion, LittleEndian)); + let ranges = RangeLists::new(debug_ranges, debug_rnglists); + + let base = DebugRngListsBase((&first - &zero) as usize); + assert_eq!( + ranges.get_offset(encoding, base, DebugRngListsIndex(0)), + Ok(RangeListsOffset(base.0 + 1000)) + ); + assert_eq!( + ranges.get_offset(encoding, base, DebugRngListsIndex(19)), + Ok(RangeListsOffset(base.0 + 1019)) + ); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/read/str.rs b/anneal/v2/vendor/gimli/src/read/str.rs new file mode 100644 index 0000000000..df7ab1ccd2 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/str.rs @@ -0,0 +1,291 @@ +use crate::common::{ + DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsBase, DebugStrOffsetsIndex, DwarfFileType, + Encoding, SectionId, +}; +use crate::endianity::Endianity; +use crate::read::{EndianSlice, Reader, ReaderOffset, Result, Section}; +use crate::Format; + +/// The `DebugStr` struct represents the DWARF strings +/// found in the `.debug_str` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugStr { + debug_str_section: R, +} + +impl<'input, Endian> DebugStr> +where + Endian: Endianity, +{ + /// Construct a new `DebugStr` instance from the data in the `.debug_str` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_str` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugStr, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_str_section_somehow = || &buf; + /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_str_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_str_section, endian)) + } +} + +impl DebugStr { + /// Lookup a string from the `.debug_str` section by DebugStrOffset. + /// + /// ``` + /// use gimli::{DebugStr, DebugStrOffset, LittleEndian}; + /// + /// # let buf = [0x01, 0x02, 0x00]; + /// # let offset = DebugStrOffset(0); + /// # let read_debug_str_section_somehow = || &buf; + /// # let debug_str_offset_somehow = || offset; + /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian); + /// println!("Found string {:?}", debug_str.get_str(debug_str_offset_somehow())); + /// ``` + pub fn get_str(&self, offset: DebugStrOffset) -> Result { + let input = &mut self.debug_str_section.clone(); + input.skip(offset.0)?; + input.read_null_terminated_slice() + } +} + +impl DebugStr { + /// Create a `DebugStr` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr + where + F: FnMut(&'a T) -> R, + { + borrow(&self.debug_str_section).into() + } +} + +impl Section for DebugStr { + fn id() -> SectionId { + SectionId::DebugStr + } + + fn reader(&self) -> &R { + &self.debug_str_section + } +} + +impl From for DebugStr { + fn from(debug_str_section: R) -> Self { + DebugStr { debug_str_section } + } +} + +/// The raw contents of the `.debug_str_offsets` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugStrOffsets { + section: R, +} + +impl DebugStrOffsets { + // TODO: add an iterator over the sets of entries in the section. + // This is not needed for common usage of the section though. + + /// Returns the `.debug_str` offset at the given `base` and `index`. + /// + /// A set of entries in the `.debug_str_offsets` section consists of a header + /// followed by a series of string table offsets. + /// + /// The `base` must be the `DW_AT_str_offsets_base` value from the compilation unit DIE. + /// This is an offset that points to the first entry following the header. + /// + /// The `index` is the value of a `DW_FORM_strx` attribute. + /// + /// The `format` must be the DWARF format of the compilation unit. This format must + /// match the header. However, note that we do not parse the header to validate this, + /// since locating the header is unreliable, and the GNU extensions do not emit it. + pub fn get_str_offset( + &self, + format: Format, + base: DebugStrOffsetsBase, + index: DebugStrOffsetsIndex, + ) -> Result> { + let input = &mut self.section.clone(); + input.skip(base.0)?; + input.skip(R::Offset::from_u64( + index.0.into_u64() * u64::from(format.word_size()), + )?)?; + input.read_offset(format).map(DebugStrOffset) + } +} + +impl DebugStrOffsets { + /// Create a `DebugStrOffsets` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugStrOffsets { + fn id() -> SectionId { + SectionId::DebugStrOffsets + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugStrOffsets { + fn from(section: R) -> Self { + DebugStrOffsets { section } + } +} + +impl DebugStrOffsetsBase +where + Offset: ReaderOffset, +{ + /// Returns a `DebugStrOffsetsBase` with the default value of DW_AT_str_offsets_base + /// for the given `Encoding` and `DwarfFileType`. + pub fn default_for_encoding_and_file( + encoding: Encoding, + file_type: DwarfFileType, + ) -> DebugStrOffsetsBase { + if encoding.version >= 5 && file_type == DwarfFileType::Dwo { + // In .dwo files, the compiler omits the DW_AT_str_offsets_base attribute (because there is + // only a single unit in the file) but we must skip past the header, which the attribute + // would normally do for us. + // initial_length_size + version + 2 bytes of padding. + DebugStrOffsetsBase(Offset::from_u8( + encoding.format.initial_length_size() + 2 + 2, + )) + } else { + DebugStrOffsetsBase(Offset::from_u8(0)) + } + } +} + +/// The `DebugLineStr` struct represents the DWARF strings +/// found in the `.debug_line_str` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugLineStr { + section: R, +} + +impl<'input, Endian> DebugLineStr> +where + Endian: Endianity, +{ + /// Construct a new `DebugLineStr` instance from the data in the `.debug_line_str` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_line_str` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugLineStr, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_line_str_section_somehow = || &buf; + /// let debug_str = DebugLineStr::new(read_debug_line_str_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_line_str_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_line_str_section, endian)) + } +} + +impl DebugLineStr { + /// Lookup a string from the `.debug_line_str` section by DebugLineStrOffset. + pub fn get_str(&self, offset: DebugLineStrOffset) -> Result { + let input = &mut self.section.clone(); + input.skip(offset.0)?; + input.read_null_terminated_slice() + } +} + +impl DebugLineStr { + /// Create a `DebugLineStr` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr + where + F: FnMut(&'a T) -> R, + { + borrow(&self.section).into() + } +} + +impl Section for DebugLineStr { + fn id() -> SectionId { + SectionId::DebugLineStr + } + + fn reader(&self) -> &R { + &self.section + } +} + +impl From for DebugLineStr { + fn from(section: R) -> Self { + DebugLineStr { section } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_util::GimliSectionMethods; + use crate::LittleEndian; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + #[test] + fn test_get_str_offset() { + for format in [Format::Dwarf32, Format::Dwarf64] { + let zero = Label::new(); + let length = Label::new(); + let start = Label::new(); + let first = Label::new(); + let end = Label::new(); + let mut section = Section::with_endian(Endian::Little) + .mark(&zero) + .initial_length(format, &length, &start) + .D16(5) + .D16(0) + .mark(&first); + for i in 0..20 { + section = section.word(format.word_size(), 1000 + i); + } + section = section.mark(&end); + length.set_const((&end - &start) as u64); + + let section = section.get_contents().unwrap(); + let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(§ion, LittleEndian)); + let base = DebugStrOffsetsBase((&first - &zero) as usize); + + assert_eq!( + debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(0)), + Ok(DebugStrOffset(1000)) + ); + assert_eq!( + debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(19)), + Ok(DebugStrOffset(1019)) + ); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/read/unit.rs b/anneal/v2/vendor/gimli/src/read/unit.rs new file mode 100644 index 0000000000..e8e38620d9 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/unit.rs @@ -0,0 +1,6128 @@ +//! Functions for parsing DWARF `.debug_info` and `.debug_types` sections. + +use core::cell::Cell; +use core::ops::{Range, RangeFrom, RangeTo}; + +use crate::common::{ + DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset, + DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset, + DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase, + DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format, + LocationListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset, +}; +use crate::constants; +use crate::endianity::Endianity; +use crate::read::abbrev::get_attribute_size; +use crate::read::{ + Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error, + Expression, Reader, ReaderOffset, Result, Section, UnitOffset, +}; + +impl DebugTypesOffset { + /// Convert an offset to be relative to the start of the given unit, + /// instead of relative to the start of the .debug_types section. + /// Returns `None` if the offset is not within the unit entries. + pub fn to_unit_offset(&self, unit: &UnitHeader) -> Option> + where + R: Reader, + { + let unit_offset = unit.offset().as_debug_types_offset()?; + let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?); + if !unit.is_valid_offset(offset) { + return None; + } + Some(offset) + } +} + +impl DebugInfoOffset { + /// Convert an offset to be relative to the start of the given unit, + /// instead of relative to the start of the .debug_info section. + /// Returns `None` if the offset is not within this unit entries. + pub fn to_unit_offset(&self, unit: &UnitHeader) -> Option> + where + R: Reader, + { + let unit_offset = unit.offset().as_debug_info_offset()?; + let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?); + if !unit.is_valid_offset(offset) { + return None; + } + Some(offset) + } +} + +impl UnitOffset { + /// Convert an offset to be relative to the start of the .debug_info section, + /// instead of relative to the start of the given unit. Returns None if the + /// provided unit lives in the .debug_types section. + pub fn to_debug_info_offset(&self, unit: &UnitHeader) -> Option> + where + R: Reader, + { + let unit_offset = unit.offset().as_debug_info_offset()?; + Some(DebugInfoOffset(unit_offset.0 + self.0)) + } + + /// Convert an offset to be relative to the start of the .debug_types section, + /// instead of relative to the start of the given unit. Returns None if the + /// provided unit lives in the .debug_info section. + pub fn to_debug_types_offset(&self, unit: &UnitHeader) -> Option> + where + R: Reader, + { + let unit_offset = unit.offset().as_debug_types_offset()?; + Some(DebugTypesOffset(unit_offset.0 + self.0)) + } +} + +/// The `DebugInfo` struct represents the DWARF debugging information found in +/// the `.debug_info` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugInfo { + debug_info_section: R, +} + +impl<'input, Endian> DebugInfo> +where + Endian: Endianity, +{ + /// Construct a new `DebugInfo` instance from the data in the `.debug_info` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_info` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugInfo, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_info_section_somehow = || &buf; + /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_info_section, endian)) + } +} + +impl DebugInfo { + /// Iterate the units in this `.debug_info` section. + /// + /// ``` + /// use gimli::{DebugInfo, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_info_section_somehow = || &buf; + /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian); + /// + /// let mut iter = debug_info.units(); + /// while let Some(unit) = iter.next().unwrap() { + /// println!("unit's length is {}", unit.unit_length()); + /// } + /// ``` + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn units(&self) -> DebugInfoUnitHeadersIter { + DebugInfoUnitHeadersIter { + input: self.debug_info_section.clone(), + offset: DebugInfoOffset(R::Offset::from_u8(0)), + } + } + + /// Get the UnitHeader located at offset from this .debug_info section. + /// + /// + pub fn header_from_offset(&self, offset: DebugInfoOffset) -> Result> { + let input = &mut self.debug_info_section.clone(); + input.skip(offset.0)?; + parse_unit_header(input, offset.into()) + } +} + +impl DebugInfo { + /// Create a `DebugInfo` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo + where + F: FnMut(&'a T) -> R, + { + borrow(&self.debug_info_section).into() + } +} + +impl Section for DebugInfo { + fn id() -> SectionId { + SectionId::DebugInfo + } + + fn reader(&self) -> &R { + &self.debug_info_section + } +} + +impl From for DebugInfo { + fn from(debug_info_section: R) -> Self { + DebugInfo { debug_info_section } + } +} + +/// An iterator over the units of a .debug_info section. +/// +/// See the [documentation on +/// `DebugInfo::units`](./struct.DebugInfo.html#method.units) for more detail. +#[derive(Clone, Debug)] +pub struct DebugInfoUnitHeadersIter { + input: R, + offset: DebugInfoOffset, +} + +impl DebugInfoUnitHeadersIter { + /// Advance the iterator to the next unit header. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + Ok(None) + } else { + let len = self.input.len(); + match parse_unit_header(&mut self.input, self.offset.into()) { + Ok(header) => { + self.offset.0 += len - self.input.len(); + Ok(Some(header)) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter { + type Item = UnitHeader; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + DebugInfoUnitHeadersIter::next(self) + } +} + +/// Parse the unit type from the unit header. +fn parse_unit_type(input: &mut R) -> Result { + let val = input.read_u8()?; + Ok(constants::DwUt(val)) +} + +/// Parse the `debug_abbrev_offset` in the compilation unit header. +fn parse_debug_abbrev_offset( + input: &mut R, + format: Format, +) -> Result> { + input.read_offset(format).map(DebugAbbrevOffset) +} + +/// Parse the `debug_info_offset` in the arange header. +pub(crate) fn parse_debug_info_offset( + input: &mut R, + format: Format, +) -> Result> { + input.read_offset(format).map(DebugInfoOffset) +} + +/// This enum specifies the type of the unit and any type +/// specific data carried in the header (e.g. the type +/// signature/type offset of a type unit). +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum UnitType +where + Offset: ReaderOffset, +{ + /// In DWARF5, a unit with type `DW_UT_compile`. In previous DWARF versions, + /// any unit appearing in the .debug_info section. + Compilation, + /// In DWARF5, a unit with type `DW_UT_type`. In DWARF4, any unit appearing + /// in the .debug_types section. + Type { + /// The unique type signature for this type unit. + type_signature: DebugTypeSignature, + /// The offset within this type unit where the type is defined. + type_offset: UnitOffset, + }, + /// A unit with type `DW_UT_partial`. The root DIE of this unit should be a + /// `DW_TAG_partial_unit`. + Partial, + /// A unit with type `DW_UT_skeleton`. The enclosed dwo_id can be used to + /// link this with the corresponding `SplitCompilation` unit in a dwo file. + /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead + /// be a `Compilation` unit with the dwo_id present as an attribute on the + /// root DIE. + Skeleton(DwoId), + /// A unit with type `DW_UT_split_compile`. The enclosed dwo_id can be used to + /// link this with the corresponding `Skeleton` unit in the original binary. + /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead + /// be a `Compilation` unit with the dwo_id present as an attribute on the + /// root DIE. + SplitCompilation(DwoId), + /// A unit with type `DW_UT_split_type`. A split type unit is identical to a + /// conventional type unit except for the section in which it appears. + SplitType { + /// The unique type signature for this type unit. + type_signature: DebugTypeSignature, + /// The offset within this type unit where the type is defined. + type_offset: UnitOffset, + }, +} + +impl UnitType +where + Offset: ReaderOffset, +{ + // TODO: This will be used by the DWARF writing code once it + // supports unit types other than simple compilation units. + #[allow(unused)] + pub(crate) fn dw_ut(&self) -> constants::DwUt { + match self { + UnitType::Compilation => constants::DW_UT_compile, + UnitType::Type { .. } => constants::DW_UT_type, + UnitType::Partial => constants::DW_UT_partial, + UnitType::Skeleton(_) => constants::DW_UT_skeleton, + UnitType::SplitCompilation(_) => constants::DW_UT_split_compile, + UnitType::SplitType { .. } => constants::DW_UT_split_type, + } + } +} + +/// The common fields for the headers of compilation units and +/// type units. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct UnitHeader::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + encoding: Encoding, + unit_length: Offset, + unit_type: UnitType, + debug_abbrev_offset: DebugAbbrevOffset, + unit_offset: UnitSectionOffset, + entries_buf: R, +} + +/// Static methods. +impl UnitHeader +where + R: Reader, + Offset: ReaderOffset, +{ + /// Construct a new `UnitHeader`. + pub fn new( + encoding: Encoding, + unit_length: Offset, + unit_type: UnitType, + debug_abbrev_offset: DebugAbbrevOffset, + unit_offset: UnitSectionOffset, + entries_buf: R, + ) -> Self { + UnitHeader { + encoding, + unit_length, + unit_type, + debug_abbrev_offset, + unit_offset, + entries_buf, + } + } +} + +/// Instance methods. +impl UnitHeader +where + R: Reader, + Offset: ReaderOffset, +{ + /// Get the offset of this unit within its section. + pub fn offset(&self) -> UnitSectionOffset { + self.unit_offset + } + + /// Return the serialized size of the common unit header for the given + /// DWARF format. + pub fn size_of_header(&self) -> usize { + let unit_length_size = self.encoding.format.initial_length_size() as usize; + let version_size = 2; + let debug_abbrev_offset_size = self.encoding.format.word_size() as usize; + let address_size_size = 1; + let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 }; + let type_specific_size = match self.unit_type { + UnitType::Compilation | UnitType::Partial => 0, + UnitType::Type { .. } | UnitType::SplitType { .. } => { + let type_signature_size = 8; + let type_offset_size = self.encoding.format.word_size() as usize; + type_signature_size + type_offset_size + } + UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8, + }; + + unit_length_size + + version_size + + debug_abbrev_offset_size + + address_size_size + + unit_type_size + + type_specific_size + } + + /// Get the length of the debugging info for this compilation unit, not + /// including the byte length of the encoded length itself. + pub fn unit_length(&self) -> Offset { + self.unit_length + } + + /// Get the length of the debugging info for this compilation unit, + /// including the byte length of the encoded length itself. + pub fn length_including_self(&self) -> Offset { + Offset::from_u8(self.format().initial_length_size()) + self.unit_length + } + + /// Return the encoding parameters for this unit. + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Get the DWARF version of the debugging info for this compilation unit. + pub fn version(&self) -> u16 { + self.encoding.version + } + + /// Get the UnitType of this unit. + pub fn type_(&self) -> UnitType { + self.unit_type + } + + /// The offset into the `.debug_abbrev` section for this compilation unit's + /// debugging information entries' abbreviations. + pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset { + self.debug_abbrev_offset + } + + /// The size of addresses (in bytes) in this compilation unit. + pub fn address_size(&self) -> u8 { + self.encoding.address_size + } + + /// Whether this compilation unit is encoded in 64- or 32-bit DWARF. + pub fn format(&self) -> Format { + self.encoding.format + } + + /// The serialized size of the header for this compilation unit. + pub fn header_size(&self) -> Offset { + self.length_including_self() - self.entries_buf.len() + } + + pub(crate) fn is_valid_offset(&self, offset: UnitOffset) -> bool { + let size_of_header = self.header_size(); + if offset.0 < size_of_header { + return false; + } + + let relative_to_entries_buf = offset.0 - size_of_header; + relative_to_entries_buf < self.entries_buf.len() + } + + /// Get the underlying bytes for the supplied range. + pub fn range(&self, idx: Range>) -> Result { + if !self.is_valid_offset(idx.start) { + return Err(Error::OffsetOutOfBounds); + } + if !self.is_valid_offset(idx.end) { + return Err(Error::OffsetOutOfBounds); + } + assert!(idx.start <= idx.end); + let size_of_header = self.header_size(); + let start = idx.start.0 - size_of_header; + let end = idx.end.0 - size_of_header; + let mut input = self.entries_buf.clone(); + input.skip(start)?; + input.truncate(end - start)?; + Ok(input) + } + + /// Get the underlying bytes for the supplied range. + pub fn range_from(&self, idx: RangeFrom>) -> Result { + if !self.is_valid_offset(idx.start) { + return Err(Error::OffsetOutOfBounds); + } + let start = idx.start.0 - self.header_size(); + let mut input = self.entries_buf.clone(); + input.skip(start)?; + Ok(input) + } + + /// Get the underlying bytes for the supplied range. + pub fn range_to(&self, idx: RangeTo>) -> Result { + if !self.is_valid_offset(idx.end) { + return Err(Error::OffsetOutOfBounds); + } + let end = idx.end.0 - self.header_size(); + let mut input = self.entries_buf.clone(); + input.truncate(end)?; + Ok(input) + } + + /// Read the `DebuggingInformationEntry` at the given offset. + pub fn entry<'me, 'abbrev>( + &'me self, + abbreviations: &'abbrev Abbreviations, + offset: UnitOffset, + ) -> Result> { + let mut input = self.range_from(offset..)?; + let entry = DebuggingInformationEntry::parse(&mut input, self, abbreviations)?; + entry.ok_or(Error::NoEntryAtGivenOffset) + } + + /// Navigate this unit's `DebuggingInformationEntry`s. + pub fn entries<'me, 'abbrev>( + &'me self, + abbreviations: &'abbrev Abbreviations, + ) -> EntriesCursor<'abbrev, 'me, R> { + EntriesCursor { + unit: self, + input: self.entries_buf.clone(), + abbreviations, + cached_current: None, + delta_depth: 0, + } + } + + /// Navigate this compilation unit's `DebuggingInformationEntry`s + /// starting at the given offset. + pub fn entries_at_offset<'me, 'abbrev>( + &'me self, + abbreviations: &'abbrev Abbreviations, + offset: UnitOffset, + ) -> Result> { + let input = self.range_from(offset..)?; + Ok(EntriesCursor { + unit: self, + input, + abbreviations, + cached_current: None, + delta_depth: 0, + }) + } + + /// Navigate this unit's `DebuggingInformationEntry`s as a tree + /// starting at the given offset. + pub fn entries_tree<'me, 'abbrev>( + &'me self, + abbreviations: &'abbrev Abbreviations, + offset: Option>, + ) -> Result> { + let input = match offset { + Some(offset) => self.range_from(offset..)?, + None => self.entries_buf.clone(), + }; + Ok(EntriesTree::new(input, self, abbreviations)) + } + + /// Read the raw data that defines the Debugging Information Entries. + pub fn entries_raw<'me, 'abbrev>( + &'me self, + abbreviations: &'abbrev Abbreviations, + offset: Option>, + ) -> Result> { + let input = match offset { + Some(offset) => self.range_from(offset..)?, + None => self.entries_buf.clone(), + }; + Ok(EntriesRaw { + input, + unit: self, + abbreviations, + depth: 0, + }) + } + + /// Parse this unit's abbreviations. + pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev) -> Result { + debug_abbrev.abbreviations(self.debug_abbrev_offset()) + } +} + +/// Parse a unit header. +fn parse_unit_header( + input: &mut R, + unit_offset: UnitSectionOffset, +) -> Result> +where + R: Reader, + Offset: ReaderOffset, +{ + let (unit_length, format) = input.read_initial_length()?; + let mut rest = input.split(unit_length)?; + + let version = rest.read_u16()?; + let abbrev_offset; + let address_size; + let unit_type; + // DWARF 1 was very different, and is obsolete, so isn't supported by this + // reader. + if 2 <= version && version <= 4 { + abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?; + address_size = rest.read_address_size()?; + // Before DWARF5, all units in the .debug_info section are compilation + // units, and all units in the .debug_types section are type units. + unit_type = match unit_offset { + UnitSectionOffset::DebugInfoOffset(_) => constants::DW_UT_compile, + UnitSectionOffset::DebugTypesOffset(_) => constants::DW_UT_type, + }; + } else if version == 5 { + unit_type = parse_unit_type(&mut rest)?; + address_size = rest.read_address_size()?; + abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?; + } else { + return Err(Error::UnknownVersion(u64::from(version))); + } + let encoding = Encoding { + format, + version, + address_size, + }; + + // Parse any data specific to this type of unit. + let unit_type = match unit_type { + constants::DW_UT_compile => UnitType::Compilation, + constants::DW_UT_type => { + let type_signature = parse_type_signature(&mut rest)?; + let type_offset = parse_type_offset(&mut rest, format)?; + UnitType::Type { + type_signature, + type_offset, + } + } + constants::DW_UT_partial => UnitType::Partial, + constants::DW_UT_skeleton => { + let dwo_id = parse_dwo_id(&mut rest)?; + UnitType::Skeleton(dwo_id) + } + constants::DW_UT_split_compile => { + let dwo_id = parse_dwo_id(&mut rest)?; + UnitType::SplitCompilation(dwo_id) + } + constants::DW_UT_split_type => { + let type_signature = parse_type_signature(&mut rest)?; + let type_offset = parse_type_offset(&mut rest, format)?; + UnitType::SplitType { + type_signature, + type_offset, + } + } + _ => return Err(Error::UnsupportedUnitType), + }; + + Ok(UnitHeader::new( + encoding, + unit_length, + unit_type, + abbrev_offset, + unit_offset, + rest, + )) +} + +/// Parse a dwo_id from a header +fn parse_dwo_id(input: &mut R) -> Result { + Ok(DwoId(input.read_u64()?)) +} + +/// A Debugging Information Entry (DIE). +/// +/// DIEs have a set of attributes and optionally have children DIEs as well. +#[derive(Clone, Debug)] +pub struct DebuggingInformationEntry<'abbrev, 'unit, R, Offset = ::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + offset: UnitOffset, + attrs_slice: R, + attrs_len: Cell>, + abbrev: &'abbrev Abbreviation, + unit: &'unit UnitHeader, +} + +impl<'abbrev, 'unit, R, Offset> DebuggingInformationEntry<'abbrev, 'unit, R, Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// Construct a new `DebuggingInformationEntry`. + pub fn new( + offset: UnitOffset, + attrs_slice: R, + abbrev: &'abbrev Abbreviation, + unit: &'unit UnitHeader, + ) -> Self { + DebuggingInformationEntry { + offset, + attrs_slice, + attrs_len: Cell::new(None), + abbrev, + unit, + } + } + + /// Get this entry's code. + pub fn code(&self) -> u64 { + self.abbrev.code() + } + + /// Get this entry's offset. + pub fn offset(&self) -> UnitOffset { + self.offset + } + + /// Get this entry's `DW_TAG_whatever` tag. + /// + /// ``` + /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian}; + /// # let info_buf = [ + /// # // Comilation unit header + /// # + /// # // 32-bit unit length = 12 + /// # 0x0c, 0x00, 0x00, 0x00, + /// # // Version 4 + /// # 0x04, 0x00, + /// # // debug_abbrev_offset + /// # 0x00, 0x00, 0x00, 0x00, + /// # // Address size + /// # 0x04, + /// # + /// # // DIEs + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # ]; + /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian); + /// # let abbrev_buf = [ + /// # // Code + /// # 0x01, + /// # // DW_TAG_subprogram + /// # 0x2e, + /// # // DW_CHILDREN_no + /// # 0x00, + /// # // Begin attributes + /// # // Attribute name = DW_AT_name + /// # 0x03, + /// # // Attribute form = DW_FORM_string + /// # 0x08, + /// # // End attributes + /// # 0x00, + /// # 0x00, + /// # // Null terminator + /// # 0x00 + /// # ]; + /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian); + /// # let unit = debug_info.units().next().unwrap().unwrap(); + /// # let abbrevs = unit.abbreviations(&debug_abbrev).unwrap(); + /// # let mut cursor = unit.entries(&abbrevs); + /// # let (_, entry) = cursor.next_dfs().unwrap().unwrap(); + /// # let mut get_some_entry = || entry; + /// let entry = get_some_entry(); + /// + /// match entry.tag() { + /// gimli::DW_TAG_subprogram => + /// println!("this entry contains debug info about a function"), + /// gimli::DW_TAG_inlined_subroutine => + /// println!("this entry contains debug info about a particular instance of inlining"), + /// gimli::DW_TAG_variable => + /// println!("this entry contains debug info about a local variable"), + /// gimli::DW_TAG_formal_parameter => + /// println!("this entry contains debug info about a function parameter"), + /// otherwise => + /// println!("this entry is some other kind of data: {:?}", otherwise), + /// }; + /// ``` + pub fn tag(&self) -> constants::DwTag { + self.abbrev.tag() + } + + /// Return true if this entry's type can have children, false otherwise. + pub fn has_children(&self) -> bool { + self.abbrev.has_children() + } + + /// Iterate over this entry's set of attributes. + /// + /// ``` + /// use gimli::{DebugAbbrev, DebugInfo, LittleEndian}; + /// + /// // Read the `.debug_info` section. + /// + /// # let info_buf = [ + /// # // Comilation unit header + /// # + /// # // 32-bit unit length = 12 + /// # 0x0c, 0x00, 0x00, 0x00, + /// # // Version 4 + /// # 0x04, 0x00, + /// # // debug_abbrev_offset + /// # 0x00, 0x00, 0x00, 0x00, + /// # // Address size + /// # 0x04, + /// # + /// # // DIEs + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # ]; + /// # let read_debug_info_section_somehow = || &info_buf; + /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian); + /// + /// // Get the data about the first compilation unit out of the `.debug_info`. + /// + /// let unit = debug_info.units().next() + /// .expect("Should have at least one compilation unit") + /// .expect("and it should parse ok"); + /// + /// // Read the `.debug_abbrev` section and parse the + /// // abbreviations for our compilation unit. + /// + /// # let abbrev_buf = [ + /// # // Code + /// # 0x01, + /// # // DW_TAG_subprogram + /// # 0x2e, + /// # // DW_CHILDREN_no + /// # 0x00, + /// # // Begin attributes + /// # // Attribute name = DW_AT_name + /// # 0x03, + /// # // Attribute form = DW_FORM_string + /// # 0x08, + /// # // End attributes + /// # 0x00, + /// # 0x00, + /// # // Null terminator + /// # 0x00 + /// # ]; + /// # let read_debug_abbrev_section_somehow = || &abbrev_buf; + /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian); + /// let abbrevs = unit.abbreviations(&debug_abbrev).unwrap(); + /// + /// // Get the first entry from that compilation unit. + /// + /// let mut cursor = unit.entries(&abbrevs); + /// let (_, entry) = cursor.next_dfs() + /// .expect("Should parse next entry") + /// .expect("Should have at least one entry"); + /// + /// // Finally, print the first entry's attributes. + /// + /// let mut attrs = entry.attrs(); + /// while let Some(attr) = attrs.next().unwrap() { + /// println!("Attribute name = {:?}", attr.name()); + /// println!("Attribute value = {:?}", attr.value()); + /// } + /// ``` + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R> { + AttrsIter { + input: self.attrs_slice.clone(), + attributes: self.abbrev.attributes(), + entry: self, + } + } + + /// Find the first attribute in this entry which has the given name, + /// and return it. Returns `Ok(None)` if no attribute is found. + pub fn attr(&self, name: constants::DwAt) -> Result>> { + let mut attrs = self.attrs(); + while let Some(attr) = attrs.next()? { + if attr.name() == name { + return Ok(Some(attr)); + } + } + Ok(None) + } + + /// Find the first attribute in this entry which has the given name, + /// and return its raw value. Returns `Ok(None)` if no attribute is found. + pub fn attr_value_raw(&self, name: constants::DwAt) -> Result>> { + self.attr(name) + .map(|attr| attr.map(|attr| attr.raw_value())) + } + + /// Find the first attribute in this entry which has the given name, + /// and return its normalized value. Returns `Ok(None)` if no + /// attribute is found. + pub fn attr_value(&self, name: constants::DwAt) -> Result>> { + self.attr(name).map(|attr| attr.map(|attr| attr.value())) + } + + /// Return the input buffer after the last attribute. + #[inline(always)] + fn after_attrs(&self) -> Result { + if let Some(attrs_len) = self.attrs_len.get() { + let mut input = self.attrs_slice.clone(); + input.skip(attrs_len)?; + Ok(input) + } else { + let mut attrs = self.attrs(); + while attrs.next()?.is_some() {} + Ok(attrs.input) + } + } + + /// Use the `DW_AT_sibling` attribute to find the input buffer for the + /// next sibling. Returns `None` if the attribute is missing or invalid. + fn sibling(&self) -> Option { + let attr = self.attr_value(constants::DW_AT_sibling); + if let Ok(Some(AttributeValue::UnitRef(offset))) = attr { + if offset.0 > self.offset.0 { + if let Ok(input) = self.unit.range_from(offset..) { + return Some(input); + } + } + } + None + } + + /// Parse an entry. Returns `Ok(None)` for null entries. + #[inline(always)] + fn parse( + input: &mut R, + unit: &'unit UnitHeader, + abbreviations: &'abbrev Abbreviations, + ) -> Result> { + let offset = unit.header_size() + input.offset_from(&unit.entries_buf); + let code = input.read_uleb128()?; + if code == 0 { + return Ok(None); + }; + let abbrev = abbreviations + .get(code) + .ok_or(Error::UnknownAbbreviation(code))?; + Ok(Some(DebuggingInformationEntry { + offset: UnitOffset(offset), + attrs_slice: input.clone(), + attrs_len: Cell::new(None), + abbrev, + unit, + })) + } +} + +/// The value of an attribute in a `DebuggingInformationEntry`. +// +// Set the discriminant size so that all variants use the same alignment +// for their data. This gives better code generation in `parse_attribute`. +#[repr(u64)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum AttributeValue::Offset> +where + R: Reader, + Offset: ReaderOffset, +{ + /// "Refers to some location in the address space of the described program." + Addr(u64), + + /// A slice of an arbitrary number of bytes. + Block(R), + + /// A one byte constant data value. How to interpret the byte depends on context. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data1(u8), + + /// A two byte constant data value. How to interpret the bytes depends on context. + /// + /// These bytes have been converted from `R::Endian`. This may need to be reversed + /// if this was not required. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data2(u16), + + /// A four byte constant data value. How to interpret the bytes depends on context. + /// + /// These bytes have been converted from `R::Endian`. This may need to be reversed + /// if this was not required. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data4(u32), + + /// An eight byte constant data value. How to interpret the bytes depends on context. + /// + /// These bytes have been converted from `R::Endian`. This may need to be reversed + /// if this was not required. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data8(u64), + + /// A signed integer constant. + Sdata(i64), + + /// An unsigned integer constant. + Udata(u64), + + /// "The information bytes contain a DWARF expression (see Section 2.5) or + /// location description (see Section 2.6)." + Exprloc(Expression), + + /// A boolean that indicates presence or absence of the attribute. + Flag(bool), + + /// An offset into another section. Which section this is an offset into + /// depends on context. + SecOffset(Offset), + + /// An offset to a set of addresses in the `.debug_addr` section. + DebugAddrBase(DebugAddrBase), + + /// An index into a set of addresses in the `.debug_addr` section. + DebugAddrIndex(DebugAddrIndex), + + /// An offset into the current compilation unit. + UnitRef(UnitOffset), + + /// An offset into the current `.debug_info` section, but possibly a + /// different compilation unit from the current one. + DebugInfoRef(DebugInfoOffset), + + /// An offset into the `.debug_info` section of the supplementary object file. + DebugInfoRefSup(DebugInfoOffset), + + /// An offset into the `.debug_line` section. + DebugLineRef(DebugLineOffset), + + /// An offset into either the `.debug_loc` section or the `.debug_loclists` section. + LocationListsRef(LocationListsOffset), + + /// An offset to a set of offsets in the `.debug_loclists` section. + DebugLocListsBase(DebugLocListsBase), + + /// An index into a set of offsets in the `.debug_loclists` section. + DebugLocListsIndex(DebugLocListsIndex), + + /// An offset into the `.debug_macinfo` section. + DebugMacinfoRef(DebugMacinfoOffset), + + /// An offset into the `.debug_macro` section. + DebugMacroRef(DebugMacroOffset), + + /// An offset into the `.debug_ranges` section. + RangeListsRef(RawRangeListsOffset), + + /// An offset to a set of offsets in the `.debug_rnglists` section. + DebugRngListsBase(DebugRngListsBase), + + /// An index into a set of offsets in the `.debug_rnglists` section. + DebugRngListsIndex(DebugRngListsIndex), + + /// A type signature. + DebugTypesRef(DebugTypeSignature), + + /// An offset into the `.debug_str` section. + DebugStrRef(DebugStrOffset), + + /// An offset into the `.debug_str` section of the supplementary object file. + DebugStrRefSup(DebugStrOffset), + + /// An offset to a set of entries in the `.debug_str_offsets` section. + DebugStrOffsetsBase(DebugStrOffsetsBase), + + /// An index into a set of entries in the `.debug_str_offsets` section. + DebugStrOffsetsIndex(DebugStrOffsetsIndex), + + /// An offset into the `.debug_line_str` section. + DebugLineStrRef(DebugLineStrOffset), + + /// A slice of bytes representing a string. Does not include a final null byte. + /// Not guaranteed to be UTF-8 or anything like that. + String(R), + + /// The value of a `DW_AT_encoding` attribute. + Encoding(constants::DwAte), + + /// The value of a `DW_AT_decimal_sign` attribute. + DecimalSign(constants::DwDs), + + /// The value of a `DW_AT_endianity` attribute. + Endianity(constants::DwEnd), + + /// The value of a `DW_AT_accessibility` attribute. + Accessibility(constants::DwAccess), + + /// The value of a `DW_AT_visibility` attribute. + Visibility(constants::DwVis), + + /// The value of a `DW_AT_virtuality` attribute. + Virtuality(constants::DwVirtuality), + + /// The value of a `DW_AT_language` attribute. + Language(constants::DwLang), + + /// The value of a `DW_AT_address_class` attribute. + AddressClass(constants::DwAddr), + + /// The value of a `DW_AT_identifier_case` attribute. + IdentifierCase(constants::DwId), + + /// The value of a `DW_AT_calling_convention` attribute. + CallingConvention(constants::DwCc), + + /// The value of a `DW_AT_inline` attribute. + Inline(constants::DwInl), + + /// The value of a `DW_AT_ordering` attribute. + Ordering(constants::DwOrd), + + /// An index into the filename entries from the line number information + /// table for the compilation unit containing this value. + FileIndex(u64), + + /// An implementation-defined identifier uniquely identifying a compilation + /// unit. + DwoId(DwoId), +} + +/// An attribute in a `DebuggingInformationEntry`, consisting of a name and +/// associated value. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct Attribute { + name: constants::DwAt, + value: AttributeValue, +} + +impl Attribute { + /// Get this attribute's name. + pub fn name(&self) -> constants::DwAt { + self.name + } + + /// Get this attribute's raw value. + pub fn raw_value(&self) -> AttributeValue { + self.value.clone() + } + + /// Get this attribute's normalized value. + /// + /// Attribute values can potentially be encoded in multiple equivalent forms, + /// and may have special meaning depending on the attribute name. This method + /// converts the attribute value to a normalized form based on the attribute + /// name. + /// + /// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings". + pub fn value(&self) -> AttributeValue { + // Table 7.5 shows the possible attribute classes for each name. + // Table 7.6 shows the possible attribute classes for each form. + // For each attribute name, we need to match on the form, and + // convert it to one of the classes that is allowed for both + // the name and the form. + // + // The individual class conversions rarely vary for each name, + // so for each class conversion we define a macro that matches + // on the allowed forms for that class. + // + // For some classes, we don't need to do any conversion, so their + // macro is empty. In the future we may want to fill them in to + // provide strict checking of the forms for each class. For now, + // they simply provide a way to document the allowed classes for + // each name. + + // DW_FORM_addr + // DW_FORM_addrx + // DW_FORM_addrx1 + // DW_FORM_addrx2 + // DW_FORM_addrx3 + // DW_FORM_addrx4 + macro_rules! address { + () => {}; + } + // DW_FORM_sec_offset + macro_rules! addrptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugAddrBase(DebugAddrBase(offset)); + } + }; + } + // DW_FORM_block + // DW_FORM_block1 + // DW_FORM_block2 + // DW_FORM_block4 + macro_rules! block { + () => {}; + } + // DW_FORM_sdata + // DW_FORM_udata + // DW_FORM_data1 + // DW_FORM_data2 + // DW_FORM_data4 + // DW_FORM_data8 + // DW_FORM_data16 + // DW_FORM_implicit_const + macro_rules! constant { + ($value:ident, $variant:ident) => { + if let Some(value) = self.$value() { + return AttributeValue::$variant(value); + } + }; + ($value:ident, $variant:ident, $constant:ident) => { + if let Some(value) = self.$value() { + return AttributeValue::$variant(constants::$constant(value)); + } + }; + } + // DW_FORM_exprloc + macro_rules! exprloc { + () => { + if let Some(value) = self.exprloc_value() { + return AttributeValue::Exprloc(value); + } + }; + } + // DW_FORM_flag + // DW_FORM_flag_present + macro_rules! flag { + () => {}; + } + // DW_FORM_sec_offset + macro_rules! lineptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugLineRef(DebugLineOffset(offset)); + } + }; + } + // This also covers `loclist` in DWARF version 5. + // DW_FORM_sec_offset + // DW_FORM_loclistx + macro_rules! loclistptr { + () => { + // DebugLocListsIndex is also an allowed form in DWARF version 5. + if let Some(offset) = self.offset_value() { + return AttributeValue::LocationListsRef(LocationListsOffset(offset)); + } + }; + } + // DW_FORM_sec_offset + macro_rules! loclistsptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset)); + } + }; + } + // DWARF version <= 4. + // DW_FORM_sec_offset + macro_rules! macinfoptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset)); + } + }; + } + // DWARF version >= 5. + // DW_FORM_sec_offset + macro_rules! macroptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugMacroRef(DebugMacroOffset(offset)); + } + }; + } + // DW_FORM_ref_addr + // DW_FORM_ref1 + // DW_FORM_ref2 + // DW_FORM_ref4 + // DW_FORM_ref8 + // DW_FORM_ref_udata + // DW_FORM_ref_sig8 + // DW_FORM_ref_sup4 + // DW_FORM_ref_sup8 + macro_rules! reference { + () => {}; + } + // This also covers `rnglist` in DWARF version 5. + // DW_FORM_sec_offset + // DW_FORM_rnglistx + macro_rules! rangelistptr { + () => { + // DebugRngListsIndex is also an allowed form in DWARF version 5. + if let Some(offset) = self.offset_value() { + return AttributeValue::RangeListsRef(RawRangeListsOffset(offset)); + } + }; + } + // DW_FORM_sec_offset + macro_rules! rnglistsptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset)); + } + }; + } + // DW_FORM_string + // DW_FORM_strp + // DW_FORM_strx + // DW_FORM_strx1 + // DW_FORM_strx2 + // DW_FORM_strx3 + // DW_FORM_strx4 + // DW_FORM_strp_sup + // DW_FORM_line_strp + macro_rules! string { + () => {}; + } + // DW_FORM_sec_offset + macro_rules! stroffsetsptr { + () => { + if let Some(offset) = self.offset_value() { + return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset)); + } + }; + } + // This isn't a separate form but it's useful to distinguish it from a generic udata. + macro_rules! dwoid { + () => { + if let Some(value) = self.udata_value() { + return AttributeValue::DwoId(DwoId(value)); + } + }; + } + + // Perform the allowed class conversions for each attribute name. + match self.name { + constants::DW_AT_sibling => { + reference!(); + } + constants::DW_AT_location => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_name => { + string!(); + } + constants::DW_AT_ordering => { + constant!(u8_value, Ordering, DwOrd); + } + constants::DW_AT_byte_size + | constants::DW_AT_bit_offset + | constants::DW_AT_bit_size => { + constant!(udata_value, Udata); + exprloc!(); + reference!(); + } + constants::DW_AT_stmt_list => { + lineptr!(); + } + constants::DW_AT_low_pc => { + address!(); + } + constants::DW_AT_high_pc => { + address!(); + constant!(udata_value, Udata); + } + constants::DW_AT_language => { + constant!(u16_value, Language, DwLang); + } + constants::DW_AT_discr => { + reference!(); + } + constants::DW_AT_discr_value => { + // constant: depends on type of DW_TAG_variant_part, + // so caller must normalize. + } + constants::DW_AT_visibility => { + constant!(u8_value, Visibility, DwVis); + } + constants::DW_AT_import => { + reference!(); + } + constants::DW_AT_string_length => { + exprloc!(); + loclistptr!(); + reference!(); + } + constants::DW_AT_common_reference => { + reference!(); + } + constants::DW_AT_comp_dir => { + string!(); + } + constants::DW_AT_const_value => { + // TODO: constant: sign depends on DW_AT_type. + block!(); + string!(); + } + constants::DW_AT_containing_type => { + reference!(); + } + constants::DW_AT_default_value => { + // TODO: constant: sign depends on DW_AT_type. + reference!(); + flag!(); + } + constants::DW_AT_inline => { + constant!(u8_value, Inline, DwInl); + } + constants::DW_AT_is_optional => { + flag!(); + } + constants::DW_AT_lower_bound => { + // TODO: constant: sign depends on DW_AT_type. + exprloc!(); + reference!(); + } + constants::DW_AT_producer => { + string!(); + } + constants::DW_AT_prototyped => { + flag!(); + } + constants::DW_AT_return_addr => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_start_scope => { + // TODO: constant + rangelistptr!(); + } + constants::DW_AT_bit_stride => { + constant!(udata_value, Udata); + exprloc!(); + reference!(); + } + constants::DW_AT_upper_bound => { + // TODO: constant: sign depends on DW_AT_type. + exprloc!(); + reference!(); + } + constants::DW_AT_abstract_origin => { + reference!(); + } + constants::DW_AT_accessibility => { + constant!(u8_value, Accessibility, DwAccess); + } + constants::DW_AT_address_class => { + constant!(udata_value, AddressClass, DwAddr); + } + constants::DW_AT_artificial => { + flag!(); + } + constants::DW_AT_base_types => { + reference!(); + } + constants::DW_AT_calling_convention => { + constant!(u8_value, CallingConvention, DwCc); + } + constants::DW_AT_count => { + // TODO: constant + exprloc!(); + reference!(); + } + constants::DW_AT_data_member_location => { + // Constants must be handled before loclistptr so that DW_FORM_data4/8 + // are correctly interpreted for DWARF version 4+. + constant!(udata_value, Udata); + exprloc!(); + loclistptr!(); + } + constants::DW_AT_decl_column => { + constant!(udata_value, Udata); + } + constants::DW_AT_decl_file => { + constant!(udata_value, FileIndex); + } + constants::DW_AT_decl_line => { + constant!(udata_value, Udata); + } + constants::DW_AT_declaration => { + flag!(); + } + constants::DW_AT_discr_list => { + block!(); + } + constants::DW_AT_encoding => { + constant!(u8_value, Encoding, DwAte); + } + constants::DW_AT_external => { + flag!(); + } + constants::DW_AT_frame_base => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_friend => { + reference!(); + } + constants::DW_AT_identifier_case => { + constant!(u8_value, IdentifierCase, DwId); + } + constants::DW_AT_macro_info => { + macinfoptr!(); + } + constants::DW_AT_namelist_item => { + reference!(); + } + constants::DW_AT_priority => { + reference!(); + } + constants::DW_AT_segment => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_specification => { + reference!(); + } + constants::DW_AT_static_link => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_type => { + reference!(); + } + constants::DW_AT_use_location => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_variable_parameter => { + flag!(); + } + constants::DW_AT_virtuality => { + constant!(u8_value, Virtuality, DwVirtuality); + } + constants::DW_AT_vtable_elem_location => { + exprloc!(); + loclistptr!(); + } + constants::DW_AT_allocated => { + // TODO: constant + exprloc!(); + reference!(); + } + constants::DW_AT_associated => { + // TODO: constant + exprloc!(); + reference!(); + } + constants::DW_AT_data_location => { + exprloc!(); + } + constants::DW_AT_byte_stride => { + constant!(udata_value, Udata); + exprloc!(); + reference!(); + } + constants::DW_AT_entry_pc => { + // TODO: constant + address!(); + } + constants::DW_AT_use_UTF8 => { + flag!(); + } + constants::DW_AT_extension => { + reference!(); + } + constants::DW_AT_ranges => { + rangelistptr!(); + } + constants::DW_AT_trampoline => { + address!(); + flag!(); + reference!(); + string!(); + } + constants::DW_AT_call_column => { + constant!(udata_value, Udata); + } + constants::DW_AT_call_file => { + constant!(udata_value, FileIndex); + } + constants::DW_AT_call_line => { + constant!(udata_value, Udata); + } + constants::DW_AT_description => { + string!(); + } + constants::DW_AT_binary_scale => { + // TODO: constant + } + constants::DW_AT_decimal_scale => { + // TODO: constant + } + constants::DW_AT_small => { + reference!(); + } + constants::DW_AT_decimal_sign => { + constant!(u8_value, DecimalSign, DwDs); + } + constants::DW_AT_digit_count => { + // TODO: constant + } + constants::DW_AT_picture_string => { + string!(); + } + constants::DW_AT_mutable => { + flag!(); + } + constants::DW_AT_threads_scaled => { + flag!(); + } + constants::DW_AT_explicit => { + flag!(); + } + constants::DW_AT_object_pointer => { + reference!(); + } + constants::DW_AT_endianity => { + constant!(u8_value, Endianity, DwEnd); + } + constants::DW_AT_elemental => { + flag!(); + } + constants::DW_AT_pure => { + flag!(); + } + constants::DW_AT_recursive => { + flag!(); + } + constants::DW_AT_signature => { + reference!(); + } + constants::DW_AT_main_subprogram => { + flag!(); + } + constants::DW_AT_data_bit_offset => { + // TODO: constant + } + constants::DW_AT_const_expr => { + flag!(); + } + constants::DW_AT_enum_class => { + flag!(); + } + constants::DW_AT_linkage_name => { + string!(); + } + constants::DW_AT_string_length_bit_size => { + // TODO: constant + } + constants::DW_AT_string_length_byte_size => { + // TODO: constant + } + constants::DW_AT_rank => { + // TODO: constant + exprloc!(); + } + constants::DW_AT_str_offsets_base => { + stroffsetsptr!(); + } + constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => { + addrptr!(); + } + constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => { + rnglistsptr!(); + } + constants::DW_AT_dwo_name => { + string!(); + } + constants::DW_AT_reference => { + flag!(); + } + constants::DW_AT_rvalue_reference => { + flag!(); + } + constants::DW_AT_macros => { + macroptr!(); + } + constants::DW_AT_call_all_calls => { + flag!(); + } + constants::DW_AT_call_all_source_calls => { + flag!(); + } + constants::DW_AT_call_all_tail_calls => { + flag!(); + } + constants::DW_AT_call_return_pc => { + address!(); + } + constants::DW_AT_call_value => { + exprloc!(); + } + constants::DW_AT_call_origin => { + exprloc!(); + } + constants::DW_AT_call_parameter => { + reference!(); + } + constants::DW_AT_call_pc => { + address!(); + } + constants::DW_AT_call_tail_call => { + flag!(); + } + constants::DW_AT_call_target => { + exprloc!(); + } + constants::DW_AT_call_target_clobbered => { + exprloc!(); + } + constants::DW_AT_call_data_location => { + exprloc!(); + } + constants::DW_AT_call_data_value => { + exprloc!(); + } + constants::DW_AT_noreturn => { + flag!(); + } + constants::DW_AT_alignment => { + // TODO: constant + } + constants::DW_AT_export_symbols => { + flag!(); + } + constants::DW_AT_deleted => { + flag!(); + } + constants::DW_AT_defaulted => { + // TODO: constant + } + constants::DW_AT_loclists_base => { + loclistsptr!(); + } + constants::DW_AT_GNU_dwo_id => { + dwoid!(); + } + _ => {} + } + self.value.clone() + } + + /// Try to convert this attribute's value to a u8. + #[inline] + pub fn u8_value(&self) -> Option { + self.value.u8_value() + } + + /// Try to convert this attribute's value to a u16. + #[inline] + pub fn u16_value(&self) -> Option { + self.value.u16_value() + } + + /// Try to convert this attribute's value to an unsigned integer. + #[inline] + pub fn udata_value(&self) -> Option { + self.value.udata_value() + } + + /// Try to convert this attribute's value to a signed integer. + #[inline] + pub fn sdata_value(&self) -> Option { + self.value.sdata_value() + } + + /// Try to convert this attribute's value to an offset. + #[inline] + pub fn offset_value(&self) -> Option { + self.value.offset_value() + } + + /// Try to convert this attribute's value to an expression or location buffer. + /// + /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`. + /// The standard doesn't mention `DW_FORM_block*` as a possible form, but + /// it is encountered in practice. + #[inline] + pub fn exprloc_value(&self) -> Option> { + self.value.exprloc_value() + } + + /// Try to return this attribute's value as a string slice. + /// + /// If this attribute's value is either an inline `DW_FORM_string` string, + /// or a `DW_FORM_strp` reference to an offset into the `.debug_str` + /// section, return the attribute's string value as `Some`. Other attribute + /// value forms are returned as `None`. + /// + /// Warning: this function does not handle all possible string forms. + /// Use `Dwarf::attr_string` instead. + #[inline] + pub fn string_value(&self, debug_str: &DebugStr) -> Option { + self.value.string_value(debug_str) + } + + /// Try to return this attribute's value as a string slice. + /// + /// If this attribute's value is either an inline `DW_FORM_string` string, + /// or a `DW_FORM_strp` reference to an offset into the `.debug_str` + /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary + /// object file, return the attribute's string value as `Some`. Other attribute + /// value forms are returned as `None`. + /// + /// Warning: this function does not handle all possible string forms. + /// Use `Dwarf::attr_string` instead. + #[inline] + pub fn string_value_sup( + &self, + debug_str: &DebugStr, + debug_str_sup: Option<&DebugStr>, + ) -> Option { + self.value.string_value_sup(debug_str, debug_str_sup) + } +} + +impl AttributeValue +where + R: Reader, + Offset: ReaderOffset, +{ + /// Try to convert this attribute's value to a u8. + pub fn u8_value(&self) -> Option { + if let Some(value) = self.udata_value() { + if value <= u64::from(u8::MAX) { + return Some(value as u8); + } + } + None + } + + /// Try to convert this attribute's value to a u16. + pub fn u16_value(&self) -> Option { + if let Some(value) = self.udata_value() { + if value <= u64::from(u16::MAX) { + return Some(value as u16); + } + } + None + } + + /// Try to convert this attribute's value to an unsigned integer. + pub fn udata_value(&self) -> Option { + Some(match *self { + AttributeValue::Data1(data) => u64::from(data), + AttributeValue::Data2(data) => u64::from(data), + AttributeValue::Data4(data) => u64::from(data), + AttributeValue::Data8(data) => data, + AttributeValue::Udata(data) => data, + AttributeValue::Sdata(data) => { + if data < 0 { + // Maybe we should emit a warning here + return None; + } + data as u64 + } + _ => return None, + }) + } + + /// Try to convert this attribute's value to a signed integer. + pub fn sdata_value(&self) -> Option { + Some(match *self { + AttributeValue::Data1(data) => i64::from(data as i8), + AttributeValue::Data2(data) => i64::from(data as i16), + AttributeValue::Data4(data) => i64::from(data as i32), + AttributeValue::Data8(data) => data as i64, + AttributeValue::Sdata(data) => data, + AttributeValue::Udata(data) => { + if data > i64::MAX as u64 { + // Maybe we should emit a warning here + return None; + } + data as i64 + } + _ => return None, + }) + } + + /// Try to convert this attribute's value to an offset. + pub fn offset_value(&self) -> Option { + // While offsets will be DW_FORM_data4/8 in DWARF version 2/3, + // these have already been converted to `SecOffset. + if let AttributeValue::SecOffset(offset) = *self { + Some(offset) + } else { + None + } + } + + /// Try to convert this attribute's value to an expression or location buffer. + /// + /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`. + /// The standard doesn't mention `DW_FORM_block*` as a possible form, but + /// it is encountered in practice. + pub fn exprloc_value(&self) -> Option> { + Some(match *self { + AttributeValue::Block(ref data) => Expression(data.clone()), + AttributeValue::Exprloc(ref data) => data.clone(), + _ => return None, + }) + } + + /// Try to return this attribute's value as a string slice. + /// + /// If this attribute's value is either an inline `DW_FORM_string` string, + /// or a `DW_FORM_strp` reference to an offset into the `.debug_str` + /// section, return the attribute's string value as `Some`. Other attribute + /// value forms are returned as `None`. + /// + /// Warning: this function does not handle all possible string forms. + /// Use `Dwarf::attr_string` instead. + pub fn string_value(&self, debug_str: &DebugStr) -> Option { + match *self { + AttributeValue::String(ref string) => Some(string.clone()), + AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(), + _ => None, + } + } + + /// Try to return this attribute's value as a string slice. + /// + /// If this attribute's value is either an inline `DW_FORM_string` string, + /// or a `DW_FORM_strp` reference to an offset into the `.debug_str` + /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary + /// object file, return the attribute's string value as `Some`. Other attribute + /// value forms are returned as `None`. + /// + /// Warning: this function does not handle all possible string forms. + /// Use `Dwarf::attr_string` instead. + pub fn string_value_sup( + &self, + debug_str: &DebugStr, + debug_str_sup: Option<&DebugStr>, + ) -> Option { + match *self { + AttributeValue::String(ref string) => Some(string.clone()), + AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(), + AttributeValue::DebugStrRefSup(offset) => { + debug_str_sup.and_then(|s| s.get_str(offset).ok()) + } + _ => None, + } + } +} + +fn length_u8_value(input: &mut R) -> Result { + let len = input.read_u8().map(R::Offset::from_u8)?; + input.split(len) +} + +fn length_u16_value(input: &mut R) -> Result { + let len = input.read_u16().map(R::Offset::from_u16)?; + input.split(len) +} + +fn length_u32_value(input: &mut R) -> Result { + let len = input.read_u32().map(R::Offset::from_u32)?; + input.split(len) +} + +fn length_uleb128_value(input: &mut R) -> Result { + let len = input.read_uleb128().and_then(R::Offset::from_u64)?; + input.split(len) +} + +// Return true if the given `name` can be a section offset in DWARF version 2/3. +// This is required to correctly handle relocations. +fn allow_section_offset(name: constants::DwAt, version: u16) -> bool { + match name { + constants::DW_AT_location + | constants::DW_AT_stmt_list + | constants::DW_AT_string_length + | constants::DW_AT_return_addr + | constants::DW_AT_start_scope + | constants::DW_AT_frame_base + | constants::DW_AT_macro_info + | constants::DW_AT_macros + | constants::DW_AT_segment + | constants::DW_AT_static_link + | constants::DW_AT_use_location + | constants::DW_AT_vtable_elem_location + | constants::DW_AT_ranges => true, + constants::DW_AT_data_member_location => version == 2 || version == 3, + _ => false, + } +} + +pub(crate) fn parse_attribute( + input: &mut R, + encoding: Encoding, + spec: AttributeSpecification, +) -> Result> { + let mut form = spec.form(); + loop { + let value = match form { + constants::DW_FORM_indirect => { + let dynamic_form = input.read_uleb128_u16()?; + form = constants::DwForm(dynamic_form); + continue; + } + constants::DW_FORM_addr => { + let addr = input.read_address(encoding.address_size)?; + AttributeValue::Addr(addr) + } + constants::DW_FORM_block1 => { + let block = length_u8_value(input)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block2 => { + let block = length_u16_value(input)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block4 => { + let block = length_u32_value(input)?; + AttributeValue::Block(block) + } + constants::DW_FORM_block => { + let block = length_uleb128_value(input)?; + AttributeValue::Block(block) + } + constants::DW_FORM_data1 => { + let data = input.read_u8()?; + AttributeValue::Data1(data) + } + constants::DW_FORM_data2 => { + let data = input.read_u16()?; + AttributeValue::Data2(data) + } + constants::DW_FORM_data4 => { + // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets. + // Ensure we handle relocations here. + if encoding.format == Format::Dwarf32 + && allow_section_offset(spec.name(), encoding.version) + { + let offset = input.read_offset(Format::Dwarf32)?; + AttributeValue::SecOffset(offset) + } else { + let data = input.read_u32()?; + AttributeValue::Data4(data) + } + } + constants::DW_FORM_data8 => { + // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets. + // Ensure we handle relocations here. + if encoding.format == Format::Dwarf64 + && allow_section_offset(spec.name(), encoding.version) + { + let offset = input.read_offset(Format::Dwarf64)?; + AttributeValue::SecOffset(offset) + } else { + let data = input.read_u64()?; + AttributeValue::Data8(data) + } + } + constants::DW_FORM_data16 => { + let block = input.split(R::Offset::from_u8(16))?; + AttributeValue::Block(block) + } + constants::DW_FORM_udata => { + let data = input.read_uleb128()?; + AttributeValue::Udata(data) + } + constants::DW_FORM_sdata => { + let data = input.read_sleb128()?; + AttributeValue::Sdata(data) + } + constants::DW_FORM_exprloc => { + let block = length_uleb128_value(input)?; + AttributeValue::Exprloc(Expression(block)) + } + constants::DW_FORM_flag => { + let present = input.read_u8()?; + AttributeValue::Flag(present != 0) + } + constants::DW_FORM_flag_present => { + // FlagPresent is this weird compile time always true thing that + // isn't actually present in the serialized DIEs, only in the abbreviation. + AttributeValue::Flag(true) + } + constants::DW_FORM_sec_offset => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::SecOffset(offset) + } + constants::DW_FORM_ref1 => { + let reference = input.read_u8().map(R::Offset::from_u8)?; + AttributeValue::UnitRef(UnitOffset(reference)) + } + constants::DW_FORM_ref2 => { + let reference = input.read_u16().map(R::Offset::from_u16)?; + AttributeValue::UnitRef(UnitOffset(reference)) + } + constants::DW_FORM_ref4 => { + let reference = input.read_u32().map(R::Offset::from_u32)?; + AttributeValue::UnitRef(UnitOffset(reference)) + } + constants::DW_FORM_ref8 => { + let reference = input.read_u64().and_then(R::Offset::from_u64)?; + AttributeValue::UnitRef(UnitOffset(reference)) + } + constants::DW_FORM_ref_udata => { + let reference = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::UnitRef(UnitOffset(reference)) + } + constants::DW_FORM_ref_addr => { + // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr + // has the same size as an address on the target system. This was changed + // in DWARF version 3. + let offset = if encoding.version == 2 { + input.read_sized_offset(encoding.address_size)? + } else { + input.read_offset(encoding.format)? + }; + AttributeValue::DebugInfoRef(DebugInfoOffset(offset)) + } + constants::DW_FORM_ref_sig8 => { + let signature = input.read_u64()?; + AttributeValue::DebugTypesRef(DebugTypeSignature(signature)) + } + constants::DW_FORM_ref_sup4 => { + let offset = input.read_u32().map(R::Offset::from_u32)?; + AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset)) + } + constants::DW_FORM_ref_sup8 => { + let offset = input.read_u64().and_then(R::Offset::from_u64)?; + AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset)) + } + constants::DW_FORM_GNU_ref_alt => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset)) + } + constants::DW_FORM_string => { + let string = input.read_null_terminated_slice()?; + AttributeValue::String(string) + } + constants::DW_FORM_strp => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugStrRef(DebugStrOffset(offset)) + } + constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugStrRefSup(DebugStrOffset(offset)) + } + constants::DW_FORM_line_strp => { + let offset = input.read_offset(encoding.format)?; + AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset)) + } + constants::DW_FORM_implicit_const => { + let data = spec + .implicit_const_value() + .ok_or(Error::InvalidImplicitConst)?; + AttributeValue::Sdata(data) + } + constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => { + let index = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx1 => { + let index = input.read_u8().map(R::Offset::from_u8)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx2 => { + let index = input.read_u16().map(R::Offset::from_u16)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx3 => { + let index = input.read_uint(3).and_then(R::Offset::from_u64)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_strx4 => { + let index = input.read_u32().map(R::Offset::from_u32)?; + AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index)) + } + constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => { + let index = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::DebugAddrIndex(DebugAddrIndex(index)) + } + constants::DW_FORM_addrx1 => { + let index = input.read_u8().map(R::Offset::from_u8)?; + AttributeValue::DebugAddrIndex(DebugAddrIndex(index)) + } + constants::DW_FORM_addrx2 => { + let index = input.read_u16().map(R::Offset::from_u16)?; + AttributeValue::DebugAddrIndex(DebugAddrIndex(index)) + } + constants::DW_FORM_addrx3 => { + let index = input.read_uint(3).and_then(R::Offset::from_u64)?; + AttributeValue::DebugAddrIndex(DebugAddrIndex(index)) + } + constants::DW_FORM_addrx4 => { + let index = input.read_u32().map(R::Offset::from_u32)?; + AttributeValue::DebugAddrIndex(DebugAddrIndex(index)) + } + constants::DW_FORM_loclistx => { + let index = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index)) + } + constants::DW_FORM_rnglistx => { + let index = input.read_uleb128().and_then(R::Offset::from_u64)?; + AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index)) + } + _ => { + return Err(Error::UnknownForm(form)); + } + }; + let attr = Attribute { + name: spec.name(), + value, + }; + return Ok(attr); + } +} + +pub(crate) fn skip_attributes( + input: &mut R, + encoding: Encoding, + specs: &[AttributeSpecification], +) -> Result<()> { + let mut skip_bytes = R::Offset::from_u8(0); + for spec in specs { + let mut form = spec.form(); + loop { + if let Some(len) = get_attribute_size(form, encoding) { + // We know the length of this attribute. Accumulate that length. + skip_bytes += R::Offset::from_u8(len); + break; + } + + // We have encountered a variable-length attribute. + if skip_bytes != R::Offset::from_u8(0) { + // Skip the accumulated skip bytes and then read the attribute normally. + input.skip(skip_bytes)?; + skip_bytes = R::Offset::from_u8(0); + } + + match form { + constants::DW_FORM_indirect => { + let dynamic_form = input.read_uleb128_u16()?; + form = constants::DwForm(dynamic_form); + continue; + } + constants::DW_FORM_block1 => { + skip_bytes = input.read_u8().map(R::Offset::from_u8)?; + } + constants::DW_FORM_block2 => { + skip_bytes = input.read_u16().map(R::Offset::from_u16)?; + } + constants::DW_FORM_block4 => { + skip_bytes = input.read_u32().map(R::Offset::from_u32)?; + } + constants::DW_FORM_block | constants::DW_FORM_exprloc => { + skip_bytes = input.read_uleb128().and_then(R::Offset::from_u64)?; + } + constants::DW_FORM_string => { + let _ = input.read_null_terminated_slice()?; + } + constants::DW_FORM_udata + | constants::DW_FORM_sdata + | constants::DW_FORM_ref_udata + | constants::DW_FORM_strx + | constants::DW_FORM_GNU_str_index + | constants::DW_FORM_addrx + | constants::DW_FORM_GNU_addr_index + | constants::DW_FORM_loclistx + | constants::DW_FORM_rnglistx => { + input.skip_leb128()?; + } + _ => { + return Err(Error::UnknownForm(form)); + } + }; + break; + } + } + if skip_bytes != R::Offset::from_u8(0) { + // Skip the remaining accumulated skip bytes. + input.skip(skip_bytes)?; + } + Ok(()) +} + +/// An iterator over a particular entry's attributes. +/// +/// See [the documentation for +/// `DebuggingInformationEntry::attrs()`](./struct.DebuggingInformationEntry.html#method.attrs) +/// for details. +/// +/// Can be [used with +/// `FallibleIterator`](./index.html#using-with-fallibleiterator). +#[derive(Clone, Copy, Debug)] +pub struct AttrsIter<'abbrev, 'entry, 'unit, R: Reader> { + input: R, + attributes: &'abbrev [AttributeSpecification], + entry: &'entry DebuggingInformationEntry<'abbrev, 'unit, R>, +} + +impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> { + /// Advance the iterator and return the next attribute. + /// + /// Returns `None` when iteration is finished. If an error + /// occurs while parsing the next attribute, then this error + /// is returned, and all subsequent calls return `None`. + #[inline(always)] + pub fn next(&mut self) -> Result>> { + if self.attributes.is_empty() { + // Now that we have parsed all of the attributes, we know where + // either (1) this entry's children start, if the abbreviation says + // this entry has children; or (2) where this entry's siblings + // begin. + if let Some(end) = self.entry.attrs_len.get() { + debug_assert_eq!(end, self.input.offset_from(&self.entry.attrs_slice)); + } else { + self.entry + .attrs_len + .set(Some(self.input.offset_from(&self.entry.attrs_slice))); + } + + return Ok(None); + } + + let spec = self.attributes[0]; + let rest_spec = &self.attributes[1..]; + match parse_attribute(&mut self.input, self.entry.unit.encoding(), spec) { + Ok(attr) => { + self.attributes = rest_spec; + Ok(Some(attr)) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl<'abbrev, 'entry, 'unit, R: Reader> fallible_iterator::FallibleIterator + for AttrsIter<'abbrev, 'entry, 'unit, R> +{ + type Item = Attribute; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + AttrsIter::next(self) + } +} + +/// A raw reader of the data that defines the Debugging Information Entries. +/// +/// `EntriesRaw` provides primitives to read the components of Debugging Information +/// Entries (DIEs). A DIE consists of an abbreviation code (read with `read_abbreviation`) +/// followed by a number of attributes (read with `read_attribute`). +/// The user must provide the control flow to read these correctly. +/// In particular, all attributes must always be read before reading another +/// abbreviation code. +/// +/// `EntriesRaw` lacks some features of `EntriesCursor`, such as the ability to skip +/// to the next sibling DIE. However, this also allows it to optimize better, since it +/// does not need to perform the extra bookkeeping required to support these features, +/// and thus it is suitable for cases where performance is important. +/// +/// ## Example Usage +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian); +/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap(); +/// let unit = get_some_unit(); +/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian); +/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap(); +/// let abbrevs = get_abbrevs_for_unit(&unit); +/// +/// let mut entries = unit.entries_raw(&abbrevs, None)?; +/// while !entries.is_empty() { +/// let abbrev = if let Some(abbrev) = entries.read_abbreviation()? { +/// abbrev +/// } else { +/// // Null entry with no attributes. +/// continue +/// }; +/// match abbrev.tag() { +/// gimli::DW_TAG_subprogram => { +/// // Loop over attributes for DIEs we care about. +/// for spec in abbrev.attributes() { +/// let attr = entries.read_attribute(*spec)?; +/// match attr.name() { +/// // Handle attributes. +/// _ => {} +/// } +/// } +/// } +/// _ => { +/// // Skip attributes for DIEs we don't care about. +/// entries.skip_attributes(abbrev.attributes()); +/// } +/// } +/// } +/// # unreachable!() +/// # } +/// ``` +#[derive(Clone, Debug)] +pub struct EntriesRaw<'abbrev, 'unit, R> +where + R: Reader, +{ + input: R, + unit: &'unit UnitHeader, + abbreviations: &'abbrev Abbreviations, + depth: isize, +} + +impl<'abbrev, 'unit, R: Reader> EntriesRaw<'abbrev, 'unit, R> { + /// Return true if there is no more input. + #[inline] + pub fn is_empty(&self) -> bool { + self.input.is_empty() + } + + /// Return the unit offset at which the reader will read next. + /// + /// If you want the offset of the next entry, then this must be called prior to reading + /// the next entry. + pub fn next_offset(&self) -> UnitOffset { + UnitOffset(self.unit.header_size() + self.input.offset_from(&self.unit.entries_buf)) + } + + /// Return the depth of the next entry. + /// + /// This depth is updated when `read_abbreviation` is called, and is updated + /// based on null entries and the `has_children` field in the abbreviation. + #[inline] + pub fn next_depth(&self) -> isize { + self.depth + } + + /// Read an abbreviation code and lookup the corresponding `Abbreviation`. + /// + /// Returns `Ok(None)` for null entries. + #[inline] + pub fn read_abbreviation(&mut self) -> Result> { + let code = self.input.read_uleb128()?; + if code == 0 { + self.depth -= 1; + return Ok(None); + }; + let abbrev = self + .abbreviations + .get(code) + .ok_or(Error::UnknownAbbreviation(code))?; + if abbrev.has_children() { + self.depth += 1; + } + Ok(Some(abbrev)) + } + + /// Read an attribute. + #[inline] + pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result> { + parse_attribute(&mut self.input, self.unit.encoding(), spec) + } + + /// Skip all the attributes of an abbreviation. + #[inline] + pub fn skip_attributes(&mut self, specs: &[AttributeSpecification]) -> Result<()> { + skip_attributes(&mut self.input, self.unit.encoding(), specs) + } +} + +/// A cursor into the Debugging Information Entries tree for a compilation unit. +/// +/// The `EntriesCursor` can traverse the DIE tree in DFS order using `next_dfs()`, +/// or skip to the next sibling of the entry the cursor is currently pointing to +/// using `next_sibling()`. +/// +/// It is also possible to traverse the DIE tree at a lower abstraction level +/// using `next_entry()`. This method does not skip over null entries, or provide +/// any indication of the current tree depth. In this case, you must use `current()` +/// to obtain the current entry, and `current().has_children()` to determine if +/// the entry following the current entry will be a sibling or child. `current()` +/// will return `None` if the current entry is a null entry, which signifies the +/// end of the current tree depth. +#[derive(Clone, Debug)] +pub struct EntriesCursor<'abbrev, 'unit, R> +where + R: Reader, +{ + input: R, + unit: &'unit UnitHeader, + abbreviations: &'abbrev Abbreviations, + cached_current: Option>, + delta_depth: isize, +} + +impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> { + /// Get a reference to the entry that the cursor is currently pointing to. + /// + /// If the cursor is not pointing at an entry, or if the current entry is a + /// null entry, then `None` is returned. + #[inline] + pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> { + self.cached_current.as_ref() + } + + /// Move the cursor to the next DIE in the tree. + /// + /// Returns `Some` if there is a next entry, even if this entry is null. + /// If there is no next entry, then `None` is returned. + pub fn next_entry(&mut self) -> Result> { + if let Some(ref current) = self.cached_current { + self.input = current.after_attrs()?; + } + + if self.input.is_empty() { + self.cached_current = None; + self.delta_depth = 0; + return Ok(None); + } + + match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) { + Ok(Some(entry)) => { + self.delta_depth = entry.has_children() as isize; + self.cached_current = Some(entry); + Ok(Some(())) + } + Ok(None) => { + self.delta_depth = -1; + self.cached_current = None; + Ok(Some(())) + } + Err(e) => { + self.input.empty(); + self.delta_depth = 0; + self.cached_current = None; + Err(e) + } + } + } + + /// Move the cursor to the next DIE in the tree in DFS order. + /// + /// Upon successful movement of the cursor, return the delta traversal + /// depth and the entry: + /// + /// * If we moved down into the previous current entry's children, we get + /// `Some((1, entry))`. + /// + /// * If we moved to the previous current entry's sibling, we get + /// `Some((0, entry))`. + /// + /// * If the previous entry does not have any siblings and we move up to + /// its parent's next sibling, then we get `Some((-1, entry))`. Note that + /// if the parent doesn't have a next sibling, then it could go up to the + /// parent's parent's next sibling and return `Some((-2, entry))`, etc. + /// + /// If there is no next entry, then `None` is returned. + /// + /// Here is an example that finds the first entry in a compilation unit that + /// does not have any children. + /// + /// ``` + /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian}; + /// # let info_buf = [ + /// # // Comilation unit header + /// # + /// # // 32-bit unit length = 25 + /// # 0x19, 0x00, 0x00, 0x00, + /// # // Version 4 + /// # 0x04, 0x00, + /// # // debug_abbrev_offset + /// # 0x00, 0x00, 0x00, 0x00, + /// # // Address size + /// # 0x04, + /// # + /// # // DIEs + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // End of children + /// # 0x00, + /// # + /// # // End of children + /// # 0x00, + /// # + /// # // End of children + /// # 0x00, + /// # ]; + /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian); + /// # + /// # let abbrev_buf = [ + /// # // Code + /// # 0x01, + /// # // DW_TAG_subprogram + /// # 0x2e, + /// # // DW_CHILDREN_yes + /// # 0x01, + /// # // Begin attributes + /// # // Attribute name = DW_AT_name + /// # 0x03, + /// # // Attribute form = DW_FORM_string + /// # 0x08, + /// # // End attributes + /// # 0x00, + /// # 0x00, + /// # // Null terminator + /// # 0x00 + /// # ]; + /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian); + /// # + /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap(); + /// + /// let unit = get_some_unit(); + /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap(); + /// let abbrevs = get_abbrevs_for_unit(&unit); + /// + /// let mut first_entry_with_no_children = None; + /// let mut cursor = unit.entries(&abbrevs); + /// + /// // Move the cursor to the root. + /// assert!(cursor.next_dfs().unwrap().is_some()); + /// + /// // Traverse the DIE tree in depth-first search order. + /// let mut depth = 0; + /// while let Some((delta_depth, current)) = cursor.next_dfs().expect("Should parse next dfs") { + /// // Update depth value, and break out of the loop when we + /// // return to the original starting position. + /// depth += delta_depth; + /// if depth <= 0 { + /// break; + /// } + /// + /// first_entry_with_no_children = Some(current.clone()); + /// } + /// + /// println!("The first entry with no children is {:?}", + /// first_entry_with_no_children.unwrap()); + /// ``` + pub fn next_dfs( + &mut self, + ) -> Result)>> { + let mut delta_depth = self.delta_depth; + loop { + // The next entry should be the one we want. + if self.next_entry()?.is_some() { + if let Some(ref entry) = self.cached_current { + return Ok(Some((delta_depth, entry))); + } + + // next_entry() read a null entry. + delta_depth += self.delta_depth; + } else { + return Ok(None); + } + } + } + + /// Move the cursor to the next sibling DIE of the current one. + /// + /// Returns `Ok(Some(entry))` when the cursor has been moved to + /// the next sibling, `Ok(None)` when there is no next sibling. + /// + /// The depth of the cursor is never changed if this method returns `Ok`. + /// Once `Ok(None)` is returned, this method will continue to return + /// `Ok(None)` until either `next_entry` or `next_dfs` is called. + /// + /// Here is an example that iterates over all of the direct children of the + /// root entry: + /// + /// ``` + /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian}; + /// # let info_buf = [ + /// # // Comilation unit header + /// # + /// # // 32-bit unit length = 25 + /// # 0x19, 0x00, 0x00, 0x00, + /// # // Version 4 + /// # 0x04, 0x00, + /// # // debug_abbrev_offset + /// # 0x00, 0x00, 0x00, 0x00, + /// # // Address size + /// # 0x04, + /// # + /// # // DIEs + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // Abbreviation code + /// # 0x01, + /// # // Attribute of form DW_FORM_string = "foo\0" + /// # 0x66, 0x6f, 0x6f, 0x00, + /// # + /// # // Children + /// # + /// # // End of children + /// # 0x00, + /// # + /// # // End of children + /// # 0x00, + /// # + /// # // End of children + /// # 0x00, + /// # ]; + /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian); + /// # + /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap(); + /// + /// # let abbrev_buf = [ + /// # // Code + /// # 0x01, + /// # // DW_TAG_subprogram + /// # 0x2e, + /// # // DW_CHILDREN_yes + /// # 0x01, + /// # // Begin attributes + /// # // Attribute name = DW_AT_name + /// # 0x03, + /// # // Attribute form = DW_FORM_string + /// # 0x08, + /// # // End attributes + /// # 0x00, + /// # 0x00, + /// # // Null terminator + /// # 0x00 + /// # ]; + /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian); + /// # + /// let unit = get_some_unit(); + /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap(); + /// let abbrevs = get_abbrevs_for_unit(&unit); + /// + /// let mut cursor = unit.entries(&abbrevs); + /// + /// // Move the cursor to the root. + /// assert!(cursor.next_dfs().unwrap().is_some()); + /// + /// // Move the cursor to the root's first child. + /// assert!(cursor.next_dfs().unwrap().is_some()); + /// + /// // Iterate the root's children. + /// loop { + /// { + /// let current = cursor.current().expect("Should be at an entry"); + /// println!("{:?} is a child of the root", current); + /// } + /// + /// if cursor.next_sibling().expect("Should parse next sibling").is_none() { + /// break; + /// } + /// } + /// ``` + pub fn next_sibling( + &mut self, + ) -> Result>> { + if self.current().is_none() { + // We're already at the null for the end of the sibling list. + return Ok(None); + } + + // Loop until we find an entry at the current level. + let mut depth = 0; + loop { + // Use is_some() and unwrap() to keep borrow checker happy. + if self.current().is_some() && self.current().unwrap().has_children() { + if let Some(sibling_input) = self.current().unwrap().sibling() { + // Fast path: this entry has a DW_AT_sibling + // attribute pointing to its sibling, so jump + // to it (which keeps us at the same depth). + self.input = sibling_input; + self.cached_current = None; + } else { + // This entry has children, so the next entry is + // down one level. + depth += 1; + } + } + + if self.next_entry()?.is_none() { + // End of input. + return Ok(None); + } + + if depth == 0 { + // Found an entry at the current level. + return Ok(self.current()); + } + + if self.current().is_none() { + // A null entry means the end of a child list, so we're + // back up a level. + depth -= 1; + } + } + } +} + +/// The state information for a tree view of the Debugging Information Entries. +/// +/// The `EntriesTree` can be used to recursively iterate through the DIE +/// tree, following the parent/child relationships. The `EntriesTree` contains +/// shared state for all nodes in the tree, avoiding any duplicate parsing of +/// entries during the traversal. +/// +/// ## Example Usage +/// ```rust,no_run +/// # fn example() -> Result<(), gimli::Error> { +/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian); +/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap(); +/// let unit = get_some_unit(); +/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian); +/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap(); +/// let abbrevs = get_abbrevs_for_unit(&unit); +/// +/// let mut tree = unit.entries_tree(&abbrevs, None)?; +/// let root = tree.root()?; +/// process_tree(root)?; +/// # unreachable!() +/// # } +/// +/// fn process_tree(mut node: gimli::EntriesTreeNode) -> gimli::Result<()> +/// where R: gimli::Reader +/// { +/// { +/// // Examine the entry attributes. +/// let mut attrs = node.entry().attrs(); +/// while let Some(attr) = attrs.next()? { +/// } +/// } +/// let mut children = node.children(); +/// while let Some(child) = children.next()? { +/// // Recursively process a child. +/// process_tree(child); +/// } +/// Ok(()) +/// } +/// ``` +#[derive(Clone, Debug)] +pub struct EntriesTree<'abbrev, 'unit, R> +where + R: Reader, +{ + root: R, + unit: &'unit UnitHeader, + abbreviations: &'abbrev Abbreviations, + input: R, + entry: Option>, + depth: isize, +} + +impl<'abbrev, 'unit, R: Reader> EntriesTree<'abbrev, 'unit, R> { + fn new(root: R, unit: &'unit UnitHeader, abbreviations: &'abbrev Abbreviations) -> Self { + let input = root.clone(); + EntriesTree { + root, + unit, + abbreviations, + input, + entry: None, + depth: 0, + } + } + + /// Returns the root node of the tree. + pub fn root<'me>(&'me mut self) -> Result> { + self.input = self.root.clone(); + self.entry = + DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations)?; + if self.entry.is_none() { + return Err(Error::UnexpectedNull); + } + self.depth = 0; + Ok(EntriesTreeNode::new(self, 1)) + } + + /// Move the cursor to the next entry at the specified depth. + /// + /// Requires `depth <= self.depth + 1`. + /// + /// Returns `true` if successful. + fn next(&mut self, depth: isize) -> Result { + if self.depth < depth { + debug_assert_eq!(self.depth + 1, depth); + + match self.entry { + Some(ref entry) => { + if !entry.has_children() { + return Ok(false); + } + self.depth += 1; + self.input = entry.after_attrs()?; + } + None => return Ok(false), + } + + if self.input.is_empty() { + self.entry = None; + return Ok(false); + } + + return match DebuggingInformationEntry::parse( + &mut self.input, + self.unit, + self.abbreviations, + ) { + Ok(entry) => { + self.entry = entry; + Ok(self.entry.is_some()) + } + Err(e) => { + self.input.empty(); + self.entry = None; + Err(e) + } + }; + } + + loop { + match self.entry { + Some(ref entry) => { + if entry.has_children() { + if let Some(sibling_input) = entry.sibling() { + // Fast path: this entry has a DW_AT_sibling + // attribute pointing to its sibling, so jump + // to it (which keeps us at the same depth). + self.input = sibling_input; + } else { + // This entry has children, so the next entry is + // down one level. + self.depth += 1; + self.input = entry.after_attrs()?; + } + } else { + // This entry has no children, so next entry is at same depth. + self.input = entry.after_attrs()?; + } + } + None => { + // This entry is a null, so next entry is up one level. + self.depth -= 1; + } + } + + if self.input.is_empty() { + self.entry = None; + return Ok(false); + } + + match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) { + Ok(entry) => { + self.entry = entry; + if self.depth == depth { + return Ok(self.entry.is_some()); + } + } + Err(e) => { + self.input.empty(); + self.entry = None; + return Err(e); + } + } + } + } +} + +/// A node in the Debugging Information Entry tree. +/// +/// The root node of a tree can be obtained +/// via [`EntriesTree::root`](./struct.EntriesTree.html#method.root). +#[derive(Debug)] +pub struct EntriesTreeNode<'abbrev, 'unit, 'tree, R: Reader> { + tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, + depth: isize, +} + +impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'unit, 'tree, R> { + fn new( + tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, + depth: isize, + ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R> { + debug_assert!(tree.entry.is_some()); + EntriesTreeNode { tree, depth } + } + + /// Returns the current entry in the tree. + pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> { + // We never create a node without an entry. + self.tree.entry.as_ref().unwrap() + } + + /// Create an iterator for the children of the current entry. + /// + /// The current entry can no longer be accessed after creating the + /// iterator. + pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> { + EntriesTreeIter::new(self.tree, self.depth) + } +} + +/// An iterator that allows traversal of the children of an +/// `EntriesTreeNode`. +/// +/// The items returned by this iterator are also `EntriesTreeNode`s, +/// which allow recursive traversal of grandchildren, etc. +#[derive(Debug)] +pub struct EntriesTreeIter<'abbrev, 'unit, 'tree, R: Reader> { + tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, + depth: isize, + empty: bool, +} + +impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'unit, 'tree, R> { + fn new( + tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, + depth: isize, + ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> { + EntriesTreeIter { + tree, + depth, + empty: false, + } + } + + /// Returns an `EntriesTreeNode` for the next child entry. + /// + /// Returns `None` if there are no more children. + pub fn next<'me>(&'me mut self) -> Result>> { + if self.empty { + Ok(None) + } else if self.tree.next(self.depth)? { + Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1))) + } else { + self.empty = true; + Ok(None) + } + } +} + +/// Parse a type unit header's unique type signature. Callers should handle +/// unique-ness checking. +fn parse_type_signature(input: &mut R) -> Result { + input.read_u64().map(DebugTypeSignature) +} + +/// Parse a type unit header's type offset. +fn parse_type_offset(input: &mut R, format: Format) -> Result> { + input.read_offset(format).map(UnitOffset) +} + +/// The `DebugTypes` struct represents the DWARF type information +/// found in the `.debug_types` section. +#[derive(Debug, Default, Clone, Copy)] +pub struct DebugTypes { + debug_types_section: R, +} + +impl<'input, Endian> DebugTypes> +where + Endian: Endianity, +{ + /// Construct a new `DebugTypes` instance from the data in the `.debug_types` + /// section. + /// + /// It is the caller's responsibility to read the `.debug_types` section and + /// present it as a `&[u8]` slice. That means using some ELF loader on + /// Linux, a Mach-O loader on macOS, etc. + /// + /// ``` + /// use gimli::{DebugTypes, LittleEndian}; + /// + /// # let buf = [0x00, 0x01, 0x02, 0x03]; + /// # let read_debug_types_section_somehow = || &buf; + /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian); + /// ``` + pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self { + Self::from(EndianSlice::new(debug_types_section, endian)) + } +} + +impl DebugTypes { + /// Create a `DebugTypes` section that references the data in `self`. + /// + /// This is useful when `R` implements `Reader` but `T` does not. + /// + /// Used by `DwarfSections::borrow`. + pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes + where + F: FnMut(&'a T) -> R, + { + borrow(&self.debug_types_section).into() + } +} + +impl Section for DebugTypes { + fn id() -> SectionId { + SectionId::DebugTypes + } + + fn reader(&self) -> &R { + &self.debug_types_section + } +} + +impl From for DebugTypes { + fn from(debug_types_section: R) -> Self { + DebugTypes { + debug_types_section, + } + } +} + +impl DebugTypes { + /// Iterate the type-units in this `.debug_types` section. + /// + /// ``` + /// use gimli::{DebugTypes, LittleEndian}; + /// + /// # let buf = []; + /// # let read_debug_types_section_somehow = || &buf; + /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian); + /// + /// let mut iter = debug_types.units(); + /// while let Some(unit) = iter.next().unwrap() { + /// println!("unit's length is {}", unit.unit_length()); + /// } + /// ``` + /// + /// Can be [used with + /// `FallibleIterator`](./index.html#using-with-fallibleiterator). + pub fn units(&self) -> DebugTypesUnitHeadersIter { + DebugTypesUnitHeadersIter { + input: self.debug_types_section.clone(), + offset: DebugTypesOffset(R::Offset::from_u8(0)), + } + } +} + +/// An iterator over the type-units of this `.debug_types` section. +/// +/// See the [documentation on +/// `DebugTypes::units`](./struct.DebugTypes.html#method.units) for +/// more detail. +#[derive(Clone, Debug)] +pub struct DebugTypesUnitHeadersIter { + input: R, + offset: DebugTypesOffset, +} + +impl DebugTypesUnitHeadersIter { + /// Advance the iterator to the next type unit header. + pub fn next(&mut self) -> Result>> { + if self.input.is_empty() { + Ok(None) + } else { + let len = self.input.len(); + match parse_unit_header(&mut self.input, self.offset.into()) { + Ok(header) => { + self.offset.0 += len - self.input.len(); + Ok(Some(header)) + } + Err(e) => { + self.input.empty(); + Err(e) + } + } + } + } +} + +#[cfg(feature = "fallible-iterator")] +impl fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter { + type Item = UnitHeader; + type Error = Error; + + fn next(&mut self) -> ::core::result::Result, Self::Error> { + DebugTypesUnitHeadersIter::next(self) + } +} + +#[cfg(test)] +// Tests require leb128::write. +#[cfg(feature = "write")] +mod tests { + use super::*; + use crate::constants; + use crate::constants::*; + use crate::endianity::{Endianity, LittleEndian}; + use crate::leb128; + use crate::read::abbrev::tests::AbbrevSectionMethods; + use crate::read::{ + Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result, + }; + use crate::test_util::GimliSectionMethods; + use alloc::vec::Vec; + use core::cell::Cell; + use test_assembler::{Endian, Label, LabelMaker, Section}; + + // Mixin methods for `Section` to help define binary test data. + + trait UnitSectionMethods { + fn unit(self, unit: &mut UnitHeader>) -> Self + where + E: Endianity; + fn die(self, code: u64, attr: F) -> Self + where + F: Fn(Section) -> Section; + fn die_null(self) -> Self; + fn attr_string(self, s: &str) -> Self; + fn attr_ref1(self, o: u8) -> Self; + fn offset(self, offset: usize, format: Format) -> Self; + } + + impl UnitSectionMethods for Section { + fn unit(self, unit: &mut UnitHeader>) -> Self + where + E: Endianity, + { + let size = self.size(); + let length = Label::new(); + let start = Label::new(); + let end = Label::new(); + + let section = match unit.format() { + Format::Dwarf32 => self.L32(&length), + Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length), + }; + + let section = match unit.version() { + 2..=4 => section + .mark(&start) + .L16(unit.version()) + .offset(unit.debug_abbrev_offset.0, unit.format()) + .D8(unit.address_size()), + 5 => section + .mark(&start) + .L16(unit.version()) + .D8(unit.type_().dw_ut().0) + .D8(unit.address_size()) + .offset(unit.debug_abbrev_offset.0, unit.format()), + _ => unreachable!(), + }; + + let section = match unit.type_() { + UnitType::Compilation | UnitType::Partial => { + unit.unit_offset = DebugInfoOffset(size as usize).into(); + section + } + UnitType::Type { + type_signature, + type_offset, + } + | UnitType::SplitType { + type_signature, + type_offset, + } => { + if unit.version() == 5 { + unit.unit_offset = DebugInfoOffset(size as usize).into(); + } else { + unit.unit_offset = DebugTypesOffset(size as usize).into(); + } + section + .L64(type_signature.0) + .offset(type_offset.0, unit.format()) + } + UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => { + unit.unit_offset = DebugInfoOffset(size as usize).into(); + section.L64(dwo_id.0) + } + }; + + let section = section.append_bytes(unit.entries_buf.slice()).mark(&end); + + unit.unit_length = (&end - &start) as usize; + length.set_const(unit.unit_length as u64); + + section + } + + fn die(self, code: u64, attr: F) -> Self + where + F: Fn(Section) -> Section, + { + let section = self.uleb(code); + attr(section) + } + + fn die_null(self) -> Self { + self.D8(0) + } + + fn attr_string(self, attr: &str) -> Self { + self.append_bytes(attr.as_bytes()).D8(0) + } + + fn attr_ref1(self, attr: u8) -> Self { + self.D8(attr) + } + + fn offset(self, offset: usize, format: Format) -> Self { + match format { + Format::Dwarf32 => self.L32(offset as u32), + Format::Dwarf64 => self.L64(offset as u64), + } + } + } + + /// Ensure that `UnitHeader` is covariant wrt R. + #[test] + fn test_unit_header_variance() { + /// This only needs to compile. + fn _f<'a: 'b, 'b, E: Endianity>( + x: UnitHeader>, + ) -> UnitHeader> { + x + } + } + + #[test] + fn test_parse_debug_abbrev_offset_32() { + let section = Section::with_endian(Endian::Little).L32(0x0403_0201); + let buf = section.get_contents().unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_abbrev_offset(buf, Format::Dwarf32) { + Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0403_0201)), + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_debug_abbrev_offset_32_incomplete() { + let buf = [0x01, 0x02]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_abbrev_offset(buf, Format::Dwarf32) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_debug_abbrev_offset_64() { + let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201); + let buf = section.get_contents().unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_abbrev_offset(buf, Format::Dwarf64) { + Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0807_0605_0403_0201)), + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_debug_abbrev_offset_64_incomplete() { + let buf = [0x01, 0x02]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_abbrev_offset(buf, Format::Dwarf64) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_debug_info_offset_32() { + let section = Section::with_endian(Endian::Little).L32(0x0403_0201); + let buf = section.get_contents().unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_info_offset(buf, Format::Dwarf32) { + Ok(val) => assert_eq!(val, DebugInfoOffset(0x0403_0201)), + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_debug_info_offset_32_incomplete() { + let buf = [0x01, 0x02]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_info_offset(buf, Format::Dwarf32) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_debug_info_offset_64() { + let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201); + let buf = section.get_contents().unwrap(); + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_info_offset(buf, Format::Dwarf64) { + Ok(val) => assert_eq!(val, DebugInfoOffset(0x0807_0605_0403_0201)), + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_debug_info_offset_64_incomplete() { + let buf = [0x01, 0x02]; + let buf = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_debug_info_offset(buf, Format::Dwarf64) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_units() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let mut unit64 = UnitHeader { + encoding: Encoding { + format: Format::Dwarf64, + version: 4, + address_size: 8, + }, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let mut unit32 = UnitHeader { + encoding: Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut unit64) + .unit(&mut unit32); + let buf = section.get_contents().unwrap(); + + let debug_info = DebugInfo::new(&buf, LittleEndian); + let mut units = debug_info.units(); + + assert_eq!(units.next(), Ok(Some(unit64))); + assert_eq!(units.next(), Ok(Some(unit32))); + assert_eq!(units.next(), Ok(None)); + } + + #[test] + fn test_unit_version_unknown_version() { + let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_unit_header(rest, DebugInfoOffset(0).into()) { + Err(Error::UnknownVersion(0xcdab)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + + let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_unit_header(rest, DebugInfoOffset(0).into()) { + Err(Error::UnknownVersion(1)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_unit_version_incomplete() { + let buf = [0x01, 0x00, 0x00, 0x00, 0x04]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_unit_header(rest, DebugInfoOffset(0).into()) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 4, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 4, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_partial_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 4, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Partial, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_partial_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Partial, + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_skeleton_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 4, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)), + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_skeleton_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)), + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_split_compilation_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 4, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)), + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_split_compilation_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)), + debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_type_offset_32_ok() { + let buf = [0x12, 0x34, 0x56, 0x78, 0x00]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_type_offset(rest, Format::Dwarf32) { + Ok(offset) => { + assert_eq!(rest.len(), 1); + assert_eq!(UnitOffset(0x7856_3412), offset); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_type_offset_64_ok() { + let buf = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_type_offset(rest, Format::Dwarf64) { + Ok(offset) => { + assert_eq!(rest.len(), 1); + assert_eq!(UnitOffset(0xffde_bc9a_7856_3412), offset); + } + otherwise => panic!("Unexpected result: {:?}", otherwise), + } + } + + #[test] + fn test_parse_type_offset_incomplete() { + // Need at least 4 bytes. + let buf = [0xff, 0xff, 0xff]; + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + match parse_type_offset(rest, Format::Dwarf32) { + Err(Error::UnexpectedEof(_)) => {} + otherwise => panic!("Unexpected result: {:?}", otherwise), + }; + } + + #[test] + fn test_parse_type_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugTypesOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugTypesOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_type_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 4, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412_7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugTypesOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugTypesOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_type_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_type_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412_7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + fn test_parse_v5_split_type_unit_header_32_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::SplitType { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_v5_split_type_unit_header_64_ok() { + let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; + let encoding = Encoding { + format: Format::Dwarf64, + version: 5, + address_size: 8, + }; + let mut expected_unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::SplitType { + type_signature: DebugTypeSignature(0xdead_beef_dead_beef), + type_offset: UnitOffset(0x7856_3412_7856_3412), + }, + debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(expected_rest, LittleEndian), + }; + let section = Section::with_endian(Endian::Little) + .unit(&mut expected_unit) + .append_bytes(expected_rest); + let buf = section.get_contents().unwrap(); + let rest = &mut EndianSlice::new(&buf, LittleEndian); + + assert_eq!( + parse_unit_header(rest, DebugInfoOffset(0).into()), + Ok(expected_unit) + ); + assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian)); + } + + fn section_contents(f: F) -> Vec + where + F: Fn(Section) -> Section, + { + f(Section::with_endian(Endian::Little)) + .get_contents() + .unwrap() + } + + #[test] + fn test_attribute_value() { + let mut unit = test_parse_attribute_unit_default(); + let endian = unit.entries_buf.endian(); + + let block_data = &[1, 2, 3, 4]; + let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data)); + let block = EndianSlice::new(&buf, endian); + + let buf = section_contents(|s| s.L32(0x0102_0304)); + let data4 = EndianSlice::new(&buf, endian); + + let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708)); + let data8 = EndianSlice::new(&buf, endian); + + let tests = [ + ( + Format::Dwarf32, + 2, + constants::DW_AT_data_member_location, + constants::DW_FORM_block, + block, + AttributeValue::Block(EndianSlice::new(block_data, endian)), + AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))), + ), + ( + Format::Dwarf32, + 2, + constants::DW_AT_data_member_location, + constants::DW_FORM_data4, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)), + ), + ( + Format::Dwarf64, + 2, + constants::DW_AT_data_member_location, + constants::DW_FORM_data4, + data4, + AttributeValue::Data4(0x0102_0304), + AttributeValue::Udata(0x0102_0304), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_data_member_location, + constants::DW_FORM_data4, + data4, + AttributeValue::Data4(0x0102_0304), + AttributeValue::Udata(0x0102_0304), + ), + ( + Format::Dwarf32, + 2, + constants::DW_AT_data_member_location, + constants::DW_FORM_data8, + data8, + AttributeValue::Data8(0x0102_0304_0506_0708), + AttributeValue::Udata(0x0102_0304_0506_0708), + ), + #[cfg(target_pointer_width = "64")] + ( + Format::Dwarf64, + 2, + constants::DW_AT_data_member_location, + constants::DW_FORM_data8, + data8, + AttributeValue::SecOffset(0x0102_0304_0506_0708), + AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)), + ), + ( + Format::Dwarf64, + 4, + constants::DW_AT_data_member_location, + constants::DW_FORM_data8, + data8, + AttributeValue::Data8(0x0102_0304_0506_0708), + AttributeValue::Udata(0x0102_0304_0506_0708), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_location, + constants::DW_FORM_data4, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)), + ), + #[cfg(target_pointer_width = "64")] + ( + Format::Dwarf64, + 4, + constants::DW_AT_location, + constants::DW_FORM_data8, + data8, + AttributeValue::SecOffset(0x0102_0304_0506_0708), + AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_str_offsets_base, + constants::DW_FORM_sec_offset, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_stmt_list, + constants::DW_FORM_sec_offset, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_addr_base, + constants::DW_FORM_sec_offset, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_rnglists_base, + constants::DW_FORM_sec_offset, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)), + ), + ( + Format::Dwarf32, + 4, + constants::DW_AT_loclists_base, + constants::DW_FORM_sec_offset, + data4, + AttributeValue::SecOffset(0x0102_0304), + AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)), + ), + ]; + + for test in tests.iter() { + let (format, version, name, form, mut input, expect_raw, expect_value) = *test; + unit.encoding.format = format; + unit.encoding.version = version; + let spec = AttributeSpecification::new(name, form, None); + let attribute = + parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute"); + assert_eq!(attribute.raw_value(), expect_raw); + assert_eq!(attribute.value(), expect_value); + } + } + + #[test] + fn test_attribute_udata_sdata_value() { + #[allow(clippy::type_complexity)] + let tests: &[( + AttributeValue>, + Option, + Option, + )] = &[ + (AttributeValue::Data1(1), Some(1), Some(1)), + ( + AttributeValue::Data1(u8::MAX), + Some(u64::from(u8::MAX)), + Some(-1), + ), + (AttributeValue::Data2(1), Some(1), Some(1)), + ( + AttributeValue::Data2(u16::MAX), + Some(u64::from(u16::MAX)), + Some(-1), + ), + (AttributeValue::Data4(1), Some(1), Some(1)), + ( + AttributeValue::Data4(u32::MAX), + Some(u64::from(u32::MAX)), + Some(-1), + ), + (AttributeValue::Data8(1), Some(1), Some(1)), + (AttributeValue::Data8(u64::MAX), Some(u64::MAX), Some(-1)), + (AttributeValue::Sdata(1), Some(1), Some(1)), + (AttributeValue::Sdata(-1), None, Some(-1)), + (AttributeValue::Udata(1), Some(1), Some(1)), + (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None), + ]; + for test in tests.iter() { + let (value, expect_udata, expect_sdata) = *test; + let attribute = Attribute { + name: DW_AT_data_member_location, + value, + }; + assert_eq!(attribute.udata_value(), expect_udata); + assert_eq!(attribute.sdata_value(), expect_sdata); + } + } + + fn test_parse_attribute_unit( + address_size: u8, + format: Format, + endian: Endian, + ) -> UnitHeader> + where + Endian: Endianity, + { + let encoding = Encoding { + format, + version: 4, + address_size, + }; + UnitHeader::new( + encoding, + 7, + UnitType::Compilation, + DebugAbbrevOffset(0x0807_0605), + DebugInfoOffset(0).into(), + EndianSlice::new(&[], endian), + ) + } + + fn test_parse_attribute_unit_default() -> UnitHeader> { + test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian) + } + + fn test_parse_attribute<'input, Endian>( + buf: &'input [u8], + len: usize, + unit: &UnitHeader>, + form: constants::DwForm, + value: AttributeValue>, + ) where + Endian: Endianity, + { + let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None); + + let expect = Attribute { + name: constants::DW_AT_low_pc, + value, + }; + + let rest = &mut EndianSlice::new(buf, Endian::default()); + match parse_attribute(rest, unit.encoding(), spec) { + Ok(attr) => { + assert_eq!(attr, expect); + assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default())); + if let Some(size) = spec.size(unit) { + assert_eq!(rest.len() + size, buf.len()); + } + } + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + }; + } + + #[test] + fn test_parse_attribute_addr() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_addr; + let value = AttributeValue::Addr(0x0403_0201); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addr8() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; + let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_addr; + let value = AttributeValue::Addr(0x0807_0605_0403_0201); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_block1() { + // Length of data (3), three bytes of data, two bytes of left over input. + let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_block1; + let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_block2() { + // Two byte length of data (2), two bytes of data, two bytes of left over input. + let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_block2; + let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_block4() { + // Four byte length of data (2), two bytes of data, no left over input. + let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_block4; + let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian)); + test_parse_attribute(&buf, 6, &unit, form, value); + } + + #[test] + fn test_parse_attribute_block() { + // LEB length of data (2, one byte), two bytes of data, no left over input. + let buf = [0x02, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_block; + let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian)); + test_parse_attribute(&buf, 3, &unit, form, value); + } + + #[test] + fn test_parse_attribute_data1() { + let buf = [0x03]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_data1; + let value = AttributeValue::Data1(0x03); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_data2() { + let buf = [0x02, 0x01, 0x0]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_data2; + let value = AttributeValue::Data2(0x0102); + test_parse_attribute(&buf, 2, &unit, form, value); + } + + #[test] + fn test_parse_attribute_data4() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_data4; + let value = AttributeValue::Data4(0x0403_0201); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_data8() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_data8; + let value = AttributeValue::Data8(0x0807_0605_0403_0201); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_udata() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_udata; + let value = AttributeValue::Udata(4097); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_sdata() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::signed(&mut writable, -4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_sdata; + let value = AttributeValue::Sdata(-4097); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_exprloc() { + // LEB length of data (2, one byte), two bytes of data, one byte left over input. + let buf = [0x02, 0x99, 0x99, 0x11]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_exprloc; + let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian))); + test_parse_attribute(&buf, 3, &unit, form, value); + } + + #[test] + fn test_parse_attribute_flag_true() { + let buf = [0x42]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_flag; + let value = AttributeValue::Flag(true); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_flag_false() { + let buf = [0x00]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_flag; + let value = AttributeValue::Flag(false); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_flag_present() { + let buf = [0x01, 0x02, 0x03, 0x04]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_flag_present; + let value = AttributeValue::Flag(true); + // DW_FORM_flag_present does not consume any bytes of the input stream. + test_parse_attribute(&buf, 0, &unit, form, value); + } + + #[test] + fn test_parse_attribute_sec_offset_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_sec_offset; + let value = AttributeValue::SecOffset(0x0403_0201); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_sec_offset_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_sec_offset; + let value = AttributeValue::SecOffset(0x0807_0605_0403_0201); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_ref1() { + let buf = [0x03]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref1; + let value = AttributeValue::UnitRef(UnitOffset(3)); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_ref2() { + let buf = [0x02, 0x01, 0x0]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref2; + let value = AttributeValue::UnitRef(UnitOffset(258)); + test_parse_attribute(&buf, 2, &unit, form, value); + } + + #[test] + fn test_parse_attribute_ref4() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref4; + let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_ref8() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref8; + let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_ref_sup4() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref_sup4; + let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_ref_sup8() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref_sup8; + let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_refudata() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref_udata; + let value = AttributeValue::UnitRef(UnitOffset(4097)); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_refaddr_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_ref_addr; + let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_refaddr_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_ref_addr; + let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_refaddr_version2() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + unit.encoding.version = 2; + let form = constants::DW_FORM_ref_addr; + let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_refaddr8_version2() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian); + unit.encoding.version = 2; + let form = constants::DW_FORM_ref_addr; + let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_gnu_ref_alt_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_GNU_ref_alt; + let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_gnu_ref_alt_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_GNU_ref_alt; + let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_refsig8() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_ref_sig8; + let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_string() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99]; + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_string; + let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian)); + test_parse_attribute(&buf, 6, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strp_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_strp; + let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_strp_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strp; + let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strp_sup_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_strp_sup; + let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_strp_sup_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strp_sup; + let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_gnu_strp_alt_32() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian); + let form = constants::DW_FORM_GNU_strp_alt; + let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn test_parse_attribute_gnu_strp_alt_64() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_GNU_strp_alt; + let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201)); + test_parse_attribute(&buf, 8, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strx() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_strx; + let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097)); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strx1() { + let buf = [0x01, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strx1; + let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01)); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strx2() { + let buf = [0x01, 0x02, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strx2; + let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201)); + test_parse_attribute(&buf, 2, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strx3() { + let buf = [0x01, 0x02, 0x03, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strx3; + let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201)); + test_parse_attribute(&buf, 3, &unit, form, value); + } + + #[test] + fn test_parse_attribute_strx4() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_strx4; + let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addrx() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_addrx; + let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097)); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addrx1() { + let buf = [0x01, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_addrx1; + let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01)); + test_parse_attribute(&buf, 1, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addrx2() { + let buf = [0x01, 0x02, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_addrx2; + let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201)); + test_parse_attribute(&buf, 2, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addrx3() { + let buf = [0x01, 0x02, 0x03, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_addrx3; + let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201)); + test_parse_attribute(&buf, 3, &unit, form, value); + } + + #[test] + fn test_parse_attribute_addrx4() { + let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99]; + let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian); + let form = constants::DW_FORM_addrx4; + let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201)); + test_parse_attribute(&buf, 4, &unit, form, value); + } + + #[test] + fn test_parse_attribute_loclistx() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_loclistx; + let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097)); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_rnglistx() { + let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, 4097).expect("should write ok") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_rnglistx; + let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097)); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_indirect() { + let mut buf = [0; 100]; + + let bytes_written = { + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into()) + .expect("should write udata") + + leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value") + }; + + let unit = test_parse_attribute_unit_default(); + let form = constants::DW_FORM_indirect; + let value = AttributeValue::Udata(9_999_999); + test_parse_attribute(&buf, bytes_written, &unit, form, value); + } + + #[test] + fn test_parse_attribute_indirect_implicit_const() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut buf = [0; 100]; + let mut writable = &mut buf[..]; + leb128::write::unsigned(&mut writable, constants::DW_FORM_implicit_const.0.into()) + .expect("should write implicit_const"); + + let input = &mut EndianSlice::new(&buf, LittleEndian); + let spec = + AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None); + assert_eq!( + parse_attribute(input, encoding, spec), + Err(Error::InvalidImplicitConst) + ); + } + + #[test] + fn test_attrs_iter() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let unit = UnitHeader::new( + encoding, + 7, + UnitType::Compilation, + DebugAbbrevOffset(0x0807_0605), + DebugInfoOffset(0).into(), + EndianSlice::new(&[], LittleEndian), + ); + + let abbrev = Abbreviation::new( + 42, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_yes, + vec![ + AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None), + AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None), + AttributeSpecification::new( + constants::DW_AT_high_pc, + constants::DW_FORM_addr, + None, + ), + ] + .into(), + ); + + // "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be + let buf = [ + 0x66, 0x6f, 0x6f, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x05, 0x00, 0x00, 0xaa, 0xaa, + 0xaa, 0xaa, + ]; + + let entry = DebuggingInformationEntry { + offset: UnitOffset(0), + attrs_slice: EndianSlice::new(&buf, LittleEndian), + attrs_len: Cell::new(None), + abbrev: &abbrev, + unit: &unit, + }; + + let mut attrs = AttrsIter { + input: EndianSlice::new(&buf, LittleEndian), + attributes: abbrev.attributes(), + entry: &entry, + }; + + match attrs.next() { + Ok(Some(attr)) => { + assert_eq!( + attr, + Attribute { + name: constants::DW_AT_name, + value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)), + } + ); + } + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + + assert!(entry.attrs_len.get().is_none()); + + match attrs.next() { + Ok(Some(attr)) => { + assert_eq!( + attr, + Attribute { + name: constants::DW_AT_low_pc, + value: AttributeValue::Addr(0x2a), + } + ); + } + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + + assert!(entry.attrs_len.get().is_none()); + + match attrs.next() { + Ok(Some(attr)) => { + assert_eq!( + attr, + Attribute { + name: constants::DW_AT_high_pc, + value: AttributeValue::Addr(0x539), + } + ); + } + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + + assert!(entry.attrs_len.get().is_none()); + + assert!(attrs.next().expect("should parse next").is_none()); + assert!(entry.attrs_len.get().is_some()); + assert_eq!( + entry.attrs_len.get().expect("should have entry.attrs_len"), + buf.len() - 4 + ) + } + + #[test] + fn test_attrs_iter_incomplete() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let unit = UnitHeader::new( + encoding, + 7, + UnitType::Compilation, + DebugAbbrevOffset(0x0807_0605), + DebugInfoOffset(0).into(), + EndianSlice::new(&[], LittleEndian), + ); + + let abbrev = Abbreviation::new( + 42, + constants::DW_TAG_subprogram, + constants::DW_CHILDREN_yes, + vec![ + AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None), + AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None), + AttributeSpecification::new( + constants::DW_AT_high_pc, + constants::DW_FORM_addr, + None, + ), + ] + .into(), + ); + + // "foo" + let buf = [0x66, 0x6f, 0x6f, 0x00]; + + let entry = DebuggingInformationEntry { + offset: UnitOffset(0), + attrs_slice: EndianSlice::new(&buf, LittleEndian), + attrs_len: Cell::new(None), + abbrev: &abbrev, + unit: &unit, + }; + + let mut attrs = AttrsIter { + input: EndianSlice::new(&buf, LittleEndian), + attributes: abbrev.attributes(), + entry: &entry, + }; + + match attrs.next() { + Ok(Some(attr)) => { + assert_eq!( + attr, + Attribute { + name: constants::DW_AT_name, + value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)), + } + ); + } + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + + assert!(entry.attrs_len.get().is_none()); + + // Return error for incomplete attribute. + assert!(attrs.next().is_err()); + assert!(entry.attrs_len.get().is_none()); + + // Return error for all subsequent calls. + assert!(attrs.next().is_err()); + assert!(attrs.next().is_err()); + assert!(attrs.next().is_err()); + assert!(attrs.next().is_err()); + assert!(entry.attrs_len.get().is_none()); + } + + fn assert_entry_name( + entry: &DebuggingInformationEntry<'_, '_, EndianSlice<'_, Endian>>, + name: &str, + ) where + Endian: Endianity, + { + let value = entry + .attr_value(constants::DW_AT_name) + .expect("Should have parsed the name attribute") + .expect("Should have found the name attribute"); + + assert_eq!( + value, + AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default())) + ); + } + + fn assert_current_name( + cursor: &EntriesCursor<'_, '_, EndianSlice<'_, Endian>>, + name: &str, + ) where + Endian: Endianity, + { + let entry = cursor.current().expect("Should have an entry result"); + assert_entry_name(entry, name); + } + + fn assert_next_entry( + cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>, + name: &str, + ) where + Endian: Endianity, + { + cursor + .next_entry() + .expect("Should parse next entry") + .expect("Should have an entry"); + assert_current_name(cursor, name); + } + + fn assert_next_entry_null(cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>) + where + Endian: Endianity, + { + cursor + .next_entry() + .expect("Should parse next entry") + .expect("Should have an entry"); + assert!(cursor.current().is_none()); + } + + fn assert_next_dfs( + cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>, + name: &str, + depth: isize, + ) where + Endian: Endianity, + { + { + let (val, entry) = cursor + .next_dfs() + .expect("Should parse next dfs") + .expect("Should not be done with traversal"); + assert_eq!(val, depth); + assert_entry_name(entry, name); + } + assert_current_name(cursor, name); + } + + fn assert_next_sibling( + cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, Endian>>, + name: &str, + ) where + Endian: Endianity, + { + { + let entry = cursor + .next_sibling() + .expect("Should parse next sibling") + .expect("Should not be done with traversal"); + assert_entry_name(entry, name); + } + assert_current_name(cursor, name); + } + + fn assert_valid_sibling_ptr(cursor: &EntriesCursor<'_, '_, EndianSlice<'_, Endian>>) + where + Endian: Endianity, + { + let sibling_ptr = cursor + .current() + .expect("Should have current entry") + .attr_value(constants::DW_AT_sibling); + match sibling_ptr { + Ok(Some(AttributeValue::UnitRef(offset))) => { + cursor + .unit + .range_from(offset..) + .expect("Sibling offset should be valid"); + } + _ => panic!("Invalid sibling pointer {:?}", sibling_ptr), + } + } + + fn entries_cursor_tests_abbrev_buf() -> Vec { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev_null(); + section.get_contents().unwrap() + } + + fn entries_cursor_tests_debug_info_buf() -> Vec { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .die(1, |s| s.attr_string("001")) + .die(1, |s| s.attr_string("002")) + .die(1, |s| s.attr_string("003")) + .die_null() + .die_null() + .die(1, |s| s.attr_string("004")) + .die(1, |s| s.attr_string("005")) + .die_null() + .die(1, |s| s.attr_string("006")) + .die_null() + .die_null() + .die(1, |s| s.attr_string("007")) + .die(1, |s| s.attr_string("008")) + .die(1, |s| s.attr_string("009")) + .die_null() + .die_null() + .die_null() + .die(1, |s| s.attr_string("010")) + .die_null() + .die_null(); + let entries_buf = section.get_contents().unwrap(); + + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&entries_buf, LittleEndian), + }; + let section = Section::with_endian(Endian::Little).unit(&mut unit); + section.get_contents().unwrap() + } + + #[test] + fn test_cursor_next_entry_incomplete() { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .die(1, |s| s.attr_string("001")) + .die(1, |s| s.attr_string("002")) + .die(1, |s| s); + let entries_buf = section.get_contents().unwrap(); + + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&entries_buf, LittleEndian), + }; + let section = Section::with_endian(Endian::Little).unit(&mut unit); + let info_buf = §ion.get_contents().unwrap(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + assert_next_entry(&mut cursor, "001"); + assert_next_entry(&mut cursor, "002"); + + { + // Entry code is present, but none of the attributes. + cursor + .next_entry() + .expect("Should parse next entry") + .expect("Should have an entry"); + let entry = cursor.current().expect("Should have an entry result"); + assert!(entry.attrs().next().is_err()); + } + + assert!(cursor.next_entry().is_err()); + assert!(cursor.next_entry().is_err()); + } + + #[test] + fn test_cursor_next_entry() { + let info_buf = &entries_cursor_tests_debug_info_buf(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + assert_next_entry(&mut cursor, "001"); + assert_next_entry(&mut cursor, "002"); + assert_next_entry(&mut cursor, "003"); + assert_next_entry_null(&mut cursor); + assert_next_entry_null(&mut cursor); + assert_next_entry(&mut cursor, "004"); + assert_next_entry(&mut cursor, "005"); + assert_next_entry_null(&mut cursor); + assert_next_entry(&mut cursor, "006"); + assert_next_entry_null(&mut cursor); + assert_next_entry_null(&mut cursor); + assert_next_entry(&mut cursor, "007"); + assert_next_entry(&mut cursor, "008"); + assert_next_entry(&mut cursor, "009"); + assert_next_entry_null(&mut cursor); + assert_next_entry_null(&mut cursor); + assert_next_entry_null(&mut cursor); + assert_next_entry(&mut cursor, "010"); + assert_next_entry_null(&mut cursor); + assert_next_entry_null(&mut cursor); + + assert!(cursor + .next_entry() + .expect("Should parse next entry") + .is_none()); + assert!(cursor.current().is_none()); + } + + #[test] + fn test_cursor_next_dfs() { + let info_buf = &entries_cursor_tests_debug_info_buf(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + assert_next_dfs(&mut cursor, "001", 0); + assert_next_dfs(&mut cursor, "002", 1); + assert_next_dfs(&mut cursor, "003", 1); + assert_next_dfs(&mut cursor, "004", -1); + assert_next_dfs(&mut cursor, "005", 1); + assert_next_dfs(&mut cursor, "006", 0); + assert_next_dfs(&mut cursor, "007", -1); + assert_next_dfs(&mut cursor, "008", 1); + assert_next_dfs(&mut cursor, "009", 1); + assert_next_dfs(&mut cursor, "010", -2); + + assert!(cursor.next_dfs().expect("Should parse next dfs").is_none()); + assert!(cursor.current().is_none()); + } + + #[test] + fn test_cursor_next_sibling_no_sibling_ptr() { + let info_buf = &entries_cursor_tests_debug_info_buf(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + assert_next_dfs(&mut cursor, "001", 0); + + // Down to the first child of the root entry. + + assert_next_dfs(&mut cursor, "002", 1); + + // Now iterate all children of the root via `next_sibling`. + + assert_next_sibling(&mut cursor, "004"); + assert_next_sibling(&mut cursor, "007"); + assert_next_sibling(&mut cursor, "010"); + + // There should be no more siblings. + + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor.current().is_none()); + } + + #[test] + fn test_cursor_next_sibling_continuation() { + let info_buf = &entries_cursor_tests_debug_info_buf(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + + assert_next_dfs(&mut cursor, "001", 0); + + // Down to the first child of the root entry. + + assert_next_dfs(&mut cursor, "002", 1); + + // Get the next sibling, then iterate its children + + assert_next_sibling(&mut cursor, "004"); + assert_next_dfs(&mut cursor, "005", 1); + assert_next_sibling(&mut cursor, "006"); + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + + // And we should be able to continue with the children of the root entry. + + assert_next_dfs(&mut cursor, "007", -1); + assert_next_sibling(&mut cursor, "010"); + + // There should be no more siblings. + + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor.current().is_none()); + } + + fn entries_cursor_sibling_abbrev_buf() -> Vec { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr(DW_AT_sibling, DW_FORM_ref1) + .abbrev_attr_null() + .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev_null(); + section.get_contents().unwrap() + } + + fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec { + let start = Label::new(); + let sibling004_ref = Label::new(); + let sibling004 = Label::new(); + let sibling009_ref = Label::new(); + let sibling009 = Label::new(); + + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .mark(&start) + .die(2, |s| s.attr_string("001")) + // Valid sibling attribute. + .die(1, |s| s.attr_string("002").D8(&sibling004_ref)) + // Invalid code to ensure the sibling attribute was used. + .die(10, |s| s.attr_string("003")) + .die_null() + .die_null() + .mark(&sibling004) + // Invalid sibling attribute. + .die(1, |s| s.attr_string("004").attr_ref1(255)) + .die(2, |s| s.attr_string("005")) + .die_null() + .die_null() + // Sibling attribute in child only. + .die(2, |s| s.attr_string("006")) + // Valid sibling attribute. + .die(1, |s| s.attr_string("007").D8(&sibling009_ref)) + // Invalid code to ensure the sibling attribute was used. + .die(10, |s| s.attr_string("008")) + .die_null() + .die_null() + .mark(&sibling009) + .die(2, |s| s.attr_string("009")) + .die_null() + .die_null() + // No sibling attribute. + .die(2, |s| s.attr_string("010")) + .die(2, |s| s.attr_string("011")) + .die_null() + .die_null() + .die_null(); + + let offset = header_size as u64 + (&sibling004 - &start) as u64; + sibling004_ref.set_const(offset); + + let offset = header_size as u64 + (&sibling009 - &start) as u64; + sibling009_ref.set_const(offset); + + section.get_contents().unwrap() + } + + fn test_cursor_next_sibling_with_ptr( + cursor: &mut EntriesCursor<'_, '_, EndianSlice<'_, LittleEndian>>, + ) { + assert_next_dfs(cursor, "001", 0); + + // Down to the first child of the root. + + assert_next_dfs(cursor, "002", 1); + + // Now iterate all children of the root via `next_sibling`. + + assert_valid_sibling_ptr(cursor); + assert_next_sibling(cursor, "004"); + assert_next_sibling(cursor, "006"); + assert_next_sibling(cursor, "010"); + + // There should be no more siblings. + + assert!(cursor + .next_sibling() + .expect("Should parse next sibling") + .is_none()); + assert!(cursor.current().is_none()); + } + + #[test] + fn test_debug_info_next_sibling_with_ptr() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&[], LittleEndian), + }; + let header_size = unit.size_of_header(); + let entries_buf = entries_cursor_sibling_entries_buf(header_size); + unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian); + let section = Section::with_endian(Endian::Little).unit(&mut unit); + let info_buf = section.get_contents().unwrap(); + let debug_info = DebugInfo::new(&info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrev_buf = entries_cursor_sibling_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + test_cursor_next_sibling_with_ptr(&mut cursor); + } + + #[test] + fn test_debug_types_next_sibling_with_ptr() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0), + type_offset: UnitOffset(0), + }, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugTypesOffset(0).into(), + entries_buf: EndianSlice::new(&[], LittleEndian), + }; + let header_size = unit.size_of_header(); + let entries_buf = entries_cursor_sibling_entries_buf(header_size); + unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian); + let section = Section::with_endian(Endian::Little).unit(&mut unit); + let info_buf = section.get_contents().unwrap(); + let debug_types = DebugTypes::new(&info_buf, LittleEndian); + + let unit = debug_types + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrev_buf = entries_cursor_sibling_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit.entries(&abbrevs); + test_cursor_next_sibling_with_ptr(&mut cursor); + } + + #[test] + fn test_entries_at_offset() { + let info_buf = &entries_cursor_tests_debug_info_buf(); + let debug_info = DebugInfo::new(info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs_buf = &entries_cursor_tests_abbrev_buf(); + let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut cursor = unit + .entries_at_offset(&abbrevs, UnitOffset(unit.header_size())) + .unwrap(); + assert_next_entry(&mut cursor, "001"); + + let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0)); + match cursor { + Err(Error::OffsetOutOfBounds) => {} + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + } + + fn entries_tree_tests_debug_abbrevs_buf() -> Vec { + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev_null() + .get_contents() + .unwrap(); + section + } + + fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec, UnitOffset) { + let start = Label::new(); + let entry2 = Label::new(); + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .mark(&start) + .die(1, |s| s.attr_string("root")) + .die(1, |s| s.attr_string("1")) + .die(1, |s| s.attr_string("1a")) + .die_null() + .die(2, |s| s.attr_string("1b")) + .die_null() + .mark(&entry2) + .die(1, |s| s.attr_string("2")) + .die(1, |s| s.attr_string("2a")) + .die(1, |s| s.attr_string("2a1")) + .die_null() + .die_null() + .die(1, |s| s.attr_string("2b")) + .die(2, |s| s.attr_string("2b1")) + .die_null() + .die_null() + .die(1, |s| s.attr_string("3")) + .die(1, |s| s.attr_string("3a")) + .die(2, |s| s.attr_string("3a1")) + .die(2, |s| s.attr_string("3a2")) + .die_null() + .die(2, |s| s.attr_string("3b")) + .die_null() + .die(2, |s| s.attr_string("final")) + .die_null() + .get_contents() + .unwrap(); + let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize); + (section, entry2) + } + + #[test] + fn test_entries_tree() { + fn assert_entry<'input, 'abbrev, 'unit, 'tree, Endian>( + node: Result< + Option>>, + >, + name: &str, + ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>> + where + Endian: Endianity, + { + let node = node + .expect("Should parse entry") + .expect("Should have entry"); + assert_entry_name(node.entry(), name); + node.children() + } + + fn assert_null( + node: Result>>>, + ) { + match node { + Ok(None) => {} + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + } + + let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf(); + let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian); + + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&[], LittleEndian), + }; + let header_size = unit.size_of_header(); + let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size); + unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian); + let info_buf = Section::with_endian(Endian::Little) + .unit(&mut unit) + .get_contents() + .unwrap(); + let debug_info = DebugInfo::new(&info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("Should parse unit") + .expect("and it should be some"); + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + let mut tree = unit + .entries_tree(&abbrevs, None) + .expect("Should have entries tree"); + + // Test we can restart iteration of the tree. + { + let mut iter = assert_entry(tree.root().map(Some), "root"); + assert_entry(iter.next(), "1"); + } + { + let mut iter = assert_entry(tree.root().map(Some), "root"); + assert_entry(iter.next(), "1"); + } + + let mut iter = assert_entry(tree.root().map(Some), "root"); + { + // Test iteration with children. + let mut iter = assert_entry(iter.next(), "1"); + { + // Test iteration with children flag, but no children. + let mut iter = assert_entry(iter.next(), "1a"); + assert_null(iter.next()); + assert_null(iter.next()); + } + { + // Test iteration without children flag. + let mut iter = assert_entry(iter.next(), "1b"); + assert_null(iter.next()); + assert_null(iter.next()); + } + assert_null(iter.next()); + assert_null(iter.next()); + } + { + // Test skipping over children. + let mut iter = assert_entry(iter.next(), "2"); + assert_entry(iter.next(), "2a"); + assert_entry(iter.next(), "2b"); + assert_null(iter.next()); + } + { + // Test skipping after partial iteration. + let mut iter = assert_entry(iter.next(), "3"); + { + let mut iter = assert_entry(iter.next(), "3a"); + assert_entry(iter.next(), "3a1"); + // Parent iter should be able to skip over "3a2". + } + assert_entry(iter.next(), "3b"); + assert_null(iter.next()); + } + assert_entry(iter.next(), "final"); + assert_null(iter.next()); + + // Test starting at an offset. + let mut tree = unit + .entries_tree(&abbrevs, Some(entry2)) + .expect("Should have entries tree"); + let mut iter = assert_entry(tree.root().map(Some), "2"); + assert_entry(iter.next(), "2a"); + assert_entry(iter.next(), "2b"); + assert_null(iter.next()); + } + + #[test] + fn test_entries_raw() { + fn assert_abbrev<'abbrev, Endian>( + entries: &mut EntriesRaw<'abbrev, '_, EndianSlice<'_, Endian>>, + tag: DwTag, + ) -> &'abbrev Abbreviation + where + Endian: Endianity, + { + let abbrev = entries + .read_abbreviation() + .expect("Should parse abbrev") + .expect("Should have abbrev"); + assert_eq!(abbrev.tag(), tag); + abbrev + } + + fn assert_null(entries: &mut EntriesRaw<'_, '_, EndianSlice<'_, Endian>>) + where + Endian: Endianity, + { + match entries.read_abbreviation() { + Ok(None) => {} + otherwise => { + panic!("Unexpected parse result = {:#?}", otherwise); + } + } + } + + fn assert_attr( + entries: &mut EntriesRaw<'_, '_, EndianSlice<'_, Endian>>, + spec: Option, + name: DwAt, + value: &str, + ) where + Endian: Endianity, + { + let spec = spec.expect("Should have attribute specification"); + let attr = entries + .read_attribute(spec) + .expect("Should parse attribute"); + assert_eq!(attr.name(), name); + assert_eq!( + attr.value(), + AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default())) + ); + } + + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr(DW_AT_linkage_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev(2, DW_TAG_variable, DW_CHILDREN_no) + .abbrev_attr(DW_AT_name, DW_FORM_string) + .abbrev_attr_null() + .abbrev_null(); + let abbrevs_buf = section.get_contents().unwrap(); + let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian); + + #[rustfmt::skip] + let section = Section::with_endian(Endian::Little) + .die(1, |s| s.attr_string("f1").attr_string("l1")) + .die(2, |s| s.attr_string("v1")) + .die(2, |s| s.attr_string("v2")) + .die(1, |s| s.attr_string("f2").attr_string("l2")) + .die_null() + .die_null(); + let entries_buf = section.get_contents().unwrap(); + + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&entries_buf, LittleEndian), + }; + let section = Section::with_endian(Endian::Little).unit(&mut unit); + let info_buf = section.get_contents().unwrap(); + let debug_info = DebugInfo::new(&info_buf, LittleEndian); + + let unit = debug_info + .units() + .next() + .expect("should have a unit result") + .expect("and it should be ok"); + + let abbrevs = unit + .abbreviations(&debug_abbrev) + .expect("Should parse abbreviations"); + + let mut entries = unit + .entries_raw(&abbrevs, None) + .expect("Should have entries"); + + assert_eq!(entries.next_depth(), 0); + let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram); + let mut attrs = abbrev.attributes().iter().copied(); + assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1"); + assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1"); + assert!(attrs.next().is_none()); + + assert_eq!(entries.next_depth(), 1); + let abbrev = assert_abbrev(&mut entries, DW_TAG_variable); + let mut attrs = abbrev.attributes().iter().copied(); + assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1"); + assert!(attrs.next().is_none()); + + assert_eq!(entries.next_depth(), 1); + let abbrev = assert_abbrev(&mut entries, DW_TAG_variable); + let mut attrs = abbrev.attributes().iter().copied(); + assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2"); + assert!(attrs.next().is_none()); + + assert_eq!(entries.next_depth(), 1); + let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram); + let mut attrs = abbrev.attributes().iter().copied(); + assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2"); + assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2"); + assert!(attrs.next().is_none()); + + assert_eq!(entries.next_depth(), 2); + assert_null(&mut entries); + + assert_eq!(entries.next_depth(), 1); + assert_null(&mut entries); + + assert_eq!(entries.next_depth(), 0); + assert!(entries.is_empty()); + } + + #[test] + fn test_debug_info_offset() { + let padding = &[0; 10]; + let entries = &[0; 20]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(entries, LittleEndian), + }; + Section::with_endian(Endian::Little) + .append_bytes(padding) + .unit(&mut unit); + let offset = padding.len(); + let header_length = unit.size_of_header(); + let length = unit.length_including_self(); + assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None); + assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None); + assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None); + assert_eq!( + DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit), + None + ); + assert_eq!( + DebugInfoOffset(offset + header_length).to_unit_offset(&unit), + Some(UnitOffset(header_length)) + ); + assert_eq!( + DebugInfoOffset(offset + length - 1).to_unit_offset(&unit), + Some(UnitOffset(length - 1)) + ); + assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None); + assert_eq!( + UnitOffset(header_length).to_debug_info_offset(&unit), + Some(DebugInfoOffset(offset + header_length)) + ); + assert_eq!( + UnitOffset(length - 1).to_debug_info_offset(&unit), + Some(DebugInfoOffset(offset + length - 1)) + ); + } + + #[test] + fn test_debug_types_offset() { + let padding = &[0; 10]; + let entries = &[0; 20]; + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Type { + type_signature: DebugTypeSignature(0), + type_offset: UnitOffset(0), + }, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugTypesOffset(0).into(), + entries_buf: EndianSlice::new(entries, LittleEndian), + }; + Section::with_endian(Endian::Little) + .append_bytes(padding) + .unit(&mut unit); + let offset = padding.len(); + let header_length = unit.size_of_header(); + let length = unit.length_including_self(); + assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None); + assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None); + assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None); + assert_eq!( + DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit), + None + ); + assert_eq!( + DebugTypesOffset(offset + header_length).to_unit_offset(&unit), + Some(UnitOffset(header_length)) + ); + assert_eq!( + DebugTypesOffset(offset + length - 1).to_unit_offset(&unit), + Some(UnitOffset(length - 1)) + ); + assert_eq!( + DebugTypesOffset(offset + length).to_unit_offset(&unit), + None + ); + assert_eq!( + UnitOffset(header_length).to_debug_types_offset(&unit), + Some(DebugTypesOffset(offset + header_length)) + ); + assert_eq!( + UnitOffset(length - 1).to_debug_types_offset(&unit), + Some(DebugTypesOffset(offset + length - 1)) + ); + } + + #[test] + fn test_length_including_self() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let mut unit = UnitHeader { + encoding, + unit_length: 0, + unit_type: UnitType::Compilation, + debug_abbrev_offset: DebugAbbrevOffset(0), + unit_offset: DebugInfoOffset(0).into(), + entries_buf: EndianSlice::new(&[], LittleEndian), + }; + unit.encoding.format = Format::Dwarf32; + assert_eq!(unit.length_including_self(), 4); + unit.encoding.format = Format::Dwarf64; + assert_eq!(unit.length_including_self(), 12); + unit.unit_length = 10; + assert_eq!(unit.length_including_self(), 22); + } + + #[test] + fn test_parse_type_unit_abbrevs() { + let types_buf = [ + // Type unit header + 0x25, 0x00, 0x00, 0x00, // 32-bit unit length = 37 + 0x04, 0x00, // Version 4 + 0x00, 0x00, 0x00, 0x00, // debug_abbrev_offset + 0x04, // Address size + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Type signature + 0x01, 0x02, 0x03, 0x04, // Type offset + // DIEs + // Abbreviation code + 0x01, // Attribute of form DW_FORM_string = "foo\0" + 0x66, 0x6f, 0x6f, 0x00, // Children + // Abbreviation code + 0x01, // Attribute of form DW_FORM_string = "foo\0" + 0x66, 0x6f, 0x6f, 0x00, // Children + // Abbreviation code + 0x01, // Attribute of form DW_FORM_string = "foo\0" + 0x66, 0x6f, 0x6f, 0x00, // Children + 0x00, // End of children + 0x00, // End of children + 0x00, // End of children + ]; + let debug_types = DebugTypes::new(&types_buf, LittleEndian); + + let abbrev_buf = [ + // Code + 0x01, // DW_TAG_subprogram + 0x2e, // DW_CHILDREN_yes + 0x01, // Begin attributes + 0x03, // Attribute name = DW_AT_name + 0x08, // Attribute form = DW_FORM_string + 0x00, 0x00, // End attributes + 0x00, // Null terminator + ]; + + let get_some_type_unit = || debug_types.units().next().unwrap().unwrap(); + + let unit = get_some_type_unit(); + + let read_debug_abbrev_section_somehow = || &abbrev_buf; + let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian); + let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap(); + } +} diff --git a/anneal/v2/vendor/gimli/src/read/util.rs b/anneal/v2/vendor/gimli/src/read/util.rs new file mode 100644 index 0000000000..39adab321f --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/util.rs @@ -0,0 +1,265 @@ +#[cfg(feature = "read")] +use alloc::boxed::Box; +#[cfg(feature = "read")] +use alloc::vec::Vec; +use core::fmt; +use core::mem::MaybeUninit; +use core::ops; +use core::ptr; +use core::slice; + +mod sealed { + /// # Safety + /// Implementer must not modify the content in storage. + pub unsafe trait Sealed { + type Storage; + + fn new_storage() -> Self::Storage; + + fn grow(_storage: &mut Self::Storage, _additional: usize) -> Result<(), CapacityFull> { + Err(CapacityFull) + } + } + + #[derive(Clone, Copy, Debug)] + pub struct CapacityFull; +} + +use sealed::*; + +/// Marker trait for types that can be used as backing storage when a growable array type is needed. +/// +/// This trait is sealed and cannot be implemented for types outside this crate. +pub trait ArrayLike: Sealed { + /// Type of the elements being stored. + type Item; + + #[doc(hidden)] + fn as_slice(storage: &Self::Storage) -> &[MaybeUninit]; + + #[doc(hidden)] + fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit]; +} + +// SAFETY: does not modify the content in storage. +unsafe impl Sealed for [T; N] { + type Storage = [MaybeUninit; N]; + + fn new_storage() -> Self::Storage { + // SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid. + unsafe { MaybeUninit::uninit().assume_init() } + } +} + +impl ArrayLike for [T; N] { + type Item = T; + + fn as_slice(storage: &Self::Storage) -> &[MaybeUninit] { + storage + } + + fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit] { + storage + } +} + +// SAFETY: does not modify the content in storage. +#[cfg(feature = "read")] +unsafe impl Sealed for Box<[T; N]> { + type Storage = Box<[MaybeUninit; N]>; + + fn new_storage() -> Self::Storage { + // SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid. + Box::new(unsafe { MaybeUninit::uninit().assume_init() }) + } +} + +#[cfg(feature = "read")] +impl ArrayLike for Box<[T; N]> { + type Item = T; + + fn as_slice(storage: &Self::Storage) -> &[MaybeUninit] { + &storage[..] + } + + fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit] { + &mut storage[..] + } +} + +#[cfg(feature = "read")] +unsafe impl Sealed for Vec { + type Storage = Box<[MaybeUninit]>; + + fn new_storage() -> Self::Storage { + Box::new([]) + } + + fn grow(storage: &mut Self::Storage, additional: usize) -> Result<(), CapacityFull> { + let mut vec: Vec<_> = core::mem::replace(storage, Box::new([])).into(); + vec.reserve(additional); + // SAFETY: This is a `Vec` of `MaybeUninit`. + unsafe { vec.set_len(vec.capacity()) }; + *storage = vec.into_boxed_slice(); + Ok(()) + } +} + +#[cfg(feature = "read")] +impl ArrayLike for Vec { + type Item = T; + + fn as_slice(storage: &Self::Storage) -> &[MaybeUninit] { + storage + } + + fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit] { + storage + } +} + +pub(crate) struct ArrayVec { + storage: A::Storage, + len: usize, +} + +impl ArrayVec { + pub fn new() -> Self { + Self { + storage: A::new_storage(), + len: 0, + } + } + + pub fn clear(&mut self) { + let ptr: *mut [A::Item] = &mut **self; + // Set length first so the type invariant is upheld even if `drop_in_place` panicks. + self.len = 0; + // SAFETY: `ptr` contains valid elements only and we "forget" them by setting the length. + unsafe { ptr::drop_in_place(ptr) }; + } + + pub fn try_push(&mut self, value: A::Item) -> Result<(), CapacityFull> { + let mut storage = A::as_mut_slice(&mut self.storage); + if self.len >= storage.len() { + A::grow(&mut self.storage, 1)?; + storage = A::as_mut_slice(&mut self.storage); + } + + storage[self.len] = MaybeUninit::new(value); + self.len += 1; + Ok(()) + } + + pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityFull> { + assert!(index <= self.len); + + let mut storage = A::as_mut_slice(&mut self.storage); + if self.len >= storage.len() { + A::grow(&mut self.storage, 1)?; + storage = A::as_mut_slice(&mut self.storage); + } + + // SAFETY: storage[index] is filled later. + unsafe { + let p = storage.as_mut_ptr().add(index); + core::ptr::copy(p as *const _, p.add(1), self.len - index); + } + storage[index] = MaybeUninit::new(element); + self.len += 1; + Ok(()) + } + + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + // SAFETY: this element is valid and we "forget" it by setting the length. + Some(unsafe { A::as_slice(&self.storage)[self.len].as_ptr().read() }) + } + } + + pub fn swap_remove(&mut self, index: usize) -> A::Item { + assert!(self.len > 0); + A::as_mut_slice(&mut self.storage).swap(index, self.len - 1); + self.pop().unwrap() + } +} + +#[cfg(feature = "read")] +impl ArrayVec> { + pub fn into_vec(mut self) -> Vec { + let len = core::mem::replace(&mut self.len, 0); + let storage = core::mem::replace(&mut self.storage, Box::new([])); + let slice = Box::leak(storage); + debug_assert!(len <= slice.len()); + // SAFETY: valid elements. + unsafe { Vec::from_raw_parts(slice.as_mut_ptr() as *mut T, len, slice.len()) } + } +} + +impl Drop for ArrayVec { + fn drop(&mut self) { + self.clear(); + } +} + +impl Default for ArrayVec { + fn default() -> Self { + Self::new() + } +} + +impl ops::Deref for ArrayVec { + type Target = [A::Item]; + + fn deref(&self) -> &[A::Item] { + let slice = &A::as_slice(&self.storage); + debug_assert!(self.len <= slice.len()); + // SAFETY: valid elements. + unsafe { slice::from_raw_parts(slice.as_ptr() as _, self.len) } + } +} + +impl ops::DerefMut for ArrayVec { + fn deref_mut(&mut self) -> &mut [A::Item] { + let slice = &mut A::as_mut_slice(&mut self.storage); + debug_assert!(self.len <= slice.len()); + // SAFETY: valid elements. + unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr() as _, self.len) } + } +} + +impl Clone for ArrayVec +where + A::Item: Clone, +{ + fn clone(&self) -> Self { + let mut new = Self::default(); + for value in &**self { + new.try_push(value.clone()).unwrap(); + } + new + } +} + +impl PartialEq for ArrayVec +where + A::Item: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl Eq for ArrayVec where A::Item: Eq {} + +impl fmt::Debug for ArrayVec +where + A::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} diff --git a/anneal/v2/vendor/gimli/src/read/value.rs b/anneal/v2/vendor/gimli/src/read/value.rs new file mode 100644 index 0000000000..114736dbbe --- /dev/null +++ b/anneal/v2/vendor/gimli/src/read/value.rs @@ -0,0 +1,1621 @@ +//! Definitions for values used in DWARF expressions. + +use crate::constants; +#[cfg(feature = "read")] +use crate::read::{AttributeValue, DebuggingInformationEntry}; +use crate::read::{Error, Reader, Result}; + +/// Convert a u64 to an i64, with sign extension if required. +/// +/// This is primarily used when needing to treat `Value::Generic` +/// as a signed value. +#[inline] +fn sign_extend(value: u64, mask: u64) -> i64 { + let value = (value & mask) as i64; + let sign = ((mask >> 1) + 1) as i64; + (value ^ sign).wrapping_sub(sign) +} + +#[inline] +fn mask_bit_size(addr_mask: u64) -> u32 { + 64 - addr_mask.leading_zeros() +} + +/// The type of an entry on the DWARF stack. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ValueType { + /// The generic type, which is address-sized and of unspecified sign, + /// as specified in the DWARF 5 standard, section 2.5.1. + /// This type is also used to represent address base types. + Generic, + /// Signed 8-bit integer type. + I8, + /// Unsigned 8-bit integer type. + U8, + /// Signed 16-bit integer type. + I16, + /// Unsigned 16-bit integer type. + U16, + /// Signed 32-bit integer type. + I32, + /// Unsigned 32-bit integer type. + U32, + /// Signed 64-bit integer type. + I64, + /// Unsigned 64-bit integer type. + U64, + /// 32-bit floating point type. + F32, + /// 64-bit floating point type. + F64, +} + +/// The value of an entry on the DWARF stack. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Value { + /// A generic value, which is address-sized and of unspecified sign. + Generic(u64), + /// A signed 8-bit integer value. + I8(i8), + /// An unsigned 8-bit integer value. + U8(u8), + /// A signed 16-bit integer value. + I16(i16), + /// An unsigned 16-bit integer value. + U16(u16), + /// A signed 32-bit integer value. + I32(i32), + /// An unsigned 32-bit integer value. + U32(u32), + /// A signed 64-bit integer value. + I64(i64), + /// An unsigned 64-bit integer value. + U64(u64), + /// A 32-bit floating point value. + F32(f32), + /// A 64-bit floating point value. + F64(f64), +} + +impl ValueType { + /// The size in bits of a value for this type. + pub fn bit_size(self, addr_mask: u64) -> u32 { + match self { + ValueType::Generic => mask_bit_size(addr_mask), + ValueType::I8 | ValueType::U8 => 8, + ValueType::I16 | ValueType::U16 => 16, + ValueType::I32 | ValueType::U32 | ValueType::F32 => 32, + ValueType::I64 | ValueType::U64 | ValueType::F64 => 64, + } + } + + /// Construct a `ValueType` from the attributes of a base type DIE. + pub fn from_encoding(encoding: constants::DwAte, byte_size: u64) -> Option { + Some(match (encoding, byte_size) { + (constants::DW_ATE_signed, 1) => ValueType::I8, + (constants::DW_ATE_signed, 2) => ValueType::I16, + (constants::DW_ATE_signed, 4) => ValueType::I32, + (constants::DW_ATE_signed, 8) => ValueType::I64, + (constants::DW_ATE_unsigned, 1) => ValueType::U8, + (constants::DW_ATE_unsigned, 2) => ValueType::U16, + (constants::DW_ATE_unsigned, 4) => ValueType::U32, + (constants::DW_ATE_unsigned, 8) => ValueType::U64, + (constants::DW_ATE_float, 4) => ValueType::F32, + (constants::DW_ATE_float, 8) => ValueType::F64, + _ => return None, + }) + } + + /// Construct a `ValueType` from a base type DIE. + #[cfg(feature = "read")] + pub fn from_entry( + entry: &DebuggingInformationEntry<'_, '_, R>, + ) -> Result> { + if entry.tag() != constants::DW_TAG_base_type { + return Ok(None); + } + let mut encoding = None; + let mut byte_size = None; + let mut endianity = constants::DW_END_default; + let mut attrs = entry.attrs(); + while let Some(attr) = attrs.next()? { + match attr.name() { + constants::DW_AT_byte_size => byte_size = attr.udata_value(), + constants::DW_AT_encoding => { + if let AttributeValue::Encoding(x) = attr.value() { + encoding = Some(x); + } + } + constants::DW_AT_endianity => { + if let AttributeValue::Endianity(x) = attr.value() { + endianity = x; + } + } + _ => {} + } + } + + if endianity != constants::DW_END_default { + // TODO: we could check if it matches the reader endianity, + // but normally it would use DW_END_default in that case. + return Ok(None); + } + + if let (Some(encoding), Some(byte_size)) = (encoding, byte_size) { + Ok(ValueType::from_encoding(encoding, byte_size)) + } else { + Ok(None) + } + } +} + +impl Value { + /// Return the `ValueType` corresponding to this `Value`. + pub fn value_type(&self) -> ValueType { + match *self { + Value::Generic(_) => ValueType::Generic, + Value::I8(_) => ValueType::I8, + Value::U8(_) => ValueType::U8, + Value::I16(_) => ValueType::I16, + Value::U16(_) => ValueType::U16, + Value::I32(_) => ValueType::I32, + Value::U32(_) => ValueType::U32, + Value::I64(_) => ValueType::I64, + Value::U64(_) => ValueType::U64, + Value::F32(_) => ValueType::F32, + Value::F64(_) => ValueType::F64, + } + } + + /// Read a `Value` with the given `value_type` from a `Reader`. + pub fn parse(value_type: ValueType, mut bytes: R) -> Result { + let value = match value_type { + ValueType::I8 => Value::I8(bytes.read_i8()?), + ValueType::U8 => Value::U8(bytes.read_u8()?), + ValueType::I16 => Value::I16(bytes.read_i16()?), + ValueType::U16 => Value::U16(bytes.read_u16()?), + ValueType::I32 => Value::I32(bytes.read_i32()?), + ValueType::U32 => Value::U32(bytes.read_u32()?), + ValueType::I64 => Value::I64(bytes.read_i64()?), + ValueType::U64 => Value::U64(bytes.read_u64()?), + ValueType::F32 => Value::F32(bytes.read_f32()?), + ValueType::F64 => Value::F64(bytes.read_f64()?), + _ => return Err(Error::UnsupportedTypeOperation), + }; + Ok(value) + } + + /// Convert a `Value` to a `u64`. + /// + /// The `ValueType` of `self` must be integral. + /// Values are sign extended if the source value is signed. + pub fn to_u64(self, addr_mask: u64) -> Result { + let value = match self { + Value::Generic(value) => value & addr_mask, + Value::I8(value) => value as u64, + Value::U8(value) => u64::from(value), + Value::I16(value) => value as u64, + Value::U16(value) => u64::from(value), + Value::I32(value) => value as u64, + Value::U32(value) => u64::from(value), + Value::I64(value) => value as u64, + Value::U64(value) => value, + _ => return Err(Error::IntegralTypeRequired), + }; + Ok(value) + } + + /// Create a `Value` with the given `value_type` from a `u64` value. + /// + /// The `value_type` may be integral or floating point. + /// The result is truncated if the `u64` value does + /// not fit the bounds of the `value_type`. + pub fn from_u64(value_type: ValueType, value: u64) -> Result { + let value = match value_type { + ValueType::Generic => Value::Generic(value), + ValueType::I8 => Value::I8(value as i8), + ValueType::U8 => Value::U8(value as u8), + ValueType::I16 => Value::I16(value as i16), + ValueType::U16 => Value::U16(value as u16), + ValueType::I32 => Value::I32(value as i32), + ValueType::U32 => Value::U32(value as u32), + ValueType::I64 => Value::I64(value as i64), + ValueType::U64 => Value::U64(value), + ValueType::F32 => Value::F32(value as f32), + ValueType::F64 => Value::F64(value as f64), + }; + Ok(value) + } + + /// Create a `Value` with the given `value_type` from a `f32` value. + /// + /// The `value_type` may be integral or floating point. + /// The result is not defined if the `f32` value does + /// not fit the bounds of the `value_type`. + fn from_f32(value_type: ValueType, value: f32) -> Result { + let value = match value_type { + ValueType::Generic => Value::Generic(value as u64), + ValueType::I8 => Value::I8(value as i8), + ValueType::U8 => Value::U8(value as u8), + ValueType::I16 => Value::I16(value as i16), + ValueType::U16 => Value::U16(value as u16), + ValueType::I32 => Value::I32(value as i32), + ValueType::U32 => Value::U32(value as u32), + ValueType::I64 => Value::I64(value as i64), + ValueType::U64 => Value::U64(value as u64), + ValueType::F32 => Value::F32(value), + ValueType::F64 => Value::F64(f64::from(value)), + }; + Ok(value) + } + + /// Create a `Value` with the given `value_type` from a `f64` value. + /// + /// The `value_type` may be integral or floating point. + /// The result is not defined if the `f64` value does + /// not fit the bounds of the `value_type`. + fn from_f64(value_type: ValueType, value: f64) -> Result { + let value = match value_type { + ValueType::Generic => Value::Generic(value as u64), + ValueType::I8 => Value::I8(value as i8), + ValueType::U8 => Value::U8(value as u8), + ValueType::I16 => Value::I16(value as i16), + ValueType::U16 => Value::U16(value as u16), + ValueType::I32 => Value::I32(value as i32), + ValueType::U32 => Value::U32(value as u32), + ValueType::I64 => Value::I64(value as i64), + ValueType::U64 => Value::U64(value as u64), + ValueType::F32 => Value::F32(value as f32), + ValueType::F64 => Value::F64(value), + }; + Ok(value) + } + + /// Convert a `Value` to the given `value_type`. + /// + /// When converting between integral types, the result is truncated + /// if the source value does not fit the bounds of the `value_type`. + /// When converting from floating point types, the result is not defined + /// if the source value does not fit the bounds of the `value_type`. + /// + /// This corresponds to the DWARF `DW_OP_convert` operation. + pub fn convert(self, value_type: ValueType, addr_mask: u64) -> Result { + match self { + Value::F32(value) => Value::from_f32(value_type, value), + Value::F64(value) => Value::from_f64(value_type, value), + _ => Value::from_u64(value_type, self.to_u64(addr_mask)?), + } + } + + /// Reinterpret the bits in a `Value` as the given `value_type`. + /// + /// The source and result value types must have equal sizes. + /// + /// This corresponds to the DWARF `DW_OP_reinterpret` operation. + pub fn reinterpret(self, value_type: ValueType, addr_mask: u64) -> Result { + if self.value_type().bit_size(addr_mask) != value_type.bit_size(addr_mask) { + return Err(Error::TypeMismatch); + } + let bits = match self { + Value::Generic(value) => value, + Value::I8(value) => value as u64, + Value::U8(value) => u64::from(value), + Value::I16(value) => value as u64, + Value::U16(value) => u64::from(value), + Value::I32(value) => value as u64, + Value::U32(value) => u64::from(value), + Value::I64(value) => value as u64, + Value::U64(value) => value, + Value::F32(value) => u64::from(f32::to_bits(value)), + Value::F64(value) => f64::to_bits(value), + }; + let value = match value_type { + ValueType::Generic => Value::Generic(bits), + ValueType::I8 => Value::I8(bits as i8), + ValueType::U8 => Value::U8(bits as u8), + ValueType::I16 => Value::I16(bits as i16), + ValueType::U16 => Value::U16(bits as u16), + ValueType::I32 => Value::I32(bits as i32), + ValueType::U32 => Value::U32(bits as u32), + ValueType::I64 => Value::I64(bits as i64), + ValueType::U64 => Value::U64(bits), + ValueType::F32 => Value::F32(f32::from_bits(bits as u32)), + ValueType::F64 => Value::F64(f64::from_bits(bits)), + }; + Ok(value) + } + + /// Perform an absolute value operation. + /// + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_abs` operation. + pub fn abs(self, addr_mask: u64) -> Result { + // wrapping_abs() can be used because DWARF specifies that the result is undefined + // for negative minimal values. + let value = match self { + Value::Generic(value) => { + Value::Generic(sign_extend(value, addr_mask).wrapping_abs() as u64) + } + Value::I8(value) => Value::I8(value.wrapping_abs()), + Value::I16(value) => Value::I16(value.wrapping_abs()), + Value::I32(value) => Value::I32(value.wrapping_abs()), + Value::I64(value) => Value::I64(value.wrapping_abs()), + // f32/f64::abs() is not available in libcore + Value::F32(value) => Value::F32(if value < 0. { -value } else { value }), + Value::F64(value) => Value::F64(if value < 0. { -value } else { value }), + Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => self, + }; + Ok(value) + } + + /// Perform a negation operation. + /// + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_neg` operation. + pub fn neg(self, addr_mask: u64) -> Result { + // wrapping_neg() can be used because DWARF specifies that the result is undefined + // for negative minimal values. + let value = match self { + Value::Generic(value) => { + Value::Generic(sign_extend(value, addr_mask).wrapping_neg() as u64) + } + Value::I8(value) => Value::I8(value.wrapping_neg()), + Value::I16(value) => Value::I16(value.wrapping_neg()), + Value::I32(value) => Value::I32(value.wrapping_neg()), + Value::I64(value) => Value::I64(value.wrapping_neg()), + Value::F32(value) => Value::F32(-value), + Value::F64(value) => Value::F64(-value), + // It's unclear if these should implicitly convert to a signed value. + // For now, we don't support them. + Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => { + return Err(Error::UnsupportedTypeOperation); + } + }; + Ok(value) + } + + /// Perform an addition operation. + /// + /// This operation requires matching types. + /// + /// This corresponds to the DWARF `DW_OP_plus` operation. + pub fn add(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + Value::Generic(v1.wrapping_add(v2) & addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_add(v2)), + (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_add(v2)), + (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_add(v2)), + (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_add(v2)), + (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_add(v2)), + (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_add(v2)), + (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_add(v2)), + (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_add(v2)), + (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 + v2), + (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 + v2), + _ => return Err(Error::TypeMismatch), + }; + Ok(value) + } + + /// Perform a subtraction operation. + /// + /// This operation requires matching types. + /// + /// This corresponds to the DWARF `DW_OP_minus` operation. + pub fn sub(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + Value::Generic(v1.wrapping_sub(v2) & addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_sub(v2)), + (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_sub(v2)), + (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_sub(v2)), + (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_sub(v2)), + (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_sub(v2)), + (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_sub(v2)), + (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_sub(v2)), + (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_sub(v2)), + (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 - v2), + (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 - v2), + _ => return Err(Error::TypeMismatch), + }; + Ok(value) + } + + /// Perform a multiplication operation. + /// + /// This operation requires matching types. + /// + /// This corresponds to the DWARF `DW_OP_mul` operation. + pub fn mul(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + Value::Generic(v1.wrapping_mul(v2) & addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_mul(v2)), + (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_mul(v2)), + (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_mul(v2)), + (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_mul(v2)), + (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_mul(v2)), + (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_mul(v2)), + (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_mul(v2)), + (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_mul(v2)), + (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 * v2), + (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 * v2), + _ => return Err(Error::TypeMismatch), + }; + Ok(value) + } + + /// Perform a division operation. + /// + /// This operation requires matching types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_div` operation. + pub fn div(self, rhs: Value, addr_mask: u64) -> Result { + match rhs { + Value::Generic(v2) if sign_extend(v2, addr_mask) == 0 => { + return Err(Error::DivisionByZero); + } + Value::I8(0) + | Value::U8(0) + | Value::I16(0) + | Value::U16(0) + | Value::I32(0) + | Value::U32(0) + | Value::I64(0) + | Value::U64(0) => { + return Err(Error::DivisionByZero); + } + _ => {} + } + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + // Signed division + Value::Generic( + sign_extend(v1, addr_mask).wrapping_div(sign_extend(v2, addr_mask)) as u64, + ) + } + (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_div(v2)), + (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_div(v2)), + (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_div(v2)), + (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_div(v2)), + (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_div(v2)), + (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_div(v2)), + (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_div(v2)), + (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_div(v2)), + (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 / v2), + (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 / v2), + _ => return Err(Error::TypeMismatch), + }; + Ok(value) + } + + /// Perform a remainder operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as an unsigned value. + /// + /// This corresponds to the DWARF `DW_OP_mod` operation. + pub fn rem(self, rhs: Value, addr_mask: u64) -> Result { + match rhs { + Value::Generic(rhs) if (rhs & addr_mask) == 0 => { + return Err(Error::DivisionByZero); + } + Value::I8(0) + | Value::U8(0) + | Value::I16(0) + | Value::U16(0) + | Value::I32(0) + | Value::U32(0) + | Value::I64(0) + | Value::U64(0) => { + return Err(Error::DivisionByZero); + } + _ => {} + } + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + // Unsigned modulus + Value::Generic((v1 & addr_mask).wrapping_rem(v2 & addr_mask)) + } + (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_rem(v2)), + (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_rem(v2)), + (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_rem(v2)), + (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_rem(v2)), + (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_rem(v2)), + (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_rem(v2)), + (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_rem(v2)), + (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_rem(v2)), + (Value::F32(_), Value::F32(_)) => return Err(Error::IntegralTypeRequired), + (Value::F64(_), Value::F64(_)) => return Err(Error::IntegralTypeRequired), + _ => return Err(Error::TypeMismatch), + }; + Ok(value) + } + + /// Perform a bitwise not operation. + /// + /// This operation requires matching integral types. + /// + /// This corresponds to the DWARF `DW_OP_not` operation. + pub fn not(self, addr_mask: u64) -> Result { + let value_type = self.value_type(); + let v = self.to_u64(addr_mask)?; + Value::from_u64(value_type, !v) + } + + /// Perform a bitwise and operation. + /// + /// This operation requires matching integral types. + /// + /// This corresponds to the DWARF `DW_OP_and` operation. + pub fn and(self, rhs: Value, addr_mask: u64) -> Result { + let value_type = self.value_type(); + if value_type != rhs.value_type() { + return Err(Error::TypeMismatch); + } + let v1 = self.to_u64(addr_mask)?; + let v2 = rhs.to_u64(addr_mask)?; + Value::from_u64(value_type, v1 & v2) + } + + /// Perform a bitwise or operation. + /// + /// This operation requires matching integral types. + /// + /// This corresponds to the DWARF `DW_OP_or` operation. + pub fn or(self, rhs: Value, addr_mask: u64) -> Result { + let value_type = self.value_type(); + if value_type != rhs.value_type() { + return Err(Error::TypeMismatch); + } + let v1 = self.to_u64(addr_mask)?; + let v2 = rhs.to_u64(addr_mask)?; + Value::from_u64(value_type, v1 | v2) + } + + /// Perform a bitwise exclusive-or operation. + /// + /// This operation requires matching integral types. + /// + /// This corresponds to the DWARF `DW_OP_xor` operation. + pub fn xor(self, rhs: Value, addr_mask: u64) -> Result { + let value_type = self.value_type(); + if value_type != rhs.value_type() { + return Err(Error::TypeMismatch); + } + let v1 = self.to_u64(addr_mask)?; + let v2 = rhs.to_u64(addr_mask)?; + Value::from_u64(value_type, v1 ^ v2) + } + + /// Convert value to bit length suitable for a shift operation. + /// + /// If the value is negative then an error is returned. + fn shift_length(self) -> Result { + let value = match self { + Value::Generic(value) => value, + Value::I8(value) if value >= 0 => value as u64, + Value::U8(value) => u64::from(value), + Value::I16(value) if value >= 0 => value as u64, + Value::U16(value) => u64::from(value), + Value::I32(value) if value >= 0 => value as u64, + Value::U32(value) => u64::from(value), + Value::I64(value) if value >= 0 => value as u64, + Value::U64(value) => value, + _ => return Err(Error::InvalidShiftExpression), + }; + Ok(value) + } + + /// Perform a shift left operation. + /// + /// This operation requires integral types. + /// If the shift length exceeds the type size, then 0 is returned. + /// If the shift length is negative then an error is returned. + /// + /// This corresponds to the DWARF `DW_OP_shl` operation. + pub fn shl(self, rhs: Value, addr_mask: u64) -> Result { + let v2 = rhs.shift_length()?; + let value = match self { + Value::Generic(v1) => Value::Generic(if v2 >= u64::from(mask_bit_size(addr_mask)) { + 0 + } else { + (v1 & addr_mask) << v2 + }), + Value::I8(v1) => Value::I8(if v2 >= 8 { 0 } else { v1 << v2 }), + Value::U8(v1) => Value::U8(if v2 >= 8 { 0 } else { v1 << v2 }), + Value::I16(v1) => Value::I16(if v2 >= 16 { 0 } else { v1 << v2 }), + Value::U16(v1) => Value::U16(if v2 >= 16 { 0 } else { v1 << v2 }), + Value::I32(v1) => Value::I32(if v2 >= 32 { 0 } else { v1 << v2 }), + Value::U32(v1) => Value::U32(if v2 >= 32 { 0 } else { v1 << v2 }), + Value::I64(v1) => Value::I64(if v2 >= 64 { 0 } else { v1 << v2 }), + Value::U64(v1) => Value::U64(if v2 >= 64 { 0 } else { v1 << v2 }), + _ => return Err(Error::IntegralTypeRequired), + }; + Ok(value) + } + + /// Perform a logical shift right operation. + /// + /// This operation requires an unsigned integral type for the value. + /// If the value type is `Generic`, then it is interpreted as an unsigned value. + /// + /// This operation requires an integral type for the shift length. + /// If the shift length exceeds the type size, then 0 is returned. + /// If the shift length is negative then an error is returned. + /// + /// This corresponds to the DWARF `DW_OP_shr` operation. + pub fn shr(self, rhs: Value, addr_mask: u64) -> Result { + let v2 = rhs.shift_length()?; + let value = match self { + Value::Generic(v1) => Value::Generic(if v2 >= u64::from(mask_bit_size(addr_mask)) { + 0 + } else { + (v1 & addr_mask) >> v2 + }), + Value::U8(v1) => Value::U8(if v2 >= 8 { 0 } else { v1 >> v2 }), + Value::U16(v1) => Value::U16(if v2 >= 16 { 0 } else { v1 >> v2 }), + Value::U32(v1) => Value::U32(if v2 >= 32 { 0 } else { v1 >> v2 }), + Value::U64(v1) => Value::U64(if v2 >= 64 { 0 } else { v1 >> v2 }), + // It's unclear if signed values should implicitly convert to an unsigned value. + // For now, we don't support them. + Value::I8(_) | Value::I16(_) | Value::I32(_) | Value::I64(_) => { + return Err(Error::UnsupportedTypeOperation); + } + _ => return Err(Error::IntegralTypeRequired), + }; + Ok(value) + } + + /// Perform an arithmetic shift right operation. + /// + /// This operation requires a signed integral type for the value. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This operation requires an integral type for the shift length. + /// If the shift length exceeds the type size, then 0 is returned for positive values, + /// and -1 is returned for negative values. + /// If the shift length is negative then an error is returned. + /// + /// This corresponds to the DWARF `DW_OP_shra` operation. + pub fn shra(self, rhs: Value, addr_mask: u64) -> Result { + let v2 = rhs.shift_length()?; + let value = match self { + Value::Generic(v1) => { + let v1 = sign_extend(v1, addr_mask); + let value = if v2 >= u64::from(mask_bit_size(addr_mask)) { + if v1 < 0 { + !0 + } else { + 0 + } + } else { + (v1 >> v2) as u64 + }; + Value::Generic(value) + } + Value::I8(v1) => Value::I8(if v2 >= 8 { + if v1 < 0 { + !0 + } else { + 0 + } + } else { + v1 >> v2 + }), + Value::I16(v1) => Value::I16(if v2 >= 16 { + if v1 < 0 { + !0 + } else { + 0 + } + } else { + v1 >> v2 + }), + Value::I32(v1) => Value::I32(if v2 >= 32 { + if v1 < 0 { + !0 + } else { + 0 + } + } else { + v1 >> v2 + }), + Value::I64(v1) => Value::I64(if v2 >= 64 { + if v1 < 0 { + !0 + } else { + 0 + } + } else { + v1 >> v2 + }), + // It's unclear if unsigned values should implicitly convert to a signed value. + // For now, we don't support them. + Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => { + return Err(Error::UnsupportedTypeOperation); + } + _ => return Err(Error::IntegralTypeRequired), + }; + Ok(value) + } + + /// Perform the `==` relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_eq` operation. + pub fn eq(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) == sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 == v2, + (Value::U8(v1), Value::U8(v2)) => v1 == v2, + (Value::I16(v1), Value::I16(v2)) => v1 == v2, + (Value::U16(v1), Value::U16(v2)) => v1 == v2, + (Value::I32(v1), Value::I32(v2)) => v1 == v2, + (Value::U32(v1), Value::U32(v2)) => v1 == v2, + (Value::I64(v1), Value::I64(v2)) => v1 == v2, + (Value::U64(v1), Value::U64(v2)) => v1 == v2, + (Value::F32(v1), Value::F32(v2)) => v1 == v2, + (Value::F64(v1), Value::F64(v2)) => v1 == v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } + + /// Perform the `>=` relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_ge` operation. + pub fn ge(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) >= sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 >= v2, + (Value::U8(v1), Value::U8(v2)) => v1 >= v2, + (Value::I16(v1), Value::I16(v2)) => v1 >= v2, + (Value::U16(v1), Value::U16(v2)) => v1 >= v2, + (Value::I32(v1), Value::I32(v2)) => v1 >= v2, + (Value::U32(v1), Value::U32(v2)) => v1 >= v2, + (Value::I64(v1), Value::I64(v2)) => v1 >= v2, + (Value::U64(v1), Value::U64(v2)) => v1 >= v2, + (Value::F32(v1), Value::F32(v2)) => v1 >= v2, + (Value::F64(v1), Value::F64(v2)) => v1 >= v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } + + /// Perform the `>` relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_gt` operation. + pub fn gt(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) > sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 > v2, + (Value::U8(v1), Value::U8(v2)) => v1 > v2, + (Value::I16(v1), Value::I16(v2)) => v1 > v2, + (Value::U16(v1), Value::U16(v2)) => v1 > v2, + (Value::I32(v1), Value::I32(v2)) => v1 > v2, + (Value::U32(v1), Value::U32(v2)) => v1 > v2, + (Value::I64(v1), Value::I64(v2)) => v1 > v2, + (Value::U64(v1), Value::U64(v2)) => v1 > v2, + (Value::F32(v1), Value::F32(v2)) => v1 > v2, + (Value::F64(v1), Value::F64(v2)) => v1 > v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } + + /// Perform the `<= relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_le` operation. + pub fn le(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) <= sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 <= v2, + (Value::U8(v1), Value::U8(v2)) => v1 <= v2, + (Value::I16(v1), Value::I16(v2)) => v1 <= v2, + (Value::U16(v1), Value::U16(v2)) => v1 <= v2, + (Value::I32(v1), Value::I32(v2)) => v1 <= v2, + (Value::U32(v1), Value::U32(v2)) => v1 <= v2, + (Value::I64(v1), Value::I64(v2)) => v1 <= v2, + (Value::U64(v1), Value::U64(v2)) => v1 <= v2, + (Value::F32(v1), Value::F32(v2)) => v1 <= v2, + (Value::F64(v1), Value::F64(v2)) => v1 <= v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } + + /// Perform the `< relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_lt` operation. + pub fn lt(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) < sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 < v2, + (Value::U8(v1), Value::U8(v2)) => v1 < v2, + (Value::I16(v1), Value::I16(v2)) => v1 < v2, + (Value::U16(v1), Value::U16(v2)) => v1 < v2, + (Value::I32(v1), Value::I32(v2)) => v1 < v2, + (Value::U32(v1), Value::U32(v2)) => v1 < v2, + (Value::I64(v1), Value::I64(v2)) => v1 < v2, + (Value::U64(v1), Value::U64(v2)) => v1 < v2, + (Value::F32(v1), Value::F32(v2)) => v1 < v2, + (Value::F64(v1), Value::F64(v2)) => v1 < v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } + + /// Perform the `!= relational operation. + /// + /// This operation requires matching integral types. + /// If the value type is `Generic`, then it is interpreted as a signed value. + /// + /// This corresponds to the DWARF `DW_OP_ne` operation. + pub fn ne(self, rhs: Value, addr_mask: u64) -> Result { + let value = match (self, rhs) { + (Value::Generic(v1), Value::Generic(v2)) => { + sign_extend(v1, addr_mask) != sign_extend(v2, addr_mask) + } + (Value::I8(v1), Value::I8(v2)) => v1 != v2, + (Value::U8(v1), Value::U8(v2)) => v1 != v2, + (Value::I16(v1), Value::I16(v2)) => v1 != v2, + (Value::U16(v1), Value::U16(v2)) => v1 != v2, + (Value::I32(v1), Value::I32(v2)) => v1 != v2, + (Value::U32(v1), Value::U32(v2)) => v1 != v2, + (Value::I64(v1), Value::I64(v2)) => v1 != v2, + (Value::U64(v1), Value::U64(v2)) => v1 != v2, + (Value::F32(v1), Value::F32(v2)) => v1 != v2, + (Value::F64(v1), Value::F64(v2)) => v1 != v2, + _ => return Err(Error::TypeMismatch), + }; + Ok(Value::Generic(value as u64)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::common::{DebugAbbrevOffset, DebugInfoOffset, Encoding, Format}; + use crate::endianity::LittleEndian; + use crate::read::{ + Abbreviation, AttributeSpecification, DebuggingInformationEntry, EndianSlice, UnitHeader, + UnitOffset, UnitType, + }; + + #[test] + #[rustfmt::skip] + fn valuetype_from_encoding() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 4, + }; + let unit = UnitHeader::new( + encoding, + 7, + UnitType::Compilation, + DebugAbbrevOffset(0), + DebugInfoOffset(0).into(), + EndianSlice::new(&[], LittleEndian), + ); + + let abbrev = Abbreviation::new( + 42, + constants::DW_TAG_base_type, + constants::DW_CHILDREN_no, + vec![ + AttributeSpecification::new( + constants::DW_AT_byte_size, + constants::DW_FORM_udata, + None, + ), + AttributeSpecification::new( + constants::DW_AT_encoding, + constants::DW_FORM_udata, + None, + ), + AttributeSpecification::new( + constants::DW_AT_endianity, + constants::DW_FORM_udata, + None, + ), + ].into(), + ); + + for &(attrs, result) in &[ + ([0x01, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I8), + ([0x02, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I16), + ([0x04, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I32), + ([0x08, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I64), + ([0x01, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U8), + ([0x02, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U16), + ([0x04, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U32), + ([0x08, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U64), + ([0x04, constants::DW_ATE_float.0, constants::DW_END_default.0], ValueType::F32), + ([0x08, constants::DW_ATE_float.0, constants::DW_END_default.0], ValueType::F64), + ] { + let entry = DebuggingInformationEntry::new( + UnitOffset(0), + EndianSlice::new(&attrs, LittleEndian), + &abbrev, + &unit, + ); + assert_eq!(ValueType::from_entry(&entry), Ok(Some(result))); + } + + for attrs in &[ + [0x03, constants::DW_ATE_signed.0, constants::DW_END_default.0], + [0x02, constants::DW_ATE_signed.0, constants::DW_END_big.0], + ] { + let entry = DebuggingInformationEntry::new( + UnitOffset(0), + EndianSlice::new(attrs, LittleEndian), + &abbrev, + &unit, + ); + assert_eq!(ValueType::from_entry(&entry), Ok(None)); + } + } + + #[test] + fn value_convert() { + let addr_mask = !0 >> 32; + for &(v, t, result) in &[ + (Value::Generic(1), ValueType::I8, Ok(Value::I8(1))), + (Value::I8(1), ValueType::U8, Ok(Value::U8(1))), + (Value::U8(1), ValueType::I16, Ok(Value::I16(1))), + (Value::I16(1), ValueType::U16, Ok(Value::U16(1))), + (Value::U16(1), ValueType::I32, Ok(Value::I32(1))), + (Value::I32(1), ValueType::U32, Ok(Value::U32(1))), + (Value::U32(1), ValueType::F32, Ok(Value::F32(1.))), + (Value::F32(1.), ValueType::I64, Ok(Value::I64(1))), + (Value::I64(1), ValueType::U64, Ok(Value::U64(1))), + (Value::U64(1), ValueType::F64, Ok(Value::F64(1.))), + (Value::F64(1.), ValueType::Generic, Ok(Value::Generic(1))), + ] { + assert_eq!(v.convert(t, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_reinterpret() { + let addr_mask = !0 >> 32; + for &(v, t, result) in &[ + // 8-bit + (Value::I8(-1), ValueType::U8, Ok(Value::U8(0xff))), + (Value::U8(0xff), ValueType::I8, Ok(Value::I8(-1))), + // 16-bit + (Value::I16(1), ValueType::U16, Ok(Value::U16(1))), + (Value::U16(1), ValueType::I16, Ok(Value::I16(1))), + // 32-bit + (Value::Generic(1), ValueType::I32, Ok(Value::I32(1))), + (Value::I32(1), ValueType::U32, Ok(Value::U32(1))), + (Value::U32(0x3f80_0000), ValueType::F32, Ok(Value::F32(1.0))), + (Value::F32(1.0), ValueType::Generic, Ok(Value::Generic(0x3f80_0000))), + // Type mismatches + (Value::Generic(1), ValueType::U8, Err(Error::TypeMismatch)), + (Value::U8(1), ValueType::U16, Err(Error::TypeMismatch)), + (Value::U16(1), ValueType::U32, Err(Error::TypeMismatch)), + (Value::U32(1), ValueType::U64, Err(Error::TypeMismatch)), + (Value::U64(1), ValueType::Generic, Err(Error::TypeMismatch)), + ] { + assert_eq!(v.reinterpret(t, addr_mask), result); + } + + let addr_mask = !0; + for &(v, t, result) in &[ + // 64-bit + (Value::Generic(1), ValueType::I64, Ok(Value::I64(1))), + (Value::I64(1), ValueType::U64, Ok(Value::U64(1))), + (Value::U64(0x3ff0_0000_0000_0000), ValueType::F64, Ok(Value::F64(1.0))), + (Value::F64(1.0), ValueType::Generic, Ok(Value::Generic(0x3ff0_0000_0000_0000))), + ] { + assert_eq!(v.reinterpret(t, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_abs() { + let addr_mask = 0xffff_ffff; + for &(v, result) in &[ + (Value::Generic(0xffff_ffff), Ok(Value::Generic(1))), + (Value::I8(-1), Ok(Value::I8(1))), + (Value::U8(1), Ok(Value::U8(1))), + (Value::I16(-1), Ok(Value::I16(1))), + (Value::U16(1), Ok(Value::U16(1))), + (Value::I32(-1), Ok(Value::I32(1))), + (Value::U32(1), Ok(Value::U32(1))), + (Value::I64(-1), Ok(Value::I64(1))), + (Value::U64(1), Ok(Value::U64(1))), + (Value::F32(-1.), Ok(Value::F32(1.))), + (Value::F64(-1.), Ok(Value::F64(1.))), + ] { + assert_eq!(v.abs(addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_neg() { + let addr_mask = 0xffff_ffff; + for &(v, result) in &[ + (Value::Generic(0xffff_ffff), Ok(Value::Generic(1))), + (Value::I8(1), Ok(Value::I8(-1))), + (Value::U8(1), Err(Error::UnsupportedTypeOperation)), + (Value::I16(1), Ok(Value::I16(-1))), + (Value::U16(1), Err(Error::UnsupportedTypeOperation)), + (Value::I32(1), Ok(Value::I32(-1))), + (Value::U32(1), Err(Error::UnsupportedTypeOperation)), + (Value::I64(1), Ok(Value::I64(-1))), + (Value::U64(1), Err(Error::UnsupportedTypeOperation)), + (Value::F32(1.), Ok(Value::F32(-1.))), + (Value::F64(1.), Ok(Value::F64(-1.))), + ] { + assert_eq!(v.neg(addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_add() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(1), Value::Generic(2), Ok(Value::Generic(3))), + (Value::I8(-1), Value::I8(2), Ok(Value::I8(1))), + (Value::U8(1), Value::U8(2), Ok(Value::U8(3))), + (Value::I16(-1), Value::I16(2), Ok(Value::I16(1))), + (Value::U16(1), Value::U16(2), Ok(Value::U16(3))), + (Value::I32(-1), Value::I32(2), Ok(Value::I32(1))), + (Value::U32(1), Value::U32(2), Ok(Value::U32(3))), + (Value::I64(-1), Value::I64(2), Ok(Value::I64(1))), + (Value::U64(1), Value::U64(2), Ok(Value::U64(3))), + (Value::F32(-1.), Value::F32(2.), Ok(Value::F32(1.))), + (Value::F64(-1.), Value::F64(2.), Ok(Value::F64(1.))), + (Value::Generic(1), Value::U32(2), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.add(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_sub() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(2), Ok(Value::Generic(1))), + (Value::I8(-1), Value::I8(2), Ok(Value::I8(-3))), + (Value::U8(3), Value::U8(2), Ok(Value::U8(1))), + (Value::I16(-1), Value::I16(2), Ok(Value::I16(-3))), + (Value::U16(3), Value::U16(2), Ok(Value::U16(1))), + (Value::I32(-1), Value::I32(2), Ok(Value::I32(-3))), + (Value::U32(3), Value::U32(2), Ok(Value::U32(1))), + (Value::I64(-1), Value::I64(2), Ok(Value::I64(-3))), + (Value::U64(3), Value::U64(2), Ok(Value::U64(1))), + (Value::F32(-1.), Value::F32(2.), Ok(Value::F32(-3.))), + (Value::F64(-1.), Value::F64(2.), Ok(Value::F64(-3.))), + (Value::Generic(3), Value::U32(2), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.sub(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_mul() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(2), Value::Generic(3), Ok(Value::Generic(6))), + (Value::I8(-2), Value::I8(3), Ok(Value::I8(-6))), + (Value::U8(2), Value::U8(3), Ok(Value::U8(6))), + (Value::I16(-2), Value::I16(3), Ok(Value::I16(-6))), + (Value::U16(2), Value::U16(3), Ok(Value::U16(6))), + (Value::I32(-2), Value::I32(3), Ok(Value::I32(-6))), + (Value::U32(2), Value::U32(3), Ok(Value::U32(6))), + (Value::I64(-2), Value::I64(3), Ok(Value::I64(-6))), + (Value::U64(2), Value::U64(3), Ok(Value::U64(6))), + (Value::F32(-2.), Value::F32(3.), Ok(Value::F32(-6.))), + (Value::F64(-2.), Value::F64(3.), Ok(Value::F64(-6.))), + (Value::Generic(2), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.mul(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_div() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(6), Value::Generic(3), Ok(Value::Generic(2))), + (Value::I8(-6), Value::I8(3), Ok(Value::I8(-2))), + (Value::U8(6), Value::U8(3), Ok(Value::U8(2))), + (Value::I16(-6), Value::I16(3), Ok(Value::I16(-2))), + (Value::U16(6), Value::U16(3), Ok(Value::U16(2))), + (Value::I32(-6), Value::I32(3), Ok(Value::I32(-2))), + (Value::U32(6), Value::U32(3), Ok(Value::U32(2))), + (Value::I64(-6), Value::I64(3), Ok(Value::I64(-2))), + (Value::U64(6), Value::U64(3), Ok(Value::U64(2))), + (Value::F32(-6.), Value::F32(3.), Ok(Value::F32(-2.))), + (Value::F64(-6.), Value::F64(3.), Ok(Value::F64(-2.))), + (Value::Generic(6), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.div(v2, addr_mask), result); + } + for &(v1, v2, result) in &[ + (Value::Generic(6), Value::Generic(0), Err(Error::DivisionByZero)), + (Value::I8(-6), Value::I8(0), Err(Error::DivisionByZero)), + (Value::U8(6), Value::U8(0), Err(Error::DivisionByZero)), + (Value::I16(-6), Value::I16(0), Err(Error::DivisionByZero)), + (Value::U16(6), Value::U16(0), Err(Error::DivisionByZero)), + (Value::I32(-6), Value::I32(0), Err(Error::DivisionByZero)), + (Value::U32(6), Value::U32(0), Err(Error::DivisionByZero)), + (Value::I64(-6), Value::I64(0), Err(Error::DivisionByZero)), + (Value::U64(6), Value::U64(0), Err(Error::DivisionByZero)), + (Value::F32(-6.), Value::F32(0.), Ok(Value::F32(-6. / 0.))), + (Value::F64(-6.), Value::F64(0.), Ok(Value::F64(-6. / 0.))), + ] { + assert_eq!(v1.div(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_rem() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(2), Ok(Value::Generic(1))), + (Value::I8(-3), Value::I8(2), Ok(Value::I8(-1))), + (Value::U8(3), Value::U8(2), Ok(Value::U8(1))), + (Value::I16(-3), Value::I16(2), Ok(Value::I16(-1))), + (Value::U16(3), Value::U16(2), Ok(Value::U16(1))), + (Value::I32(-3), Value::I32(2), Ok(Value::I32(-1))), + (Value::U32(3), Value::U32(2), Ok(Value::U32(1))), + (Value::I64(-3), Value::I64(2), Ok(Value::I64(-1))), + (Value::U64(3), Value::U64(2), Ok(Value::U64(1))), + (Value::F32(-3.), Value::F32(2.), Err(Error::IntegralTypeRequired)), + (Value::F64(-3.), Value::F64(2.), Err(Error::IntegralTypeRequired)), + (Value::Generic(3), Value::U32(2), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.rem(v2, addr_mask), result); + } + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(0), Err(Error::DivisionByZero)), + (Value::I8(-3), Value::I8(0), Err(Error::DivisionByZero)), + (Value::U8(3), Value::U8(0), Err(Error::DivisionByZero)), + (Value::I16(-3), Value::I16(0), Err(Error::DivisionByZero)), + (Value::U16(3), Value::U16(0), Err(Error::DivisionByZero)), + (Value::I32(-3), Value::I32(0), Err(Error::DivisionByZero)), + (Value::U32(3), Value::U32(0), Err(Error::DivisionByZero)), + (Value::I64(-3), Value::I64(0), Err(Error::DivisionByZero)), + (Value::U64(3), Value::U64(0), Err(Error::DivisionByZero)), + ] { + assert_eq!(v1.rem(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_not() { + let addr_mask = 0xffff_ffff; + for &(v, result) in &[ + (Value::Generic(1), Ok(Value::Generic(!1))), + (Value::I8(1), Ok(Value::I8(!1))), + (Value::U8(1), Ok(Value::U8(!1))), + (Value::I16(1), Ok(Value::I16(!1))), + (Value::U16(1), Ok(Value::U16(!1))), + (Value::I32(1), Ok(Value::I32(!1))), + (Value::U32(1), Ok(Value::U32(!1))), + (Value::I64(1), Ok(Value::I64(!1))), + (Value::U64(1), Ok(Value::U64(!1))), + (Value::F32(1.), Err(Error::IntegralTypeRequired)), + (Value::F64(1.), Err(Error::IntegralTypeRequired)), + ] { + assert_eq!(v.not(addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_and() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(1))), + (Value::I8(3), Value::I8(5), Ok(Value::I8(1))), + (Value::U8(3), Value::U8(5), Ok(Value::U8(1))), + (Value::I16(3), Value::I16(5), Ok(Value::I16(1))), + (Value::U16(3), Value::U16(5), Ok(Value::U16(1))), + (Value::I32(3), Value::I32(5), Ok(Value::I32(1))), + (Value::U32(3), Value::U32(5), Ok(Value::U32(1))), + (Value::I64(3), Value::I64(5), Ok(Value::I64(1))), + (Value::U64(3), Value::U64(5), Ok(Value::U64(1))), + (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)), + (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)), + (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.and(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_or() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(7))), + (Value::I8(3), Value::I8(5), Ok(Value::I8(7))), + (Value::U8(3), Value::U8(5), Ok(Value::U8(7))), + (Value::I16(3), Value::I16(5), Ok(Value::I16(7))), + (Value::U16(3), Value::U16(5), Ok(Value::U16(7))), + (Value::I32(3), Value::I32(5), Ok(Value::I32(7))), + (Value::U32(3), Value::U32(5), Ok(Value::U32(7))), + (Value::I64(3), Value::I64(5), Ok(Value::I64(7))), + (Value::U64(3), Value::U64(5), Ok(Value::U64(7))), + (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)), + (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)), + (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.or(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_xor() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(6))), + (Value::I8(3), Value::I8(5), Ok(Value::I8(6))), + (Value::U8(3), Value::U8(5), Ok(Value::U8(6))), + (Value::I16(3), Value::I16(5), Ok(Value::I16(6))), + (Value::U16(3), Value::U16(5), Ok(Value::U16(6))), + (Value::I32(3), Value::I32(5), Ok(Value::I32(6))), + (Value::U32(3), Value::U32(5), Ok(Value::U32(6))), + (Value::I64(3), Value::I64(5), Ok(Value::I64(6))), + (Value::U64(3), Value::U64(5), Ok(Value::U64(6))), + (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)), + (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)), + (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.xor(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_shl() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + // One of each type + (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(96))), + (Value::I8(3), Value::U8(5), Ok(Value::I8(96))), + (Value::U8(3), Value::I8(5), Ok(Value::U8(96))), + (Value::I16(3), Value::U16(5), Ok(Value::I16(96))), + (Value::U16(3), Value::I16(5), Ok(Value::U16(96))), + (Value::I32(3), Value::U32(5), Ok(Value::I32(96))), + (Value::U32(3), Value::I32(5), Ok(Value::U32(96))), + (Value::I64(3), Value::U64(5), Ok(Value::I64(96))), + (Value::U64(3), Value::I64(5), Ok(Value::U64(96))), + (Value::F32(3.), Value::U8(5), Err(Error::IntegralTypeRequired)), + (Value::F64(3.), Value::U8(5), Err(Error::IntegralTypeRequired)), + // Invalid shifts + (Value::U8(3), Value::I8(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(3), Value::I16(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(3), Value::I32(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(3), Value::I64(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(3), Value::F32(5.), Err(Error::InvalidShiftExpression)), + (Value::U8(3), Value::F64(5.), Err(Error::InvalidShiftExpression)), + // Large shifts + (Value::Generic(3), Value::Generic(32), Ok(Value::Generic(0))), + (Value::I8(3), Value::U8(8), Ok(Value::I8(0))), + (Value::U8(3), Value::I8(9), Ok(Value::U8(0))), + (Value::I16(3), Value::U16(17), Ok(Value::I16(0))), + (Value::U16(3), Value::I16(16), Ok(Value::U16(0))), + (Value::I32(3), Value::U32(32), Ok(Value::I32(0))), + (Value::U32(3), Value::I32(33), Ok(Value::U32(0))), + (Value::I64(3), Value::U64(65), Ok(Value::I64(0))), + (Value::U64(3), Value::I64(64), Ok(Value::U64(0))), + ] { + assert_eq!(v1.shl(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_shr() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + // One of each type + (Value::Generic(96), Value::Generic(5), Ok(Value::Generic(3))), + (Value::I8(96), Value::U8(5), Err(Error::UnsupportedTypeOperation)), + (Value::U8(96), Value::I8(5), Ok(Value::U8(3))), + (Value::I16(96), Value::U16(5), Err(Error::UnsupportedTypeOperation)), + (Value::U16(96), Value::I16(5), Ok(Value::U16(3))), + (Value::I32(96), Value::U32(5), Err(Error::UnsupportedTypeOperation)), + (Value::U32(96), Value::I32(5), Ok(Value::U32(3))), + (Value::I64(96), Value::U64(5), Err(Error::UnsupportedTypeOperation)), + (Value::U64(96), Value::I64(5), Ok(Value::U64(3))), + (Value::F32(96.), Value::U8(5), Err(Error::IntegralTypeRequired)), + (Value::F64(96.), Value::U8(5), Err(Error::IntegralTypeRequired)), + // Invalid shifts + (Value::U8(96), Value::I8(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I16(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I32(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I64(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::F32(5.), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::F64(5.), Err(Error::InvalidShiftExpression)), + // Large shifts + (Value::Generic(96), Value::Generic(32), Ok(Value::Generic(0))), + (Value::U8(96), Value::I8(9), Ok(Value::U8(0))), + (Value::U16(96), Value::I16(16), Ok(Value::U16(0))), + (Value::U32(96), Value::I32(33), Ok(Value::U32(0))), + (Value::U64(96), Value::I64(64), Ok(Value::U64(0))), + ] { + assert_eq!(v1.shr(v2, addr_mask), result); + } + } + + #[test] + #[rustfmt::skip] + fn value_shra() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + // One of each type + (Value::Generic(u64::from(-96i32 as u32)), Value::Generic(5), Ok(Value::Generic(-3i64 as u64))), + (Value::I8(-96), Value::U8(5), Ok(Value::I8(-3))), + (Value::U8(96), Value::I8(5), Err(Error::UnsupportedTypeOperation)), + (Value::I16(-96), Value::U16(5), Ok(Value::I16(-3))), + (Value::U16(96), Value::I16(5), Err(Error::UnsupportedTypeOperation)), + (Value::I32(-96), Value::U32(5), Ok(Value::I32(-3))), + (Value::U32(96), Value::I32(5), Err(Error::UnsupportedTypeOperation)), + (Value::I64(-96), Value::U64(5), Ok(Value::I64(-3))), + (Value::U64(96), Value::I64(5), Err(Error::UnsupportedTypeOperation)), + (Value::F32(96.), Value::U8(5), Err(Error::IntegralTypeRequired)), + (Value::F64(96.), Value::U8(5), Err(Error::IntegralTypeRequired)), + // Invalid shifts + (Value::U8(96), Value::I8(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I16(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I32(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::I64(-5), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::F32(5.), Err(Error::InvalidShiftExpression)), + (Value::U8(96), Value::F64(5.), Err(Error::InvalidShiftExpression)), + // Large shifts + (Value::Generic(96), Value::Generic(32), Ok(Value::Generic(0))), + (Value::I8(96), Value::U8(8), Ok(Value::I8(0))), + (Value::I8(-96), Value::U8(8), Ok(Value::I8(-1))), + (Value::I16(96), Value::U16(17), Ok(Value::I16(0))), + (Value::I16(-96), Value::U16(17), Ok(Value::I16(-1))), + (Value::I32(96), Value::U32(32), Ok(Value::I32(0))), + (Value::I32(-96), Value::U32(32), Ok(Value::I32(-1))), + (Value::I64(96), Value::U64(65), Ok(Value::I64(0))), + (Value::I64(-96), Value::U64(65), Ok(Value::I64(-1))), + ] { + assert_eq!(v1.shra(v2, addr_mask), result); + } + } + + #[test] + fn value_eq() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(3), Ok(Value::Generic(1))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))), + (Value::I8(3), Value::I8(3), Ok(Value::Generic(1))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))), + (Value::U8(3), Value::U8(3), Ok(Value::Generic(1))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))), + (Value::I16(3), Value::I16(3), Ok(Value::Generic(1))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))), + (Value::U16(3), Value::U16(3), Ok(Value::Generic(1))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))), + (Value::I32(3), Value::I32(3), Ok(Value::Generic(1))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))), + (Value::U32(3), Value::U32(3), Ok(Value::Generic(1))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))), + (Value::I64(3), Value::I64(3), Ok(Value::Generic(1))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))), + (Value::U64(3), Value::U64(3), Ok(Value::Generic(1))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))), + (Value::F32(3.), Value::F32(3.), Ok(Value::Generic(1))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))), + (Value::F64(3.), Value::F64(3.), Ok(Value::Generic(1))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.eq(v2, addr_mask), result); + } + } + + #[test] + fn value_ne() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(3), Ok(Value::Generic(0))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))), + (Value::I8(3), Value::I8(3), Ok(Value::Generic(0))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))), + (Value::U8(3), Value::U8(3), Ok(Value::Generic(0))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))), + (Value::I16(3), Value::I16(3), Ok(Value::Generic(0))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))), + (Value::U16(3), Value::U16(3), Ok(Value::Generic(0))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))), + (Value::I32(3), Value::I32(3), Ok(Value::Generic(0))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))), + (Value::U32(3), Value::U32(3), Ok(Value::Generic(0))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))), + (Value::I64(3), Value::I64(3), Ok(Value::Generic(0))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))), + (Value::U64(3), Value::U64(3), Ok(Value::Generic(0))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))), + (Value::F32(3.), Value::F32(3.), Ok(Value::Generic(0))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))), + (Value::F64(3.), Value::F64(3.), Ok(Value::Generic(0))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.ne(v2, addr_mask), result); + } + } + + #[test] + fn value_ge() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(1))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))), + (Value::I8(3), Value::I8(!3), Ok(Value::Generic(1))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))), + (Value::U8(3), Value::U8(!3), Ok(Value::Generic(0))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))), + (Value::I16(3), Value::I16(!3), Ok(Value::Generic(1))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))), + (Value::U16(3), Value::U16(!3), Ok(Value::Generic(0))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))), + (Value::I32(3), Value::I32(!3), Ok(Value::Generic(1))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))), + (Value::U32(3), Value::U32(!3), Ok(Value::Generic(0))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))), + (Value::I64(3), Value::I64(!3), Ok(Value::Generic(1))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))), + (Value::U64(3), Value::U64(!3), Ok(Value::Generic(0))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))), + (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(1))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))), + (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(1))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.ge(v2, addr_mask), result); + } + } + + #[test] + fn value_gt() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(1))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))), + (Value::I8(3), Value::I8(!3), Ok(Value::Generic(1))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))), + (Value::U8(3), Value::U8(!3), Ok(Value::Generic(0))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))), + (Value::I16(3), Value::I16(!3), Ok(Value::Generic(1))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))), + (Value::U16(3), Value::U16(!3), Ok(Value::Generic(0))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))), + (Value::I32(3), Value::I32(!3), Ok(Value::Generic(1))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))), + (Value::U32(3), Value::U32(!3), Ok(Value::Generic(0))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))), + (Value::I64(3), Value::I64(!3), Ok(Value::Generic(1))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))), + (Value::U64(3), Value::U64(!3), Ok(Value::Generic(0))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))), + (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(1))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))), + (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(1))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.gt(v2, addr_mask), result); + } + } + + #[test] + fn value_le() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(0))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))), + (Value::I8(3), Value::I8(!3), Ok(Value::Generic(0))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))), + (Value::U8(3), Value::U8(!3), Ok(Value::Generic(1))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))), + (Value::I16(3), Value::I16(!3), Ok(Value::Generic(0))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))), + (Value::U16(3), Value::U16(!3), Ok(Value::Generic(1))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))), + (Value::I32(3), Value::I32(!3), Ok(Value::Generic(0))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))), + (Value::U32(3), Value::U32(!3), Ok(Value::Generic(1))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))), + (Value::I64(3), Value::I64(!3), Ok(Value::Generic(0))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))), + (Value::U64(3), Value::U64(!3), Ok(Value::Generic(1))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))), + (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(0))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))), + (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(0))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.le(v2, addr_mask), result); + } + } + + #[test] + fn value_lt() { + let addr_mask = 0xffff_ffff; + for &(v1, v2, result) in &[ + (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(0))), + (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))), + (Value::I8(3), Value::I8(!3), Ok(Value::Generic(0))), + (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))), + (Value::U8(3), Value::U8(!3), Ok(Value::Generic(1))), + (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))), + (Value::I16(3), Value::I16(!3), Ok(Value::Generic(0))), + (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))), + (Value::U16(3), Value::U16(!3), Ok(Value::Generic(1))), + (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))), + (Value::I32(3), Value::I32(!3), Ok(Value::Generic(0))), + (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))), + (Value::U32(3), Value::U32(!3), Ok(Value::Generic(1))), + (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))), + (Value::I64(3), Value::I64(!3), Ok(Value::Generic(0))), + (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))), + (Value::U64(3), Value::U64(!3), Ok(Value::Generic(1))), + (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))), + (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(0))), + (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))), + (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(0))), + (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))), + (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)), + ] { + assert_eq!(v1.lt(v2, addr_mask), result); + } + } +} diff --git a/anneal/v2/vendor/gimli/src/test_util.rs b/anneal/v2/vendor/gimli/src/test_util.rs new file mode 100644 index 0000000000..706aaf9346 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/test_util.rs @@ -0,0 +1,53 @@ +#![allow(missing_docs)] + +use crate::Format; +use test_assembler::{Label, Section}; + +pub trait GimliSectionMethods { + fn sleb(self, val: i64) -> Self; + fn uleb(self, val: u64) -> Self; + fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self; + fn word(self, size: u8, val: u64) -> Self; + fn word_label(self, size: u8, val: &Label) -> Self; +} + +impl GimliSectionMethods for Section { + fn sleb(mut self, mut val: i64) -> Self { + while val & !0x3f != 0 && val | 0x3f != -1 { + self = self.D8(val as u8 | 0x80); + val >>= 7; + } + self.D8(val as u8 & 0x7f) + } + + fn uleb(mut self, mut val: u64) -> Self { + while val & !0x7f != 0 { + self = self.D8(val as u8 | 0x80); + val >>= 7; + } + self.D8(val as u8) + } + + fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self { + match format { + Format::Dwarf32 => self.D32(length).mark(start), + Format::Dwarf64 => self.D32(0xffff_ffff).D64(length).mark(start), + } + } + + fn word(self, size: u8, val: u64) -> Self { + match size { + 4 => self.D32(val as u32), + 8 => self.D64(val), + _ => panic!("unsupported word size"), + } + } + + fn word_label(self, size: u8, val: &Label) -> Self { + match size { + 4 => self.D32(val), + 8 => self.D64(val), + _ => panic!("unsupported word size"), + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/abbrev.rs b/anneal/v2/vendor/gimli/src/write/abbrev.rs new file mode 100644 index 0000000000..7cdfa969c4 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/abbrev.rs @@ -0,0 +1,188 @@ +use alloc::vec::Vec; +use indexmap::IndexSet; +use std::ops::{Deref, DerefMut}; + +use crate::common::{DebugAbbrevOffset, SectionId}; +use crate::constants; +use crate::write::{Result, Section, Writer}; + +/// A table of abbreviations that will be stored in a `.debug_abbrev` section. +// Requirements: +// - values are `Abbreviation` +// - insertion returns an abbreviation code for use in writing a DIE +// - inserting a duplicate returns the code of the existing value +#[derive(Debug, Default)] +pub(crate) struct AbbreviationTable { + abbrevs: IndexSet, +} + +impl AbbreviationTable { + /// Add an abbreviation to the table and return its code. + pub fn add(&mut self, abbrev: Abbreviation) -> u64 { + let (code, _) = self.abbrevs.insert_full(abbrev); + // Code must be non-zero + (code + 1) as u64 + } + + /// Write the abbreviation table to the `.debug_abbrev` section. + pub fn write(&self, w: &mut DebugAbbrev) -> Result<()> { + for (code, abbrev) in self.abbrevs.iter().enumerate() { + w.write_uleb128((code + 1) as u64)?; + abbrev.write(w)?; + } + // Null abbreviation code + w.write_u8(0) + } +} + +/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type: +/// its tag type, whether it has children, and its set of attributes. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) struct Abbreviation { + tag: constants::DwTag, + has_children: bool, + attributes: Vec, +} + +impl Abbreviation { + /// Construct a new `Abbreviation`. + #[inline] + pub fn new( + tag: constants::DwTag, + has_children: bool, + attributes: Vec, + ) -> Abbreviation { + Abbreviation { + tag, + has_children, + attributes, + } + } + + /// Write the abbreviation to the `.debug_abbrev` section. + pub fn write(&self, w: &mut DebugAbbrev) -> Result<()> { + w.write_uleb128(self.tag.0.into())?; + w.write_u8(if self.has_children { + constants::DW_CHILDREN_yes.0 + } else { + constants::DW_CHILDREN_no.0 + })?; + for attr in &self.attributes { + attr.write(w)?; + } + // Null name and form + w.write_u8(0)?; + w.write_u8(0) + } +} + +/// The description of an attribute in an abbreviated type. +// TODO: support implicit const +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct AttributeSpecification { + name: constants::DwAt, + form: constants::DwForm, +} + +impl AttributeSpecification { + /// Construct a new `AttributeSpecification`. + #[inline] + pub fn new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification { + AttributeSpecification { name, form } + } + + /// Write the attribute specification to the `.debug_abbrev` section. + #[inline] + pub fn write(&self, w: &mut DebugAbbrev) -> Result<()> { + w.write_uleb128(self.name.0.into())?; + w.write_uleb128(self.form.0.into()) + } +} + +define_section!( + DebugAbbrev, + DebugAbbrevOffset, + "A writable `.debug_abbrev` section." +); + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::constants; + use crate::read; + use crate::write::EndianVec; + use crate::LittleEndian; + + #[test] + fn test_abbreviation_table() { + let mut abbrevs = AbbreviationTable::default(); + let abbrev1 = Abbreviation::new( + constants::DW_TAG_subprogram, + false, + vec![AttributeSpecification::new( + constants::DW_AT_name, + constants::DW_FORM_string, + )], + ); + let abbrev2 = Abbreviation::new( + constants::DW_TAG_compile_unit, + true, + vec![ + AttributeSpecification::new(constants::DW_AT_producer, constants::DW_FORM_strp), + AttributeSpecification::new(constants::DW_AT_language, constants::DW_FORM_data2), + ], + ); + let code1 = abbrevs.add(abbrev1.clone()); + assert_eq!(code1, 1); + let code2 = abbrevs.add(abbrev2.clone()); + assert_eq!(code2, 2); + assert_eq!(abbrevs.add(abbrev1.clone()), code1); + assert_eq!(abbrevs.add(abbrev2.clone()), code2); + + let mut debug_abbrev = DebugAbbrev::from(EndianVec::new(LittleEndian)); + let debug_abbrev_offset = debug_abbrev.offset(); + assert_eq!(debug_abbrev_offset, DebugAbbrevOffset(0)); + abbrevs.write(&mut debug_abbrev).unwrap(); + assert_eq!(debug_abbrev.offset(), DebugAbbrevOffset(17)); + + let read_debug_abbrev = read::DebugAbbrev::new(debug_abbrev.slice(), LittleEndian); + let read_abbrevs = read_debug_abbrev + .abbreviations(debug_abbrev_offset) + .unwrap(); + + let read_abbrev1 = read_abbrevs.get(code1).unwrap(); + assert_eq!(abbrev1.tag, read_abbrev1.tag()); + assert_eq!(abbrev1.has_children, read_abbrev1.has_children()); + assert_eq!(abbrev1.attributes.len(), read_abbrev1.attributes().len()); + assert_eq!( + abbrev1.attributes[0].name, + read_abbrev1.attributes()[0].name() + ); + assert_eq!( + abbrev1.attributes[0].form, + read_abbrev1.attributes()[0].form() + ); + + let read_abbrev2 = read_abbrevs.get(code2).unwrap(); + assert_eq!(abbrev2.tag, read_abbrev2.tag()); + assert_eq!(abbrev2.has_children, read_abbrev2.has_children()); + assert_eq!(abbrev2.attributes.len(), read_abbrev2.attributes().len()); + assert_eq!( + abbrev2.attributes[0].name, + read_abbrev2.attributes()[0].name() + ); + assert_eq!( + abbrev2.attributes[0].form, + read_abbrev2.attributes()[0].form() + ); + assert_eq!( + abbrev2.attributes[1].name, + read_abbrev2.attributes()[1].name() + ); + assert_eq!( + abbrev2.attributes[1].form, + read_abbrev2.attributes()[1].form() + ); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/cfi.rs b/anneal/v2/vendor/gimli/src/write/cfi.rs new file mode 100644 index 0000000000..8ef683f27a --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/cfi.rs @@ -0,0 +1,1070 @@ +use alloc::vec::Vec; +use indexmap::IndexSet; +use std::ops::{Deref, DerefMut}; + +use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId}; +use crate::constants; +use crate::write::{Address, BaseId, Error, Expression, Result, Section, Writer}; + +define_section!( + DebugFrame, + DebugFrameOffset, + "A writable `.debug_frame` section." +); + +define_section!(EhFrame, EhFrameOffset, "A writable `.eh_frame` section."); + +define_id!(CieId, "An identifier for a CIE in a `FrameTable`."); + +/// A table of frame description entries. +#[derive(Debug, Default)] +pub struct FrameTable { + /// Base id for CIEs. + base_id: BaseId, + /// The common information entries. + cies: IndexSet, + /// The frame description entries. + fdes: Vec<(CieId, FrameDescriptionEntry)>, +} + +impl FrameTable { + /// Add a CIE and return its id. + /// + /// If the CIE already exists, then return the id of the existing CIE. + pub fn add_cie(&mut self, cie: CommonInformationEntry) -> CieId { + let (index, _) = self.cies.insert_full(cie); + CieId::new(self.base_id, index) + } + + /// The number of CIEs. + pub fn cie_count(&self) -> usize { + self.cies.len() + } + + /// Add a FDE. + /// + /// Does not check for duplicates. + /// + /// # Panics + /// + /// Panics if the CIE id is invalid. + pub fn add_fde(&mut self, cie: CieId, fde: FrameDescriptionEntry) { + debug_assert_eq!(self.base_id, cie.base_id); + self.fdes.push((cie, fde)); + } + + /// The number of FDEs. + pub fn fde_count(&self) -> usize { + self.fdes.len() + } + + /// Write the frame table entries to the given `.debug_frame` section. + pub fn write_debug_frame(&self, w: &mut DebugFrame) -> Result<()> { + self.write(&mut w.0, false) + } + + /// Write the frame table entries to the given `.eh_frame` section. + pub fn write_eh_frame(&self, w: &mut EhFrame) -> Result<()> { + self.write(&mut w.0, true) + } + + fn write(&self, w: &mut W, eh_frame: bool) -> Result<()> { + let mut cie_offsets = vec![None; self.cies.len()]; + for (cie_id, fde) in &self.fdes { + let cie_index = cie_id.index; + let cie = self.cies.get_index(cie_index).unwrap(); + let cie_offset = match cie_offsets[cie_index] { + Some(offset) => offset, + None => { + // Only write CIEs as they are referenced. + let offset = cie.write(w, eh_frame)?; + cie_offsets[cie_index] = Some(offset); + offset + } + }; + + fde.write(w, eh_frame, cie_offset, cie)?; + } + // TODO: write length 0 terminator for eh_frame? + Ok(()) + } +} + +/// A common information entry. This contains information that is shared between FDEs. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct CommonInformationEntry { + encoding: Encoding, + + /// A constant that is factored out of code offsets. + /// + /// This should be set to the minimum instruction length. + /// Writing a code offset that is not a multiple of this factor will generate an error. + code_alignment_factor: u8, + + /// A constant that is factored out of data offsets. + /// + /// This should be set to the minimum data alignment for the frame. + /// Writing a data offset that is not a multiple of this factor will generate an error. + data_alignment_factor: i8, + + /// The return address register. This might not correspond to an actual machine register. + return_address_register: Register, + + /// The address of the personality function and its encoding. + pub personality: Option<(constants::DwEhPe, Address)>, + + /// The encoding to use for the LSDA address in FDEs. + /// + /// If set then all FDEs which use this CIE must have a LSDA address. + pub lsda_encoding: Option, + + /// The encoding to use for addresses in FDEs. + pub fde_address_encoding: constants::DwEhPe, + + /// True for signal trampolines. + pub signal_trampoline: bool, + + /// The initial instructions upon entry to this function. + instructions: Vec, +} + +impl CommonInformationEntry { + /// Create a new common information entry. + /// + /// The encoding version must be a CFI version, not a DWARF version. + pub fn new( + encoding: Encoding, + code_alignment_factor: u8, + data_alignment_factor: i8, + return_address_register: Register, + ) -> Self { + CommonInformationEntry { + encoding, + code_alignment_factor, + data_alignment_factor, + return_address_register, + personality: None, + lsda_encoding: None, + fde_address_encoding: constants::DW_EH_PE_absptr, + signal_trampoline: false, + instructions: Vec::new(), + } + } + + /// Add an initial instruction. + pub fn add_instruction(&mut self, instruction: CallFrameInstruction) { + self.instructions.push(instruction); + } + + fn has_augmentation(&self) -> bool { + self.personality.is_some() + || self.lsda_encoding.is_some() + || self.signal_trampoline + || self.fde_address_encoding != constants::DW_EH_PE_absptr + } + + /// Returns the section offset of the CIE. + fn write(&self, w: &mut W, eh_frame: bool) -> Result { + let encoding = self.encoding; + let offset = w.len(); + + let length_offset = w.write_initial_length(encoding.format)?; + let length_base = w.len(); + + if eh_frame { + w.write_u32(0)?; + } else { + match encoding.format { + Format::Dwarf32 => w.write_u32(0xffff_ffff)?, + Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?, + } + } + + if eh_frame { + if encoding.version != 1 { + return Err(Error::UnsupportedVersion(encoding.version)); + }; + } else { + match encoding.version { + 1 | 3 | 4 => {} + _ => return Err(Error::UnsupportedVersion(encoding.version)), + }; + } + w.write_u8(encoding.version as u8)?; + + let augmentation = self.has_augmentation(); + if augmentation { + w.write_u8(b'z')?; + if self.lsda_encoding.is_some() { + w.write_u8(b'L')?; + } + if self.personality.is_some() { + w.write_u8(b'P')?; + } + if self.fde_address_encoding != constants::DW_EH_PE_absptr { + w.write_u8(b'R')?; + } + if self.signal_trampoline { + w.write_u8(b'S')?; + } + } + w.write_u8(0)?; + + if encoding.version >= 4 { + w.write_u8(encoding.address_size)?; + w.write_u8(0)?; // segment_selector_size + } + + w.write_uleb128(self.code_alignment_factor.into())?; + w.write_sleb128(self.data_alignment_factor.into())?; + + if !eh_frame && encoding.version == 1 { + let register = self.return_address_register.0 as u8; + if u16::from(register) != self.return_address_register.0 { + return Err(Error::ValueTooLarge); + } + w.write_u8(register)?; + } else { + w.write_uleb128(self.return_address_register.0.into())?; + } + + if augmentation { + let augmentation_length_offset = w.len(); + w.write_u8(0)?; + let augmentation_length_base = w.len(); + + if let Some(eh_pe) = self.lsda_encoding { + w.write_u8(eh_pe.0)?; + } + if let Some((eh_pe, address)) = self.personality { + w.write_u8(eh_pe.0)?; + w.write_eh_pointer(address, eh_pe, encoding.address_size)?; + } + if self.fde_address_encoding != constants::DW_EH_PE_absptr { + w.write_u8(self.fde_address_encoding.0)?; + } + + let augmentation_length = (w.len() - augmentation_length_base) as u64; + debug_assert!(augmentation_length < 0x80); + w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?; + } + + for instruction in &self.instructions { + instruction.write(w, encoding, self)?; + } + + write_nop( + w, + encoding.format.word_size() as usize + w.len() - length_base, + encoding.address_size, + )?; + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, encoding.format)?; + + Ok(offset) + } +} + +/// A frame description entry. There should be one FDE per function. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FrameDescriptionEntry { + /// The initial address of the function. + address: Address, + + /// The length in bytes of the function. + length: u32, + + /// The address of the LSDA. + pub lsda: Option
, + + /// The instructions for this function, ordered by offset. + instructions: Vec<(u32, CallFrameInstruction)>, +} + +impl FrameDescriptionEntry { + /// Create a new frame description entry for a function. + pub fn new(address: Address, length: u32) -> Self { + FrameDescriptionEntry { + address, + length, + lsda: None, + instructions: Vec::new(), + } + } + + /// Add an instruction. + /// + /// Instructions must be added in increasing order of offset, or writing will fail. + pub fn add_instruction(&mut self, offset: u32, instruction: CallFrameInstruction) { + debug_assert!(self.instructions.last().map(|x| x.0).unwrap_or(0) <= offset); + self.instructions.push((offset, instruction)); + } + + fn write( + &self, + w: &mut W, + eh_frame: bool, + cie_offset: usize, + cie: &CommonInformationEntry, + ) -> Result<()> { + let encoding = cie.encoding; + let length_offset = w.write_initial_length(encoding.format)?; + let length_base = w.len(); + + if eh_frame { + // .eh_frame uses a relative offset which doesn't need relocation. + w.write_udata((w.len() - cie_offset) as u64, 4)?; + } else { + w.write_offset( + cie_offset, + SectionId::DebugFrame, + encoding.format.word_size(), + )?; + } + + if cie.fde_address_encoding != constants::DW_EH_PE_absptr { + w.write_eh_pointer( + self.address, + cie.fde_address_encoding, + encoding.address_size, + )?; + w.write_eh_pointer_data( + self.length.into(), + cie.fde_address_encoding.format(), + encoding.address_size, + )?; + } else { + w.write_address(self.address, encoding.address_size)?; + w.write_udata(self.length.into(), encoding.address_size)?; + } + + if cie.has_augmentation() { + let augmentation_length_offset = w.len(); + w.write_u8(0)?; + let augmentation_length_base = w.len(); + + debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some()); + if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) { + w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?; + } + + let augmentation_length = (w.len() - augmentation_length_base) as u64; + debug_assert!(augmentation_length < 0x80); + w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?; + } + + let mut prev_offset = 0; + for (offset, instruction) in &self.instructions { + write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?; + prev_offset = *offset; + instruction.write(w, encoding, cie)?; + } + + write_nop( + w, + encoding.format.word_size() as usize + w.len() - length_base, + encoding.address_size, + )?; + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, encoding.format)?; + + Ok(()) + } +} + +/// An instruction in a frame description entry. +/// +/// This may be a CFA definition, a register rule, or some other directive. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum CallFrameInstruction { + /// Define the CFA rule to use the provided register and offset. + Cfa(Register, i32), + /// Update the CFA rule to use the provided register. The offset is unchanged. + CfaRegister(Register), + /// Update the CFA rule to use the provided offset. The register is unchanged. + CfaOffset(i32), + /// Define the CFA rule to use the provided expression. + CfaExpression(Expression), + + /// Restore the initial rule for the register. + Restore(Register), + /// The previous value of the register is not recoverable. + Undefined(Register), + /// The register has not been modified. + SameValue(Register), + /// The previous value of the register is saved at address CFA + offset. + Offset(Register, i32), + /// The previous value of the register is CFA + offset. + ValOffset(Register, i32), + /// The previous value of the register is stored in another register. + Register(Register, Register), + /// The previous value of the register is saved at address given by the expression. + Expression(Register, Expression), + /// The previous value of the register is given by the expression. + ValExpression(Register, Expression), + + /// Push all register rules onto a stack. + RememberState, + /// Pop all register rules off the stack. + RestoreState, + /// The size of the arguments that have been pushed onto the stack. + ArgsSize(u32), + + /// AAarch64 extension: negate the `RA_SIGN_STATE` pseudo-register. + NegateRaState, +} + +impl CallFrameInstruction { + fn write( + &self, + w: &mut W, + encoding: Encoding, + cie: &CommonInformationEntry, + ) -> Result<()> { + match *self { + CallFrameInstruction::Cfa(register, offset) => { + if offset < 0 { + let offset = factored_data_offset(offset, cie.data_alignment_factor)?; + w.write_u8(constants::DW_CFA_def_cfa_sf.0)?; + w.write_uleb128(register.0.into())?; + w.write_sleb128(offset.into())?; + } else { + // Unfactored offset. + w.write_u8(constants::DW_CFA_def_cfa.0)?; + w.write_uleb128(register.0.into())?; + w.write_uleb128(offset as u64)?; + } + } + CallFrameInstruction::CfaRegister(register) => { + w.write_u8(constants::DW_CFA_def_cfa_register.0)?; + w.write_uleb128(register.0.into())?; + } + CallFrameInstruction::CfaOffset(offset) => { + if offset < 0 { + let offset = factored_data_offset(offset, cie.data_alignment_factor)?; + w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?; + w.write_sleb128(offset.into())?; + } else { + // Unfactored offset. + w.write_u8(constants::DW_CFA_def_cfa_offset.0)?; + w.write_uleb128(offset as u64)?; + } + } + CallFrameInstruction::CfaExpression(ref expression) => { + w.write_u8(constants::DW_CFA_def_cfa_expression.0)?; + w.write_uleb128(expression.size(encoding, None)? as u64)?; + expression.write(w, None, encoding, None)?; + } + CallFrameInstruction::Restore(register) => { + if register.0 < 0x40 { + w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?; + } else { + w.write_u8(constants::DW_CFA_restore_extended.0)?; + w.write_uleb128(register.0.into())?; + } + } + CallFrameInstruction::Undefined(register) => { + w.write_u8(constants::DW_CFA_undefined.0)?; + w.write_uleb128(register.0.into())?; + } + CallFrameInstruction::SameValue(register) => { + w.write_u8(constants::DW_CFA_same_value.0)?; + w.write_uleb128(register.0.into())?; + } + CallFrameInstruction::Offset(register, offset) => { + let offset = factored_data_offset(offset, cie.data_alignment_factor)?; + if offset < 0 { + w.write_u8(constants::DW_CFA_offset_extended_sf.0)?; + w.write_uleb128(register.0.into())?; + w.write_sleb128(offset.into())?; + } else if register.0 < 0x40 { + w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?; + w.write_uleb128(offset as u64)?; + } else { + w.write_u8(constants::DW_CFA_offset_extended.0)?; + w.write_uleb128(register.0.into())?; + w.write_uleb128(offset as u64)?; + } + } + CallFrameInstruction::ValOffset(register, offset) => { + let offset = factored_data_offset(offset, cie.data_alignment_factor)?; + if offset < 0 { + w.write_u8(constants::DW_CFA_val_offset_sf.0)?; + w.write_uleb128(register.0.into())?; + w.write_sleb128(offset.into())?; + } else { + w.write_u8(constants::DW_CFA_val_offset.0)?; + w.write_uleb128(register.0.into())?; + w.write_uleb128(offset as u64)?; + } + } + CallFrameInstruction::Register(register1, register2) => { + w.write_u8(constants::DW_CFA_register.0)?; + w.write_uleb128(register1.0.into())?; + w.write_uleb128(register2.0.into())?; + } + CallFrameInstruction::Expression(register, ref expression) => { + w.write_u8(constants::DW_CFA_expression.0)?; + w.write_uleb128(register.0.into())?; + w.write_uleb128(expression.size(encoding, None)? as u64)?; + expression.write(w, None, encoding, None)?; + } + CallFrameInstruction::ValExpression(register, ref expression) => { + w.write_u8(constants::DW_CFA_val_expression.0)?; + w.write_uleb128(register.0.into())?; + w.write_uleb128(expression.size(encoding, None)? as u64)?; + expression.write(w, None, encoding, None)?; + } + CallFrameInstruction::RememberState => { + w.write_u8(constants::DW_CFA_remember_state.0)?; + } + CallFrameInstruction::RestoreState => { + w.write_u8(constants::DW_CFA_restore_state.0)?; + } + CallFrameInstruction::ArgsSize(size) => { + w.write_u8(constants::DW_CFA_GNU_args_size.0)?; + w.write_uleb128(size.into())?; + } + CallFrameInstruction::NegateRaState => { + w.write_u8(constants::DW_CFA_AARCH64_negate_ra_state.0)?; + } + } + Ok(()) + } +} + +fn write_advance_loc( + w: &mut W, + code_alignment_factor: u8, + prev_offset: u32, + offset: u32, +) -> Result<()> { + if offset == prev_offset { + return Ok(()); + } + let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?; + if delta < 0x40 { + w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?; + } else if delta < 0x100 { + w.write_u8(constants::DW_CFA_advance_loc1.0)?; + w.write_u8(delta as u8)?; + } else if delta < 0x10000 { + w.write_u8(constants::DW_CFA_advance_loc2.0)?; + w.write_u16(delta as u16)?; + } else { + w.write_u8(constants::DW_CFA_advance_loc4.0)?; + w.write_u32(delta)?; + } + Ok(()) +} + +fn write_nop(w: &mut W, len: usize, align: u8) -> Result<()> { + debug_assert_eq!(align & (align - 1), 0); + let tail_len = (!len + 1) & (align as usize - 1); + for _ in 0..tail_len { + w.write_u8(constants::DW_CFA_nop.0)?; + } + Ok(()) +} + +fn factored_code_delta(prev_offset: u32, offset: u32, factor: u8) -> Result { + if offset < prev_offset { + return Err(Error::InvalidFrameCodeOffset(offset)); + } + let delta = offset - prev_offset; + let factor = u32::from(factor); + let factored_delta = delta / factor; + if delta != factored_delta * factor { + return Err(Error::InvalidFrameCodeOffset(offset)); + } + Ok(factored_delta) +} + +fn factored_data_offset(offset: i32, factor: i8) -> Result { + let factor = i32::from(factor); + let factored_offset = offset / factor; + if offset != factored_offset * factor { + return Err(Error::InvalidFrameDataOffset(offset)); + } + Ok(factored_offset) +} + +#[cfg(feature = "read")] +pub(crate) mod convert { + use super::*; + use crate::read::{self, Reader}; + use crate::write::{ConvertError, ConvertResult}; + use std::collections::{hash_map, HashMap}; + + impl FrameTable { + /// Create a frame table by reading the data in the given section. + /// + /// `convert_address` is a function to convert read addresses into the `Address` + /// type. For non-relocatable addresses, this function may simply return + /// `Address::Constant(address)`. For relocatable addresses, it is the caller's + /// responsibility to determine the symbol and addend corresponding to the address + /// and return `Address::Symbol { symbol, addend }`. + pub fn from( + frame: &Section, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult + where + R: Reader, + Section: read::UnwindSection, + Section::Offset: read::UnwindOffset, + { + let bases = read::BaseAddresses::default().set_eh_frame(0); + + let mut frame_table = FrameTable::default(); + + let mut cie_ids = HashMap::new(); + let mut entries = frame.entries(&bases); + while let Some(entry) = entries.next()? { + let partial = match entry { + read::CieOrFde::Cie(_) => continue, + read::CieOrFde::Fde(partial) => partial, + }; + + // TODO: is it worth caching the parsed CIEs? It would be better if FDEs only + // stored a reference. + let from_fde = partial.parse(Section::cie_from_offset)?; + let from_cie = from_fde.cie(); + let cie_id = match cie_ids.entry(from_cie.offset()) { + hash_map::Entry::Occupied(o) => *o.get(), + hash_map::Entry::Vacant(e) => { + let cie = + CommonInformationEntry::from(from_cie, frame, &bases, convert_address)?; + let cie_id = frame_table.add_cie(cie); + e.insert(cie_id); + cie_id + } + }; + let fde = FrameDescriptionEntry::from(&from_fde, frame, &bases, convert_address)?; + frame_table.add_fde(cie_id, fde); + } + + Ok(frame_table) + } + } + + impl CommonInformationEntry { + fn from( + from_cie: &read::CommonInformationEntry, + frame: &Section, + bases: &read::BaseAddresses, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult + where + R: Reader, + Section: read::UnwindSection, + Section::Offset: read::UnwindOffset, + { + let mut cie = CommonInformationEntry::new( + from_cie.encoding(), + from_cie.code_alignment_factor() as u8, + from_cie.data_alignment_factor() as i8, + from_cie.return_address_register(), + ); + + cie.personality = match from_cie.personality_with_encoding() { + // We treat these the same because the encoding already determines + // whether it is indirect. + Some((eh_pe, read::Pointer::Direct(p))) + | Some((eh_pe, read::Pointer::Indirect(p))) => { + let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?; + Some((eh_pe, address)) + } + _ => None, + }; + cie.lsda_encoding = from_cie.lsda_encoding(); + cie.fde_address_encoding = from_cie + .fde_address_encoding() + .unwrap_or(constants::DW_EH_PE_absptr); + cie.signal_trampoline = from_cie.is_signal_trampoline(); + + let mut offset = 0; + let mut from_instructions = from_cie.instructions(frame, bases); + while let Some(from_instruction) = from_instructions.next()? { + if let Some(instruction) = CallFrameInstruction::from( + from_instruction, + from_cie, + frame, + convert_address, + &mut offset, + )? { + cie.instructions.push(instruction); + } + } + Ok(cie) + } + } + + impl FrameDescriptionEntry { + fn from( + from_fde: &read::FrameDescriptionEntry, + frame: &Section, + bases: &read::BaseAddresses, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult + where + R: Reader, + Section: read::UnwindSection, + Section::Offset: read::UnwindOffset, + { + let address = + convert_address(from_fde.initial_address()).ok_or(ConvertError::InvalidAddress)?; + let length = from_fde.len() as u32; + let mut fde = FrameDescriptionEntry::new(address, length); + + match from_fde.lsda() { + // We treat these the same because the encoding already determines + // whether it is indirect. + Some(read::Pointer::Direct(p)) | Some(read::Pointer::Indirect(p)) => { + let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?; + fde.lsda = Some(address); + } + None => {} + } + + let from_cie = from_fde.cie(); + let mut offset = 0; + let mut from_instructions = from_fde.instructions(frame, bases); + while let Some(from_instruction) = from_instructions.next()? { + if let Some(instruction) = CallFrameInstruction::from( + from_instruction, + from_cie, + frame, + convert_address, + &mut offset, + )? { + fde.instructions.push((offset, instruction)); + } + } + + Ok(fde) + } + } + + impl CallFrameInstruction { + fn from( + from_instruction: read::CallFrameInstruction, + from_cie: &read::CommonInformationEntry, + frame: &Section, + convert_address: &dyn Fn(u64) -> Option
, + offset: &mut u32, + ) -> ConvertResult> + where + R: Reader, + Section: read::UnwindSection, + { + let convert_expression = + |x| Expression::from(x, from_cie.encoding(), None, None, None, convert_address); + // TODO: validate integer type conversions + Ok(Some(match from_instruction { + read::CallFrameInstruction::SetLoc { .. } => { + return Err(ConvertError::UnsupportedCfiInstruction); + } + read::CallFrameInstruction::AdvanceLoc { delta } => { + *offset += delta * from_cie.code_alignment_factor() as u32; + return Ok(None); + } + read::CallFrameInstruction::DefCfa { register, offset } => { + CallFrameInstruction::Cfa(register, offset as i32) + } + read::CallFrameInstruction::DefCfaSf { + register, + factored_offset, + } => { + let offset = factored_offset * from_cie.data_alignment_factor(); + CallFrameInstruction::Cfa(register, offset as i32) + } + read::CallFrameInstruction::DefCfaRegister { register } => { + CallFrameInstruction::CfaRegister(register) + } + + read::CallFrameInstruction::DefCfaOffset { offset } => { + CallFrameInstruction::CfaOffset(offset as i32) + } + read::CallFrameInstruction::DefCfaOffsetSf { factored_offset } => { + let offset = factored_offset * from_cie.data_alignment_factor(); + CallFrameInstruction::CfaOffset(offset as i32) + } + read::CallFrameInstruction::DefCfaExpression { expression } => { + let expression = expression.get(frame)?; + CallFrameInstruction::CfaExpression(convert_expression(expression)?) + } + read::CallFrameInstruction::Undefined { register } => { + CallFrameInstruction::Undefined(register) + } + read::CallFrameInstruction::SameValue { register } => { + CallFrameInstruction::SameValue(register) + } + read::CallFrameInstruction::Offset { + register, + factored_offset, + } => { + let offset = factored_offset as i64 * from_cie.data_alignment_factor(); + CallFrameInstruction::Offset(register, offset as i32) + } + read::CallFrameInstruction::OffsetExtendedSf { + register, + factored_offset, + } => { + let offset = factored_offset * from_cie.data_alignment_factor(); + CallFrameInstruction::Offset(register, offset as i32) + } + read::CallFrameInstruction::ValOffset { + register, + factored_offset, + } => { + let offset = factored_offset as i64 * from_cie.data_alignment_factor(); + CallFrameInstruction::ValOffset(register, offset as i32) + } + read::CallFrameInstruction::ValOffsetSf { + register, + factored_offset, + } => { + let offset = factored_offset * from_cie.data_alignment_factor(); + CallFrameInstruction::ValOffset(register, offset as i32) + } + read::CallFrameInstruction::Register { + dest_register, + src_register, + } => CallFrameInstruction::Register(dest_register, src_register), + read::CallFrameInstruction::Expression { + register, + expression, + } => { + let expression = expression.get(frame)?; + CallFrameInstruction::Expression(register, convert_expression(expression)?) + } + read::CallFrameInstruction::ValExpression { + register, + expression, + } => { + let expression = expression.get(frame)?; + CallFrameInstruction::ValExpression(register, convert_expression(expression)?) + } + read::CallFrameInstruction::Restore { register } => { + CallFrameInstruction::Restore(register) + } + read::CallFrameInstruction::RememberState => CallFrameInstruction::RememberState, + read::CallFrameInstruction::RestoreState => CallFrameInstruction::RestoreState, + read::CallFrameInstruction::ArgsSize { size } => { + CallFrameInstruction::ArgsSize(size as u32) + } + read::CallFrameInstruction::NegateRaState => CallFrameInstruction::NegateRaState, + read::CallFrameInstruction::Nop => return Ok(None), + })) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::arch::X86_64; + use crate::read; + use crate::write::EndianVec; + use crate::{LittleEndian, Vendor}; + + #[test] + fn test_frame_table() { + for &version in &[1, 3, 4] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut frames = FrameTable::default(); + + let cie1 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA); + let cie1_id = frames.add_cie(cie1.clone()); + assert_eq!(cie1_id, frames.add_cie(cie1.clone())); + + let mut cie2 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA); + cie2.lsda_encoding = Some(constants::DW_EH_PE_absptr); + cie2.personality = + Some((constants::DW_EH_PE_absptr, Address::Constant(0x1234))); + cie2.signal_trampoline = true; + let cie2_id = frames.add_cie(cie2.clone()); + assert_ne!(cie1_id, cie2_id); + assert_eq!(cie2_id, frames.add_cie(cie2.clone())); + + let fde1 = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10); + frames.add_fde(cie1_id, fde1.clone()); + + let fde2 = FrameDescriptionEntry::new(Address::Constant(0x2000), 0x20); + frames.add_fde(cie1_id, fde2.clone()); + + let mut fde3 = FrameDescriptionEntry::new(Address::Constant(0x3000), 0x30); + fde3.lsda = Some(Address::Constant(0x3300)); + frames.add_fde(cie2_id, fde3.clone()); + + let mut fde4 = FrameDescriptionEntry::new(Address::Constant(0x4000), 0x40); + fde4.lsda = Some(Address::Constant(0x4400)); + frames.add_fde(cie2_id, fde4.clone()); + + let mut cie3 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA); + cie3.fde_address_encoding = + constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4; + cie3.lsda_encoding = + Some(constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4); + cie3.personality = Some(( + constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4, + Address::Constant(0x1235), + )); + cie3.signal_trampoline = true; + let cie3_id = frames.add_cie(cie3.clone()); + assert_ne!(cie2_id, cie3_id); + assert_eq!(cie3_id, frames.add_cie(cie3.clone())); + + let mut fde5 = FrameDescriptionEntry::new(Address::Constant(0x5000), 0x50); + fde5.lsda = Some(Address::Constant(0x5500)); + frames.add_fde(cie3_id, fde5.clone()); + + // Test writing `.debug_frame`. + let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian)); + frames.write_debug_frame(&mut debug_frame).unwrap(); + + let mut read_debug_frame = + read::DebugFrame::new(debug_frame.slice(), LittleEndian); + read_debug_frame.set_address_size(address_size); + let convert_frames = FrameTable::from(&read_debug_frame, &|address| { + Some(Address::Constant(address)) + }) + .unwrap(); + assert_eq!(frames.cies, convert_frames.cies); + assert_eq!(frames.fdes.len(), convert_frames.fdes.len()); + for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) { + assert_eq!(a.1, b.1); + } + + if version == 1 { + // Test writing `.eh_frame`. + let mut eh_frame = EhFrame::from(EndianVec::new(LittleEndian)); + frames.write_eh_frame(&mut eh_frame).unwrap(); + + let mut read_eh_frame = read::EhFrame::new(eh_frame.slice(), LittleEndian); + read_eh_frame.set_address_size(address_size); + let convert_frames = FrameTable::from(&read_eh_frame, &|address| { + Some(Address::Constant(address)) + }) + .unwrap(); + assert_eq!(frames.cies, convert_frames.cies); + assert_eq!(frames.fdes.len(), convert_frames.fdes.len()); + for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) { + assert_eq!(a.1, b.1); + } + } + } + } + } + } + + #[test] + fn test_frame_instruction() { + let mut expression = Expression::new(); + expression.op_constu(0); + + let cie_instructions = [ + CallFrameInstruction::Cfa(X86_64::RSP, 8), + CallFrameInstruction::Offset(X86_64::RA, -8), + ]; + + let fde_instructions = [ + (0, CallFrameInstruction::Cfa(X86_64::RSP, 0)), + (0, CallFrameInstruction::Cfa(X86_64::RSP, -8)), + (2, CallFrameInstruction::CfaRegister(X86_64::RBP)), + (4, CallFrameInstruction::CfaOffset(8)), + (4, CallFrameInstruction::CfaOffset(0)), + (4, CallFrameInstruction::CfaOffset(-8)), + (6, CallFrameInstruction::CfaExpression(expression.clone())), + (8, CallFrameInstruction::Restore(Register(1))), + (8, CallFrameInstruction::Restore(Register(101))), + (10, CallFrameInstruction::Undefined(Register(2))), + (12, CallFrameInstruction::SameValue(Register(3))), + (14, CallFrameInstruction::Offset(Register(4), 16)), + (14, CallFrameInstruction::Offset(Register(104), 16)), + (16, CallFrameInstruction::ValOffset(Register(5), -24)), + (16, CallFrameInstruction::ValOffset(Register(5), 24)), + (18, CallFrameInstruction::Register(Register(6), Register(7))), + ( + 20, + CallFrameInstruction::Expression(Register(8), expression.clone()), + ), + ( + 22, + CallFrameInstruction::ValExpression(Register(9), expression.clone()), + ), + (24 + 0x80, CallFrameInstruction::RememberState), + (26 + 0x280, CallFrameInstruction::RestoreState), + (28 + 0x20280, CallFrameInstruction::ArgsSize(23)), + ]; + + let fde_instructions_aarch64 = [(0, CallFrameInstruction::NegateRaState)]; + + for &version in &[1, 3, 4] { + for &address_size in &[4, 8] { + for &vendor in &[Vendor::Default, Vendor::AArch64] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut frames = FrameTable::default(); + + let mut cie = CommonInformationEntry::new(encoding, 2, 8, X86_64::RA); + for i in &cie_instructions { + cie.add_instruction(i.clone()); + } + let cie_id = frames.add_cie(cie); + + let mut fde = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10); + for (o, i) in &fde_instructions { + fde.add_instruction(*o, i.clone()); + } + frames.add_fde(cie_id, fde); + + if vendor == Vendor::AArch64 { + let mut fde = + FrameDescriptionEntry::new(Address::Constant(0x2000), 0x10); + for (o, i) in &fde_instructions_aarch64 { + fde.add_instruction(*o, i.clone()); + } + frames.add_fde(cie_id, fde); + } + + let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian)); + frames.write_debug_frame(&mut debug_frame).unwrap(); + + let mut read_debug_frame = + read::DebugFrame::new(debug_frame.slice(), LittleEndian); + read_debug_frame.set_address_size(address_size); + read_debug_frame.set_vendor(vendor); + let frames = FrameTable::from(&read_debug_frame, &|address| { + Some(Address::Constant(address)) + }) + .unwrap(); + + assert_eq!( + &frames.cies.get_index(0).unwrap().instructions, + &cie_instructions + ); + assert_eq!(&frames.fdes[0].1.instructions, &fde_instructions); + if vendor == Vendor::AArch64 { + assert_eq!(&frames.fdes[1].1.instructions, &fde_instructions_aarch64); + } + } + } + } + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/dwarf.rs b/anneal/v2/vendor/gimli/src/write/dwarf.rs new file mode 100644 index 0000000000..59c2a6d9a7 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/dwarf.rs @@ -0,0 +1,148 @@ +use alloc::vec::Vec; + +use crate::common::Encoding; +use crate::write::{ + AbbreviationTable, LineProgram, LineString, LineStringTable, Result, Sections, StringTable, + Unit, UnitTable, Writer, +}; + +/// Writable DWARF information for more than one unit. +#[derive(Debug, Default)] +pub struct Dwarf { + /// A table of units. These are primarily stored in the `.debug_info` section, + /// but they also contain information that is stored in other sections. + pub units: UnitTable, + + /// Extra line number programs that are not associated with a unit. + /// + /// These should only be used when generating DWARF5 line-only debug + /// information. + pub line_programs: Vec, + + /// A table of strings that will be stored in the `.debug_line_str` section. + pub line_strings: LineStringTable, + + /// A table of strings that will be stored in the `.debug_str` section. + pub strings: StringTable, +} + +impl Dwarf { + /// Create a new `Dwarf` instance. + #[inline] + pub fn new() -> Self { + Self::default() + } + + /// Write the DWARF information to the given sections. + pub fn write(&mut self, sections: &mut Sections) -> Result<()> { + let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; + let strings = self.strings.write(&mut sections.debug_str)?; + self.units.write(sections, &line_strings, &strings)?; + for line_program in &self.line_programs { + line_program.write( + &mut sections.debug_line, + line_program.encoding(), + &line_strings, + &strings, + )?; + } + Ok(()) + } + + /// Get a reference to the data for a line string. + pub fn get_line_string<'a>(&'a self, string: &'a LineString) -> &'a [u8] { + string.get(&self.strings, &self.line_strings) + } +} + +/// Writable DWARF information for a single unit. +#[derive(Debug)] +pub struct DwarfUnit { + /// A unit. This is primarily stored in the `.debug_info` section, + /// but also contains information that is stored in other sections. + pub unit: Unit, + + /// A table of strings that will be stored in the `.debug_line_str` section. + pub line_strings: LineStringTable, + + /// A table of strings that will be stored in the `.debug_str` section. + pub strings: StringTable, +} + +impl DwarfUnit { + /// Create a new `DwarfUnit`. + /// + /// Note: you should set `self.unit.line_program` after creation. + /// This cannot be done earlier because it may need to reference + /// `self.line_strings`. + pub fn new(encoding: Encoding) -> Self { + let unit = Unit::new(encoding, LineProgram::none()); + DwarfUnit { + unit, + line_strings: LineStringTable::default(), + strings: StringTable::default(), + } + } + + /// Write the DWARf information to the given sections. + pub fn write(&mut self, sections: &mut Sections) -> Result<()> { + let line_strings = self.line_strings.write(&mut sections.debug_line_str)?; + let strings = self.strings.write(&mut sections.debug_str)?; + + let abbrev_offset = sections.debug_abbrev.offset(); + let mut abbrevs = AbbreviationTable::default(); + + self.unit.write( + sections, + abbrev_offset, + &mut abbrevs, + &line_strings, + &strings, + )?; + // None should exist because we didn't give out any UnitId. + assert!(sections.debug_info_refs.is_empty()); + assert!(sections.debug_loc_refs.is_empty()); + assert!(sections.debug_loclists_refs.is_empty()); + + abbrevs.write(&mut sections.debug_abbrev)?; + Ok(()) + } + + /// Get a reference to the data for a line string. + pub fn get_line_string<'a>(&'a self, string: &'a LineString) -> &'a [u8] { + string.get(&self.strings, &self.line_strings) + } +} + +#[cfg(feature = "read")] +pub(crate) mod convert { + use super::*; + use crate::read::{self, Reader}; + use crate::write::{Address, ConvertResult}; + + impl Dwarf { + /// Create a `write::Dwarf` by converting a `read::Dwarf`. + /// + /// `convert_address` is a function to convert read addresses into the `Address` + /// type. For non-relocatable addresses, this function may simply return + /// `Address::Constant(address)`. For relocatable addresses, it is the caller's + /// responsibility to determine the symbol and addend corresponding to the address + /// and return `Address::Symbol { symbol, addend }`. + pub fn from>( + dwarf: &read::Dwarf, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult { + let mut line_strings = LineStringTable::default(); + let mut strings = StringTable::default(); + let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?; + // TODO: convert the line programs that were not referenced by a unit. + let line_programs = Vec::new(); + Ok(Dwarf { + units, + line_programs, + line_strings, + strings, + }) + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/endian_vec.rs b/anneal/v2/vendor/gimli/src/write/endian_vec.rs new file mode 100644 index 0000000000..7b040606a0 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/endian_vec.rs @@ -0,0 +1,117 @@ +use alloc::vec::Vec; +use std::mem; + +use crate::endianity::Endianity; +use crate::write::{Error, Result, Writer}; + +/// A `Vec` with endianity metadata. +/// +/// This implements the `Writer` trait, which is used for all writing of DWARF sections. +#[derive(Debug, Clone)] +pub struct EndianVec +where + Endian: Endianity, +{ + vec: Vec, + endian: Endian, +} + +impl EndianVec +where + Endian: Endianity, +{ + /// Construct an empty `EndianVec` with the given endianity. + pub fn new(endian: Endian) -> EndianVec { + EndianVec { + vec: Vec::new(), + endian, + } + } + + /// Return a reference to the raw slice. + pub fn slice(&self) -> &[u8] { + &self.vec + } + + /// Convert into a `Vec`. + pub fn into_vec(self) -> Vec { + self.vec + } + + /// Take any written data out of the `EndianVec`, leaving an empty `Vec` in its place. + pub fn take(&mut self) -> Vec { + let mut vec = Vec::new(); + mem::swap(&mut self.vec, &mut vec); + vec + } +} + +impl Writer for EndianVec +where + Endian: Endianity, +{ + type Endian = Endian; + + #[inline] + fn endian(&self) -> Self::Endian { + self.endian + } + + #[inline] + fn len(&self) -> usize { + self.vec.len() + } + + fn write(&mut self, bytes: &[u8]) -> Result<()> { + self.vec.extend(bytes); + Ok(()) + } + + fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { + if offset > self.vec.len() { + return Err(Error::OffsetOutOfBounds); + } + let to = &mut self.vec[offset..]; + if bytes.len() > to.len() { + return Err(Error::LengthOutOfBounds); + } + let to = &mut to[..bytes.len()]; + to.copy_from_slice(bytes); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::LittleEndian; + + #[test] + fn test_endian_vec() { + let mut w = EndianVec::new(LittleEndian); + assert_eq!(w.endian(), LittleEndian); + assert_eq!(w.len(), 0); + + w.write(&[1, 2]).unwrap(); + assert_eq!(w.slice(), &[1, 2]); + assert_eq!(w.len(), 2); + + w.write(&[3, 4, 5]).unwrap(); + assert_eq!(w.slice(), &[1, 2, 3, 4, 5]); + assert_eq!(w.len(), 5); + + w.write_at(0, &[6, 7]).unwrap(); + assert_eq!(w.slice(), &[6, 7, 3, 4, 5]); + assert_eq!(w.len(), 5); + + w.write_at(3, &[8, 9]).unwrap(); + assert_eq!(w.slice(), &[6, 7, 3, 8, 9]); + assert_eq!(w.len(), 5); + + assert_eq!(w.write_at(4, &[6, 7]), Err(Error::LengthOutOfBounds)); + assert_eq!(w.write_at(5, &[6, 7]), Err(Error::LengthOutOfBounds)); + assert_eq!(w.write_at(6, &[6, 7]), Err(Error::OffsetOutOfBounds)); + + assert_eq!(w.into_vec(), vec![6, 7, 3, 8, 9]); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/line.rs b/anneal/v2/vendor/gimli/src/write/line.rs new file mode 100644 index 0000000000..bc180235bd --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/line.rs @@ -0,0 +1,2165 @@ +use alloc::vec::Vec; +use indexmap::{IndexMap, IndexSet}; +use std::ops::{Deref, DerefMut}; + +use crate::common::{DebugLineOffset, Encoding, Format, LineEncoding, SectionId}; +use crate::constants; +use crate::leb128; +use crate::write::{ + Address, DebugLineStrOffsets, DebugStrOffsets, Error, LineStringId, LineStringTable, Result, + Section, StringId, StringTable, Writer, +}; + +/// The number assigned to the first special opcode. +// +// We output all instructions for all DWARF versions, since readers +// should be able to ignore instructions they don't support. +const OPCODE_BASE: u8 = 13; + +/// A line number program. +#[derive(Debug, Clone)] +pub struct LineProgram { + /// True if this line program was created with `LineProgram::none()`. + none: bool, + encoding: Encoding, + line_encoding: LineEncoding, + + /// A list of source directory path names. + /// + /// If a path is relative, then the directory is located relative to the working + /// directory of the compilation unit. + /// + /// The first entry is for the working directory of the compilation unit. + directories: IndexSet, + + /// A list of source file entries. + /// + /// Each entry has a path name and a directory. + /// + /// If a path is a relative, then the file is located relative to the + /// directory. Otherwise the directory is meaningless. + /// + /// Does not include comp_file, even for version >= 5. + files: IndexMap<(LineString, DirectoryId), FileInfo>, + + /// True if the file entries may have valid timestamps. + /// + /// Entries may still have a timestamp of 0 even if this is set. + /// For version <= 4, this is ignored. + /// For version 5, this controls whether to emit `DW_LNCT_timestamp`. + pub file_has_timestamp: bool, + + /// True if the file entries may have valid sizes. + /// + /// Entries may still have a size of 0 even if this is set. + /// For version <= 4, this is ignored. + /// For version 5, this controls whether to emit `DW_LNCT_size`. + pub file_has_size: bool, + + /// True if the file entries have valid MD5 checksums. + /// + /// For version <= 4, this is ignored. + /// For version 5, this controls whether to emit `DW_LNCT_MD5`. + pub file_has_md5: bool, + + /// True if the file entries have embedded source code. + /// + /// For version <= 4, this is ignored. + /// For version 5, this controls whether to emit `DW_LNCT_LLVM_source`. + pub file_has_source: bool, + + prev_row: LineRow, + row: LineRow, + // TODO: this probably should be either rows or sequences instead + instructions: Vec, + in_sequence: bool, +} + +impl LineProgram { + /// Create a new `LineProgram`. + /// + /// `working_dir` defines the working directory of the compilation unit. + /// + /// `source_dir`, `source_file` and `source_file_info` define the first + /// file entry. `source_dir` may be relative to `working_dir`, and may be + /// `None` if `source_file` is in `working_dir`. The first file entry + /// is usually the primary source file. + /// + /// The standard specifies that `working_dir` should be the same as the + /// `DW_AT_comp_dir` attribute of the compilation unit DIE, and the + /// combination of `source_dir` and `source_file` should be the same + /// as the `DW_AT_name` attribute of the compilation unit DIE. + /// However, neither of these are enforced by this library. + /// + /// # Panics + /// + /// Panics if `line_encoding.line_base` > 0. + /// + /// Panics if `line_encoding.line_base` + `line_encoding.line_range` <= 0. + /// + /// Panics if `working_dir`, `source_dir`, or `source_file` are empty or + /// contain a null byte. + pub fn new( + encoding: Encoding, + line_encoding: LineEncoding, + working_dir: LineString, + source_dir: Option, + source_file: LineString, + source_file_info: Option, + ) -> LineProgram { + // We require a special opcode for a line advance of 0. + // See the debug_asserts in generate_row(). + assert!(line_encoding.line_base <= 0); + assert!(line_encoding.line_base + line_encoding.line_range as i8 > 0); + let mut program = LineProgram { + none: false, + encoding, + line_encoding, + directories: IndexSet::new(), + files: IndexMap::new(), + prev_row: LineRow::initial_state(encoding, line_encoding), + row: LineRow::initial_state(encoding, line_encoding), + instructions: Vec::new(), + in_sequence: false, + file_has_timestamp: false, + file_has_size: false, + file_has_md5: false, + file_has_source: false, + }; + // For all DWARF versions, directory index 0 is working_dir. + // For version <= 4, the entry is implicit. We still add + // it here so that we use it, but we don't emit it. + let working_dir_id = program.add_directory(working_dir); + // For DWARF version >= 5, file index 0 is source_file and must exist. + if encoding.version >= 5 { + let source_dir_id = match source_dir { + Some(source_dir) => program.add_directory(source_dir), + None => working_dir_id, + }; + program.add_file(source_file, source_dir_id, source_file_info); + } + program + } + + /// Create a new `LineProgram` with no fields set. + /// + /// This can be used when the `LineProgram` will not be used. + /// + /// You should not attempt to add files or line instructions to + /// this line program, or write it to the `.debug_line` section. + pub fn none() -> Self { + let encoding = Encoding { + format: Format::Dwarf32, + version: 2, + address_size: 0, + }; + let line_encoding = LineEncoding::default(); + LineProgram { + none: true, + encoding, + line_encoding, + directories: IndexSet::new(), + files: IndexMap::new(), + prev_row: LineRow::initial_state(encoding, line_encoding), + row: LineRow::initial_state(encoding, line_encoding), + instructions: Vec::new(), + in_sequence: false, + file_has_timestamp: false, + file_has_size: false, + file_has_md5: false, + file_has_source: false, + } + } + + /// Return true if this line program was created with `LineProgram::none()`. + #[inline] + pub fn is_none(&self) -> bool { + self.none + } + + /// Return the encoding parameters for this line program. + #[inline] + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Return the DWARF version for this line program. + #[inline] + pub fn version(&self) -> u16 { + self.encoding.version + } + + /// Return the address size in bytes for this line program. + #[inline] + pub fn address_size(&self) -> u8 { + self.encoding.address_size + } + + /// Return the DWARF format for this line program. + #[inline] + pub fn format(&self) -> Format { + self.encoding.format + } + + /// Return the id for the working directory of the compilation unit. + #[inline] + pub fn default_directory(&self) -> DirectoryId { + DirectoryId(0) + } + + /// Add a directory entry and return its id. + /// + /// If the directory already exists, then return the id of the existing entry. + /// + /// If the path is relative, then the directory is located relative to the working + /// directory of the compilation unit. + /// + /// # Panics + /// + /// Panics if `directory` is empty or contains a null byte. + pub fn add_directory(&mut self, directory: LineString) -> DirectoryId { + if let LineString::String(ref val) = directory { + // For DWARF version <= 4, directories must not be empty. + // The first directory isn't emitted so skip the check for it. + if self.encoding.version <= 4 && !self.directories.is_empty() { + assert!(!val.is_empty()); + } + assert!(!val.contains(&0)); + } + let (index, _) = self.directories.insert_full(directory); + DirectoryId(index) + } + + /// Get a reference to a directory entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + pub fn get_directory(&self, id: DirectoryId) -> &LineString { + self.directories.get_index(id.0).unwrap() + } + + /// Add a file entry and return its id. + /// + /// If the file already exists, then return the id of the existing entry. + /// + /// If the file path is relative, then the file is located relative + /// to the directory. Otherwise the directory is meaningless, but it + /// is still used as a key for file entries. + /// + /// If `info` is `None`, then new entries are assigned + /// default information, and existing entries are unmodified. + /// + /// If `info` is not `None`, then it is always assigned to the + /// entry, even if the entry already exists. + /// + /// # Panics + /// + /// Panics if 'file' is empty or contains a null byte. + pub fn add_file( + &mut self, + file: LineString, + directory: DirectoryId, + info: Option, + ) -> FileId { + if let LineString::String(ref val) = file { + if self.encoding.version <= 4 { + assert!(!val.is_empty()); + } + assert!(!val.contains(&0)); + } + + let key = (file, directory); + let index = if let Some(info) = info { + let (index, _) = self.files.insert_full(key, info); + index + } else { + let entry = self.files.entry(key); + let index = entry.index(); + entry.or_default(); + index + }; + FileId::new(index) + } + + /// Get an iterator for the files. + pub fn files(&self) -> impl Iterator { + self.files + .iter() + .enumerate() + .map(move |(index, entry)| (FileId::new(index), &(entry.0).0, (entry.0).1)) + } + + /// Get a reference to a file entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + pub fn get_file(&self, id: FileId) -> (&LineString, DirectoryId) { + self.files + .get_index(id.index()) + .map(|entry| (&(entry.0).0, (entry.0).1)) + .unwrap() + } + + /// Get a reference to the info for a file entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + pub fn get_file_info(&self, id: FileId) -> &FileInfo { + self.files + .get_index(id.index()) + .map(|entry| entry.1) + .unwrap() + } + + /// Get a mutable reference to the info for a file entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + pub fn get_file_info_mut(&mut self, id: FileId) -> &mut FileInfo { + self.files + .get_index_mut(id.index()) + .map(|entry| entry.1) + .unwrap() + } + + /// Begin a new sequence and set its base address. + /// + /// # Panics + /// + /// Panics if a sequence has already begun. + pub fn begin_sequence(&mut self, address: Option
) { + assert!(!self.in_sequence); + self.in_sequence = true; + if let Some(address) = address { + self.instructions.push(LineInstruction::SetAddress(address)); + } + } + + /// End the sequence, and reset the row to its default values. + /// + /// Only the `address_offset` and op_index` fields of the current row are used. + /// + /// # Panics + /// + /// Panics if a sequence has not begun. + pub fn end_sequence(&mut self, address_offset: u64) { + assert!(self.in_sequence); + self.in_sequence = false; + self.row.address_offset = address_offset; + let op_advance = self.op_advance(); + if op_advance != 0 { + self.instructions + .push(LineInstruction::AdvancePc(op_advance)); + } + self.instructions.push(LineInstruction::EndSequence); + self.prev_row = LineRow::initial_state(self.encoding, self.line_encoding); + self.row = LineRow::initial_state(self.encoding, self.line_encoding); + } + + /// Return true if a sequence has begun. + #[inline] + pub fn in_sequence(&self) -> bool { + self.in_sequence + } + + /// Returns a reference to the data for the current row. + #[inline] + pub fn row(&mut self) -> &mut LineRow { + &mut self.row + } + + /// Generates the line number information instructions for the current row. + /// + /// After the instructions are generated, it sets `discriminator` to 0, and sets + /// `basic_block`, `prologue_end`, and `epilogue_begin` to false. + /// + /// # Panics + /// + /// Panics if a sequence has not begun. + /// Panics if the address_offset decreases. + pub fn generate_row(&mut self) { + assert!(self.in_sequence); + + // Output fields that are reset on every row. + if self.row.discriminator != 0 { + self.instructions + .push(LineInstruction::SetDiscriminator(self.row.discriminator)); + self.row.discriminator = 0; + } + if self.row.basic_block { + self.instructions.push(LineInstruction::SetBasicBlock); + self.row.basic_block = false; + } + if self.row.prologue_end { + self.instructions.push(LineInstruction::SetPrologueEnd); + self.row.prologue_end = false; + } + if self.row.epilogue_begin { + self.instructions.push(LineInstruction::SetEpilogueBegin); + self.row.epilogue_begin = false; + } + + // Output fields that are not reset on every row. + if self.row.is_statement != self.prev_row.is_statement { + self.instructions.push(LineInstruction::NegateStatement); + } + if self.row.file != self.prev_row.file { + self.instructions + .push(LineInstruction::SetFile(self.row.file)); + } + if self.row.column != self.prev_row.column { + self.instructions + .push(LineInstruction::SetColumn(self.row.column)); + } + if self.row.isa != self.prev_row.isa { + self.instructions + .push(LineInstruction::SetIsa(self.row.isa)); + } + + // Advance the line, address, and operation index. + let line_base = i64::from(self.line_encoding.line_base) as u64; + let line_range = u64::from(self.line_encoding.line_range); + let line_advance = self.row.line as i64 - self.prev_row.line as i64; + let op_advance = self.op_advance(); + + // Default to special advances of 0. + let special_base = u64::from(OPCODE_BASE); + // TODO: handle lack of special opcodes for 0 line advance + debug_assert!(self.line_encoding.line_base <= 0); + debug_assert!(self.line_encoding.line_base + self.line_encoding.line_range as i8 >= 0); + let special_default = special_base.wrapping_sub(line_base); + let mut special = special_default; + let mut use_special = false; + + if line_advance != 0 { + let special_line = (line_advance as u64).wrapping_sub(line_base); + if special_line < line_range { + special = special_base + special_line; + use_special = true; + } else { + self.instructions + .push(LineInstruction::AdvanceLine(line_advance)); + } + } + + if op_advance != 0 { + // Using ConstAddPc can save a byte. + let (special_op_advance, const_add_pc) = if special + op_advance * line_range <= 255 { + (op_advance, false) + } else { + let op_range = (255 - special_base) / line_range; + (op_advance - op_range, true) + }; + + let special_op = special_op_advance * line_range; + if special + special_op <= 255 { + special += special_op; + use_special = true; + if const_add_pc { + self.instructions.push(LineInstruction::ConstAddPc); + } + } else { + self.instructions + .push(LineInstruction::AdvancePc(op_advance)); + } + } + + if use_special && special != special_default { + debug_assert!(special >= special_base); + debug_assert!(special <= 255); + self.instructions + .push(LineInstruction::Special(special as u8)); + } else { + self.instructions.push(LineInstruction::Copy); + } + + self.prev_row = self.row; + } + + fn op_advance(&self) -> u64 { + debug_assert!(self.row.address_offset >= self.prev_row.address_offset); + let mut address_advance = self.row.address_offset - self.prev_row.address_offset; + if self.line_encoding.minimum_instruction_length != 1 { + debug_assert_eq!( + self.row.address_offset % u64::from(self.line_encoding.minimum_instruction_length), + 0 + ); + address_advance /= u64::from(self.line_encoding.minimum_instruction_length); + } + address_advance * u64::from(self.line_encoding.maximum_operations_per_instruction) + + self.row.op_index + - self.prev_row.op_index + } + + /// Returns true if the line number program has no instructions. + /// + /// Does not check the file or directory entries. + #[inline] + pub fn is_empty(&self) -> bool { + self.instructions.is_empty() + } + + /// Write the line number program to the given section. + /// + /// # Panics + /// + /// Panics if `self.is_none()`. + pub fn write( + &self, + w: &mut DebugLine, + encoding: Encoding, + debug_line_str_offsets: &DebugLineStrOffsets, + debug_str_offsets: &DebugStrOffsets, + ) -> Result { + assert!(!self.is_none()); + + if encoding.version < self.version() + || encoding.format != self.format() + || encoding.address_size != self.address_size() + { + return Err(Error::IncompatibleLineProgramEncoding); + } + + let offset = w.offset(); + + let length_offset = w.write_initial_length(self.format())?; + let length_base = w.len(); + + if self.version() < 2 || self.version() > 5 { + return Err(Error::UnsupportedVersion(self.version())); + } + w.write_u16(self.version())?; + + if self.version() >= 5 { + w.write_u8(self.address_size())?; + // Segment selector size. + w.write_u8(0)?; + } + + let header_length_offset = w.len(); + w.write_udata(0, self.format().word_size())?; + let header_length_base = w.len(); + + w.write_u8(self.line_encoding.minimum_instruction_length)?; + if self.version() >= 4 { + w.write_u8(self.line_encoding.maximum_operations_per_instruction)?; + } else if self.line_encoding.maximum_operations_per_instruction != 1 { + return Err(Error::NeedVersion(4)); + }; + w.write_u8(if self.line_encoding.default_is_stmt { + 1 + } else { + 0 + })?; + w.write_u8(self.line_encoding.line_base as u8)?; + w.write_u8(self.line_encoding.line_range)?; + w.write_u8(OPCODE_BASE)?; + w.write(&[0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1])?; + + if self.version() <= 4 { + // The first directory is stored as DW_AT_comp_dir. + for dir in self.directories.iter().skip(1) { + dir.write( + w, + constants::DW_FORM_string, + self.encoding, + debug_line_str_offsets, + debug_str_offsets, + )?; + } + w.write_u8(0)?; + + for ((file, dir), info) in self.files.iter() { + file.write( + w, + constants::DW_FORM_string, + self.encoding, + debug_line_str_offsets, + debug_str_offsets, + )?; + w.write_uleb128(dir.0 as u64)?; + w.write_uleb128(info.timestamp)?; + w.write_uleb128(info.size)?; + } + w.write_u8(0)?; + } else { + // Directory entry formats (only ever 1). + w.write_u8(1)?; + w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?; + let dir_form = self.directories.get_index(0).unwrap().form(); + w.write_uleb128(dir_form.0.into())?; + + // Directory entries. + w.write_uleb128(self.directories.len() as u64)?; + for dir in self.directories.iter() { + dir.write( + w, + dir_form, + self.encoding, + debug_line_str_offsets, + debug_str_offsets, + )?; + } + + // File name entry formats. + let count = 2 + + if self.file_has_timestamp { 1 } else { 0 } + + if self.file_has_size { 1 } else { 0 } + + if self.file_has_md5 { 1 } else { 0 } + + if self.file_has_source { 1 } else { 0 }; + w.write_u8(count)?; + w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?; + let file_form = (self.files.get_index(0).unwrap().0).0.form(); + w.write_uleb128(file_form.0.into())?; + w.write_uleb128(u64::from(constants::DW_LNCT_directory_index.0))?; + w.write_uleb128(constants::DW_FORM_udata.0.into())?; + if self.file_has_timestamp { + w.write_uleb128(u64::from(constants::DW_LNCT_timestamp.0))?; + w.write_uleb128(constants::DW_FORM_udata.0.into())?; + } + if self.file_has_size { + w.write_uleb128(u64::from(constants::DW_LNCT_size.0))?; + w.write_uleb128(constants::DW_FORM_udata.0.into())?; + } + if self.file_has_md5 { + w.write_uleb128(u64::from(constants::DW_LNCT_MD5.0))?; + w.write_uleb128(constants::DW_FORM_data16.0.into())?; + } + let file_source_form = self + .files + .iter() + .find_map(|file| file.1.source.as_ref().map(LineString::form)) + .unwrap_or(constants::DW_FORM_string); + // Create a string to use for files with no source. + // Note: An empty DW_LNCT_LLVM_source is interpreted as missing + // source code. Included source code should always be + // terminated by a "\n" line ending. + let file_source_empty = match file_source_form { + // If any file source is set, then `get_empty` will succeed. + // If all are missing then `file_source_form` will be `DW_FORM_string`. + constants::DW_FORM_line_strp => debug_line_str_offsets + .get_empty() + .map(LineString::LineStringRef), + constants::DW_FORM_strp => debug_str_offsets.get_empty().map(LineString::StringRef), + _ => None, + } + .unwrap_or(LineString::String(Vec::new())); + if self.file_has_source { + w.write_uleb128(u64::from(constants::DW_LNCT_LLVM_source.0))?; + w.write_uleb128(file_source_form.0.into())?; + } + + // File name entries. + w.write_uleb128(self.files.len() as u64)?; + let mut write_file = |file: &LineString, dir: DirectoryId, info: &FileInfo| { + file.write( + w, + file_form, + self.encoding, + debug_line_str_offsets, + debug_str_offsets, + )?; + w.write_uleb128(dir.0 as u64)?; + if self.file_has_timestamp { + w.write_uleb128(info.timestamp)?; + } + if self.file_has_size { + w.write_uleb128(info.size)?; + } + if self.file_has_md5 { + w.write(&info.md5)?; + } + if self.file_has_source { + let source = info.source.as_ref().unwrap_or(&file_source_empty); + source.write( + w, + file_source_form, + self.encoding, + debug_line_str_offsets, + debug_str_offsets, + )?; + } + Ok(()) + }; + for ((file, dir), info) in self.files.iter() { + write_file(file, *dir, info)?; + } + } + + let header_length = (w.len() - header_length_base) as u64; + w.write_udata_at( + header_length_offset, + header_length, + self.format().word_size(), + )?; + + for instruction in &self.instructions { + instruction.write(w, self.encoding)?; + } + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, self.format())?; + + Ok(offset) + } +} + +/// A row in the line number table that corresponds to a machine instruction. +#[derive(Debug, Clone, Copy)] +pub struct LineRow { + /// The offset of the instruction from the start address of the sequence. + pub address_offset: u64, + /// The index of an operation within a VLIW instruction. + /// + /// The index of the first operation is 0. + /// Set to 0 for non-VLIW instructions. + pub op_index: u64, + + /// The source file corresponding to the instruction. + pub file: FileId, + /// The line number within the source file. + /// + /// Lines are numbered beginning at 1. Set to 0 if there is no source line. + pub line: u64, + /// The column number within the source line. + /// + /// Columns are numbered beginning at 1. Set to 0 for the "left edge" of the line. + pub column: u64, + /// An additional discriminator used to distinguish between source locations. + /// This value is assigned arbitrarily by the DWARF producer. + pub discriminator: u64, + + /// Set to true if the instruction is a recommended breakpoint for a statement. + pub is_statement: bool, + /// Set to true if the instruction is the beginning of a basic block. + pub basic_block: bool, + /// Set to true if the instruction is a recommended breakpoint at the entry of a + /// function. + pub prologue_end: bool, + /// Set to true if the instruction is a recommended breakpoint prior to the exit of + /// a function. + pub epilogue_begin: bool, + + /// The instruction set architecture of the instruction. + /// + /// Set to 0 for the default ISA. Other values are defined by the architecture ABI. + pub isa: u64, +} + +impl LineRow { + /// Return the initial state as specified in the DWARF standard. + fn initial_state(encoding: Encoding, line_encoding: LineEncoding) -> Self { + LineRow { + address_offset: 0, + op_index: 0, + + file: FileId::initial_state(encoding.version), + line: 1, + column: 0, + discriminator: 0, + + is_statement: line_encoding.default_is_stmt, + basic_block: false, + prologue_end: false, + epilogue_begin: false, + + isa: 0, + } + } +} + +/// An instruction in a line number program. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum LineInstruction { + // Special opcodes + Special(u8), + + // Standard opcodes + Copy, + AdvancePc(u64), + AdvanceLine(i64), + SetFile(FileId), + SetColumn(u64), + NegateStatement, + SetBasicBlock, + ConstAddPc, + // DW_LNS_fixed_advance_pc is not supported. + SetPrologueEnd, + SetEpilogueBegin, + SetIsa(u64), + + // Extended opcodes + EndSequence, + // TODO: this doubles the size of this enum. + SetAddress(Address), + // DW_LNE_define_file is not supported. + SetDiscriminator(u64), +} + +impl LineInstruction { + /// Write the line number instruction to the given section. + fn write(self, w: &mut DebugLine, encoding: Encoding) -> Result<()> { + use self::LineInstruction::*; + match self { + Special(val) => w.write_u8(val)?, + Copy => w.write_u8(constants::DW_LNS_copy.0)?, + AdvancePc(val) => { + w.write_u8(constants::DW_LNS_advance_pc.0)?; + w.write_uleb128(val)?; + } + AdvanceLine(val) => { + w.write_u8(constants::DW_LNS_advance_line.0)?; + w.write_sleb128(val)?; + } + SetFile(val) => { + w.write_u8(constants::DW_LNS_set_file.0)?; + w.write_uleb128(val.raw(encoding.version))?; + } + SetColumn(val) => { + w.write_u8(constants::DW_LNS_set_column.0)?; + w.write_uleb128(val)?; + } + NegateStatement => w.write_u8(constants::DW_LNS_negate_stmt.0)?, + SetBasicBlock => w.write_u8(constants::DW_LNS_set_basic_block.0)?, + ConstAddPc => w.write_u8(constants::DW_LNS_const_add_pc.0)?, + SetPrologueEnd => w.write_u8(constants::DW_LNS_set_prologue_end.0)?, + SetEpilogueBegin => w.write_u8(constants::DW_LNS_set_epilogue_begin.0)?, + SetIsa(val) => { + w.write_u8(constants::DW_LNS_set_isa.0)?; + w.write_uleb128(val)?; + } + EndSequence => { + w.write_u8(0)?; + w.write_uleb128(1)?; + w.write_u8(constants::DW_LNE_end_sequence.0)?; + } + SetAddress(address) => { + w.write_u8(0)?; + w.write_uleb128(1 + u64::from(encoding.address_size))?; + w.write_u8(constants::DW_LNE_set_address.0)?; + w.write_address(address, encoding.address_size)?; + } + SetDiscriminator(val) => { + let mut bytes = [0u8; 10]; + // bytes is long enough so this will never fail. + let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap(); + w.write_u8(0)?; + w.write_uleb128(1 + len as u64)?; + w.write_u8(constants::DW_LNE_set_discriminator.0)?; + w.write(&bytes[..len])?; + } + } + Ok(()) + } +} + +/// A string value for use in defining paths in line number programs. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum LineString { + /// A slice of bytes representing a string. Must not include null bytes. + /// Not guaranteed to be UTF-8 or anything like that. + String(Vec), + + /// A reference to a string in the `.debug_str` section. + StringRef(StringId), + + /// A reference to a string in the `.debug_line_str` section. + LineStringRef(LineStringId), +} + +impl LineString { + /// Create a `LineString` using the normal form for the given encoding. + pub fn new(val: T, encoding: Encoding, line_strings: &mut LineStringTable) -> Self + where + T: Into>, + { + let val = val.into(); + if encoding.version <= 4 { + LineString::String(val) + } else { + LineString::LineStringRef(line_strings.add(val)) + } + } + + /// Get a reference to the string data. + pub fn get<'a>( + &'a self, + strings: &'a StringTable, + line_strings: &'a LineStringTable, + ) -> &'a [u8] { + match self { + LineString::String(val) => val, + LineString::StringRef(val) => strings.get(*val), + LineString::LineStringRef(val) => line_strings.get(*val), + } + } + + fn form(&self) -> constants::DwForm { + match *self { + LineString::String(..) => constants::DW_FORM_string, + LineString::StringRef(..) => constants::DW_FORM_strp, + LineString::LineStringRef(..) => constants::DW_FORM_line_strp, + } + } + + fn write( + &self, + w: &mut DebugLine, + form: constants::DwForm, + encoding: Encoding, + debug_line_str_offsets: &DebugLineStrOffsets, + debug_str_offsets: &DebugStrOffsets, + ) -> Result<()> { + if form != self.form() { + return Err(Error::LineStringFormMismatch); + } + + match *self { + LineString::String(ref val) => { + if encoding.version <= 4 { + debug_assert!(!val.is_empty()); + } + w.write(val)?; + w.write_u8(0)?; + } + LineString::StringRef(val) => { + if encoding.version < 5 { + return Err(Error::NeedVersion(5)); + } + w.write_offset( + debug_str_offsets.get(val).0, + SectionId::DebugStr, + encoding.format.word_size(), + )?; + } + LineString::LineStringRef(val) => { + if encoding.version < 5 { + return Err(Error::NeedVersion(5)); + } + w.write_offset( + debug_line_str_offsets.get(val).0, + SectionId::DebugLineStr, + encoding.format.word_size(), + )?; + } + } + Ok(()) + } +} + +/// An identifier for a directory in a `LineProgram`. +/// +/// Defaults to the working directory of the compilation unit. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct DirectoryId(usize); + +// Force FileId access via the methods. +mod id { + /// An identifier for a file in a `LineProgram`. + // + // We internally use a 0-based index for all versions, but + // emit a 1-based index for DWARF version <= 4. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct FileId(usize); + + impl FileId { + /// Create a `FileId` given a 0-based index into `LineProgram::files`. + pub(crate) fn new(index: usize) -> Self { + FileId(index) + } + + /// The 0-based index of the file in `LineProgram::files`. + pub(super) fn index(self) -> usize { + self.0 + } + + /// The initial state of the file register. + pub(super) fn initial_state(version: u16) -> Self { + if version == 5 { + // For version 5, the files are 0-based and the default file is 1, + // which is a 0-based index of 1. + FileId(1) + } else { + // For version <= 4, the files are 1-based and the default file is 1, + // which is a 0-based index of 0. + // For version >= 6, the files are 0-based and the default file is 0, + // which is a 0-based index of 0. + FileId(0) + } + } + + /// Convert to a raw value used for writing. + /// + /// This converts to a 1-based index for DWARF version <= 4. + pub(crate) fn raw(self, version: u16) -> u64 { + if version <= 4 { + self.0 as u64 + 1 + } else { + self.0 as u64 + } + } + } +} +pub use self::id::*; + +/// Extra information for file in a `LineProgram`. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct FileInfo { + /// The implementation defined timestamp of the last modification of the file, + /// or 0 if not available. + pub timestamp: u64, + + /// The size of the file in bytes, or 0 if not available. + pub size: u64, + + /// A 16-byte MD5 digest of the file contents. + /// + /// Only used if version >= 5 and `LineProgram::file_has_md5` is `true`. + pub md5: [u8; 16], + + /// Optionally some embedded sourcecode. + /// + /// Only used if version >= 5 and `LineProgram::file_has_source` is `true`. + pub source: Option, +} + +define_section!( + DebugLine, + DebugLineOffset, + "A writable `.debug_line` section." +); + +#[cfg(feature = "read")] +mod convert { + use super::*; + use crate::read::{self, Reader}; + use crate::write::{self, ConvertError, ConvertResult}; + + impl LineProgram { + /// Create a line number program by reading the data from the given program. + /// + /// Return the program and a mapping from file index to `FileId`. + pub fn from>( + mut from_program: read::IncompleteLineProgram, + dwarf: &read::Dwarf, + line_strings: &mut write::LineStringTable, + strings: &mut write::StringTable, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult<(LineProgram, Vec)> { + // Create mappings in case the source has duplicate files or directories. + let mut dirs = Vec::new(); + let mut files = Vec::new(); + + let mut program = { + let from_header = from_program.header(); + let encoding = from_header.encoding(); + + let working_dir = match from_header.directory(0) { + Some(working_dir) => { + LineString::from(working_dir, dwarf, line_strings, strings)? + } + None => LineString::new(&[][..], encoding, line_strings), + }; + + let (source_dir, source_file) = match from_header.file(0) { + Some(source_file) => { + let source_dir_index = source_file.directory_index(); + let source_dir = if source_dir_index != 0 { + match from_header.directory(source_dir_index) { + Some(source_dir) => Some(LineString::from( + source_dir, + dwarf, + line_strings, + strings, + )?), + None => return Err(ConvertError::InvalidDirectoryIndex), + } + } else { + None + }; + let source_file = LineString::from( + source_file.path_name(), + dwarf, + line_strings, + strings, + )?; + (source_dir, source_file) + } + None => (None, LineString::new(&[][..], encoding, line_strings)), + }; + + if from_header.line_base() > 0 { + return Err(ConvertError::InvalidLineBase); + } + let mut program = LineProgram::new( + encoding, + from_header.line_encoding(), + working_dir, + source_dir, + source_file, + None, // We'll set this later if needed when we add the file again. + ); + + if from_header.version() <= 4 { + // The first directory is implicit. + dirs.push(DirectoryId(0)); + // A file index of 0 is invalid for version <= 4, but putting + // something there makes the indexing easier. + files.push(FileId::new(0)); + } + + for from_dir in from_header.include_directories() { + let from_dir = + LineString::from(from_dir.clone(), dwarf, line_strings, strings)?; + dirs.push(program.add_directory(from_dir)); + } + + program.file_has_timestamp = from_header.file_has_timestamp(); + program.file_has_size = from_header.file_has_size(); + program.file_has_md5 = from_header.file_has_md5(); + program.file_has_source = from_header.file_has_source(); + for from_file in from_header.file_names().iter() { + let from_name = + LineString::from(from_file.path_name(), dwarf, line_strings, strings)?; + let from_dir = from_file.directory_index(); + if from_dir >= dirs.len() as u64 { + return Err(ConvertError::InvalidDirectoryIndex); + } + let from_dir = dirs[from_dir as usize]; + let from_info = Some(FileInfo { + timestamp: from_file.timestamp(), + size: from_file.size(), + md5: *from_file.md5(), + source: match from_file.source() { + Some(source) => { + Some(LineString::from(source, dwarf, line_strings, strings)?) + } + None => None, + }, + }); + files.push(program.add_file(from_name, from_dir, from_info)); + } + + program + }; + + // We can't use the `from_program.rows()` because that wouldn't let + // us preserve address relocations. + let mut from_row = read::LineRow::new(from_program.header()); + let mut instructions = from_program.header().instructions(); + let mut address = None; + while let Some(instruction) = instructions.next_instruction(from_program.header())? { + match instruction { + read::LineInstruction::SetAddress(val) => { + if program.in_sequence() { + return Err(ConvertError::UnsupportedLineInstruction); + } + match convert_address(val) { + Some(val) => address = Some(val), + None => return Err(ConvertError::InvalidAddress), + } + from_row + .execute(read::LineInstruction::SetAddress(0), &mut from_program)?; + } + read::LineInstruction::DefineFile(_) => { + return Err(ConvertError::UnsupportedLineInstruction); + } + _ => { + if from_row.execute(instruction, &mut from_program)? { + if !program.in_sequence() { + program.begin_sequence(address); + address = None; + } + if from_row.end_sequence() { + program.end_sequence(from_row.address()); + } else { + program.row().address_offset = from_row.address(); + program.row().op_index = from_row.op_index(); + program.row().file = { + let file = from_row.file_index(); + if file >= files.len() as u64 { + return Err(ConvertError::InvalidFileIndex); + } + if file == 0 && program.version() <= 4 { + return Err(ConvertError::InvalidFileIndex); + } + files[file as usize] + }; + program.row().line = match from_row.line() { + Some(line) => line.get(), + None => 0, + }; + program.row().column = match from_row.column() { + read::ColumnType::LeftEdge => 0, + read::ColumnType::Column(val) => val.get(), + }; + program.row().discriminator = from_row.discriminator(); + program.row().is_statement = from_row.is_stmt(); + program.row().basic_block = from_row.basic_block(); + program.row().prologue_end = from_row.prologue_end(); + program.row().epilogue_begin = from_row.epilogue_begin(); + program.row().isa = from_row.isa(); + program.generate_row(); + } + from_row.reset(from_program.header()); + } + } + }; + } + Ok((program, files)) + } + } + + impl LineString { + fn from>( + from_attr: read::AttributeValue, + dwarf: &read::Dwarf, + line_strings: &mut write::LineStringTable, + strings: &mut write::StringTable, + ) -> ConvertResult { + Ok(match from_attr { + read::AttributeValue::String(r) => LineString::String(r.to_slice()?.to_vec()), + read::AttributeValue::DebugStrRef(offset) => { + let r = dwarf.debug_str.get_str(offset)?; + let id = strings.add(r.to_slice()?); + LineString::StringRef(id) + } + read::AttributeValue::DebugLineStrRef(offset) => { + let r = dwarf.debug_line_str.get_str(offset)?; + let id = line_strings.add(r.to_slice()?); + LineString::LineStringRef(id) + } + _ => return Err(ConvertError::UnsupportedLineStringForm), + }) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::read; + use crate::write::{AttributeValue, Dwarf, EndianVec, Sections, Unit}; + use crate::LittleEndian; + + #[test] + fn test_line_program() { + let dir1 = LineString::String(b"dir1".to_vec()); + let file1 = LineString::String(b"file1".to_vec()); + let dir2 = LineString::String(b"dir2".to_vec()); + let file2 = LineString::String(b"file2".to_vec()); + + let mut dwarf = Dwarf::new(); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + dir1.clone(), + None, + file1.clone(), + None, + ); + + assert_eq!(&dir1, program.get_directory(program.default_directory())); + program.file_has_timestamp = true; + program.file_has_size = true; + if encoding.version >= 5 { + program.file_has_md5 = true; + } + + // Note: Embedded source code is an accepted extension + // that will become part of DWARF v6. We're using the LLVM extension + // here for v5. + if encoding.version >= 5 { + program.file_has_source = true; + } + + let dir_id = program.add_directory(dir2.clone()); + assert_eq!(&dir2, program.get_directory(dir_id)); + assert_eq!(dir_id, program.add_directory(dir2.clone())); + + let file_info = FileInfo { + timestamp: 1, + size: 2, + md5: if encoding.version >= 5 { + [3; 16] + } else { + [0; 16] + }, + source: (encoding.version >= 5) + .then(|| LineString::String(b"the source code\n".to_vec())), + }; + let file_id = program.add_file(file2.clone(), dir_id, Some(file_info.clone())); + assert_eq!((&file2, dir_id), program.get_file(file_id)); + assert_eq!(file_info, *program.get_file_info(file_id)); + + program.get_file_info_mut(file_id).size = 3; + assert_ne!(file_info, *program.get_file_info(file_id)); + assert_eq!(file_id, program.add_file(file2.clone(), dir_id, None)); + assert_ne!(file_info, *program.get_file_info(file_id)); + assert_eq!( + file_id, + program.add_file(file2.clone(), dir_id, Some(file_info.clone())) + ); + assert_eq!(file_info, *program.get_file_info(file_id)); + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set( + constants::DW_AT_comp_dir, + AttributeValue::String(b"dir1".to_vec()), + ); + root.set( + constants::DW_AT_name, + AttributeValue::String(b"file1".to_vec()), + ); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + root.set( + constants::DW_AT_decl_file, + AttributeValue::FileIndex(Some(file_id)), + ); + + dwarf.units.add(unit); + } + } + } + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + let read_dwarf = sections.read(LittleEndian); + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap(); + + let mut convert_units = convert_dwarf.units.iter(); + for (_, unit) in dwarf.units.iter() { + let program = &unit.line_program; + let root = unit.get(unit.root()); + let Some(AttributeValue::FileIndex(Some(file_id))) = + root.get(constants::DW_AT_decl_file) + else { + panic!("missing DW_AT_decl_file"); + }; + + let (_, convert_unit) = convert_units.next().unwrap(); + let convert_program = &convert_unit.line_program; + let convert_root = convert_unit.get(convert_unit.root()); + let Some(AttributeValue::FileIndex(Some(convert_file_id))) = + convert_root.get(constants::DW_AT_decl_file) + else { + panic!("missing DW_AT_decl_file"); + }; + + assert_eq!(convert_program.version(), program.version()); + assert_eq!(convert_program.address_size(), program.address_size()); + assert_eq!(convert_program.format(), program.format()); + + let (file, dir) = program.get_file(*file_id); + let (convert_file, convert_dir) = convert_program.get_file(*convert_file_id); + assert_eq!(file, convert_file); + assert_eq!( + program.get_directory(dir), + convert_program.get_directory(convert_dir) + ); + assert_eq!( + program.get_file_info(*file_id), + convert_program.get_file_info(*convert_file_id) + ); + } + } + + #[test] + fn test_line_row() { + let dir1 = &b"dir1"[..]; + let file1 = &b"file1"[..]; + let file2 = &b"file2"[..]; + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let line_base = -5; + let line_range = 14; + let neg_line_base = (-line_base) as u8; + let mut program = LineProgram::new( + encoding, + LineEncoding { + line_base, + line_range, + ..Default::default() + }, + LineString::String(dir1.to_vec()), + None, + LineString::String(file1.to_vec()), + None, + ); + let dir_id = program.default_directory(); + let file1_id = + program.add_file(LineString::String(file1.to_vec()), dir_id, None); + let file2_id = + program.add_file(LineString::String(file2.to_vec()), dir_id, None); + + // Test sequences. + { + let mut program = program.clone(); + let address = Address::Constant(0x12); + program.begin_sequence(Some(address)); + assert_eq!( + program.instructions, + vec![LineInstruction::SetAddress(address)] + ); + } + + { + let mut program = program.clone(); + program.begin_sequence(None); + assert_eq!(program.instructions, Vec::new()); + } + + { + let mut program = program.clone(); + program.begin_sequence(None); + program.end_sequence(0x1234); + assert_eq!( + program.instructions, + vec![ + LineInstruction::AdvancePc(0x1234), + LineInstruction::EndSequence + ] + ); + } + + // Create a base program. + program.begin_sequence(None); + program.row.line = 0x1000; + program.generate_row(); + let base_row = program.row; + let base_instructions = program.instructions.clone(); + + // Create test cases. + let mut tests = Vec::new(); + + let row = base_row; + tests.push((row, vec![LineInstruction::Copy])); + + let mut row = base_row; + row.line -= u64::from(neg_line_base); + tests.push((row, vec![LineInstruction::Special(OPCODE_BASE)])); + + let mut row = base_row; + row.line += u64::from(line_range) - 1; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![LineInstruction::Special(OPCODE_BASE + line_range - 1)], + )); + + let mut row = base_row; + row.line += u64::from(line_range); + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![ + LineInstruction::AdvanceLine(i64::from(line_range - neg_line_base)), + LineInstruction::Copy, + ], + )); + + let mut row = base_row; + row.address_offset = 1; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![LineInstruction::Special(OPCODE_BASE + line_range)], + )); + + let op_range = (255 - OPCODE_BASE) / line_range; + let mut row = base_row; + row.address_offset = u64::from(op_range); + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![LineInstruction::Special( + OPCODE_BASE + op_range * line_range, + )], + )); + + let mut row = base_row; + row.address_offset = u64::from(op_range); + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range); + row.line -= u64::from(neg_line_base); + tests.push((row, vec![LineInstruction::Special(255)])); + + let mut row = base_row; + row.address_offset = u64::from(op_range); + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 1; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![LineInstruction::ConstAddPc, LineInstruction::Copy], + )); + + let mut row = base_row; + row.address_offset = u64::from(op_range); + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 2; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![ + LineInstruction::ConstAddPc, + LineInstruction::Special(OPCODE_BASE + 6), + ], + )); + + let mut row = base_row; + row.address_offset = u64::from(op_range) * 2; + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range); + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![LineInstruction::ConstAddPc, LineInstruction::Special(255)], + )); + + let mut row = base_row; + row.address_offset = u64::from(op_range) * 2; + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 1; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![ + LineInstruction::AdvancePc(row.address_offset), + LineInstruction::Copy, + ], + )); + + let mut row = base_row; + row.address_offset = u64::from(op_range) * 2; + row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 2; + row.line -= u64::from(neg_line_base); + tests.push(( + row, + vec![ + LineInstruction::AdvancePc(row.address_offset), + LineInstruction::Special(OPCODE_BASE + 6), + ], + )); + + let mut row = base_row; + row.address_offset = 0x1234; + tests.push(( + row, + vec![LineInstruction::AdvancePc(0x1234), LineInstruction::Copy], + )); + + let mut row = base_row; + row.line += 0x1234; + tests.push(( + row, + vec![LineInstruction::AdvanceLine(0x1234), LineInstruction::Copy], + )); + + let mut row = base_row; + row.file = file1_id; + if version == 5 { + // Version 5 is 0-based, but the default file is 1, so this row + // will need to set the file. + tests.push(( + row, + vec![LineInstruction::SetFile(file1_id), LineInstruction::Copy], + )); + } else { + // This is the first file, so normally this is already the default. + tests.push((row, vec![LineInstruction::Copy])); + } + + let mut row = base_row; + row.file = file2_id; + if version == 5 { + tests.push((row, vec![LineInstruction::Copy])); + } else { + tests.push(( + row, + vec![LineInstruction::SetFile(file2_id), LineInstruction::Copy], + )); + } + + let mut row = base_row; + row.column = 0x1234; + tests.push(( + row, + vec![LineInstruction::SetColumn(0x1234), LineInstruction::Copy], + )); + + let mut row = base_row; + row.discriminator = 0x1234; + tests.push(( + row, + vec![ + LineInstruction::SetDiscriminator(0x1234), + LineInstruction::Copy, + ], + )); + + let mut row = base_row; + row.is_statement = !row.is_statement; + tests.push(( + row, + vec![LineInstruction::NegateStatement, LineInstruction::Copy], + )); + + let mut row = base_row; + row.basic_block = true; + tests.push(( + row, + vec![LineInstruction::SetBasicBlock, LineInstruction::Copy], + )); + + let mut row = base_row; + row.prologue_end = true; + tests.push(( + row, + vec![LineInstruction::SetPrologueEnd, LineInstruction::Copy], + )); + + let mut row = base_row; + row.epilogue_begin = true; + tests.push(( + row, + vec![LineInstruction::SetEpilogueBegin, LineInstruction::Copy], + )); + + let mut row = base_row; + row.isa = 0x1234; + tests.push(( + row, + vec![LineInstruction::SetIsa(0x1234), LineInstruction::Copy], + )); + + for test in tests { + // Test generate_row(). + let mut program = program.clone(); + program.row = test.0; + program.generate_row(); + assert_eq!( + &program.instructions[base_instructions.len()..], + &test.1[..] + ); + + // Test LineProgram::from(). + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + let read_dwarf = sections.read(LittleEndian); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + let convert_unit = convert_dwarf.units.iter().next().unwrap().1; + let convert_program = &convert_unit.line_program; + + assert_eq!( + &convert_program.instructions[base_instructions.len()..], + &test.1[..] + ); + } + } + } + } + } + + #[test] + fn test_line_instruction() { + let dir1 = &b"dir1"[..]; + let file1 = &b"file1"[..]; + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(dir1.to_vec()), + None, + LineString::String(file1.to_vec()), + None, + ); + let dir_id = program.default_directory(); + let file_id = + program.add_file(LineString::String(file1.to_vec()), dir_id, None); + + for (inst, expect_inst) in &[ + ( + LineInstruction::Special(OPCODE_BASE), + read::LineInstruction::Special(OPCODE_BASE), + ), + ( + LineInstruction::Special(255), + read::LineInstruction::Special(255), + ), + (LineInstruction::Copy, read::LineInstruction::Copy), + ( + LineInstruction::AdvancePc(0x12), + read::LineInstruction::AdvancePc(0x12), + ), + ( + LineInstruction::AdvanceLine(0x12), + read::LineInstruction::AdvanceLine(0x12), + ), + ( + LineInstruction::SetFile(file_id), + read::LineInstruction::SetFile(file_id.raw(encoding.version)), + ), + ( + LineInstruction::SetColumn(0x12), + read::LineInstruction::SetColumn(0x12), + ), + ( + LineInstruction::NegateStatement, + read::LineInstruction::NegateStatement, + ), + ( + LineInstruction::SetBasicBlock, + read::LineInstruction::SetBasicBlock, + ), + ( + LineInstruction::ConstAddPc, + read::LineInstruction::ConstAddPc, + ), + ( + LineInstruction::SetPrologueEnd, + read::LineInstruction::SetPrologueEnd, + ), + ( + LineInstruction::SetEpilogueBegin, + read::LineInstruction::SetEpilogueBegin, + ), + ( + LineInstruction::SetIsa(0x12), + read::LineInstruction::SetIsa(0x12), + ), + ( + LineInstruction::EndSequence, + read::LineInstruction::EndSequence, + ), + ( + LineInstruction::SetAddress(Address::Constant(0x12)), + read::LineInstruction::SetAddress(0x12), + ), + ( + LineInstruction::SetDiscriminator(0x12), + read::LineInstruction::SetDiscriminator(0x12), + ), + ][..] + { + let mut program = program.clone(); + program.instructions.push(*inst); + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let read_unit_header = read_dwarf.units().next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let read_header = read_unit.line_program.as_ref().unwrap().header(); + let mut read_insts = read_header.instructions(); + assert_eq!( + *expect_inst, + read_insts.next_instruction(read_header).unwrap().unwrap() + ); + assert_eq!(None, read_insts.next_instruction(read_header).unwrap()); + } + } + } + } + } + + // Test that the address/line advance is correct. We don't test for optimality. + #[test] + fn test_advance() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 8, + }; + + let dir1 = &b"dir1"[..]; + let file1 = &b"file1"[..]; + + let addresses = 0..50; + let lines = -10..25i64; + + for minimum_instruction_length in [1, 4] { + for maximum_operations_per_instruction in [1, 3] { + for line_base in [-5, 0] { + for line_range in [10, 20] { + let line_encoding = LineEncoding { + minimum_instruction_length, + maximum_operations_per_instruction, + line_base, + line_range, + default_is_stmt: true, + }; + let mut program = LineProgram::new( + encoding, + line_encoding, + LineString::String(dir1.to_vec()), + None, + LineString::String(file1.to_vec()), + None, + ); + for address_advance in addresses.clone() { + program.begin_sequence(Some(Address::Constant(0x1000))); + program.row().line = 0x10000; + program.generate_row(); + for line_advance in lines.clone() { + { + let row = program.row(); + row.address_offset += + address_advance * u64::from(minimum_instruction_length); + row.line = row.line.wrapping_add(line_advance as u64); + } + program.generate_row(); + } + let address_offset = program.row().address_offset + + u64::from(minimum_instruction_length); + program.end_sequence(address_offset); + } + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let read_unit_header = read_dwarf.units().next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let read_program = read_unit.line_program.clone().unwrap(); + + let mut rows = read_program.rows(); + for address_advance in addresses.clone() { + let mut address; + let mut line; + { + let row = rows.next_row().unwrap().unwrap().1; + address = row.address(); + line = row.line().unwrap().get(); + } + assert_eq!(address, 0x1000); + assert_eq!(line, 0x10000); + for line_advance in lines.clone() { + let row = rows.next_row().unwrap().unwrap().1; + assert_eq!( + row.address() - address, + address_advance * u64::from(minimum_instruction_length) + ); + assert_eq!( + (row.line().unwrap().get() as i64) - (line as i64), + line_advance + ); + address = row.address(); + line = row.line().unwrap().get(); + } + let row = rows.next_row().unwrap().unwrap().1; + assert!(row.end_sequence()); + } + } + } + } + } + } + + #[test] + fn test_line_string() { + let version = 5; + + let file1 = "file1"; + + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let files: &mut [&mut dyn Fn(&mut Dwarf) -> LineString] = &mut [ + &mut |_dwarf| LineString::String(file1.as_bytes().to_vec()), + &mut |dwarf| LineString::StringRef(dwarf.strings.add(file1)), + &mut |dwarf| LineString::LineStringRef(dwarf.line_strings.add(file1)), + ]; + + for file in files { + let mut dwarf = Dwarf::new(); + let file = file(&mut dwarf); + + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(b"dir".to_vec()), + None, + file.clone(), + None, + ); + program.begin_sequence(Some(Address::Constant(0x1000))); + program.row().line = 0x10000; + program.generate_row(); + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let read_unit_header = read_dwarf.units().next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let read_program = read_unit.line_program.clone().unwrap(); + let read_header = read_program.header(); + let read_file = read_header.file(0).unwrap(); + let read_path = read_unit.attr_string(read_file.path_name()).unwrap(); + assert_eq!(read_path.slice(), file1.as_bytes()); + } + } + } + } + + #[test] + fn test_missing_comp_dir() { + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(Vec::new()), + None, + LineString::String(Vec::new()), + None, + ); + // Ensure the program is not empty. + let dir_id = program.default_directory(); + let file_id = + program.add_file(LineString::String(b"file1".to_vec()), dir_id, None); + program.begin_sequence(Some(Address::Constant(0x1000))); + program.row().file = file_id; + program.row().line = 0x10000; + program.generate_row(); + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + // Testing missing DW_AT_comp_dir/DW_AT_name. + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + let read_dwarf = sections.read(LittleEndian); + let _convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + } + } + } + } + + #[test] + fn test_separate_working_dir() { + let working_dir = LineString::String(b"working".to_vec()); + let source_dir = LineString::String(b"source".to_vec()); + let source_file = LineString::String(b"file".to_vec()); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + working_dir.clone(), + Some(source_dir.clone()), + source_file.clone(), + None, + ); + + assert_eq!( + &working_dir, + program.get_directory(program.default_directory()) + ); + + // Ensure the program is not empty. + let dir_id = program.add_directory(source_dir.clone()); + let file_id = program.add_file(source_file.clone(), dir_id, None); + program.begin_sequence(Some(Address::Constant(0x1000))); + program.row().file = file_id; + program.row().line = 0x10000; + program.generate_row(); + + // Test LineProgram::from(). + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set( + constants::DW_AT_comp_dir, + AttributeValue::String(b"working".to_vec()), + ); + root.set( + constants::DW_AT_name, + AttributeValue::String(b"source/file".to_vec()), + ); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + let read_dwarf = sections.read(LittleEndian); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + let convert_unit = convert_dwarf.units.iter().next().unwrap().1; + let convert_program = &convert_unit.line_program; + + assert_eq!( + &working_dir, + convert_program.get_directory(convert_program.default_directory()) + ); + let (_file_id, file, dir_id) = convert_program.files().next().unwrap(); + assert_eq!(&source_file, file); + assert_eq!(&source_dir, convert_program.get_directory(dir_id)); + } + } + } + } + + #[test] + fn test_file_source() { + let version = 5; + + let source1 = "source1"; + + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let sources: &mut [&mut dyn Fn(&mut Dwarf) -> LineString] = &mut [ + &mut |_dwarf| LineString::String(source1.as_bytes().to_vec()), + &mut |dwarf| LineString::StringRef(dwarf.strings.add(source1)), + &mut |dwarf| LineString::LineStringRef(dwarf.line_strings.add(source1)), + ]; + + for source in sources { + let mut dwarf = Dwarf::new(); + let source = Some(source(&mut dwarf)); + + let mut program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(b"dir".to_vec()), + None, + LineString::String(b"file".to_vec()), + Some(FileInfo { + timestamp: 0, + size: 0, + md5: [0; 16], + source, + }), + ); + program.file_has_source = true; + + let file_id = program.files().next().unwrap().0; + program.begin_sequence(Some(Address::Constant(0x1000))); + program.row().file = file_id; + program.row().line = 0x10000; + program.generate_row(); + + let mut unit = Unit::new(encoding, program); + let root = unit.get_mut(unit.root()); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let read_unit_header = read_dwarf.units().next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let read_program = read_unit.line_program.clone().unwrap(); + let read_header = read_program.header(); + let read_file = read_header.file(0).unwrap(); + let read_source = read_unit.attr_string(read_file.source().unwrap()).unwrap(); + assert_eq!(read_source.slice(), source1.as_bytes()); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + let (_, convert_unit) = convert_dwarf.units.iter().next().unwrap(); + let convert_program = &convert_unit.line_program; + let convert_file_id = convert_program.files().next().unwrap().0; + let convert_file_info = convert_program.get_file_info(convert_file_id); + assert_eq!( + convert_dwarf.get_line_string(convert_file_info.source.as_ref().unwrap()), + source1.as_bytes(), + ); + } + } + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/loc.rs b/anneal/v2/vendor/gimli/src/write/loc.rs new file mode 100644 index 0000000000..7f67d197b0 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/loc.rs @@ -0,0 +1,561 @@ +use alloc::vec::Vec; +use indexmap::IndexSet; +use std::ops::{Deref, DerefMut}; + +use crate::common::{Encoding, LocationListsOffset, SectionId}; +use crate::write::{ + Address, BaseId, DebugInfoReference, Error, Expression, Result, Section, Sections, UnitOffsets, + Writer, +}; + +define_section!( + DebugLoc, + LocationListsOffset, + "A writable `.debug_loc` section." +); +define_section!( + DebugLocLists, + LocationListsOffset, + "A writable `.debug_loclists` section." +); + +define_offsets!( + LocationListOffsets: LocationListId => LocationListsOffset, + "The section offsets of a series of location lists within the `.debug_loc` or `.debug_loclists` sections." +); + +define_id!( + LocationListId, + "An identifier for a location list in a `LocationListTable`." +); + +/// A table of location lists that will be stored in a `.debug_loc` or `.debug_loclists` section. +#[derive(Debug, Default)] +pub struct LocationListTable { + base_id: BaseId, + locations: IndexSet, +} + +impl LocationListTable { + /// Add a location list to the table. + pub fn add(&mut self, loc_list: LocationList) -> LocationListId { + let (index, _) = self.locations.insert_full(loc_list); + LocationListId::new(self.base_id, index) + } + + /// Get a reference to a location list. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get(&self, id: LocationListId) -> &LocationList { + debug_assert_eq!(self.base_id, id.base_id); + &self.locations[id.index] + } + + /// Write the location list table to the appropriate section for the given DWARF version. + pub(crate) fn write( + &self, + sections: &mut Sections, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + ) -> Result { + if self.locations.is_empty() { + return Ok(LocationListOffsets::none()); + } + + match encoding.version { + 2..=4 => self.write_loc( + &mut sections.debug_loc, + &mut sections.debug_loc_refs, + encoding, + unit_offsets, + ), + 5 => self.write_loclists( + &mut sections.debug_loclists, + &mut sections.debug_loclists_refs, + encoding, + unit_offsets, + ), + _ => Err(Error::UnsupportedVersion(encoding.version)), + } + } + + /// Write the location list table to the `.debug_loc` section. + fn write_loc( + &self, + w: &mut DebugLoc, + refs: &mut Vec, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + ) -> Result { + let address_size = encoding.address_size; + let mut offsets = Vec::new(); + for loc_list in self.locations.iter() { + offsets.push(w.offset()); + for loc in &loc_list.0 { + // Note that we must ensure none of the ranges have both begin == 0 and end == 0. + // We do this by ensuring that begin != end, which is a bit more restrictive + // than required, but still seems reasonable. + match *loc { + Location::BaseAddress { address } => { + let marker = !0 >> (64 - address_size * 8); + w.write_udata(marker, address_size)?; + w.write_address(address, address_size)?; + } + Location::OffsetPair { + begin, + end, + ref data, + } => { + if begin == end { + return Err(Error::InvalidRange); + } + w.write_udata(begin, address_size)?; + w.write_udata(end, address_size)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::StartEnd { + begin, + end, + ref data, + } => { + if begin == end { + return Err(Error::InvalidRange); + } + w.write_address(begin, address_size)?; + w.write_address(end, address_size)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::StartLength { + begin, + length, + ref data, + } => { + let end = match begin { + Address::Constant(begin) => Address::Constant(begin + length), + Address::Symbol { symbol, addend } => Address::Symbol { + symbol, + addend: addend + length as i64, + }, + }; + if begin == end { + return Err(Error::InvalidRange); + } + w.write_address(begin, address_size)?; + w.write_address(end, address_size)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::DefaultLocation { .. } => { + return Err(Error::InvalidRange); + } + } + } + w.write_udata(0, address_size)?; + w.write_udata(0, address_size)?; + } + Ok(LocationListOffsets { + base_id: self.base_id, + offsets, + }) + } + + /// Write the location list table to the `.debug_loclists` section. + fn write_loclists( + &self, + w: &mut DebugLocLists, + refs: &mut Vec, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + ) -> Result { + let mut offsets = Vec::new(); + + if encoding.version != 5 { + return Err(Error::NeedVersion(5)); + } + + let length_offset = w.write_initial_length(encoding.format)?; + let length_base = w.len(); + + w.write_u16(encoding.version)?; + w.write_u8(encoding.address_size)?; + w.write_u8(0)?; // segment_selector_size + w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28) + // FIXME implement DW_FORM_rnglistx writing and implement the offset entry list + + for loc_list in self.locations.iter() { + offsets.push(w.offset()); + for loc in &loc_list.0 { + match *loc { + Location::BaseAddress { address } => { + w.write_u8(crate::constants::DW_LLE_base_address.0)?; + w.write_address(address, encoding.address_size)?; + } + Location::OffsetPair { + begin, + end, + ref data, + } => { + w.write_u8(crate::constants::DW_LLE_offset_pair.0)?; + w.write_uleb128(begin)?; + w.write_uleb128(end)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::StartEnd { + begin, + end, + ref data, + } => { + w.write_u8(crate::constants::DW_LLE_start_end.0)?; + w.write_address(begin, encoding.address_size)?; + w.write_address(end, encoding.address_size)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::StartLength { + begin, + length, + ref data, + } => { + w.write_u8(crate::constants::DW_LLE_start_length.0)?; + w.write_address(begin, encoding.address_size)?; + w.write_uleb128(length)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + Location::DefaultLocation { ref data } => { + w.write_u8(crate::constants::DW_LLE_default_location.0)?; + write_expression(&mut w.0, refs, encoding, unit_offsets, data)?; + } + } + } + + w.write_u8(crate::constants::DW_LLE_end_of_list.0)?; + } + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, encoding.format)?; + + Ok(LocationListOffsets { + base_id: self.base_id, + offsets, + }) + } +} + +/// A locations list that will be stored in a `.debug_loc` or `.debug_loclists` section. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct LocationList(pub Vec); + +/// A single location. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum Location { + /// DW_LLE_base_address + BaseAddress { + /// Base address. + address: Address, + }, + /// DW_LLE_offset_pair + OffsetPair { + /// Start of range relative to base address. + begin: u64, + /// End of range relative to base address. + end: u64, + /// Location description. + data: Expression, + }, + /// DW_LLE_start_end + StartEnd { + /// Start of range. + begin: Address, + /// End of range. + end: Address, + /// Location description. + data: Expression, + }, + /// DW_LLE_start_length + StartLength { + /// Start of range. + begin: Address, + /// Length of range. + length: u64, + /// Location description. + data: Expression, + }, + /// DW_LLE_default_location + DefaultLocation { + /// Location description. + data: Expression, + }, +} + +fn write_expression( + w: &mut W, + refs: &mut Vec, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + val: &Expression, +) -> Result<()> { + let size = val.size(encoding, unit_offsets)? as u64; + if encoding.version <= 4 { + w.write_udata(size, 2)?; + } else { + w.write_uleb128(size)?; + } + val.write(w, Some(refs), encoding, unit_offsets)?; + Ok(()) +} + +#[cfg(feature = "read")] +mod convert { + use super::*; + + use crate::read::{self, Reader}; + use crate::write::{ConvertError, ConvertResult, ConvertUnitContext}; + + impl LocationList { + /// Create a location list by reading the data from the give location list iter. + pub(crate) fn from>( + mut from: read::RawLocListIter, + context: &ConvertUnitContext<'_, R>, + ) -> ConvertResult { + let mut have_base_address = context.base_address != Address::Constant(0); + let convert_address = + |x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress); + let convert_expression = |x| { + Expression::from( + x, + context.unit.encoding(), + Some(context.dwarf), + Some(context.unit), + Some(context.entry_ids), + context.convert_address, + ) + }; + let mut loc_list = Vec::new(); + while let Some(from_loc) = from.next()? { + let loc = match from_loc { + read::RawLocListEntry::AddressOrOffsetPair { begin, end, data } => { + // These were parsed as addresses, even if they are offsets. + let begin = convert_address(begin)?; + let end = convert_address(end)?; + let data = convert_expression(data)?; + match (begin, end) { + (Address::Constant(begin_offset), Address::Constant(end_offset)) => { + if have_base_address { + Location::OffsetPair { + begin: begin_offset, + end: end_offset, + data, + } + } else { + Location::StartEnd { begin, end, data } + } + } + _ => { + if have_base_address { + // At least one of begin/end is an address, but we also have + // a base address. Adding addresses is undefined. + return Err(ConvertError::InvalidRangeRelativeAddress); + } + Location::StartEnd { begin, end, data } + } + } + } + read::RawLocListEntry::BaseAddress { addr } => { + have_base_address = true; + let address = convert_address(addr)?; + Location::BaseAddress { address } + } + read::RawLocListEntry::BaseAddressx { addr } => { + have_base_address = true; + let address = convert_address(context.dwarf.address(context.unit, addr)?)?; + Location::BaseAddress { address } + } + read::RawLocListEntry::StartxEndx { begin, end, data } => { + let begin = convert_address(context.dwarf.address(context.unit, begin)?)?; + let end = convert_address(context.dwarf.address(context.unit, end)?)?; + let data = convert_expression(data)?; + Location::StartEnd { begin, end, data } + } + read::RawLocListEntry::StartxLength { + begin, + length, + data, + } => { + let begin = convert_address(context.dwarf.address(context.unit, begin)?)?; + let data = convert_expression(data)?; + Location::StartLength { + begin, + length, + data, + } + } + read::RawLocListEntry::OffsetPair { begin, end, data } => { + let data = convert_expression(data)?; + Location::OffsetPair { begin, end, data } + } + read::RawLocListEntry::StartEnd { begin, end, data } => { + let begin = convert_address(begin)?; + let end = convert_address(end)?; + let data = convert_expression(data)?; + Location::StartEnd { begin, end, data } + } + read::RawLocListEntry::StartLength { + begin, + length, + data, + } => { + let begin = convert_address(begin)?; + let data = convert_expression(data)?; + Location::StartLength { + begin, + length, + data, + } + } + read::RawLocListEntry::DefaultLocation { data } => { + let data = convert_expression(data)?; + Location::DefaultLocation { data } + } + }; + // In some cases, existing data may contain begin == end, filtering + // these out. + match loc { + Location::StartLength { length: 0, .. } => continue, + Location::StartEnd { begin, end, .. } if begin == end => continue, + Location::OffsetPair { begin, end, .. } if begin == end => continue, + _ => (), + } + loc_list.push(loc); + } + Ok(LocationList(loc_list)) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::common::{ + DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase, + DebugStrOffsetsBase, Format, + }; + use crate::read; + use crate::write::{ + ConvertUnitContext, EndianVec, LineStringTable, RangeListTable, StringTable, + }; + use crate::LittleEndian; + use std::collections::HashMap; + use std::sync::Arc; + + #[test] + fn test_loc_list() { + let mut line_strings = LineStringTable::default(); + let mut strings = StringTable::default(); + let mut expression = Expression::new(); + expression.op_constu(0); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let mut loc_list = LocationList(vec![ + Location::StartLength { + begin: Address::Constant(6666), + length: 7777, + data: expression.clone(), + }, + Location::StartEnd { + begin: Address::Constant(4444), + end: Address::Constant(5555), + data: expression.clone(), + }, + Location::BaseAddress { + address: Address::Constant(1111), + }, + Location::OffsetPair { + begin: 2222, + end: 3333, + data: expression.clone(), + }, + ]); + if version >= 5 { + loc_list.0.push(Location::DefaultLocation { + data: expression.clone(), + }); + } + + let mut locations = LocationListTable::default(); + let loc_list_id = locations.add(loc_list.clone()); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap(); + assert!(sections.debug_loc_refs.is_empty()); + assert!(sections.debug_loclists_refs.is_empty()); + + let read_debug_loc = + read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian); + let read_debug_loclists = + read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian); + let read_loc = read::LocationLists::new(read_debug_loc, read_debug_loclists); + let offset = loc_list_offsets.get(loc_list_id); + let read_loc_list = read_loc.raw_locations(offset, encoding).unwrap(); + + let dwarf = read::Dwarf { + locations: read_loc, + ..Default::default() + }; + let unit = read::Unit { + header: read::UnitHeader::new( + encoding, + 0, + read::UnitType::Compilation, + DebugAbbrevOffset(0), + DebugInfoOffset(0).into(), + read::EndianSlice::default(), + ), + abbreviations: Arc::new(read::Abbreviations::default()), + name: None, + comp_dir: None, + low_pc: 0, + str_offsets_base: DebugStrOffsetsBase(0), + addr_base: DebugAddrBase(0), + loclists_base: DebugLocListsBase(0), + rnglists_base: DebugRngListsBase(0), + line_program: None, + dwo_id: None, + }; + let context = ConvertUnitContext { + dwarf: &dwarf, + unit: &unit, + line_strings: &mut line_strings, + strings: &mut strings, + ranges: &mut RangeListTable::default(), + locations: &mut locations, + convert_address: &|address| Some(Address::Constant(address)), + base_address: Address::Constant(0), + line_program_offset: None, + line_program_files: Vec::new(), + entry_ids: &HashMap::new(), + }; + let convert_loc_list = LocationList::from(read_loc_list, &context).unwrap(); + + if version <= 4 { + loc_list.0[0] = Location::StartEnd { + begin: Address::Constant(6666), + end: Address::Constant(6666 + 7777), + data: expression.clone(), + }; + } + assert_eq!(loc_list, convert_loc_list); + } + } + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/mod.rs b/anneal/v2/vendor/gimli/src/write/mod.rs new file mode 100644 index 0000000000..b7adbbe265 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/mod.rs @@ -0,0 +1,428 @@ +//! Write DWARF debugging information. +//! +//! ## API Structure +//! +//! This module works by building up a representation of the debugging information +//! in memory, and then writing it all at once. It supports two major use cases: +//! +//! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF +//! for a single compilation unit. +//! +//! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple +//! compilation units. +//! +//! The module also supports reading in DWARF debugging information and writing it out +//! again, possibly after modifying it. Create a [`read::Dwarf`](../read/struct.Dwarf.html) +//! instance, and then use [`Dwarf::from`](./struct.Dwarf.html#method.from) to convert +//! it to a writable instance. +//! +//! ## Example Usage +//! +//! Write a compilation unit containing only the top level DIE. +//! +//! ```rust +//! use gimli::write::{ +//! Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections, +//! }; +//! +//! fn example() -> Result<(), Error> { +//! // Choose the encoding parameters. +//! let encoding = gimli::Encoding { +//! format: gimli::Format::Dwarf32, +//! version: 5, +//! address_size: 8, +//! }; +//! // Create a container for a single compilation unit. +//! let mut dwarf = DwarfUnit::new(encoding); +//! // Set a range attribute on the root DIE. +//! let range_list = RangeList(vec![Range::StartLength { +//! begin: Address::Constant(0x100), +//! length: 42, +//! }]); +//! let range_list_id = dwarf.unit.ranges.add(range_list); +//! let root = dwarf.unit.root(); +//! dwarf.unit.get_mut(root).set( +//! gimli::DW_AT_ranges, +//! AttributeValue::RangeListRef(range_list_id), +//! ); +//! // Create a `Vec` for each DWARF section. +//! let mut sections = Sections::new(EndianVec::new(gimli::LittleEndian)); +//! // Finally, write the DWARF data to the sections. +//! dwarf.write(&mut sections)?; +//! sections.for_each(|id, data| { +//! // Here you can add the data to the output object file. +//! Ok(()) +//! }) +//! } +//! # fn main() { +//! # example().unwrap(); +//! # } + +use std::error; +use std::fmt; +use std::result; + +use crate::constants; + +mod endian_vec; +pub use self::endian_vec::*; + +mod writer; +pub use self::writer::*; + +mod relocate; +pub use self::relocate::*; + +#[macro_use] +mod section; +pub use self::section::*; + +macro_rules! define_id { + ($name:ident, $docs:expr) => { + #[doc=$docs] + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct $name { + base_id: BaseId, + index: usize, + } + + impl $name { + #[inline] + fn new(base_id: BaseId, index: usize) -> Self { + $name { base_id, index } + } + } + }; +} + +macro_rules! define_offsets { + ($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => { + #[doc=$off_doc] + #[derive(Debug)] + pub struct $offsets { + base_id: BaseId, + // We know ids start at 0. + offsets: Vec<$offset>, + } + + impl $offsets { + /// Return an empty list of offsets. + #[inline] + pub fn none() -> Self { + $offsets { + base_id: BaseId::default(), + offsets: Vec::new(), + } + } + + /// Get the offset + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get(&self, id: $id) -> $offset { + debug_assert_eq!(self.base_id, id.base_id); + self.offsets[id.index] + } + + /// Return the number of offsets. + #[inline] + pub fn count(&self) -> usize { + self.offsets.len() + } + } + }; +} + +mod abbrev; +pub use self::abbrev::*; + +mod cfi; +pub use self::cfi::*; + +mod dwarf; +pub use self::dwarf::*; + +mod line; +pub use self::line::*; + +mod loc; +pub use self::loc::*; + +mod op; +pub use self::op::*; + +mod range; +pub use self::range::*; + +mod str; +pub use self::str::*; + +mod unit; +pub use self::unit::*; + +/// An error that occurred when writing. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Error { + /// The given offset is out of bounds. + OffsetOutOfBounds, + /// The given length is out of bounds. + LengthOutOfBounds, + /// The attribute value is an invalid for writing. + InvalidAttributeValue, + /// The value is too large for the encoding form. + ValueTooLarge, + /// Unsupported word size. + UnsupportedWordSize(u8), + /// Unsupported DWARF version. + UnsupportedVersion(u16), + /// The unit length is too large for the requested DWARF format. + InitialLengthOverflow, + /// The address is invalid. + InvalidAddress, + /// The reference is invalid. + InvalidReference, + /// A requested feature requires a different DWARF version. + NeedVersion(u16), + /// Strings in line number program have mismatched forms. + LineStringFormMismatch, + /// The range is empty or otherwise invalid. + InvalidRange, + /// The line number program encoding is incompatible with the unit encoding. + IncompatibleLineProgramEncoding, + /// Could not encode code offset for a frame instruction. + InvalidFrameCodeOffset(u32), + /// Could not encode data offset for a frame instruction. + InvalidFrameDataOffset(i32), + /// Unsupported eh_frame pointer encoding. + UnsupportedPointerEncoding(constants::DwEhPe), + /// Unsupported reference in CFI expression. + UnsupportedCfiExpressionReference, + /// Unsupported forward reference in expression. + UnsupportedExpressionForwardReference, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { + match *self { + Error::OffsetOutOfBounds => write!(f, "The given offset is out of bounds."), + Error::LengthOutOfBounds => write!(f, "The given length is out of bounds."), + Error::InvalidAttributeValue => { + write!(f, "The attribute value is an invalid for writing.") + } + Error::ValueTooLarge => write!(f, "The value is too large for the encoding form."), + Error::UnsupportedWordSize(size) => write!(f, "Unsupported word size: {}", size), + Error::UnsupportedVersion(version) => { + write!(f, "Unsupported DWARF version: {}", version) + } + Error::InitialLengthOverflow => write!( + f, + "The unit length is too large for the requested DWARF format." + ), + Error::InvalidAddress => write!(f, "The address is invalid."), + Error::InvalidReference => write!(f, "The reference is invalid."), + Error::NeedVersion(version) => write!( + f, + "A requested feature requires a DWARF version {}.", + version + ), + Error::LineStringFormMismatch => { + write!(f, "Strings in line number program have mismatched forms.") + } + Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."), + Error::IncompatibleLineProgramEncoding => write!( + f, + "The line number program encoding is incompatible with the unit encoding." + ), + Error::InvalidFrameCodeOffset(offset) => write!( + f, + "Could not encode code offset ({}) for a frame instruction.", + offset, + ), + Error::InvalidFrameDataOffset(offset) => write!( + f, + "Could not encode data offset ({}) for a frame instruction.", + offset, + ), + Error::UnsupportedPointerEncoding(eh_pe) => { + write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe) + } + Error::UnsupportedCfiExpressionReference => { + write!(f, "Unsupported reference in CFI expression.") + } + Error::UnsupportedExpressionForwardReference => { + write!(f, "Unsupported forward reference in expression.") + } + } + } +} + +impl error::Error for Error {} + +/// The result of a write. +pub type Result = result::Result; + +/// An address. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Address { + /// A fixed address that does not require relocation. + Constant(u64), + /// An address that is relative to a symbol which may be relocated. + Symbol { + /// The symbol that the address is relative to. + /// + /// The meaning of this value is decided by the writer, but + /// will typically be an index into a symbol table. + symbol: usize, + /// The offset of the address relative to the symbol. + /// + /// This will typically be used as the addend in a relocation. + addend: i64, + }, +} + +/// A reference to a `.debug_info` entry. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Reference { + /// An external symbol. + /// + /// The meaning of this value is decided by the writer, but + /// will typically be an index into a symbol table. + Symbol(usize), + /// An entry in the same section. + /// + /// This only supports references in units that are emitted together. + Entry(UnitId, UnitEntryId), +} + +// This type is only used in debug assertions. +#[cfg(not(debug_assertions))] +type BaseId = (); + +#[cfg(debug_assertions)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +struct BaseId(usize); + +#[cfg(debug_assertions)] +impl Default for BaseId { + fn default() -> Self { + use std::sync::atomic; + static BASE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0); + BaseId(BASE_ID.fetch_add(1, atomic::Ordering::Relaxed)) + } +} + +#[cfg(feature = "read")] +mod convert { + use super::*; + use crate::read; + + pub(crate) use super::unit::convert::*; + + /// An error that occurred when converting a read value into a write value. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub enum ConvertError { + /// An error occurred when reading. + Read(read::Error), + /// Writing of this attribute value is not implemented yet. + UnsupportedAttributeValue, + /// This attribute value is an invalid name/form combination. + InvalidAttributeValue, + /// A `.debug_info` reference does not refer to a valid entry. + InvalidDebugInfoOffset, + /// An address could not be converted. + InvalidAddress, + /// Writing this line number instruction is not implemented yet. + UnsupportedLineInstruction, + /// Writing this form of line string is not implemented yet. + UnsupportedLineStringForm, + /// A `.debug_line` file index is invalid. + InvalidFileIndex, + /// A `.debug_line` directory index is invalid. + InvalidDirectoryIndex, + /// A `.debug_line` line base is invalid. + InvalidLineBase, + /// A `.debug_line` reference is invalid. + InvalidLineRef, + /// A `.debug_info` unit entry reference is invalid. + InvalidUnitRef, + /// A `.debug_info` reference is invalid. + InvalidDebugInfoRef, + /// Invalid relative address in a range list. + InvalidRangeRelativeAddress, + /// Writing this CFI instruction is not implemented yet. + UnsupportedCfiInstruction, + /// Writing indirect pointers is not implemented yet. + UnsupportedIndirectAddress, + /// Writing this expression operation is not implemented yet. + UnsupportedOperation, + /// Operation branch target is invalid. + InvalidBranchTarget, + /// Writing this unit type is not supported yet. + UnsupportedUnitType, + } + + impl fmt::Display for ConvertError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { + use self::ConvertError::*; + match *self { + Read(ref e) => e.fmt(f), + UnsupportedAttributeValue => { + write!(f, "Writing of this attribute value is not implemented yet.") + } + InvalidAttributeValue => write!( + f, + "This attribute value is an invalid name/form combination." + ), + InvalidDebugInfoOffset => write!( + f, + "A `.debug_info` reference does not refer to a valid entry." + ), + InvalidAddress => write!(f, "An address could not be converted."), + UnsupportedLineInstruction => write!( + f, + "Writing this line number instruction is not implemented yet." + ), + UnsupportedLineStringForm => write!( + f, + "Writing this form of line string is not implemented yet." + ), + InvalidFileIndex => write!(f, "A `.debug_line` file index is invalid."), + InvalidDirectoryIndex => write!(f, "A `.debug_line` directory index is invalid."), + InvalidLineBase => write!(f, "A `.debug_line` line base is invalid."), + InvalidLineRef => write!(f, "A `.debug_line` reference is invalid."), + InvalidUnitRef => write!(f, "A `.debug_info` unit entry reference is invalid."), + InvalidDebugInfoRef => write!(f, "A `.debug_info` reference is invalid."), + InvalidRangeRelativeAddress => { + write!(f, "Invalid relative address in a range list.") + } + UnsupportedCfiInstruction => { + write!(f, "Writing this CFI instruction is not implemented yet.") + } + UnsupportedIndirectAddress => { + write!(f, "Writing indirect pointers is not implemented yet.") + } + UnsupportedOperation => write!( + f, + "Writing this expression operation is not implemented yet." + ), + InvalidBranchTarget => write!(f, "Operation branch target is invalid."), + UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."), + } + } + } + + impl error::Error for ConvertError {} + + impl From for ConvertError { + fn from(e: read::Error) -> Self { + ConvertError::Read(e) + } + } + + /// The result of a conversion. + pub type ConvertResult = result::Result; +} +#[cfg(feature = "read")] +pub use self::convert::*; diff --git a/anneal/v2/vendor/gimli/src/write/op.rs b/anneal/v2/vendor/gimli/src/write/op.rs new file mode 100644 index 0000000000..f4c632b1d7 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/op.rs @@ -0,0 +1,1762 @@ +use alloc::boxed::Box; +use alloc::vec::Vec; + +use crate::common::{Encoding, Register}; +use crate::constants::{self, DwOp}; +use crate::leb128::write::{sleb128_size, uleb128_size}; +use crate::write::{ + Address, DebugInfoReference, Error, Reference, Result, UnitEntryId, UnitOffsets, Writer, +}; + +/// The bytecode for a DWARF expression or location description. +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] +pub struct Expression { + operations: Vec, +} + +impl Expression { + /// Create an empty expression. + #[inline] + pub fn new() -> Self { + Self::default() + } + + /// Create an expression from raw bytecode. + /// + /// This does not support operations that require references, such as `DW_OP_addr`. + #[inline] + pub fn raw(bytecode: Vec) -> Self { + Expression { + operations: vec![Operation::Raw(bytecode)], + } + } + + /// Add an operation to the expression. + /// + /// This should only be used for operations that have no explicit operands. + pub fn op(&mut self, opcode: DwOp) { + self.operations.push(Operation::Simple(opcode)); + } + + /// Add a `DW_OP_addr` operation to the expression. + pub fn op_addr(&mut self, address: Address) { + self.operations.push(Operation::Address(address)); + } + + /// Add a `DW_OP_constu` operation to the expression. + /// + /// This may be emitted as a smaller equivalent operation. + pub fn op_constu(&mut self, value: u64) { + self.operations.push(Operation::UnsignedConstant(value)); + } + + /// Add a `DW_OP_consts` operation to the expression. + /// + /// This may be emitted as a smaller equivalent operation. + pub fn op_consts(&mut self, value: i64) { + self.operations.push(Operation::SignedConstant(value)); + } + + /// Add a `DW_OP_const_type` or `DW_OP_GNU_const_type` operation to the expression. + pub fn op_const_type(&mut self, base: UnitEntryId, value: Box<[u8]>) { + self.operations.push(Operation::ConstantType(base, value)); + } + + /// Add a `DW_OP_fbreg` operation to the expression. + pub fn op_fbreg(&mut self, offset: i64) { + self.operations.push(Operation::FrameOffset(offset)); + } + + /// Add a `DW_OP_bregx` operation to the expression. + /// + /// This may be emitted as a smaller equivalent operation. + pub fn op_breg(&mut self, register: Register, offset: i64) { + self.operations + .push(Operation::RegisterOffset(register, offset)); + } + + /// Add a `DW_OP_regval_type` or `DW_OP_GNU_regval_type` operation to the expression. + /// + /// This may be emitted as a smaller equivalent operation. + pub fn op_regval_type(&mut self, register: Register, base: UnitEntryId) { + self.operations + .push(Operation::RegisterType(register, base)); + } + + /// Add a `DW_OP_pick` operation to the expression. + /// + /// This may be emitted as a `DW_OP_dup` or `DW_OP_over` operation. + pub fn op_pick(&mut self, index: u8) { + self.operations.push(Operation::Pick(index)); + } + + /// Add a `DW_OP_deref` operation to the expression. + pub fn op_deref(&mut self) { + self.operations.push(Operation::Deref { space: false }); + } + + /// Add a `DW_OP_xderef` operation to the expression. + pub fn op_xderef(&mut self) { + self.operations.push(Operation::Deref { space: true }); + } + + /// Add a `DW_OP_deref_size` operation to the expression. + pub fn op_deref_size(&mut self, size: u8) { + self.operations + .push(Operation::DerefSize { size, space: false }); + } + + /// Add a `DW_OP_xderef_size` operation to the expression. + pub fn op_xderef_size(&mut self, size: u8) { + self.operations + .push(Operation::DerefSize { size, space: true }); + } + + /// Add a `DW_OP_deref_type` or `DW_OP_GNU_deref_type` operation to the expression. + pub fn op_deref_type(&mut self, size: u8, base: UnitEntryId) { + self.operations.push(Operation::DerefType { + size, + base, + space: false, + }); + } + + /// Add a `DW_OP_xderef_type` operation to the expression. + pub fn op_xderef_type(&mut self, size: u8, base: UnitEntryId) { + self.operations.push(Operation::DerefType { + size, + base, + space: true, + }); + } + + /// Add a `DW_OP_plus_uconst` operation to the expression. + pub fn op_plus_uconst(&mut self, value: u64) { + self.operations.push(Operation::PlusConstant(value)); + } + + /// Add a `DW_OP_skip` operation to the expression. + /// + /// Returns the index of the operation. The caller must call `set_target` with + /// this index to set the target of the branch. + pub fn op_skip(&mut self) -> usize { + let index = self.next_index(); + self.operations.push(Operation::Skip(!0)); + index + } + + /// Add a `DW_OP_bra` operation to the expression. + /// + /// Returns the index of the operation. The caller must call `set_target` with + /// this index to set the target of the branch. + pub fn op_bra(&mut self) -> usize { + let index = self.next_index(); + self.operations.push(Operation::Branch(!0)); + index + } + + /// Return the index that will be assigned to the next operation. + /// + /// This can be passed to `set_target`. + #[inline] + pub fn next_index(&self) -> usize { + self.operations.len() + } + + /// Set the target of a `DW_OP_skip` or `DW_OP_bra` operation . + pub fn set_target(&mut self, operation: usize, new_target: usize) { + debug_assert!(new_target <= self.next_index()); + debug_assert_ne!(operation, new_target); + match self.operations[operation] { + Operation::Skip(ref mut target) | Operation::Branch(ref mut target) => { + *target = new_target; + } + _ => unimplemented!(), + } + } + + /// Add a `DW_OP_call4` operation to the expression. + pub fn op_call(&mut self, entry: UnitEntryId) { + self.operations.push(Operation::Call(entry)); + } + + /// Add a `DW_OP_call_ref` operation to the expression. + pub fn op_call_ref(&mut self, entry: Reference) { + self.operations.push(Operation::CallRef(entry)); + } + + /// Add a `DW_OP_convert` or `DW_OP_GNU_convert` operation to the expression. + /// + /// `base` is the DIE of the base type, or `None` for the generic type. + pub fn op_convert(&mut self, base: Option) { + self.operations.push(Operation::Convert(base)); + } + + /// Add a `DW_OP_reinterpret` or `DW_OP_GNU_reinterpret` operation to the expression. + /// + /// `base` is the DIE of the base type, or `None` for the generic type. + pub fn op_reinterpret(&mut self, base: Option) { + self.operations.push(Operation::Reinterpret(base)); + } + + /// Add a `DW_OP_entry_value` or `DW_OP_GNU_entry_value` operation to the expression. + pub fn op_entry_value(&mut self, expression: Expression) { + self.operations.push(Operation::EntryValue(expression)); + } + + /// Add a `DW_OP_regx` operation to the expression. + /// + /// This may be emitted as a smaller equivalent operation. + pub fn op_reg(&mut self, register: Register) { + self.operations.push(Operation::Register(register)); + } + + /// Add a `DW_OP_implicit_value` operation to the expression. + pub fn op_implicit_value(&mut self, data: Box<[u8]>) { + self.operations.push(Operation::ImplicitValue(data)); + } + + /// Add a `DW_OP_implicit_pointer` or `DW_OP_GNU_implicit_pointer` operation to the expression. + pub fn op_implicit_pointer(&mut self, entry: Reference, byte_offset: i64) { + self.operations + .push(Operation::ImplicitPointer { entry, byte_offset }); + } + + /// Add a `DW_OP_piece` operation to the expression. + pub fn op_piece(&mut self, size_in_bytes: u64) { + self.operations.push(Operation::Piece { size_in_bytes }); + } + + /// Add a `DW_OP_bit_piece` operation to the expression. + pub fn op_bit_piece(&mut self, size_in_bits: u64, bit_offset: u64) { + self.operations.push(Operation::BitPiece { + size_in_bits, + bit_offset, + }); + } + + /// Add a `DW_OP_GNU_parameter_ref` operation to the expression. + pub fn op_gnu_parameter_ref(&mut self, entry: UnitEntryId) { + self.operations.push(Operation::ParameterRef(entry)); + } + + /// Add a `DW_OP_WASM_location 0x0` operation to the expression. + pub fn op_wasm_local(&mut self, index: u32) { + self.operations.push(Operation::WasmLocal(index)); + } + + /// Add a `DW_OP_WASM_location 0x1` operation to the expression. + pub fn op_wasm_global(&mut self, index: u32) { + self.operations.push(Operation::WasmGlobal(index)); + } + + /// Add a `DW_OP_WASM_location 0x2` operation to the expression. + pub fn op_wasm_stack(&mut self, index: u32) { + self.operations.push(Operation::WasmStack(index)); + } + + pub(crate) fn size( + &self, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + ) -> Result { + let mut size = 0; + for operation in &self.operations { + size += operation.size(encoding, unit_offsets)?; + } + Ok(size) + } + + pub(crate) fn write( + &self, + w: &mut W, + mut refs: Option<&mut Vec>, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + ) -> Result<()> { + // TODO: only calculate offsets if needed? + let mut offsets = Vec::with_capacity(self.operations.len()); + let mut offset = w.len(); + for operation in &self.operations { + offsets.push(offset); + offset += operation.size(encoding, unit_offsets)?; + } + offsets.push(offset); + for (operation, offset) in self.operations.iter().zip(offsets.iter().copied()) { + debug_assert_eq!(w.len(), offset); + operation.write(w, refs.as_deref_mut(), encoding, unit_offsets, &offsets)?; + } + debug_assert_eq!(w.len(), offset); + Ok(()) + } +} + +/// A single DWARF operation. +// +// This type is intentionally not public so that we can change the +// representation of expressions as needed. +// +// Variants are listed in the order they appear in Section 2.5. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum Operation { + /// Raw bytecode. + /// + /// Does not support references. + Raw(Vec), + /// An operation that has no explicit operands. + /// + /// Represents: + /// - `DW_OP_drop`, `DW_OP_swap`, `DW_OP_rot` + /// - `DW_OP_push_object_address`, `DW_OP_form_tls_address`, `DW_OP_call_frame_cfa` + /// - `DW_OP_abs`, `DW_OP_and`, `DW_OP_div`, `DW_OP_minus`, `DW_OP_mod`, `DW_OP_mul`, + /// `DW_OP_neg`, `DW_OP_not`, `DW_OP_or`, `DW_OP_plus`, `DW_OP_shl`, `DW_OP_shr`, + /// `DW_OP_shra`, `DW_OP_xor` + /// - `DW_OP_le`, `DW_OP_ge`, `DW_OP_eq`, `DW_OP_lt`, `DW_OP_gt`, `DW_OP_ne` + /// - `DW_OP_nop` + /// - `DW_OP_stack_value` + Simple(DwOp), + /// Relocate the address if needed, and push it on the stack. + /// + /// Represents `DW_OP_addr`. + Address(Address), + /// Push an unsigned constant value on the stack. + /// + /// Represents `DW_OP_constu`. + UnsignedConstant(u64), + /// Push a signed constant value on the stack. + /// + /// Represents `DW_OP_consts`. + SignedConstant(i64), + /* TODO: requires .debug_addr write support + /// Read the address at the given index in `.debug_addr, relocate the address if needed, + /// and push it on the stack. + /// + /// Represents `DW_OP_addrx`. + AddressIndex(DebugAddrIndex), + /// Read the address at the given index in `.debug_addr, and push it on the stack. + /// Do not relocate the address. + /// + /// Represents `DW_OP_constx`. + ConstantIndex(DebugAddrIndex), + */ + /// Interpret the value bytes as a constant of a given type, and push it on the stack. + /// + /// Represents `DW_OP_const_type`. + ConstantType(UnitEntryId, Box<[u8]>), + /// Compute the frame base (using `DW_AT_frame_base`), add the + /// given offset, and then push the resulting sum on the stack. + /// + /// Represents `DW_OP_fbreg`. + FrameOffset(i64), + /// Find the contents of the given register, add the offset, and then + /// push the resulting sum on the stack. + /// + /// Represents `DW_OP_bregx`. + RegisterOffset(Register, i64), + /// Interpret the contents of the given register as a value of the given type, + /// and push it on the stack. + /// + /// Represents `DW_OP_regval_type`. + RegisterType(Register, UnitEntryId), + /// Copy the item at a stack index and push it on top of the stack. + /// + /// Represents `DW_OP_pick`, `DW_OP_dup`, and `DW_OP_over`. + Pick(u8), + /// Pop the topmost value of the stack, dereference it, and push the + /// resulting value. + /// + /// Represents `DW_OP_deref` and `DW_OP_xderef`. + Deref { + /// True if the dereference operation takes an address space + /// argument from the stack; false otherwise. + space: bool, + }, + /// Pop the topmost value of the stack, dereference it to obtain a value + /// of the given size, and push the resulting value. + /// + /// Represents `DW_OP_deref_size` and `DW_OP_xderef_size`. + DerefSize { + /// True if the dereference operation takes an address space + /// argument from the stack; false otherwise. + space: bool, + /// The size of the data to dereference. + size: u8, + }, + /// Pop the topmost value of the stack, dereference it to obtain a value + /// of the given type, and push the resulting value. + /// + /// Represents `DW_OP_deref_type` and `DW_OP_xderef_type`. + DerefType { + /// True if the dereference operation takes an address space + /// argument from the stack; false otherwise. + space: bool, + /// The size of the data to dereference. + size: u8, + /// The DIE of the base type, or `None` for the generic type. + base: UnitEntryId, + }, + /// Add an unsigned constant to the topmost value on the stack. + /// + /// Represents `DW_OP_plus_uconst`. + PlusConstant(u64), + /// Unconditional branch to the target location. + /// + /// The value is the index within the expression of the operation to branch to. + /// This will be converted to a relative offset when writing. + /// + /// Represents `DW_OP_skip`. + Skip(usize), + /// Branch to the target location if the top of stack is nonzero. + /// + /// The value is the index within the expression of the operation to branch to. + /// This will be converted to a relative offset when writing. + /// + /// Represents `DW_OP_bra`. + Branch(usize), + /// Evaluate a DWARF expression as a subroutine. + /// + /// The expression comes from the `DW_AT_location` attribute of the indicated DIE. + /// + /// Represents `DW_OP_call4`. + Call(UnitEntryId), + /// Evaluate an external DWARF expression as a subroutine. + /// + /// The expression comes from the `DW_AT_location` attribute of the indicated DIE, + /// which may be in another compilation unit or shared object. + /// + /// Represents `DW_OP_call_ref`. + CallRef(Reference), + /// Pop the top stack entry, convert it to a different type, and push it on the stack. + /// + /// Represents `DW_OP_convert`. + Convert(Option), + /// Pop the top stack entry, reinterpret the bits in its value as a different type, + /// and push it on the stack. + /// + /// Represents `DW_OP_reinterpret`. + Reinterpret(Option), + /// Evaluate an expression at the entry to the current subprogram, and push it on the stack. + /// + /// Represents `DW_OP_entry_value`. + EntryValue(Expression), + // FIXME: EntryRegister + /// Indicate that this piece's location is in the given register. + /// + /// Completes the piece or expression. + /// + /// Represents `DW_OP_regx`. + Register(Register), + /// The object has no location, but has a known constant value. + /// + /// Completes the piece or expression. + /// + /// Represents `DW_OP_implicit_value`. + ImplicitValue(Box<[u8]>), + /// The object is a pointer to a value which has no actual location, such as + /// an implicit value or a stack value. + /// + /// Completes the piece or expression. + /// + /// Represents `DW_OP_implicit_pointer`. + ImplicitPointer { + /// The DIE of the value that this is an implicit pointer into. + entry: Reference, + /// The byte offset into the value that the implicit pointer points to. + byte_offset: i64, + }, + /// Terminate a piece. + /// + /// Represents `DW_OP_piece`. + Piece { + /// The size of this piece in bytes. + size_in_bytes: u64, + }, + /// Terminate a piece with a size in bits. + /// + /// Represents `DW_OP_bit_piece`. + BitPiece { + /// The size of this piece in bits. + size_in_bits: u64, + /// The bit offset of this piece. + bit_offset: u64, + }, + /// This represents a parameter that was optimized out. + /// + /// The entry is the definition of the parameter, and is matched to + /// the `DW_TAG_GNU_call_site_parameter` in the caller that also + /// points to the same definition of the parameter. + /// + /// Represents `DW_OP_GNU_parameter_ref`. + ParameterRef(UnitEntryId), + /// The index of a local in the currently executing function. + /// + /// Represents `DW_OP_WASM_location 0x00`. + WasmLocal(u32), + /// The index of a global. + /// + /// Represents `DW_OP_WASM_location 0x01`. + WasmGlobal(u32), + /// The index of an item on the operand stack. + /// + /// Represents `DW_OP_WASM_location 0x02`. + WasmStack(u32), +} + +impl Operation { + fn size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> Result { + let base_size = |entry| match unit_offsets { + Some(offsets) => offsets + .unit_offset(entry) + .map(uleb128_size) + .ok_or(Error::UnsupportedExpressionForwardReference), + None => Err(Error::UnsupportedCfiExpressionReference), + }; + Ok(1 + match *self { + Operation::Raw(ref bytecode) => return Ok(bytecode.len()), + Operation::Simple(_) => 0, + Operation::Address(_) => encoding.address_size as usize, + Operation::UnsignedConstant(value) => { + if value < 32 { + 0 + } else { + uleb128_size(value) + } + } + Operation::SignedConstant(value) => sleb128_size(value), + Operation::ConstantType(base, ref value) => base_size(base)? + 1 + value.len(), + Operation::FrameOffset(offset) => sleb128_size(offset), + Operation::RegisterOffset(register, offset) => { + if register.0 < 32 { + sleb128_size(offset) + } else { + uleb128_size(register.0.into()) + sleb128_size(offset) + } + } + Operation::RegisterType(register, base) => { + uleb128_size(register.0.into()) + base_size(base)? + } + Operation::Pick(index) => { + if index > 1 { + 1 + } else { + 0 + } + } + Operation::Deref { .. } => 0, + Operation::DerefSize { .. } => 1, + Operation::DerefType { base, .. } => 1 + base_size(base)?, + Operation::PlusConstant(value) => uleb128_size(value), + Operation::Skip(_) => 2, + Operation::Branch(_) => 2, + Operation::Call(_) => 4, + Operation::CallRef(_) => encoding.format.word_size() as usize, + Operation::Convert(base) => match base { + Some(base) => base_size(base)?, + None => 1, + }, + Operation::Reinterpret(base) => match base { + Some(base) => base_size(base)?, + None => 1, + }, + Operation::EntryValue(ref expression) => { + let length = expression.size(encoding, unit_offsets)?; + uleb128_size(length as u64) + length + } + Operation::Register(register) => { + if register.0 < 32 { + 0 + } else { + uleb128_size(register.0.into()) + } + } + Operation::ImplicitValue(ref data) => uleb128_size(data.len() as u64) + data.len(), + Operation::ImplicitPointer { byte_offset, .. } => { + let size = if encoding.version == 2 { + encoding.address_size + } else { + encoding.format.word_size() + }; + size as usize + sleb128_size(byte_offset) + } + Operation::Piece { size_in_bytes } => uleb128_size(size_in_bytes), + Operation::BitPiece { + size_in_bits, + bit_offset, + } => uleb128_size(size_in_bits) + uleb128_size(bit_offset), + Operation::ParameterRef(_) => 4, + Operation::WasmLocal(index) + | Operation::WasmGlobal(index) + | Operation::WasmStack(index) => 1 + uleb128_size(index.into()), + }) + } + + pub(crate) fn write( + &self, + w: &mut W, + refs: Option<&mut Vec>, + encoding: Encoding, + unit_offsets: Option<&UnitOffsets>, + offsets: &[usize], + ) -> Result<()> { + let entry_offset = |entry| match unit_offsets { + Some(offsets) => offsets + .unit_offset(entry) + .ok_or(Error::UnsupportedExpressionForwardReference), + None => Err(Error::UnsupportedCfiExpressionReference), + }; + match *self { + Operation::Raw(ref bytecode) => w.write(bytecode)?, + Operation::Simple(opcode) => w.write_u8(opcode.0)?, + Operation::Address(address) => { + w.write_u8(constants::DW_OP_addr.0)?; + w.write_address(address, encoding.address_size)?; + } + Operation::UnsignedConstant(value) => { + if value < 32 { + w.write_u8(constants::DW_OP_lit0.0 + value as u8)?; + } else { + w.write_u8(constants::DW_OP_constu.0)?; + w.write_uleb128(value)?; + } + } + Operation::SignedConstant(value) => { + w.write_u8(constants::DW_OP_consts.0)?; + w.write_sleb128(value)?; + } + Operation::ConstantType(base, ref value) => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_const_type.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_const_type.0)?; + } + w.write_uleb128(entry_offset(base)?)?; + w.write_udata(value.len() as u64, 1)?; + w.write(value)?; + } + Operation::FrameOffset(offset) => { + w.write_u8(constants::DW_OP_fbreg.0)?; + w.write_sleb128(offset)?; + } + Operation::RegisterOffset(register, offset) => { + if register.0 < 32 { + w.write_u8(constants::DW_OP_breg0.0 + register.0 as u8)?; + } else { + w.write_u8(constants::DW_OP_bregx.0)?; + w.write_uleb128(register.0.into())?; + } + w.write_sleb128(offset)?; + } + Operation::RegisterType(register, base) => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_regval_type.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_regval_type.0)?; + } + w.write_uleb128(register.0.into())?; + w.write_uleb128(entry_offset(base)?)?; + } + Operation::Pick(index) => match index { + 0 => w.write_u8(constants::DW_OP_dup.0)?, + 1 => w.write_u8(constants::DW_OP_over.0)?, + _ => { + w.write_u8(constants::DW_OP_pick.0)?; + w.write_u8(index)?; + } + }, + Operation::Deref { space } => { + if space { + w.write_u8(constants::DW_OP_xderef.0)?; + } else { + w.write_u8(constants::DW_OP_deref.0)?; + } + } + Operation::DerefSize { space, size } => { + if space { + w.write_u8(constants::DW_OP_xderef_size.0)?; + } else { + w.write_u8(constants::DW_OP_deref_size.0)?; + } + w.write_u8(size)?; + } + Operation::DerefType { space, size, base } => { + if space { + w.write_u8(constants::DW_OP_xderef_type.0)?; + } else { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_deref_type.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_deref_type.0)?; + } + } + w.write_u8(size)?; + w.write_uleb128(entry_offset(base)?)?; + } + Operation::PlusConstant(value) => { + w.write_u8(constants::DW_OP_plus_uconst.0)?; + w.write_uleb128(value)?; + } + Operation::Skip(target) => { + w.write_u8(constants::DW_OP_skip.0)?; + let offset = offsets[target] as i64 - (w.len() as i64 + 2); + w.write_sdata(offset, 2)?; + } + Operation::Branch(target) => { + w.write_u8(constants::DW_OP_bra.0)?; + let offset = offsets[target] as i64 - (w.len() as i64 + 2); + w.write_sdata(offset, 2)?; + } + Operation::Call(entry) => { + w.write_u8(constants::DW_OP_call4.0)?; + // TODO: this probably won't work in practice, because we may + // only know the offsets of base type DIEs at this point. + w.write_udata(entry_offset(entry)?, 4)?; + } + Operation::CallRef(entry) => { + w.write_u8(constants::DW_OP_call_ref.0)?; + let size = encoding.format.word_size(); + match entry { + Reference::Symbol(symbol) => w.write_reference(symbol, size)?, + Reference::Entry(unit, entry) => { + let refs = refs.ok_or(Error::InvalidReference)?; + refs.push(DebugInfoReference { + offset: w.len(), + unit, + entry, + size, + }); + w.write_udata(0, size)?; + } + } + } + Operation::Convert(base) => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_convert.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_convert.0)?; + } + match base { + Some(base) => w.write_uleb128(entry_offset(base)?)?, + None => w.write_u8(0)?, + } + } + Operation::Reinterpret(base) => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_reinterpret.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_reinterpret.0)?; + } + match base { + Some(base) => w.write_uleb128(entry_offset(base)?)?, + None => w.write_u8(0)?, + } + } + Operation::EntryValue(ref expression) => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_entry_value.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_entry_value.0)?; + } + let length = expression.size(encoding, unit_offsets)?; + w.write_uleb128(length as u64)?; + expression.write(w, refs, encoding, unit_offsets)?; + } + Operation::Register(register) => { + if register.0 < 32 { + w.write_u8(constants::DW_OP_reg0.0 + register.0 as u8)?; + } else { + w.write_u8(constants::DW_OP_regx.0)?; + w.write_uleb128(register.0.into())?; + } + } + Operation::ImplicitValue(ref data) => { + w.write_u8(constants::DW_OP_implicit_value.0)?; + w.write_uleb128(data.len() as u64)?; + w.write(data)?; + } + Operation::ImplicitPointer { entry, byte_offset } => { + if encoding.version >= 5 { + w.write_u8(constants::DW_OP_implicit_pointer.0)?; + } else { + w.write_u8(constants::DW_OP_GNU_implicit_pointer.0)?; + } + let size = if encoding.version == 2 { + encoding.address_size + } else { + encoding.format.word_size() + }; + match entry { + Reference::Symbol(symbol) => { + w.write_reference(symbol, size)?; + } + Reference::Entry(unit, entry) => { + let refs = refs.ok_or(Error::InvalidReference)?; + refs.push(DebugInfoReference { + offset: w.len(), + unit, + entry, + size, + }); + w.write_udata(0, size)?; + } + } + w.write_sleb128(byte_offset)?; + } + Operation::Piece { size_in_bytes } => { + w.write_u8(constants::DW_OP_piece.0)?; + w.write_uleb128(size_in_bytes)?; + } + Operation::BitPiece { + size_in_bits, + bit_offset, + } => { + w.write_u8(constants::DW_OP_bit_piece.0)?; + w.write_uleb128(size_in_bits)?; + w.write_uleb128(bit_offset)?; + } + Operation::ParameterRef(entry) => { + w.write_u8(constants::DW_OP_GNU_parameter_ref.0)?; + w.write_udata(entry_offset(entry)?, 4)?; + } + Operation::WasmLocal(index) => { + w.write(&[constants::DW_OP_WASM_location.0, 0])?; + w.write_uleb128(index.into())?; + } + Operation::WasmGlobal(index) => { + w.write(&[constants::DW_OP_WASM_location.0, 1])?; + w.write_uleb128(index.into())?; + } + Operation::WasmStack(index) => { + w.write(&[constants::DW_OP_WASM_location.0, 2])?; + w.write_uleb128(index.into())?; + } + } + Ok(()) + } +} + +#[cfg(feature = "read")] +pub(crate) mod convert { + use super::*; + use crate::common::UnitSectionOffset; + use crate::read::{self, Reader}; + use crate::write::{ConvertError, ConvertResult, UnitId}; + use std::collections::HashMap; + + impl Expression { + /// Create an expression from the input expression. + pub fn from>( + from_expression: read::Expression, + encoding: Encoding, + dwarf: Option<&read::Dwarf>, + unit: Option<&read::Unit>, + entry_ids: Option<&HashMap>, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult { + let convert_unit_offset = |offset: read::UnitOffset| -> ConvertResult<_> { + let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?; + let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; + let id = entry_ids + .get(&offset.to_unit_section_offset(unit)) + .ok_or(ConvertError::InvalidUnitRef)?; + Ok(id.1) + }; + let convert_debug_info_offset = |offset| -> ConvertResult<_> { + // TODO: support relocations + let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?; + let id = entry_ids + .get(&UnitSectionOffset::DebugInfoOffset(offset)) + .ok_or(ConvertError::InvalidDebugInfoRef)?; + Ok(Reference::Entry(id.0, id.1)) + }; + + // Calculate offsets for use in branch/skip operations. + let mut offsets = Vec::new(); + let mut offset = 0; + let mut from_operations = from_expression.clone().operations(encoding); + while from_operations.next()?.is_some() { + offsets.push(offset); + offset = from_operations.offset_from(&from_expression); + } + offsets.push(from_expression.0.len()); + + let mut from_operations = from_expression.clone().operations(encoding); + let mut operations = Vec::new(); + while let Some(from_operation) = from_operations.next()? { + let operation = match from_operation { + read::Operation::Deref { + base_type, + size, + space, + } => { + if base_type.0 != 0 { + let base = convert_unit_offset(base_type)?; + Operation::DerefType { space, size, base } + } else if size != encoding.address_size { + Operation::DerefSize { space, size } + } else { + Operation::Deref { space } + } + } + read::Operation::Drop => Operation::Simple(constants::DW_OP_drop), + read::Operation::Pick { index } => Operation::Pick(index), + read::Operation::Swap => Operation::Simple(constants::DW_OP_swap), + read::Operation::Rot => Operation::Simple(constants::DW_OP_rot), + read::Operation::Abs => Operation::Simple(constants::DW_OP_abs), + read::Operation::And => Operation::Simple(constants::DW_OP_and), + read::Operation::Div => Operation::Simple(constants::DW_OP_div), + read::Operation::Minus => Operation::Simple(constants::DW_OP_minus), + read::Operation::Mod => Operation::Simple(constants::DW_OP_mod), + read::Operation::Mul => Operation::Simple(constants::DW_OP_mul), + read::Operation::Neg => Operation::Simple(constants::DW_OP_neg), + read::Operation::Not => Operation::Simple(constants::DW_OP_not), + read::Operation::Or => Operation::Simple(constants::DW_OP_or), + read::Operation::Plus => Operation::Simple(constants::DW_OP_plus), + read::Operation::PlusConstant { value } => Operation::PlusConstant(value), + read::Operation::Shl => Operation::Simple(constants::DW_OP_shl), + read::Operation::Shr => Operation::Simple(constants::DW_OP_shr), + read::Operation::Shra => Operation::Simple(constants::DW_OP_shra), + read::Operation::Xor => Operation::Simple(constants::DW_OP_xor), + read::Operation::Eq => Operation::Simple(constants::DW_OP_eq), + read::Operation::Ge => Operation::Simple(constants::DW_OP_ge), + read::Operation::Gt => Operation::Simple(constants::DW_OP_gt), + read::Operation::Le => Operation::Simple(constants::DW_OP_le), + read::Operation::Lt => Operation::Simple(constants::DW_OP_lt), + read::Operation::Ne => Operation::Simple(constants::DW_OP_ne), + read::Operation::Bra { target } => { + let offset = from_operations + .offset_from(&from_expression) + .wrapping_add(i64::from(target) as usize); + let index = offsets + .binary_search(&offset) + .map_err(|_| ConvertError::InvalidBranchTarget)?; + Operation::Branch(index) + } + read::Operation::Skip { target } => { + let offset = from_operations + .offset_from(&from_expression) + .wrapping_add(i64::from(target) as usize); + let index = offsets + .binary_search(&offset) + .map_err(|_| ConvertError::InvalidBranchTarget)?; + Operation::Skip(index) + } + read::Operation::UnsignedConstant { value } => { + Operation::UnsignedConstant(value) + } + read::Operation::SignedConstant { value } => Operation::SignedConstant(value), + read::Operation::Register { register } => Operation::Register(register), + read::Operation::RegisterOffset { + register, + offset, + base_type, + } => { + if base_type.0 != 0 { + Operation::RegisterType(register, convert_unit_offset(base_type)?) + } else { + Operation::RegisterOffset(register, offset) + } + } + read::Operation::FrameOffset { offset } => Operation::FrameOffset(offset), + read::Operation::Nop => Operation::Simple(constants::DW_OP_nop), + read::Operation::PushObjectAddress => { + Operation::Simple(constants::DW_OP_push_object_address) + } + read::Operation::Call { offset } => match offset { + read::DieReference::UnitRef(offset) => { + Operation::Call(convert_unit_offset(offset)?) + } + read::DieReference::DebugInfoRef(offset) => { + Operation::CallRef(convert_debug_info_offset(offset)?) + } + }, + read::Operation::TLS => Operation::Simple(constants::DW_OP_form_tls_address), + read::Operation::CallFrameCFA => { + Operation::Simple(constants::DW_OP_call_frame_cfa) + } + read::Operation::Piece { + size_in_bits, + bit_offset: None, + } => Operation::Piece { + size_in_bytes: size_in_bits / 8, + }, + read::Operation::Piece { + size_in_bits, + bit_offset: Some(bit_offset), + } => Operation::BitPiece { + size_in_bits, + bit_offset, + }, + read::Operation::ImplicitValue { data } => { + Operation::ImplicitValue(data.to_slice()?.into_owned().into()) + } + read::Operation::StackValue => Operation::Simple(constants::DW_OP_stack_value), + read::Operation::ImplicitPointer { value, byte_offset } => { + let entry = convert_debug_info_offset(value)?; + Operation::ImplicitPointer { entry, byte_offset } + } + read::Operation::EntryValue { expression } => { + let expression = Expression::from( + read::Expression(expression), + encoding, + dwarf, + unit, + entry_ids, + convert_address, + )?; + Operation::EntryValue(expression) + } + read::Operation::ParameterRef { offset } => { + let entry = convert_unit_offset(offset)?; + Operation::ParameterRef(entry) + } + read::Operation::Address { address } => { + let address = + convert_address(address).ok_or(ConvertError::InvalidAddress)?; + Operation::Address(address) + } + read::Operation::AddressIndex { index } => { + let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?; + let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; + let val = dwarf.address(unit, index)?; + let address = convert_address(val).ok_or(ConvertError::InvalidAddress)?; + Operation::Address(address) + } + read::Operation::ConstantIndex { index } => { + let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?; + let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; + let val = dwarf.address(unit, index)?; + Operation::UnsignedConstant(val) + } + read::Operation::TypedLiteral { base_type, value } => { + let entry = convert_unit_offset(base_type)?; + Operation::ConstantType(entry, value.to_slice()?.into_owned().into()) + } + read::Operation::Convert { base_type } => { + if base_type.0 == 0 { + Operation::Convert(None) + } else { + let entry = convert_unit_offset(base_type)?; + Operation::Convert(Some(entry)) + } + } + read::Operation::Reinterpret { base_type } => { + if base_type.0 == 0 { + Operation::Reinterpret(None) + } else { + let entry = convert_unit_offset(base_type)?; + Operation::Reinterpret(Some(entry)) + } + } + read::Operation::WasmLocal { index } => Operation::WasmLocal(index), + read::Operation::WasmGlobal { index } => Operation::WasmGlobal(index), + read::Operation::WasmStack { index } => Operation::WasmStack(index), + }; + operations.push(operation); + } + Ok(Expression { operations }) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::common::{DebugInfoOffset, Format}; + use crate::read; + use crate::write::{AttributeValue, Dwarf, EndianVec, LineProgram, Sections, Unit}; + use crate::LittleEndian; + use std::collections::HashMap; + + #[test] + #[allow(clippy::type_complexity)] + fn test_operation() { + for version in [2, 3, 4, 5] { + for address_size in [4, 8] { + for format in [Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // Create an entry that can be referenced by the expression. + let entry_id = unit.add(unit.root(), constants::DW_TAG_base_type); + let reference = Reference::Entry(unit_id, entry_id); + + // The offsets for the above entry when reading back the expression. + struct ReadState { + debug_info_offset: DebugInfoOffset, + entry_offset: read::UnitOffset, + } + + let mut reg_expression = Expression::new(); + reg_expression.op_reg(Register(23)); + + let operations: &[( + &dyn Fn(&mut Expression), + Operation, + &dyn Fn(&ReadState) -> read::Operation<_>, + )] = &[ + ( + &|x| x.op_deref(), + Operation::Deref { space: false }, + &|_| read::Operation::Deref { + base_type: read::UnitOffset(0), + size: address_size, + space: false, + }, + ), + ( + &|x| x.op_xderef(), + Operation::Deref { space: true }, + &|_| read::Operation::Deref { + base_type: read::UnitOffset(0), + size: address_size, + space: true, + }, + ), + ( + &|x| x.op_deref_size(2), + Operation::DerefSize { + space: false, + size: 2, + }, + &|_| read::Operation::Deref { + base_type: read::UnitOffset(0), + size: 2, + space: false, + }, + ), + ( + &|x| x.op_xderef_size(2), + Operation::DerefSize { + space: true, + size: 2, + }, + &|_| read::Operation::Deref { + base_type: read::UnitOffset(0), + size: 2, + space: true, + }, + ), + ( + &|x| x.op_deref_type(2, entry_id), + Operation::DerefType { + space: false, + size: 2, + base: entry_id, + }, + &|x| read::Operation::Deref { + base_type: x.entry_offset, + size: 2, + space: false, + }, + ), + ( + &|x| x.op_xderef_type(2, entry_id), + Operation::DerefType { + space: true, + size: 2, + base: entry_id, + }, + &|x| read::Operation::Deref { + base_type: x.entry_offset, + size: 2, + space: true, + }, + ), + ( + &|x| x.op(constants::DW_OP_drop), + Operation::Simple(constants::DW_OP_drop), + &|_| read::Operation::Drop, + ), + (&|x| x.op_pick(0), Operation::Pick(0), &|_| { + read::Operation::Pick { index: 0 } + }), + (&|x| x.op_pick(1), Operation::Pick(1), &|_| { + read::Operation::Pick { index: 1 } + }), + (&|x| x.op_pick(2), Operation::Pick(2), &|_| { + read::Operation::Pick { index: 2 } + }), + ( + &|x| x.op(constants::DW_OP_swap), + Operation::Simple(constants::DW_OP_swap), + &|_| read::Operation::Swap, + ), + ( + &|x| x.op(constants::DW_OP_rot), + Operation::Simple(constants::DW_OP_rot), + &|_| read::Operation::Rot, + ), + ( + &|x| x.op(constants::DW_OP_abs), + Operation::Simple(constants::DW_OP_abs), + &|_| read::Operation::Abs, + ), + ( + &|x| x.op(constants::DW_OP_and), + Operation::Simple(constants::DW_OP_and), + &|_| read::Operation::And, + ), + ( + &|x| x.op(constants::DW_OP_div), + Operation::Simple(constants::DW_OP_div), + &|_| read::Operation::Div, + ), + ( + &|x| x.op(constants::DW_OP_minus), + Operation::Simple(constants::DW_OP_minus), + &|_| read::Operation::Minus, + ), + ( + &|x| x.op(constants::DW_OP_mod), + Operation::Simple(constants::DW_OP_mod), + &|_| read::Operation::Mod, + ), + ( + &|x| x.op(constants::DW_OP_mul), + Operation::Simple(constants::DW_OP_mul), + &|_| read::Operation::Mul, + ), + ( + &|x| x.op(constants::DW_OP_neg), + Operation::Simple(constants::DW_OP_neg), + &|_| read::Operation::Neg, + ), + ( + &|x| x.op(constants::DW_OP_not), + Operation::Simple(constants::DW_OP_not), + &|_| read::Operation::Not, + ), + ( + &|x| x.op(constants::DW_OP_or), + Operation::Simple(constants::DW_OP_or), + &|_| read::Operation::Or, + ), + ( + &|x| x.op(constants::DW_OP_plus), + Operation::Simple(constants::DW_OP_plus), + &|_| read::Operation::Plus, + ), + ( + &|x| x.op_plus_uconst(23), + Operation::PlusConstant(23), + &|_| read::Operation::PlusConstant { value: 23 }, + ), + ( + &|x| x.op(constants::DW_OP_shl), + Operation::Simple(constants::DW_OP_shl), + &|_| read::Operation::Shl, + ), + ( + &|x| x.op(constants::DW_OP_shr), + Operation::Simple(constants::DW_OP_shr), + &|_| read::Operation::Shr, + ), + ( + &|x| x.op(constants::DW_OP_shra), + Operation::Simple(constants::DW_OP_shra), + &|_| read::Operation::Shra, + ), + ( + &|x| x.op(constants::DW_OP_xor), + Operation::Simple(constants::DW_OP_xor), + &|_| read::Operation::Xor, + ), + ( + &|x| x.op(constants::DW_OP_eq), + Operation::Simple(constants::DW_OP_eq), + &|_| read::Operation::Eq, + ), + ( + &|x| x.op(constants::DW_OP_ge), + Operation::Simple(constants::DW_OP_ge), + &|_| read::Operation::Ge, + ), + ( + &|x| x.op(constants::DW_OP_gt), + Operation::Simple(constants::DW_OP_gt), + &|_| read::Operation::Gt, + ), + ( + &|x| x.op(constants::DW_OP_le), + Operation::Simple(constants::DW_OP_le), + &|_| read::Operation::Le, + ), + ( + &|x| x.op(constants::DW_OP_lt), + Operation::Simple(constants::DW_OP_lt), + &|_| read::Operation::Lt, + ), + ( + &|x| x.op(constants::DW_OP_ne), + Operation::Simple(constants::DW_OP_ne), + &|_| read::Operation::Ne, + ), + ( + &|x| x.op_constu(23), + Operation::UnsignedConstant(23), + &|_| read::Operation::UnsignedConstant { value: 23 }, + ), + ( + &|x| x.op_consts(-23), + Operation::SignedConstant(-23), + &|_| read::Operation::SignedConstant { value: -23 }, + ), + ( + &|x| x.op_reg(Register(23)), + Operation::Register(Register(23)), + &|_| read::Operation::Register { + register: Register(23), + }, + ), + ( + &|x| x.op_reg(Register(123)), + Operation::Register(Register(123)), + &|_| read::Operation::Register { + register: Register(123), + }, + ), + ( + &|x| x.op_breg(Register(23), 34), + Operation::RegisterOffset(Register(23), 34), + &|_| read::Operation::RegisterOffset { + register: Register(23), + offset: 34, + base_type: read::UnitOffset(0), + }, + ), + ( + &|x| x.op_breg(Register(123), 34), + Operation::RegisterOffset(Register(123), 34), + &|_| read::Operation::RegisterOffset { + register: Register(123), + offset: 34, + base_type: read::UnitOffset(0), + }, + ), + ( + &|x| x.op_regval_type(Register(23), entry_id), + Operation::RegisterType(Register(23), entry_id), + &|x| read::Operation::RegisterOffset { + register: Register(23), + offset: 0, + base_type: x.entry_offset, + }, + ), + (&|x| x.op_fbreg(34), Operation::FrameOffset(34), &|_| { + read::Operation::FrameOffset { offset: 34 } + }), + ( + &|x| x.op(constants::DW_OP_nop), + Operation::Simple(constants::DW_OP_nop), + &|_| read::Operation::Nop, + ), + ( + &|x| x.op(constants::DW_OP_push_object_address), + Operation::Simple(constants::DW_OP_push_object_address), + &|_| read::Operation::PushObjectAddress, + ), + (&|x| x.op_call(entry_id), Operation::Call(entry_id), &|x| { + read::Operation::Call { + offset: read::DieReference::UnitRef(x.entry_offset), + } + }), + ( + &|x| x.op_call_ref(reference), + Operation::CallRef(reference), + &|x| read::Operation::Call { + offset: read::DieReference::DebugInfoRef(x.debug_info_offset), + }, + ), + ( + &|x| x.op(constants::DW_OP_form_tls_address), + Operation::Simple(constants::DW_OP_form_tls_address), + &|_| read::Operation::TLS, + ), + ( + &|x| x.op(constants::DW_OP_call_frame_cfa), + Operation::Simple(constants::DW_OP_call_frame_cfa), + &|_| read::Operation::CallFrameCFA, + ), + ( + &|x| x.op_piece(23), + Operation::Piece { size_in_bytes: 23 }, + &|_| read::Operation::Piece { + size_in_bits: 23 * 8, + bit_offset: None, + }, + ), + ( + &|x| x.op_bit_piece(23, 34), + Operation::BitPiece { + size_in_bits: 23, + bit_offset: 34, + }, + &|_| read::Operation::Piece { + size_in_bits: 23, + bit_offset: Some(34), + }, + ), + ( + &|x| x.op_implicit_value(vec![23].into()), + Operation::ImplicitValue(vec![23].into()), + &|_| read::Operation::ImplicitValue { + data: read::EndianSlice::new(&[23], LittleEndian), + }, + ), + ( + &|x| x.op(constants::DW_OP_stack_value), + Operation::Simple(constants::DW_OP_stack_value), + &|_| read::Operation::StackValue, + ), + ( + &|x| x.op_implicit_pointer(reference, 23), + Operation::ImplicitPointer { + entry: reference, + byte_offset: 23, + }, + &|x| read::Operation::ImplicitPointer { + value: x.debug_info_offset, + byte_offset: 23, + }, + ), + ( + &|x| x.op_entry_value(reg_expression.clone()), + Operation::EntryValue(reg_expression.clone()), + &|_| read::Operation::EntryValue { + expression: read::EndianSlice::new( + &[constants::DW_OP_reg23.0], + LittleEndian, + ), + }, + ), + ( + &|x| x.op_gnu_parameter_ref(entry_id), + Operation::ParameterRef(entry_id), + &|x| read::Operation::ParameterRef { + offset: x.entry_offset, + }, + ), + ( + &|x| x.op_addr(Address::Constant(23)), + Operation::Address(Address::Constant(23)), + &|_| read::Operation::Address { address: 23 }, + ), + ( + &|x| x.op_const_type(entry_id, vec![23].into()), + Operation::ConstantType(entry_id, vec![23].into()), + &|x| read::Operation::TypedLiteral { + base_type: x.entry_offset, + value: read::EndianSlice::new(&[23], LittleEndian), + }, + ), + (&|x| x.op_convert(None), Operation::Convert(None), &|_| { + read::Operation::Convert { + base_type: read::UnitOffset(0), + } + }), + ( + &|x| x.op_convert(Some(entry_id)), + Operation::Convert(Some(entry_id)), + &|x| read::Operation::Convert { + base_type: x.entry_offset, + }, + ), + ( + &|x| x.op_reinterpret(None), + Operation::Reinterpret(None), + &|_| read::Operation::Reinterpret { + base_type: read::UnitOffset(0), + }, + ), + ( + &|x| x.op_reinterpret(Some(entry_id)), + Operation::Reinterpret(Some(entry_id)), + &|x| read::Operation::Reinterpret { + base_type: x.entry_offset, + }, + ), + ( + &|x| x.op_wasm_local(1000), + Operation::WasmLocal(1000), + &|_| read::Operation::WasmLocal { index: 1000 }, + ), + ( + &|x| x.op_wasm_global(1000), + Operation::WasmGlobal(1000), + &|_| read::Operation::WasmGlobal { index: 1000 }, + ), + ( + &|x| x.op_wasm_stack(1000), + Operation::WasmStack(1000), + &|_| read::Operation::WasmStack { index: 1000 }, + ), + ]; + + // Create a single expression containing all operations. + let mut expression = Expression::new(); + let start_index = expression.next_index(); + for (f, o, _) in operations { + f(&mut expression); + assert_eq!(expression.operations.last(), Some(o)); + } + + let bra_index = expression.op_bra(); + let skip_index = expression.op_skip(); + expression.op(constants::DW_OP_nop); + let end_index = expression.next_index(); + expression.set_target(bra_index, start_index); + expression.set_target(skip_index, end_index); + + // Create an entry containing the expression. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + let subprogram = unit.get_mut(subprogram_id); + subprogram.set( + constants::DW_AT_location, + AttributeValue::Exprloc(expression), + ); + + // Write the DWARF, then parse it. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + let read_unit_header = read_units.next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let mut read_entries = read_unit.entries(); + let (_, read_entry) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(read_entry.tag(), constants::DW_TAG_compile_unit); + + // Determine the offset of the entry that can be referenced by the expression. + let (_, read_entry) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(read_entry.tag(), constants::DW_TAG_base_type); + let read_state = ReadState { + debug_info_offset: read_entry + .offset() + .to_debug_info_offset(&read_unit.header) + .unwrap(), + entry_offset: read_entry.offset(), + }; + + // Get the expression. + let (_, read_entry) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(read_entry.tag(), constants::DW_TAG_subprogram); + let read_attr = read_entry + .attr_value(constants::DW_AT_location) + .unwrap() + .unwrap(); + let read_expression = read_attr.exprloc_value().unwrap(); + let mut read_operations = read_expression.operations(encoding); + for (_, _, operation) in operations { + assert_eq!(read_operations.next(), Ok(Some(operation(&read_state)))); + } + + // 4 = DW_OP_skip + i16 + DW_OP_nop + assert_eq!( + read_operations.next(), + Ok(Some(read::Operation::Bra { + target: -(read_expression.0.len() as i16) + 4 + })) + ); + // 1 = DW_OP_nop + assert_eq!( + read_operations.next(), + Ok(Some(read::Operation::Skip { target: 1 })) + ); + assert_eq!(read_operations.next(), Ok(Some(read::Operation::Nop))); + assert_eq!(read_operations.next(), Ok(None)); + + let mut entry_ids = HashMap::new(); + entry_ids.insert(read_state.debug_info_offset.into(), (unit_id, entry_id)); + let convert_expression = Expression::from( + read_expression, + encoding, + Some(&read_dwarf), + Some(&read_unit), + Some(&entry_ids), + &|address| Some(Address::Constant(address)), + ) + .unwrap(); + let mut convert_operations = convert_expression.operations.iter(); + for (_, operation, _) in operations { + assert_eq!(convert_operations.next(), Some(operation)); + } + assert_eq!( + convert_operations.next(), + Some(&Operation::Branch(start_index)) + ); + assert_eq!(convert_operations.next(), Some(&Operation::Skip(end_index))); + assert_eq!( + convert_operations.next(), + Some(&Operation::Simple(constants::DW_OP_nop)) + ); + } + } + } + } + + #[test] + #[allow(clippy::type_complexity)] + fn test_expression_raw() { + for version in [2, 3, 4, 5] { + for address_size in [4, 8] { + for format in [Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + let subprogram = unit.get_mut(subprogram_id); + let expression = Expression::raw(vec![constants::DW_OP_constu.0, 23]); + subprogram.set( + constants::DW_AT_location, + AttributeValue::Exprloc(expression), + ); + + // Write the DWARF, then parse it. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + let read_unit_header = read_units.next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit_header).unwrap(); + let mut read_entries = read_unit.entries(); + let (_, read_entry) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(read_entry.tag(), constants::DW_TAG_compile_unit); + let (_, read_entry) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(read_entry.tag(), constants::DW_TAG_subprogram); + let read_attr = read_entry + .attr_value(constants::DW_AT_location) + .unwrap() + .unwrap(); + let read_expression = read_attr.exprloc_value().unwrap(); + let mut read_operations = read_expression.operations(encoding); + assert_eq!( + read_operations.next(), + Ok(Some(read::Operation::UnsignedConstant { value: 23 })) + ); + assert_eq!(read_operations.next(), Ok(None)); + } + } + } + } + + #[test] + fn test_forward_ref() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // First, create an entry that will contain the expression. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + + // Now create the entry to be referenced by the expression. + let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type); + + // Create an expression containing the reference. + let mut expression = Expression::new(); + expression.op_deref_type(2, entry_id); + + // Add the expression to the subprogram. + unit.get_mut(subprogram_id).set( + constants::DW_AT_location, + AttributeValue::Exprloc(expression), + ); + + // Writing the DWARF should fail. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + assert_eq!( + dwarf.write(&mut sections), + Err(Error::UnsupportedExpressionForwardReference) + ); + } + + #[test] + fn test_missing_unit_ref() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // Create the entry to be referenced by the expression. + let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type); + // And delete it so that it is not available when writing the expression. + unit.get_mut(unit.root()).delete_child(entry_id); + + // Create an expression containing the reference. + let mut expression = Expression::new(); + expression.op_deref_type(2, entry_id); + + // Create an entry containing the expression. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(subprogram_id).set( + constants::DW_AT_location, + AttributeValue::Exprloc(expression), + ); + + // Writing the DWARF should fail. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + assert_eq!( + dwarf.write(&mut sections), + Err(Error::UnsupportedExpressionForwardReference) + ); + } + + #[test] + fn test_missing_debuginfo_ref() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // Create the entry to be referenced by the expression. + let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type); + // And delete it so that it is not available when writing the expression. + unit.get_mut(unit.root()).delete_child(entry_id); + + // Create an expression containing the reference. + let mut expression = Expression::new(); + expression.op_call_ref(Reference::Entry(unit_id, entry_id)); + + // Create an entry containing the expression. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(subprogram_id).set( + constants::DW_AT_location, + AttributeValue::Exprloc(expression), + ); + + // Writing the DWARF should fail. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference)); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/range.rs b/anneal/v2/vendor/gimli/src/write/range.rs new file mode 100644 index 0000000000..10a55fb6b5 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/range.rs @@ -0,0 +1,427 @@ +use alloc::vec::Vec; +use indexmap::IndexSet; +use std::ops::{Deref, DerefMut}; + +use crate::common::{Encoding, RangeListsOffset, SectionId}; +use crate::write::{Address, BaseId, Error, Result, Section, Sections, Writer}; + +define_section!( + DebugRanges, + RangeListsOffset, + "A writable `.debug_ranges` section." +); +define_section!( + DebugRngLists, + RangeListsOffset, + "A writable `.debug_rnglists` section." +); + +define_offsets!( + RangeListOffsets: RangeListId => RangeListsOffset, + "The section offsets of a series of range lists within the `.debug_ranges` or `.debug_rnglists` sections." +); + +define_id!( + RangeListId, + "An identifier for a range list in a `RangeListTable`." +); + +/// A table of range lists that will be stored in a `.debug_ranges` or `.debug_rnglists` section. +#[derive(Debug, Default)] +pub struct RangeListTable { + base_id: BaseId, + ranges: IndexSet, +} + +impl RangeListTable { + /// Add a range list to the table. + pub fn add(&mut self, range_list: RangeList) -> RangeListId { + let (index, _) = self.ranges.insert_full(range_list); + RangeListId::new(self.base_id, index) + } + + /// Get a reference to a location list. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get(&self, id: RangeListId) -> &RangeList { + debug_assert_eq!(self.base_id, id.base_id); + &self.ranges[id.index] + } + + /// Write the range list table to the appropriate section for the given DWARF version. + pub(crate) fn write( + &self, + sections: &mut Sections, + encoding: Encoding, + ) -> Result { + if self.ranges.is_empty() { + return Ok(RangeListOffsets::none()); + } + + match encoding.version { + 2..=4 => self.write_ranges(&mut sections.debug_ranges, encoding.address_size), + 5 => self.write_rnglists(&mut sections.debug_rnglists, encoding), + _ => Err(Error::UnsupportedVersion(encoding.version)), + } + } + + /// Write the range list table to the `.debug_ranges` section. + fn write_ranges( + &self, + w: &mut DebugRanges, + address_size: u8, + ) -> Result { + let mut offsets = Vec::new(); + for range_list in self.ranges.iter() { + offsets.push(w.offset()); + for range in &range_list.0 { + // Note that we must ensure none of the ranges have both begin == 0 and end == 0. + // We do this by ensuring that begin != end, which is a bit more restrictive + // than required, but still seems reasonable. + match *range { + Range::BaseAddress { address } => { + let marker = !0 >> (64 - address_size * 8); + w.write_udata(marker, address_size)?; + w.write_address(address, address_size)?; + } + Range::OffsetPair { begin, end } => { + if begin == end { + return Err(Error::InvalidRange); + } + w.write_udata(begin, address_size)?; + w.write_udata(end, address_size)?; + } + Range::StartEnd { begin, end } => { + if begin == end { + return Err(Error::InvalidRange); + } + w.write_address(begin, address_size)?; + w.write_address(end, address_size)?; + } + Range::StartLength { begin, length } => { + let end = match begin { + Address::Constant(begin) => Address::Constant(begin + length), + Address::Symbol { symbol, addend } => Address::Symbol { + symbol, + addend: addend + length as i64, + }, + }; + if begin == end { + return Err(Error::InvalidRange); + } + w.write_address(begin, address_size)?; + w.write_address(end, address_size)?; + } + } + } + w.write_udata(0, address_size)?; + w.write_udata(0, address_size)?; + } + Ok(RangeListOffsets { + base_id: self.base_id, + offsets, + }) + } + + /// Write the range list table to the `.debug_rnglists` section. + fn write_rnglists( + &self, + w: &mut DebugRngLists, + encoding: Encoding, + ) -> Result { + let mut offsets = Vec::new(); + + if encoding.version != 5 { + return Err(Error::NeedVersion(5)); + } + + let length_offset = w.write_initial_length(encoding.format)?; + let length_base = w.len(); + + w.write_u16(encoding.version)?; + w.write_u8(encoding.address_size)?; + w.write_u8(0)?; // segment_selector_size + w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28) + // FIXME implement DW_FORM_rnglistx writing and implement the offset entry list + + for range_list in self.ranges.iter() { + offsets.push(w.offset()); + for range in &range_list.0 { + match *range { + Range::BaseAddress { address } => { + w.write_u8(crate::constants::DW_RLE_base_address.0)?; + w.write_address(address, encoding.address_size)?; + } + Range::OffsetPair { begin, end } => { + w.write_u8(crate::constants::DW_RLE_offset_pair.0)?; + w.write_uleb128(begin)?; + w.write_uleb128(end)?; + } + Range::StartEnd { begin, end } => { + w.write_u8(crate::constants::DW_RLE_start_end.0)?; + w.write_address(begin, encoding.address_size)?; + w.write_address(end, encoding.address_size)?; + } + Range::StartLength { begin, length } => { + w.write_u8(crate::constants::DW_RLE_start_length.0)?; + w.write_address(begin, encoding.address_size)?; + w.write_uleb128(length)?; + } + } + } + + w.write_u8(crate::constants::DW_RLE_end_of_list.0)?; + } + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, encoding.format)?; + + Ok(RangeListOffsets { + base_id: self.base_id, + offsets, + }) + } +} + +/// A range list that will be stored in a `.debug_ranges` or `.debug_rnglists` section. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct RangeList(pub Vec); + +/// A single range. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum Range { + /// DW_RLE_base_address + BaseAddress { + /// Base address. + address: Address, + }, + /// DW_RLE_offset_pair + OffsetPair { + /// Start of range relative to base address. + begin: u64, + /// End of range relative to base address. + end: u64, + }, + /// DW_RLE_start_end + StartEnd { + /// Start of range. + begin: Address, + /// End of range. + end: Address, + }, + /// DW_RLE_start_length + StartLength { + /// Start of range. + begin: Address, + /// Length of range. + length: u64, + }, +} + +#[cfg(feature = "read")] +mod convert { + use super::*; + + use crate::read::{self, Reader}; + use crate::write::{ConvertError, ConvertResult, ConvertUnitContext}; + + impl RangeList { + /// Create a range list by reading the data from the give range list iter. + pub(crate) fn from>( + mut from: read::RawRngListIter, + context: &ConvertUnitContext<'_, R>, + ) -> ConvertResult { + let mut have_base_address = context.base_address != Address::Constant(0); + let convert_address = + |x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress); + let mut ranges = Vec::new(); + while let Some(from_range) = from.next()? { + let range = match from_range { + read::RawRngListEntry::AddressOrOffsetPair { begin, end } => { + // These were parsed as addresses, even if they are offsets. + let begin = convert_address(begin)?; + let end = convert_address(end)?; + match (begin, end) { + (Address::Constant(begin_offset), Address::Constant(end_offset)) => { + if have_base_address { + Range::OffsetPair { + begin: begin_offset, + end: end_offset, + } + } else { + Range::StartEnd { begin, end } + } + } + _ => { + if have_base_address { + // At least one of begin/end is an address, but we also have + // a base address. Adding addresses is undefined. + return Err(ConvertError::InvalidRangeRelativeAddress); + } + Range::StartEnd { begin, end } + } + } + } + read::RawRngListEntry::BaseAddress { addr } => { + have_base_address = true; + let address = convert_address(addr)?; + Range::BaseAddress { address } + } + read::RawRngListEntry::BaseAddressx { addr } => { + have_base_address = true; + let address = convert_address(context.dwarf.address(context.unit, addr)?)?; + Range::BaseAddress { address } + } + read::RawRngListEntry::StartxEndx { begin, end } => { + let begin = convert_address(context.dwarf.address(context.unit, begin)?)?; + let end = convert_address(context.dwarf.address(context.unit, end)?)?; + Range::StartEnd { begin, end } + } + read::RawRngListEntry::StartxLength { begin, length } => { + let begin = convert_address(context.dwarf.address(context.unit, begin)?)?; + Range::StartLength { begin, length } + } + read::RawRngListEntry::OffsetPair { begin, end } => { + Range::OffsetPair { begin, end } + } + read::RawRngListEntry::StartEnd { begin, end } => { + let begin = convert_address(begin)?; + let end = convert_address(end)?; + Range::StartEnd { begin, end } + } + read::RawRngListEntry::StartLength { begin, length } => { + let begin = convert_address(begin)?; + Range::StartLength { begin, length } + } + }; + // Filtering empty ranges out. + match range { + Range::StartLength { length: 0, .. } => continue, + Range::StartEnd { begin, end, .. } if begin == end => continue, + Range::OffsetPair { begin, end, .. } if begin == end => continue, + _ => (), + } + ranges.push(range); + } + Ok(RangeList(ranges)) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::common::{ + DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase, + DebugStrOffsetsBase, Format, + }; + use crate::read; + use crate::write::{ + ConvertUnitContext, EndianVec, LineStringTable, LocationListTable, Range, RangeListTable, + StringTable, + }; + use crate::LittleEndian; + use std::collections::HashMap; + use std::sync::Arc; + + #[test] + fn test_range() { + let mut line_strings = LineStringTable::default(); + let mut strings = StringTable::default(); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let mut range_list = RangeList(vec![ + Range::StartLength { + begin: Address::Constant(6666), + length: 7777, + }, + Range::StartEnd { + begin: Address::Constant(4444), + end: Address::Constant(5555), + }, + Range::BaseAddress { + address: Address::Constant(1111), + }, + Range::OffsetPair { + begin: 2222, + end: 3333, + }, + ]); + + let mut ranges = RangeListTable::default(); + let range_list_id = ranges.add(range_list.clone()); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + let range_list_offsets = ranges.write(&mut sections, encoding).unwrap(); + + let read_debug_ranges = + read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian); + let read_debug_rnglists = + read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian); + let read_ranges = read::RangeLists::new(read_debug_ranges, read_debug_rnglists); + let offset = range_list_offsets.get(range_list_id); + let read_range_list = read_ranges.raw_ranges(offset, encoding).unwrap(); + + let dwarf = read::Dwarf { + ranges: read_ranges, + ..Default::default() + }; + let unit = read::Unit { + header: read::UnitHeader::new( + encoding, + 0, + read::UnitType::Compilation, + DebugAbbrevOffset(0), + DebugInfoOffset(0).into(), + read::EndianSlice::default(), + ), + abbreviations: Arc::new(read::Abbreviations::default()), + name: None, + comp_dir: None, + low_pc: 0, + str_offsets_base: DebugStrOffsetsBase(0), + addr_base: DebugAddrBase(0), + loclists_base: DebugLocListsBase(0), + rnglists_base: DebugRngListsBase(0), + line_program: None, + dwo_id: None, + }; + let context = ConvertUnitContext { + dwarf: &dwarf, + unit: &unit, + line_strings: &mut line_strings, + strings: &mut strings, + ranges: &mut ranges, + locations: &mut LocationListTable::default(), + convert_address: &|address| Some(Address::Constant(address)), + base_address: Address::Constant(0), + line_program_offset: None, + line_program_files: Vec::new(), + entry_ids: &HashMap::new(), + }; + let convert_range_list = RangeList::from(read_range_list, &context).unwrap(); + + if version <= 4 { + range_list.0[0] = Range::StartEnd { + begin: Address::Constant(6666), + end: Address::Constant(6666 + 7777), + }; + } + assert_eq!(range_list, convert_range_list); + } + } + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/relocate.rs b/anneal/v2/vendor/gimli/src/write/relocate.rs new file mode 100644 index 0000000000..ff8dde13b7 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/relocate.rs @@ -0,0 +1,280 @@ +use crate::constants; +use crate::write::{Address, Error, Result, Writer}; +use crate::SectionId; + +/// A relocation to be applied to a section. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Relocation { + /// The offset within the section where the relocation should be applied. + pub offset: usize, + /// The size of the value to be relocated. + pub size: u8, + /// The target of the relocation. + pub target: RelocationTarget, + /// The addend to be applied to the relocated value. + pub addend: i64, + /// The pointer encoding for relocations in unwind information. + pub eh_pe: Option, +} + +/// The target of a relocation. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RelocationTarget { + /// The relocation target is a symbol. + /// + /// The meaning of this value is decided by the writer, but + /// will typically be an index into a symbol table. + Symbol(usize), + /// The relocation target is a section. + Section(SectionId), +} + +/// A `Writer` which also records relocations. +pub trait RelocateWriter { + /// The type of the writer being used to write the section data. + type Writer: Writer; + + /// Get the writer being used to write the section data. + fn writer(&self) -> &Self::Writer; + + /// Get the writer being used to write the section data. + fn writer_mut(&mut self) -> &mut Self::Writer; + + /// Record a relocation. + fn relocate(&mut self, relocation: Relocation); +} + +impl Writer for T { + type Endian = <::Writer as Writer>::Endian; + + fn endian(&self) -> Self::Endian { + self.writer().endian() + } + + fn len(&self) -> usize { + self.writer().len() + } + + fn write(&mut self, bytes: &[u8]) -> Result<()> { + self.writer_mut().write(bytes) + } + + fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { + self.writer_mut().write_at(offset, bytes) + } + + fn write_address(&mut self, address: Address, size: u8) -> Result<()> { + match address { + Address::Constant(val) => self.writer_mut().write_udata(val, size), + Address::Symbol { symbol, addend } => { + self.relocate(Relocation { + offset: self.len(), + size, + target: RelocationTarget::Symbol(symbol), + addend, + eh_pe: None, + }); + self.writer_mut().write_udata(0, size) + } + } + } + + fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { + self.relocate(Relocation { + offset: self.len(), + size, + target: RelocationTarget::Section(section), + addend: val as i64, + eh_pe: None, + }); + self.writer_mut().write_udata(0, size) + } + + fn write_offset_at( + &mut self, + offset: usize, + val: usize, + section: SectionId, + size: u8, + ) -> Result<()> { + self.relocate(Relocation { + offset, + size, + target: RelocationTarget::Section(section), + addend: val as i64, + eh_pe: None, + }); + self.writer_mut().write_udata_at(offset, 0, size) + } + + fn write_eh_pointer( + &mut self, + address: Address, + eh_pe: constants::DwEhPe, + size: u8, + ) -> Result<()> { + match address { + Address::Constant(_) => self.writer_mut().write_eh_pointer(address, eh_pe, size), + Address::Symbol { symbol, addend } => { + let size = match eh_pe.format() { + constants::DW_EH_PE_absptr => size, + constants::DW_EH_PE_udata2 => 2, + constants::DW_EH_PE_udata4 => 4, + constants::DW_EH_PE_udata8 => 8, + constants::DW_EH_PE_sdata2 => 2, + constants::DW_EH_PE_sdata4 => 4, + constants::DW_EH_PE_sdata8 => 8, + _ => return Err(Error::UnsupportedPointerEncoding(eh_pe)), + }; + self.relocate(Relocation { + offset: self.len(), + size, + target: RelocationTarget::Symbol(symbol), + addend, + eh_pe: Some(eh_pe), + }); + self.writer_mut().write_udata(0, size) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::write::EndianVec; + use crate::{LittleEndian, SectionId}; + use alloc::vec::Vec; + + struct Section { + writer: EndianVec, + relocations: Vec, + } + + impl RelocateWriter for Section { + type Writer = EndianVec; + + fn writer(&self) -> &Self::Writer { + &self.writer + } + + fn writer_mut(&mut self) -> &mut Self::Writer { + &mut self.writer + } + + fn relocate(&mut self, relocation: Relocation) { + self.relocations.push(relocation); + } + } + + #[test] + fn test_relocate_writer() { + let mut expected_data = Vec::new(); + let mut expected_relocations = Vec::new(); + + let mut section = Section { + writer: EndianVec::new(LittleEndian), + relocations: Vec::new(), + }; + + // No relocation for plain data. + section.write_udata(0x12345678, 4).unwrap(); + expected_data.extend_from_slice(&0x12345678u32.to_le_bytes()); + + // No relocation for a constant address. + section + .write_address(Address::Constant(0x87654321), 4) + .unwrap(); + expected_data.extend_from_slice(&0x87654321u32.to_le_bytes()); + + // Relocation for a symbol address. + let offset = section.len(); + section + .write_address( + Address::Symbol { + symbol: 1, + addend: 0x12345678, + }, + 4, + ) + .unwrap(); + expected_data.extend_from_slice(&[0; 4]); + expected_relocations.push(Relocation { + offset, + size: 4, + target: RelocationTarget::Symbol(1), + addend: 0x12345678, + eh_pe: None, + }); + + // Relocation for a section offset. + let offset = section.len(); + section + .write_offset(0x12345678, SectionId::DebugAbbrev, 4) + .unwrap(); + expected_data.extend_from_slice(&[0; 4]); + expected_relocations.push(Relocation { + offset, + size: 4, + target: RelocationTarget::Section(SectionId::DebugAbbrev), + addend: 0x12345678, + eh_pe: None, + }); + + // Relocation for a section offset at a specific offset. + let offset = section.len(); + section.write_udata(0x12345678, 4).unwrap(); + section + .write_offset_at(offset, 0x12345678, SectionId::DebugStr, 4) + .unwrap(); + expected_data.extend_from_slice(&[0; 4]); + expected_relocations.push(Relocation { + offset, + size: 4, + target: RelocationTarget::Section(SectionId::DebugStr), + addend: 0x12345678, + eh_pe: None, + }); + + // No relocation for a constant in unwind information. + section + .write_eh_pointer(Address::Constant(0x87654321), constants::DW_EH_PE_absptr, 8) + .unwrap(); + expected_data.extend_from_slice(&0x87654321u64.to_le_bytes()); + + // No relocation for a relative constant in unwind information. + let offset = section.len(); + section + .write_eh_pointer( + Address::Constant(offset as u64 - 8), + constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4, + 8, + ) + .unwrap(); + expected_data.extend_from_slice(&(-8i32).to_le_bytes()); + + // Relocation for a symbol in unwind information. + let offset = section.len(); + section + .write_eh_pointer( + Address::Symbol { + symbol: 2, + addend: 0x12345678, + }, + constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4, + 8, + ) + .unwrap(); + expected_data.extend_from_slice(&[0; 4]); + expected_relocations.push(Relocation { + offset, + size: 4, + target: RelocationTarget::Symbol(2), + addend: 0x12345678, + eh_pe: Some(constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4), + }); + + assert_eq!(section.writer.into_vec(), expected_data); + assert_eq!(section.relocations, expected_relocations); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/section.rs b/anneal/v2/vendor/gimli/src/write/section.rs new file mode 100644 index 0000000000..6439680647 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/section.rs @@ -0,0 +1,227 @@ +use std::ops::DerefMut; +use std::result; +use std::vec::Vec; + +use crate::common::SectionId; +use crate::write::{ + DebugAbbrev, DebugFrame, DebugInfo, DebugInfoReference, DebugLine, DebugLineStr, DebugLoc, + DebugLocLists, DebugRanges, DebugRngLists, DebugStr, EhFrame, Writer, +}; + +macro_rules! define_section { + ($name:ident, $offset:ident, $docs:expr) => { + #[doc=$docs] + #[derive(Debug, Default)] + pub struct $name(pub W); + + impl $name { + /// Return the offset of the next write. + pub fn offset(&self) -> $offset { + $offset(self.len()) + } + } + + impl From for $name { + #[inline] + fn from(w: W) -> Self { + $name(w) + } + } + + impl Deref for $name { + type Target = W; + + #[inline] + fn deref(&self) -> &W { + &self.0 + } + } + + impl DerefMut for $name { + #[inline] + fn deref_mut(&mut self) -> &mut W { + &mut self.0 + } + } + + impl Section for $name { + #[inline] + fn id(&self) -> SectionId { + SectionId::$name + } + } + }; +} + +/// Functionality common to all writable DWARF sections. +pub trait Section: DerefMut { + /// Returns the DWARF section kind for this type. + fn id(&self) -> SectionId; + + /// Returns the ELF section name for this type. + fn name(&self) -> &'static str { + self.id().name() + } +} + +/// All of the writable DWARF sections. +#[derive(Debug, Default)] +pub struct Sections { + /// The `.debug_abbrev` section. + pub debug_abbrev: DebugAbbrev, + /// The `.debug_info` section. + pub debug_info: DebugInfo, + /// The `.debug_line` section. + pub debug_line: DebugLine, + /// The `.debug_line_str` section. + pub debug_line_str: DebugLineStr, + /// The `.debug_ranges` section. + pub debug_ranges: DebugRanges, + /// The `.debug_rnglists` section. + pub debug_rnglists: DebugRngLists, + /// The `.debug_loc` section. + pub debug_loc: DebugLoc, + /// The `.debug_loclists` section. + pub debug_loclists: DebugLocLists, + /// The `.debug_str` section. + pub debug_str: DebugStr, + /// The `.debug_frame` section. + pub debug_frame: DebugFrame, + /// The `.eh_frame` section. + pub eh_frame: EhFrame, + /// Unresolved references in the `.debug_info` section. + pub(crate) debug_info_refs: Vec, + /// Unresolved references in the `.debug_loc` section. + pub(crate) debug_loc_refs: Vec, + /// Unresolved references in the `.debug_loclists` section. + pub(crate) debug_loclists_refs: Vec, +} + +impl Sections { + /// Create a new `Sections` using clones of the given `section`. + pub fn new(section: W) -> Self { + Sections { + debug_abbrev: DebugAbbrev(section.clone()), + debug_info: DebugInfo(section.clone()), + debug_line: DebugLine(section.clone()), + debug_line_str: DebugLineStr(section.clone()), + debug_ranges: DebugRanges(section.clone()), + debug_rnglists: DebugRngLists(section.clone()), + debug_loc: DebugLoc(section.clone()), + debug_loclists: DebugLocLists(section.clone()), + debug_str: DebugStr(section.clone()), + debug_frame: DebugFrame(section.clone()), + eh_frame: EhFrame(section), + debug_info_refs: Vec::new(), + debug_loc_refs: Vec::new(), + debug_loclists_refs: Vec::new(), + } + } +} + +impl Sections { + /// Get the section with the given `id`. + pub fn get(&self, id: SectionId) -> Option<&W> { + match id { + SectionId::DebugAbbrev => Some(&self.debug_abbrev.0), + SectionId::DebugInfo => Some(&self.debug_info.0), + SectionId::DebugLine => Some(&self.debug_line.0), + SectionId::DebugLineStr => Some(&self.debug_line_str.0), + SectionId::DebugRanges => Some(&self.debug_ranges.0), + SectionId::DebugRngLists => Some(&self.debug_rnglists.0), + SectionId::DebugLoc => Some(&self.debug_loc.0), + SectionId::DebugLocLists => Some(&self.debug_loclists.0), + SectionId::DebugStr => Some(&self.debug_str.0), + SectionId::DebugFrame => Some(&self.debug_frame.0), + SectionId::EhFrame => Some(&self.eh_frame.0), + _ => None, + } + } + + /// Get the section with the given `id`. + pub fn get_mut(&mut self, id: SectionId) -> Option<&mut W> { + match id { + SectionId::DebugAbbrev => Some(&mut self.debug_abbrev.0), + SectionId::DebugInfo => Some(&mut self.debug_info.0), + SectionId::DebugLine => Some(&mut self.debug_line.0), + SectionId::DebugLineStr => Some(&mut self.debug_line_str.0), + SectionId::DebugRanges => Some(&mut self.debug_ranges.0), + SectionId::DebugRngLists => Some(&mut self.debug_rnglists.0), + SectionId::DebugLoc => Some(&mut self.debug_loc.0), + SectionId::DebugLocLists => Some(&mut self.debug_loclists.0), + SectionId::DebugStr => Some(&mut self.debug_str.0), + SectionId::DebugFrame => Some(&mut self.debug_frame.0), + SectionId::EhFrame => Some(&mut self.eh_frame.0), + _ => None, + } + } + + /// For each section, call `f` once with a shared reference. + pub fn for_each<'a, F, E>(&'a self, mut f: F) -> result::Result<(), E> + where + F: FnMut(SectionId, &'a W) -> result::Result<(), E>, + { + macro_rules! f { + ($s:expr) => { + f($s.id(), &$s) + }; + } + // Ordered so that earlier sections do not reference later sections. + f!(self.debug_abbrev)?; + f!(self.debug_str)?; + f!(self.debug_line_str)?; + f!(self.debug_line)?; + f!(self.debug_ranges)?; + f!(self.debug_rnglists)?; + f!(self.debug_loc)?; + f!(self.debug_loclists)?; + f!(self.debug_info)?; + f!(self.debug_frame)?; + f!(self.eh_frame)?; + Ok(()) + } + + /// For each section, call `f` once with a mutable reference. + pub fn for_each_mut<'a, F, E>(&'a mut self, mut f: F) -> result::Result<(), E> + where + F: FnMut(SectionId, &'a mut W) -> result::Result<(), E>, + { + macro_rules! f { + ($s:expr) => { + f($s.id(), &mut $s) + }; + } + // Ordered so that earlier sections do not reference later sections. + f!(self.debug_abbrev)?; + f!(self.debug_str)?; + f!(self.debug_line_str)?; + f!(self.debug_line)?; + f!(self.debug_ranges)?; + f!(self.debug_rnglists)?; + f!(self.debug_loc)?; + f!(self.debug_loclists)?; + f!(self.debug_info)?; + f!(self.debug_frame)?; + f!(self.eh_frame)?; + Ok(()) + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::{read, write::EndianVec, Endianity}; + + impl Sections> { + pub(crate) fn read(&self, endian: E) -> read::Dwarf> { + read::Dwarf::load(|section_id| -> read::Result<_> { + Ok(read::EndianSlice::new( + self.get(section_id).map(|w| w.slice()).unwrap_or_default(), + endian, + )) + }) + .unwrap() + } + } +} diff --git a/anneal/v2/vendor/gimli/src/write/str.rs b/anneal/v2/vendor/gimli/src/write/str.rs new file mode 100644 index 0000000000..11ea403a8e --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/str.rs @@ -0,0 +1,198 @@ +use alloc::vec::Vec; +use indexmap::IndexSet; +use std::ops::{Deref, DerefMut}; + +use crate::common::{DebugLineStrOffset, DebugStrOffset, SectionId}; +use crate::write::{BaseId, Result, Section, Writer}; + +// Requirements: +// - values are `[u8]`, null bytes are not allowed +// - insertion returns a fixed id +// - inserting a duplicate returns the id of the existing value +// - able to convert an id to a section offset +// Optional? +// - able to get an existing value given an id +// +// Limitations of current implementation (using IndexSet): +// - inserting requires either an allocation for duplicates, +// or a double lookup for non-duplicates +// - doesn't preserve offsets when updating an existing `.debug_str` section +// +// Possible changes: +// - calculate offsets as we add values, and use that as the id. +// This would avoid the need for DebugStrOffsets but would make it +// hard to implement `get`. +macro_rules! define_string_table { + ($name:ident, $id:ident, $section:ident, $offset:ident, $offsets:ident, $docs:expr) => { + #[doc=$docs] + #[derive(Debug, Default)] + pub struct $name { + base_id: BaseId, + strings: IndexSet>, + } + + impl $name { + /// Add a string to the string table and return its id. + /// + /// If the string already exists, then return the id of the existing string. + /// + /// # Panics + /// + /// Panics if `bytes` contains a null byte. + pub fn add(&mut self, bytes: T) -> $id + where + T: Into>, + { + let bytes = bytes.into(); + assert!(!bytes.contains(&0)); + let (index, _) = self.strings.insert_full(bytes); + $id::new(self.base_id, index) + } + + /// Return the number of strings in the table. + #[inline] + pub fn count(&self) -> usize { + self.strings.len() + } + + /// Get a reference to a string in the table. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + pub fn get(&self, id: $id) -> &[u8] { + debug_assert_eq!(self.base_id, id.base_id); + self.strings.get_index(id.index).map(Vec::as_slice).unwrap() + } + + /// Write the string table to the `.debug_str` section. + /// + /// Returns the offsets at which the strings are written. + pub fn write(&self, w: &mut $section) -> Result<$offsets> { + let mut offsets = Vec::new(); + let mut empty = None; + for bytes in self.strings.iter() { + offsets.push(w.offset()); + w.write(bytes)?; + if empty.is_none() { + empty = Some(w.offset()); + } + w.write_u8(0)?; + } + // Record the offset of the first null, for use as an empty string. + if let Some(empty) = empty { + offsets.push(empty); + } + + Ok($offsets { + base_id: self.base_id, + offsets, + }) + } + } + + impl $offsets { + pub(crate) fn get_empty(&self) -> Option<$id> { + if self.offsets.is_empty() { + None + } else { + // The last offset is always the empty string. + Some($id::new(self.base_id, self.offsets.len() - 1)) + } + } + } + }; +} + +define_id!(StringId, "An identifier for a string in a `StringTable`."); + +define_string_table!( + StringTable, + StringId, + DebugStr, + DebugStrOffset, + DebugStrOffsets, + "A table of strings that will be stored in a `.debug_str` section." +); + +define_section!(DebugStr, DebugStrOffset, "A writable `.debug_str` section."); + +define_offsets!( + DebugStrOffsets: StringId => DebugStrOffset, + "The section offsets of all strings within a `.debug_str` section." +); + +define_id!( + LineStringId, + "An identifier for a string in a `LineStringTable`." +); + +define_string_table!( + LineStringTable, + LineStringId, + DebugLineStr, + DebugLineStrOffset, + DebugLineStrOffsets, + "A table of strings that will be stored in a `.debug_line_str` section." +); + +define_section!( + DebugLineStr, + DebugLineStrOffset, + "A writable `.debug_line_str` section." +); + +define_offsets!( + DebugLineStrOffsets: LineStringId => DebugLineStrOffset, + "The section offsets of all strings within a `.debug_line_str` section." +); + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::read; + use crate::write::EndianVec; + use crate::LittleEndian; + + #[test] + fn test_string_table() { + let mut strings = StringTable::default(); + assert_eq!(strings.count(), 0); + let id1 = strings.add(&b"one"[..]); + let id2 = strings.add(&b"two"[..]); + assert_eq!(strings.add(&b"one"[..]), id1); + assert_eq!(strings.add(&b"two"[..]), id2); + assert_eq!(strings.get(id1), &b"one"[..]); + assert_eq!(strings.get(id2), &b"two"[..]); + assert_eq!(strings.count(), 2); + + let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian)); + let offsets = strings.write(&mut debug_str).unwrap(); + assert_eq!(debug_str.slice(), b"one\0two\0"); + assert_eq!(offsets.get(id1), DebugStrOffset(0)); + assert_eq!(offsets.get(id2), DebugStrOffset(4)); + assert_eq!(offsets.get(offsets.get_empty().unwrap()), DebugStrOffset(3)); + assert_eq!(offsets.count(), 3); + } + + #[test] + fn test_string_table_read() { + let mut strings = StringTable::default(); + let id1 = strings.add(&b"one"[..]); + let id2 = strings.add(&b"two"[..]); + + let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian)); + let offsets = strings.write(&mut debug_str).unwrap(); + + let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian); + let str1 = read_debug_str.get_str(offsets.get(id1)).unwrap(); + let str2 = read_debug_str.get_str(offsets.get(id2)).unwrap(); + let str3 = read_debug_str + .get_str(offsets.get(offsets.get_empty().unwrap())) + .unwrap(); + assert_eq!(str1.slice(), &b"one"[..]); + assert_eq!(str2.slice(), &b"two"[..]); + assert_eq!(str3.slice(), b""); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/unit.rs b/anneal/v2/vendor/gimli/src/write/unit.rs new file mode 100644 index 0000000000..fa70595925 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/unit.rs @@ -0,0 +1,3107 @@ +use alloc::vec::Vec; +use std::ops::{Deref, DerefMut}; +use std::slice; + +use crate::common::{ + DebugAbbrevOffset, DebugInfoOffset, DebugLineOffset, DebugMacinfoOffset, DebugMacroOffset, + DebugStrOffset, DebugTypeSignature, Encoding, Format, SectionId, +}; +use crate::constants; +use crate::leb128::write::{sleb128_size, uleb128_size}; +use crate::write::{ + Abbreviation, AbbreviationTable, Address, AttributeSpecification, BaseId, DebugLineStrOffsets, + DebugStrOffsets, Error, Expression, FileId, LineProgram, LineStringId, LocationListId, + LocationListOffsets, LocationListTable, RangeListId, RangeListOffsets, RangeListTable, + Reference, Result, Section, Sections, StringId, Writer, +}; + +define_id!(UnitId, "An identifier for a unit in a `UnitTable`."); + +define_id!(UnitEntryId, "An identifier for an entry in a `Unit`."); + +/// A table of units that will be stored in the `.debug_info` section. +#[derive(Debug, Default)] +pub struct UnitTable { + base_id: BaseId, + units: Vec, +} + +impl UnitTable { + /// Create a new unit and add it to the table. + /// + /// `address_size` must be in bytes. + /// + /// Returns the `UnitId` of the new unit. + #[inline] + pub fn add(&mut self, unit: Unit) -> UnitId { + let id = UnitId::new(self.base_id, self.units.len()); + self.units.push(unit); + id + } + + /// Return the number of units. + #[inline] + pub fn count(&self) -> usize { + self.units.len() + } + + /// Return the id of a unit. + /// + /// # Panics + /// + /// Panics if `index >= self.count()`. + #[inline] + pub fn id(&self, index: usize) -> UnitId { + assert!(index < self.count()); + UnitId::new(self.base_id, index) + } + + /// Get a reference to a unit. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get(&self, id: UnitId) -> &Unit { + debug_assert_eq!(self.base_id, id.base_id); + &self.units[id.index] + } + + /// Get a mutable reference to a unit. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get_mut(&mut self, id: UnitId) -> &mut Unit { + debug_assert_eq!(self.base_id, id.base_id); + &mut self.units[id.index] + } + + /// Get an iterator for the units. + pub fn iter(&self) -> impl Iterator { + self.units + .iter() + .enumerate() + .map(move |(index, unit)| (UnitId::new(self.base_id, index), unit)) + } + + /// Get a mutable iterator for the units. + pub fn iter_mut(&mut self) -> impl Iterator { + let base_id = self.base_id; + self.units + .iter_mut() + .enumerate() + .map(move |(index, unit)| (UnitId::new(base_id, index), unit)) + } + + /// Write the units to the given sections. + /// + /// `strings` must contain the `.debug_str` offsets of the corresponding + /// `StringTable`. + pub fn write( + &mut self, + sections: &mut Sections, + line_strings: &DebugLineStrOffsets, + strings: &DebugStrOffsets, + ) -> Result { + let mut offsets = DebugInfoOffsets { + base_id: self.base_id, + units: Vec::new(), + }; + for unit in &mut self.units { + // TODO: maybe share abbreviation tables + let abbrev_offset = sections.debug_abbrev.offset(); + let mut abbrevs = AbbreviationTable::default(); + + offsets.units.push(unit.write( + sections, + abbrev_offset, + &mut abbrevs, + line_strings, + strings, + )?); + + abbrevs.write(&mut sections.debug_abbrev)?; + } + + write_section_refs( + &mut sections.debug_info_refs, + &mut sections.debug_info.0, + &offsets, + )?; + write_section_refs( + &mut sections.debug_loc_refs, + &mut sections.debug_loc.0, + &offsets, + )?; + write_section_refs( + &mut sections.debug_loclists_refs, + &mut sections.debug_loclists.0, + &offsets, + )?; + + Ok(offsets) + } +} + +fn write_section_refs( + references: &mut Vec, + w: &mut W, + offsets: &DebugInfoOffsets, +) -> Result<()> { + for r in references.drain(..) { + let entry_offset = offsets + .entry(r.unit, r.entry) + .ok_or(Error::InvalidReference)? + .0; + debug_assert_ne!(entry_offset, 0); + w.write_offset_at(r.offset, entry_offset, SectionId::DebugInfo, r.size)?; + } + Ok(()) +} + +/// A unit's debugging information. +#[derive(Debug)] +pub struct Unit { + base_id: BaseId, + /// The encoding parameters for this unit. + encoding: Encoding, + /// The line number program for this unit. + pub line_program: LineProgram, + /// A table of range lists used by this unit. + pub ranges: RangeListTable, + /// A table of location lists used by this unit. + pub locations: LocationListTable, + /// All entries in this unit. The order is unrelated to the tree order. + // Requirements: + // - entries form a tree + // - entries can be added in any order + // - entries have a fixed id + // - able to quickly lookup an entry from its id + // Limitations of current implementation: + // - mutable iteration of children is messy due to borrow checker + entries: Vec, + /// The index of the root entry in entries. + root: UnitEntryId, +} + +impl Unit { + /// Create a new `Unit`. + pub fn new(encoding: Encoding, line_program: LineProgram) -> Self { + let base_id = BaseId::default(); + let ranges = RangeListTable::default(); + let locations = LocationListTable::default(); + let mut entries = Vec::new(); + let root = DebuggingInformationEntry::new( + base_id, + &mut entries, + None, + constants::DW_TAG_compile_unit, + ); + Unit { + base_id, + encoding, + line_program, + ranges, + locations, + entries, + root, + } + } + + /// Return the encoding parameters for this unit. + #[inline] + pub fn encoding(&self) -> Encoding { + self.encoding + } + + /// Return the DWARF version for this unit. + #[inline] + pub fn version(&self) -> u16 { + self.encoding.version + } + + /// Return the address size in bytes for this unit. + #[inline] + pub fn address_size(&self) -> u8 { + self.encoding.address_size + } + + /// Return the DWARF format for this unit. + #[inline] + pub fn format(&self) -> Format { + self.encoding.format + } + + /// Return the number of `DebuggingInformationEntry`s created for this unit. + /// + /// This includes entries that no longer have a parent. + #[inline] + pub fn count(&self) -> usize { + self.entries.len() + } + + /// Return the id of the root entry. + #[inline] + pub fn root(&self) -> UnitEntryId { + self.root + } + + /// Add a new `DebuggingInformationEntry` to this unit and return its id. + /// + /// The `parent` must be within the same unit. + /// + /// # Panics + /// + /// Panics if `parent` is invalid. + #[inline] + pub fn add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId { + debug_assert_eq!(self.base_id, parent.base_id); + DebuggingInformationEntry::new(self.base_id, &mut self.entries, Some(parent), tag) + } + + /// Get a reference to an entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get(&self, id: UnitEntryId) -> &DebuggingInformationEntry { + debug_assert_eq!(self.base_id, id.base_id); + &self.entries[id.index] + } + + /// Get a mutable reference to an entry. + /// + /// # Panics + /// + /// Panics if `id` is invalid. + #[inline] + pub fn get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry { + debug_assert_eq!(self.base_id, id.base_id); + &mut self.entries[id.index] + } + + /// Return true if `self.line_program` is used by a DIE. + fn line_program_in_use(&self) -> bool { + if self.line_program.is_none() { + return false; + } + if !self.line_program.is_empty() { + return true; + } + + for entry in &self.entries { + for attr in &entry.attrs { + if let AttributeValue::FileIndex(Some(_)) = attr.value { + return true; + } + } + } + + false + } + + /// Write the unit to the given sections. + pub(crate) fn write( + &mut self, + sections: &mut Sections, + abbrev_offset: DebugAbbrevOffset, + abbrevs: &mut AbbreviationTable, + line_strings: &DebugLineStrOffsets, + strings: &DebugStrOffsets, + ) -> Result { + let line_program = if self.line_program_in_use() { + self.entries[self.root.index] + .set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + Some(self.line_program.write( + &mut sections.debug_line, + self.encoding, + line_strings, + strings, + )?) + } else { + self.entries[self.root.index].delete(constants::DW_AT_stmt_list); + None + }; + + // TODO: use .debug_types for type units in DWARF v4. + let w = &mut sections.debug_info; + + let mut offsets = UnitOffsets { + base_id: self.base_id, + unit: w.offset(), + // Entries can be written in any order, so create the complete vec now. + entries: vec![EntryOffset::none(); self.entries.len()], + }; + + let length_offset = w.write_initial_length(self.format())?; + let length_base = w.len(); + + w.write_u16(self.version())?; + if 2 <= self.version() && self.version() <= 4 { + w.write_offset( + abbrev_offset.0, + SectionId::DebugAbbrev, + self.format().word_size(), + )?; + w.write_u8(self.address_size())?; + } else if self.version() == 5 { + w.write_u8(constants::DW_UT_compile.0)?; + w.write_u8(self.address_size())?; + w.write_offset( + abbrev_offset.0, + SectionId::DebugAbbrev, + self.format().word_size(), + )?; + } else { + return Err(Error::UnsupportedVersion(self.version())); + } + + // Calculate all DIE offsets, so that we are able to output references to them. + // However, references to base types in expressions use ULEB128, so base types + // must be moved to the front before we can calculate offsets. + self.reorder_base_types(); + let mut offset = w.len(); + self.entries[self.root.index].calculate_offsets( + self, + &mut offset, + &mut offsets, + abbrevs, + )?; + + let range_lists = self.ranges.write(sections, self.encoding)?; + // Location lists can't be written until we have DIE offsets. + let loc_lists = self + .locations + .write(sections, self.encoding, Some(&offsets))?; + + let w = &mut sections.debug_info; + let mut unit_refs = Vec::new(); + self.entries[self.root.index].write( + w, + &mut sections.debug_info_refs, + &mut unit_refs, + self, + &mut offsets, + line_program, + line_strings, + strings, + &range_lists, + &loc_lists, + )?; + + let length = (w.len() - length_base) as u64; + w.write_initial_length_at(length_offset, length, self.format())?; + + for (offset, entry) in unit_refs { + // This does not need relocation. + w.write_udata_at( + offset.0, + offsets.unit_offset(entry).ok_or(Error::InvalidReference)?, + self.format().word_size(), + )?; + } + + Ok(offsets) + } + + /// Reorder base types to come first so that typed stack operations + /// can get their offset. + fn reorder_base_types(&mut self) { + let root = &self.entries[self.root.index]; + let mut root_children = Vec::with_capacity(root.children.len()); + for entry in &root.children { + if self.entries[entry.index].tag == constants::DW_TAG_base_type { + root_children.push(*entry); + } + } + for entry in &root.children { + if self.entries[entry.index].tag != constants::DW_TAG_base_type { + root_children.push(*entry); + } + } + self.entries[self.root.index].children = root_children; + } +} + +/// A Debugging Information Entry (DIE). +/// +/// DIEs have a set of attributes and optionally have children DIEs as well. +/// +/// DIEs form a tree without any cycles. This is enforced by specifying the +/// parent when creating a DIE, and disallowing changes of parent. +#[derive(Debug)] +pub struct DebuggingInformationEntry { + id: UnitEntryId, + parent: Option, + tag: constants::DwTag, + /// Whether to emit `DW_AT_sibling`. + sibling: bool, + attrs: Vec, + children: Vec, +} + +impl DebuggingInformationEntry { + /// Create a new `DebuggingInformationEntry`. + /// + /// # Panics + /// + /// Panics if `parent` is invalid. + #[allow(clippy::new_ret_no_self)] + fn new( + base_id: BaseId, + entries: &mut Vec, + parent: Option, + tag: constants::DwTag, + ) -> UnitEntryId { + let id = UnitEntryId::new(base_id, entries.len()); + entries.push(DebuggingInformationEntry { + id, + parent, + tag, + sibling: false, + attrs: Vec::new(), + children: Vec::new(), + }); + if let Some(parent) = parent { + debug_assert_eq!(base_id, parent.base_id); + assert_ne!(parent, id); + entries[parent.index].children.push(id); + } + id + } + + /// Return the id of this entry. + #[inline] + pub fn id(&self) -> UnitEntryId { + self.id + } + + /// Return the parent of this entry. + #[inline] + pub fn parent(&self) -> Option { + self.parent + } + + /// Return the tag of this entry. + #[inline] + pub fn tag(&self) -> constants::DwTag { + self.tag + } + + /// Return `true` if a `DW_AT_sibling` attribute will be emitted. + #[inline] + pub fn sibling(&self) -> bool { + self.sibling + } + + /// Set whether a `DW_AT_sibling` attribute will be emitted. + /// + /// The attribute will only be emitted if the DIE has children. + #[inline] + pub fn set_sibling(&mut self, sibling: bool) { + self.sibling = sibling; + } + + /// Iterate over the attributes of this entry. + #[inline] + pub fn attrs(&self) -> slice::Iter<'_, Attribute> { + self.attrs.iter() + } + + /// Iterate over the attributes of this entry for modification. + #[inline] + pub fn attrs_mut(&mut self) -> slice::IterMut<'_, Attribute> { + self.attrs.iter_mut() + } + + /// Get an attribute. + pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> { + self.attrs + .iter() + .find(|attr| attr.name == name) + .map(|attr| &attr.value) + } + + /// Get an attribute for modification. + pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> { + self.attrs + .iter_mut() + .find(|attr| attr.name == name) + .map(|attr| &mut attr.value) + } + + /// Set an attribute. + /// + /// Replaces any existing attribute with the same name. + /// + /// # Panics + /// + /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead. + pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) { + assert_ne!(name, constants::DW_AT_sibling); + if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) { + attr.value = value; + return; + } + self.attrs.push(Attribute { name, value }); + } + + /// Delete an attribute. + /// + /// Replaces any existing attribute with the same name. + pub fn delete(&mut self, name: constants::DwAt) { + self.attrs.retain(|x| x.name != name); + } + + /// Iterate over the children of this entry. + /// + /// Note: use `Unit::add` to add a new child to this entry. + #[inline] + pub fn children(&self) -> slice::Iter<'_, UnitEntryId> { + self.children.iter() + } + + /// Delete a child entry and all of its children. + pub fn delete_child(&mut self, id: UnitEntryId) { + self.children.retain(|&child| child != id); + } + + /// Return the type abbreviation for this DIE. + fn abbreviation(&self, encoding: Encoding) -> Result { + let mut attrs = Vec::new(); + + if self.sibling && !self.children.is_empty() { + let form = match encoding.format { + Format::Dwarf32 => constants::DW_FORM_ref4, + Format::Dwarf64 => constants::DW_FORM_ref8, + }; + attrs.push(AttributeSpecification::new(constants::DW_AT_sibling, form)); + } + + for attr in &self.attrs { + attrs.push(attr.specification(encoding)?); + } + + Ok(Abbreviation::new( + self.tag, + !self.children.is_empty(), + attrs, + )) + } + + fn calculate_offsets( + &self, + unit: &Unit, + offset: &mut usize, + offsets: &mut UnitOffsets, + abbrevs: &mut AbbreviationTable, + ) -> Result<()> { + offsets.entries[self.id.index].offset = DebugInfoOffset(*offset); + offsets.entries[self.id.index].abbrev = abbrevs.add(self.abbreviation(unit.encoding())?); + *offset += self.size(unit, offsets)?; + if !self.children.is_empty() { + for child in &self.children { + unit.entries[child.index].calculate_offsets(unit, offset, offsets, abbrevs)?; + } + // Null child + *offset += 1; + } + Ok(()) + } + + fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> Result { + let mut size = uleb128_size(offsets.abbrev(self.id)); + if self.sibling && !self.children.is_empty() { + size += unit.format().word_size() as usize; + } + for attr in &self.attrs { + size += attr.value.size(unit, offsets)?; + } + Ok(size) + } + + /// Write the entry to the given sections. + fn write( + &self, + w: &mut DebugInfo, + debug_info_refs: &mut Vec, + unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>, + unit: &Unit, + offsets: &mut UnitOffsets, + line_program: Option, + line_strings: &DebugLineStrOffsets, + strings: &DebugStrOffsets, + range_lists: &RangeListOffsets, + loc_lists: &LocationListOffsets, + ) -> Result<()> { + debug_assert_eq!(offsets.debug_info_offset(self.id), Some(w.offset())); + w.write_uleb128(offsets.abbrev(self.id))?; + + let sibling_offset = if self.sibling && !self.children.is_empty() { + let offset = w.offset(); + w.write_udata(0, unit.format().word_size())?; + Some(offset) + } else { + None + }; + + for attr in &self.attrs { + attr.value.write( + w, + debug_info_refs, + unit_refs, + unit, + offsets, + line_program, + line_strings, + strings, + range_lists, + loc_lists, + )?; + } + + if !self.children.is_empty() { + for child in &self.children { + unit.entries[child.index].write( + w, + debug_info_refs, + unit_refs, + unit, + offsets, + line_program, + line_strings, + strings, + range_lists, + loc_lists, + )?; + } + // Null child + w.write_u8(0)?; + } + + if let Some(offset) = sibling_offset { + let next_offset = (w.offset().0 - offsets.unit.0) as u64; + // This does not need relocation. + w.write_udata_at(offset.0, next_offset, unit.format().word_size())?; + } + Ok(()) + } +} + +/// An attribute in a `DebuggingInformationEntry`, consisting of a name and +/// associated value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Attribute { + name: constants::DwAt, + value: AttributeValue, +} + +impl Attribute { + /// Get the name of this attribute. + #[inline] + pub fn name(&self) -> constants::DwAt { + self.name + } + + /// Get the value of this attribute. + #[inline] + pub fn get(&self) -> &AttributeValue { + &self.value + } + + /// Set the value of this attribute. + #[inline] + pub fn set(&mut self, value: AttributeValue) { + self.value = value; + } + + /// Return the type specification for this attribute. + fn specification(&self, encoding: Encoding) -> Result { + Ok(AttributeSpecification::new( + self.name, + self.value.form(encoding)?, + )) + } +} + +/// The value of an attribute in a `DebuggingInformationEntry`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AttributeValue { + /// "Refers to some location in the address space of the described program." + Address(Address), + + /// A slice of an arbitrary number of bytes. + Block(Vec), + + /// A one byte constant data value. How to interpret the byte depends on context. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data1(u8), + + /// A two byte constant data value. How to interpret the bytes depends on context. + /// + /// This value will be converted to the target endian before writing. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data2(u16), + + /// A four byte constant data value. How to interpret the bytes depends on context. + /// + /// This value will be converted to the target endian before writing. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data4(u32), + + /// An eight byte constant data value. How to interpret the bytes depends on context. + /// + /// This value will be converted to the target endian before writing. + /// + /// From section 7 of the standard: "Depending on context, it may be a + /// signed integer, an unsigned integer, a floating-point constant, or + /// anything else." + Data8(u64), + + /// A signed integer constant. + Sdata(i64), + + /// An unsigned integer constant. + Udata(u64), + + /// "The information bytes contain a DWARF expression (see Section 2.5) or + /// location description (see Section 2.6)." + Exprloc(Expression), + + /// A boolean that indicates presence or absence of the attribute. + Flag(bool), + + /// An attribute that is always present. + FlagPresent, + + /// A reference to a `DebuggingInformationEntry` in this unit. + UnitRef(UnitEntryId), + + /// A reference to a `DebuggingInformationEntry` in a potentially different unit. + DebugInfoRef(Reference), + + /// An offset into the `.debug_info` section of the supplementary object file. + /// + /// The API does not currently assist with generating this offset. + /// This variant will be removed from the API once support for writing + /// supplementary object files is implemented. + DebugInfoRefSup(DebugInfoOffset), + + /// A reference to a line number program. + LineProgramRef, + + /// A reference to a location list. + LocationListRef(LocationListId), + + /// An offset into the `.debug_macinfo` section. + /// + /// The API does not currently assist with generating this offset. + /// This variant will be removed from the API once support for writing + /// `.debug_macinfo` sections is implemented. + DebugMacinfoRef(DebugMacinfoOffset), + + /// An offset into the `.debug_macro` section. + /// + /// The API does not currently assist with generating this offset. + /// This variant will be removed from the API once support for writing + /// `.debug_macro` sections is implemented. + DebugMacroRef(DebugMacroOffset), + + /// A reference to a range list. + RangeListRef(RangeListId), + + /// A type signature. + /// + /// The API does not currently assist with generating this signature. + /// This variant will be removed from the API once support for writing + /// `.debug_types` sections is implemented. + DebugTypesRef(DebugTypeSignature), + + /// A reference to a string in the `.debug_str` section. + StringRef(StringId), + + /// An offset into the `.debug_str` section of the supplementary object file. + /// + /// The API does not currently assist with generating this offset. + /// This variant will be removed from the API once support for writing + /// supplementary object files is implemented. + DebugStrRefSup(DebugStrOffset), + + /// A reference to a string in the `.debug_line_str` section. + LineStringRef(LineStringId), + + /// A slice of bytes representing a string. Must not include null bytes. + /// Not guaranteed to be UTF-8 or anything like that. + String(Vec), + + /// The value of a `DW_AT_encoding` attribute. + Encoding(constants::DwAte), + + /// The value of a `DW_AT_decimal_sign` attribute. + DecimalSign(constants::DwDs), + + /// The value of a `DW_AT_endianity` attribute. + Endianity(constants::DwEnd), + + /// The value of a `DW_AT_accessibility` attribute. + Accessibility(constants::DwAccess), + + /// The value of a `DW_AT_visibility` attribute. + Visibility(constants::DwVis), + + /// The value of a `DW_AT_virtuality` attribute. + Virtuality(constants::DwVirtuality), + + /// The value of a `DW_AT_language` attribute. + Language(constants::DwLang), + + /// The value of a `DW_AT_address_class` attribute. + AddressClass(constants::DwAddr), + + /// The value of a `DW_AT_identifier_case` attribute. + IdentifierCase(constants::DwId), + + /// The value of a `DW_AT_calling_convention` attribute. + CallingConvention(constants::DwCc), + + /// The value of a `DW_AT_inline` attribute. + Inline(constants::DwInl), + + /// The value of a `DW_AT_ordering` attribute. + Ordering(constants::DwOrd), + + /// An index into the filename entries from the line number information + /// table for the unit containing this value. + FileIndex(Option), +} + +impl AttributeValue { + /// Return the form that will be used to encode this value. + pub fn form(&self, encoding: Encoding) -> Result { + // TODO: missing forms: + // - DW_FORM_indirect + // - DW_FORM_implicit_const + // - FW_FORM_block1/block2/block4 + // - DW_FORM_str/strx1/strx2/strx3/strx4 + // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4 + // - DW_FORM_data16 + // - DW_FORM_line_strp + // - DW_FORM_loclistx + // - DW_FORM_rnglistx + let form = match *self { + AttributeValue::Address(_) => constants::DW_FORM_addr, + AttributeValue::Block(_) => constants::DW_FORM_block, + AttributeValue::Data1(_) => constants::DW_FORM_data1, + AttributeValue::Data2(_) => constants::DW_FORM_data2, + AttributeValue::Data4(_) => constants::DW_FORM_data4, + AttributeValue::Data8(_) => constants::DW_FORM_data8, + AttributeValue::Exprloc(_) => constants::DW_FORM_exprloc, + AttributeValue::Flag(_) => constants::DW_FORM_flag, + AttributeValue::FlagPresent => constants::DW_FORM_flag_present, + AttributeValue::UnitRef(_) => { + // Using a fixed size format lets us write a placeholder before we know + // the value. + match encoding.format { + Format::Dwarf32 => constants::DW_FORM_ref4, + Format::Dwarf64 => constants::DW_FORM_ref8, + } + } + AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr, + AttributeValue::DebugInfoRefSup(_) => { + // TODO: should this depend on the size of supplementary section? + match encoding.format { + Format::Dwarf32 => constants::DW_FORM_ref_sup4, + Format::Dwarf64 => constants::DW_FORM_ref_sup8, + } + } + AttributeValue::LineProgramRef + | AttributeValue::LocationListRef(_) + | AttributeValue::DebugMacinfoRef(_) + | AttributeValue::DebugMacroRef(_) + | AttributeValue::RangeListRef(_) => { + if encoding.version == 2 || encoding.version == 3 { + match encoding.format { + Format::Dwarf32 => constants::DW_FORM_data4, + Format::Dwarf64 => constants::DW_FORM_data8, + } + } else { + constants::DW_FORM_sec_offset + } + } + AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8, + AttributeValue::StringRef(_) => constants::DW_FORM_strp, + AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup, + AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp, + AttributeValue::String(_) => constants::DW_FORM_string, + AttributeValue::Encoding(_) + | AttributeValue::DecimalSign(_) + | AttributeValue::Endianity(_) + | AttributeValue::Accessibility(_) + | AttributeValue::Visibility(_) + | AttributeValue::Virtuality(_) + | AttributeValue::Language(_) + | AttributeValue::AddressClass(_) + | AttributeValue::IdentifierCase(_) + | AttributeValue::CallingConvention(_) + | AttributeValue::Inline(_) + | AttributeValue::Ordering(_) + | AttributeValue::FileIndex(_) + | AttributeValue::Udata(_) => constants::DW_FORM_udata, + AttributeValue::Sdata(_) => constants::DW_FORM_sdata, + }; + Ok(form) + } + + fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> Result { + macro_rules! debug_assert_form { + ($form:expr) => { + debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form) + }; + } + Ok(match *self { + AttributeValue::Address(_) => { + debug_assert_form!(constants::DW_FORM_addr); + unit.address_size() as usize + } + AttributeValue::Block(ref val) => { + debug_assert_form!(constants::DW_FORM_block); + uleb128_size(val.len() as u64) + val.len() + } + AttributeValue::Data1(_) => { + debug_assert_form!(constants::DW_FORM_data1); + 1 + } + AttributeValue::Data2(_) => { + debug_assert_form!(constants::DW_FORM_data2); + 2 + } + AttributeValue::Data4(_) => { + debug_assert_form!(constants::DW_FORM_data4); + 4 + } + AttributeValue::Data8(_) => { + debug_assert_form!(constants::DW_FORM_data8); + 8 + } + AttributeValue::Sdata(val) => { + debug_assert_form!(constants::DW_FORM_sdata); + sleb128_size(val) + } + AttributeValue::Udata(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val) + } + AttributeValue::Exprloc(ref val) => { + debug_assert_form!(constants::DW_FORM_exprloc); + let size = val.size(unit.encoding(), Some(offsets))?; + uleb128_size(size as u64) + size + } + AttributeValue::Flag(_) => { + debug_assert_form!(constants::DW_FORM_flag); + 1 + } + AttributeValue::FlagPresent => { + debug_assert_form!(constants::DW_FORM_flag_present); + 0 + } + AttributeValue::UnitRef(_) => { + match unit.format() { + Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4), + Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8), + } + unit.format().word_size() as usize + } + AttributeValue::DebugInfoRef(_) => { + debug_assert_form!(constants::DW_FORM_ref_addr); + if unit.version() == 2 { + unit.address_size() as usize + } else { + unit.format().word_size() as usize + } + } + AttributeValue::DebugInfoRefSup(_) => { + match unit.format() { + Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4), + Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8), + } + unit.format().word_size() as usize + } + AttributeValue::LineProgramRef => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + unit.format().word_size() as usize + } + AttributeValue::LocationListRef(_) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + unit.format().word_size() as usize + } + AttributeValue::DebugMacinfoRef(_) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + unit.format().word_size() as usize + } + AttributeValue::DebugMacroRef(_) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + unit.format().word_size() as usize + } + AttributeValue::RangeListRef(_) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + unit.format().word_size() as usize + } + AttributeValue::DebugTypesRef(_) => { + debug_assert_form!(constants::DW_FORM_ref_sig8); + 8 + } + AttributeValue::StringRef(_) => { + debug_assert_form!(constants::DW_FORM_strp); + unit.format().word_size() as usize + } + AttributeValue::DebugStrRefSup(_) => { + debug_assert_form!(constants::DW_FORM_strp_sup); + unit.format().word_size() as usize + } + AttributeValue::LineStringRef(_) => { + debug_assert_form!(constants::DW_FORM_line_strp); + unit.format().word_size() as usize + } + AttributeValue::String(ref val) => { + debug_assert_form!(constants::DW_FORM_string); + val.len() + 1 + } + AttributeValue::Encoding(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::DecimalSign(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Endianity(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Accessibility(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Visibility(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Virtuality(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Language(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::AddressClass(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0) + } + AttributeValue::IdentifierCase(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::CallingConvention(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Inline(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::Ordering(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.0 as u64) + } + AttributeValue::FileIndex(val) => { + debug_assert_form!(constants::DW_FORM_udata); + uleb128_size(val.map(|id| id.raw(unit.version())).unwrap_or(0)) + } + }) + } + + /// Write the attribute value to the given sections. + fn write( + &self, + w: &mut DebugInfo, + debug_info_refs: &mut Vec, + unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>, + unit: &Unit, + offsets: &UnitOffsets, + line_program: Option, + line_strings: &DebugLineStrOffsets, + strings: &DebugStrOffsets, + range_lists: &RangeListOffsets, + loc_lists: &LocationListOffsets, + ) -> Result<()> { + macro_rules! debug_assert_form { + ($form:expr) => { + debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form) + }; + } + match *self { + AttributeValue::Address(val) => { + debug_assert_form!(constants::DW_FORM_addr); + w.write_address(val, unit.address_size())?; + } + AttributeValue::Block(ref val) => { + debug_assert_form!(constants::DW_FORM_block); + w.write_uleb128(val.len() as u64)?; + w.write(val)?; + } + AttributeValue::Data1(val) => { + debug_assert_form!(constants::DW_FORM_data1); + w.write_u8(val)?; + } + AttributeValue::Data2(val) => { + debug_assert_form!(constants::DW_FORM_data2); + w.write_u16(val)?; + } + AttributeValue::Data4(val) => { + debug_assert_form!(constants::DW_FORM_data4); + w.write_u32(val)?; + } + AttributeValue::Data8(val) => { + debug_assert_form!(constants::DW_FORM_data8); + w.write_u64(val)?; + } + AttributeValue::Sdata(val) => { + debug_assert_form!(constants::DW_FORM_sdata); + w.write_sleb128(val)?; + } + AttributeValue::Udata(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(val)?; + } + AttributeValue::Exprloc(ref val) => { + debug_assert_form!(constants::DW_FORM_exprloc); + w.write_uleb128(val.size(unit.encoding(), Some(offsets))? as u64)?; + val.write( + &mut w.0, + Some(debug_info_refs), + unit.encoding(), + Some(offsets), + )?; + } + AttributeValue::Flag(val) => { + debug_assert_form!(constants::DW_FORM_flag); + w.write_u8(val as u8)?; + } + AttributeValue::FlagPresent => { + debug_assert_form!(constants::DW_FORM_flag_present); + } + AttributeValue::UnitRef(id) => { + match unit.format() { + Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4), + Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8), + } + unit_refs.push((w.offset(), id)); + w.write_udata(0, unit.format().word_size())?; + } + AttributeValue::DebugInfoRef(reference) => { + debug_assert_form!(constants::DW_FORM_ref_addr); + let size = if unit.version() == 2 { + unit.address_size() + } else { + unit.format().word_size() + }; + match reference { + Reference::Symbol(symbol) => w.write_reference(symbol, size)?, + Reference::Entry(unit, entry) => { + debug_info_refs.push(DebugInfoReference { + offset: w.len(), + unit, + entry, + size, + }); + w.write_udata(0, size)?; + } + } + } + AttributeValue::DebugInfoRefSup(val) => { + match unit.format() { + Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4), + Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8), + } + w.write_udata(val.0 as u64, unit.format().word_size())?; + } + AttributeValue::LineProgramRef => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + match line_program { + Some(line_program) => { + w.write_offset( + line_program.0, + SectionId::DebugLine, + unit.format().word_size(), + )?; + } + None => return Err(Error::InvalidAttributeValue), + } + } + AttributeValue::LocationListRef(val) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + let section = if unit.version() <= 4 { + SectionId::DebugLoc + } else { + SectionId::DebugLocLists + }; + w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?; + } + AttributeValue::DebugMacinfoRef(val) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?; + } + AttributeValue::DebugMacroRef(val) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?; + } + AttributeValue::RangeListRef(val) => { + if unit.version() >= 4 { + debug_assert_form!(constants::DW_FORM_sec_offset); + } + let section = if unit.version() <= 4 { + SectionId::DebugRanges + } else { + SectionId::DebugRngLists + }; + w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?; + } + AttributeValue::DebugTypesRef(val) => { + debug_assert_form!(constants::DW_FORM_ref_sig8); + w.write_u64(val.0)?; + } + AttributeValue::StringRef(val) => { + debug_assert_form!(constants::DW_FORM_strp); + w.write_offset( + strings.get(val).0, + SectionId::DebugStr, + unit.format().word_size(), + )?; + } + AttributeValue::DebugStrRefSup(val) => { + debug_assert_form!(constants::DW_FORM_strp_sup); + w.write_udata(val.0 as u64, unit.format().word_size())?; + } + AttributeValue::LineStringRef(val) => { + debug_assert_form!(constants::DW_FORM_line_strp); + w.write_offset( + line_strings.get(val).0, + SectionId::DebugLineStr, + unit.format().word_size(), + )?; + } + AttributeValue::String(ref val) => { + debug_assert_form!(constants::DW_FORM_string); + w.write(val)?; + w.write_u8(0)?; + } + AttributeValue::Encoding(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::DecimalSign(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Endianity(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Accessibility(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Visibility(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Virtuality(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Language(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::AddressClass(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(val.0)?; + } + AttributeValue::IdentifierCase(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::CallingConvention(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Inline(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::Ordering(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(u64::from(val.0))?; + } + AttributeValue::FileIndex(val) => { + debug_assert_form!(constants::DW_FORM_udata); + w.write_uleb128(val.map(|id| id.raw(unit.version())).unwrap_or(0))?; + } + } + Ok(()) + } +} + +define_section!( + DebugInfo, + DebugInfoOffset, + "A writable `.debug_info` section." +); + +/// The section offsets of all elements within a `.debug_info` section. +#[derive(Debug, Default)] +pub struct DebugInfoOffsets { + base_id: BaseId, + units: Vec, +} + +impl DebugInfoOffsets { + /// Get the `.debug_info` section offset for the given unit. + #[inline] + pub fn unit(&self, unit: UnitId) -> DebugInfoOffset { + debug_assert_eq!(self.base_id, unit.base_id); + self.units[unit.index].unit + } + + /// Get the `.debug_info` section offset for the given entry. + #[inline] + pub fn entry(&self, unit: UnitId, entry: UnitEntryId) -> Option { + debug_assert_eq!(self.base_id, unit.base_id); + self.units[unit.index].debug_info_offset(entry) + } +} + +/// The section offsets of all elements of a unit within a `.debug_info` section. +#[derive(Debug)] +pub(crate) struct UnitOffsets { + base_id: BaseId, + unit: DebugInfoOffset, + entries: Vec, +} + +impl UnitOffsets { + /// Get the `.debug_info` offset for the given entry. + /// + /// Returns `None` if the offset has not been calculated yet. + #[inline] + fn debug_info_offset(&self, entry: UnitEntryId) -> Option { + debug_assert_eq!(self.base_id, entry.base_id); + let offset = self.entries[entry.index].offset; + if offset.0 == 0 { + None + } else { + Some(offset) + } + } + + /// Get the unit offset for the given entry. + /// + /// Returns `None` if the offset has not been calculated yet. + /// This may occur if the entry is orphaned or if a reference + /// to the entry occurs before the entry itself is written. + #[inline] + pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> Option { + self.debug_info_offset(entry) + .map(|offset| (offset.0 - self.unit.0) as u64) + } + + /// Get the abbreviation code for the given entry. + #[inline] + pub(crate) fn abbrev(&self, entry: UnitEntryId) -> u64 { + debug_assert_eq!(self.base_id, entry.base_id); + self.entries[entry.index].abbrev + } +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct EntryOffset { + offset: DebugInfoOffset, + abbrev: u64, +} + +impl EntryOffset { + fn none() -> Self { + EntryOffset { + offset: DebugInfoOffset(0), + abbrev: 0, + } + } +} + +/// A reference to a `.debug_info` entry that has yet to be resolved. +#[derive(Debug, Clone, Copy)] +pub(crate) struct DebugInfoReference { + /// The offset within the section of the reference. + pub offset: usize, + /// The size of the reference. + pub size: u8, + /// The unit containing the entry. + pub unit: UnitId, + /// The entry being referenced. + pub entry: UnitEntryId, +} + +#[cfg(feature = "read")] +pub(crate) mod convert { + use super::*; + use crate::common::{DwoId, UnitSectionOffset}; + use crate::read::{self, Reader}; + use crate::write::{self, ConvertError, ConvertResult, LocationList, RangeList}; + use std::collections::HashMap; + + pub(crate) struct ConvertUnit> { + from_unit: read::Unit, + base_id: BaseId, + encoding: Encoding, + entries: Vec, + entry_offsets: Vec, + root: UnitEntryId, + } + + pub(crate) struct ConvertUnitContext<'a, R: Reader> { + pub dwarf: &'a read::Dwarf, + pub unit: &'a read::Unit, + pub line_strings: &'a mut write::LineStringTable, + pub strings: &'a mut write::StringTable, + pub ranges: &'a mut write::RangeListTable, + pub locations: &'a mut write::LocationListTable, + pub convert_address: &'a dyn Fn(u64) -> Option
, + pub base_address: Address, + pub line_program_offset: Option, + pub line_program_files: Vec, + pub entry_ids: &'a HashMap, + } + + impl UnitTable { + /// Create a unit table by reading the data in the given sections. + /// + /// This also updates the given tables with the values that are referenced from + /// attributes in this section. + /// + /// `convert_address` is a function to convert read addresses into the `Address` + /// type. For non-relocatable addresses, this function may simply return + /// `Address::Constant(address)`. For relocatable addresses, it is the caller's + /// responsibility to determine the symbol and addend corresponding to the address + /// and return `Address::Symbol { symbol, addend }`. + pub fn from>( + dwarf: &read::Dwarf, + line_strings: &mut write::LineStringTable, + strings: &mut write::StringTable, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult { + let base_id = BaseId::default(); + let mut unit_entries = Vec::new(); + let mut entry_ids = HashMap::new(); + + let mut from_units = dwarf.units(); + while let Some(from_unit) = from_units.next()? { + let unit_id = UnitId::new(base_id, unit_entries.len()); + unit_entries.push(Unit::convert_entries( + from_unit, + unit_id, + &mut entry_ids, + dwarf, + )?); + } + + // Attributes must be converted in a separate pass so that we can handle + // references to other compilation units. + let mut units = Vec::new(); + for unit_entries in unit_entries.drain(..) { + units.push(Unit::convert_attributes( + unit_entries, + &entry_ids, + dwarf, + line_strings, + strings, + convert_address, + )?); + } + + Ok(UnitTable { base_id, units }) + } + } + + impl Unit { + /// Create a unit by reading the data in the input sections. + /// + /// Does not add entry attributes. + pub(crate) fn convert_entries>( + from_header: read::UnitHeader, + unit_id: UnitId, + entry_ids: &mut HashMap, + dwarf: &read::Dwarf, + ) -> ConvertResult> { + match from_header.type_() { + read::UnitType::Compilation => (), + _ => return Err(ConvertError::UnsupportedUnitType), + } + let base_id = BaseId::default(); + + let from_unit = dwarf.unit(from_header)?; + let encoding = from_unit.encoding(); + + let mut entries = Vec::new(); + let mut entry_offsets = Vec::new(); + + let mut from_tree = from_unit.entries_tree(None)?; + let from_root = from_tree.root()?; + let root = DebuggingInformationEntry::convert_entry( + from_root, + &from_unit, + base_id, + &mut entries, + &mut entry_offsets, + entry_ids, + None, + unit_id, + )?; + + Ok(ConvertUnit { + from_unit, + base_id, + encoding, + entries, + entry_offsets, + root, + }) + } + + /// Create entry attributes by reading the data in the input sections. + fn convert_attributes>( + unit: ConvertUnit, + entry_ids: &HashMap, + dwarf: &read::Dwarf, + line_strings: &mut write::LineStringTable, + strings: &mut write::StringTable, + convert_address: &dyn Fn(u64) -> Option
, + ) -> ConvertResult { + let from_unit = unit.from_unit; + let base_address = + convert_address(from_unit.low_pc).ok_or(ConvertError::InvalidAddress)?; + + let (line_program_offset, line_program, line_program_files) = + match from_unit.line_program { + Some(ref from_program) => { + let from_program = from_program.clone(); + let line_program_offset = from_program.header().offset(); + let (line_program, line_program_files) = LineProgram::from( + from_program, + dwarf, + line_strings, + strings, + convert_address, + )?; + (Some(line_program_offset), line_program, line_program_files) + } + None => (None, LineProgram::none(), Vec::new()), + }; + + let mut ranges = RangeListTable::default(); + let mut locations = LocationListTable::default(); + + let mut context = ConvertUnitContext { + entry_ids, + dwarf, + unit: &from_unit, + line_strings, + strings, + ranges: &mut ranges, + locations: &mut locations, + convert_address, + base_address, + line_program_offset, + line_program_files, + }; + + let mut entries = unit.entries; + for entry in &mut entries { + entry.convert_attributes(&mut context, &unit.entry_offsets)?; + } + + Ok(Unit { + base_id: unit.base_id, + encoding: unit.encoding, + line_program, + ranges, + locations, + entries, + root: unit.root, + }) + } + } + + impl DebuggingInformationEntry { + /// Create an entry by reading the data in the input sections. + /// + /// Does not add the entry attributes. + fn convert_entry>( + from: read::EntriesTreeNode<'_, '_, '_, R>, + from_unit: &read::Unit, + base_id: BaseId, + entries: &mut Vec, + entry_offsets: &mut Vec, + entry_ids: &mut HashMap, + parent: Option, + unit_id: UnitId, + ) -> ConvertResult { + let from_entry = from.entry(); + let id = DebuggingInformationEntry::new(base_id, entries, parent, from_entry.tag()); + let offset = from_entry.offset(); + entry_offsets.push(offset); + entry_ids.insert(offset.to_unit_section_offset(from_unit), (unit_id, id)); + + let mut from_children = from.children(); + while let Some(from_child) = from_children.next()? { + DebuggingInformationEntry::convert_entry( + from_child, + from_unit, + base_id, + entries, + entry_offsets, + entry_ids, + Some(id), + unit_id, + )?; + } + Ok(id) + } + + /// Create an entry's attributes by reading the data in the input sections. + fn convert_attributes>( + &mut self, + context: &mut ConvertUnitContext<'_, R>, + entry_offsets: &[read::UnitOffset], + ) -> ConvertResult<()> { + let offset = entry_offsets[self.id.index]; + let from = context.unit.entry(offset)?; + let mut from_attrs = from.attrs(); + while let Some(from_attr) = from_attrs.next()? { + if from_attr.name() == constants::DW_AT_sibling { + // This may point to a null entry, so we have to treat it differently. + self.set_sibling(true); + } else if from_attr.name() == constants::DW_AT_GNU_locviews { + // This is a GNU extension that is not supported, and is safe to ignore. + // TODO: remove this when we support it. + } else if let Some(attr) = Attribute::from(context, &from_attr)? { + self.set(attr.name, attr.value); + } + } + Ok(()) + } + } + + impl Attribute { + /// Create an attribute by reading the data in the given sections. + pub(crate) fn from>( + context: &mut ConvertUnitContext<'_, R>, + from: &read::Attribute, + ) -> ConvertResult> { + let value = AttributeValue::from(context, from.value())?; + Ok(value.map(|value| Attribute { + name: from.name(), + value, + })) + } + } + + impl AttributeValue { + /// Create an attribute value by reading the data in the given sections. + pub(crate) fn from>( + context: &mut ConvertUnitContext<'_, R>, + from: read::AttributeValue, + ) -> ConvertResult> { + let to = match from { + read::AttributeValue::Addr(val) => match (context.convert_address)(val) { + Some(val) => AttributeValue::Address(val), + None => return Err(ConvertError::InvalidAddress), + }, + read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()), + read::AttributeValue::Data1(val) => AttributeValue::Data1(val), + read::AttributeValue::Data2(val) => AttributeValue::Data2(val), + read::AttributeValue::Data4(val) => AttributeValue::Data4(val), + read::AttributeValue::Data8(val) => AttributeValue::Data8(val), + read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val), + read::AttributeValue::Udata(val) => AttributeValue::Udata(val), + read::AttributeValue::Exprloc(expression) => { + let expression = Expression::from( + expression, + context.unit.encoding(), + Some(context.dwarf), + Some(context.unit), + Some(context.entry_ids), + context.convert_address, + )?; + AttributeValue::Exprloc(expression) + } + // TODO: it would be nice to preserve the flag form. + read::AttributeValue::Flag(val) => AttributeValue::Flag(val), + read::AttributeValue::DebugAddrBase(_base) => { + // We convert all address indices to addresses, + // so this is unneeded. + return Ok(None); + } + read::AttributeValue::DebugAddrIndex(index) => { + let val = context.dwarf.address(context.unit, index)?; + match (context.convert_address)(val) { + Some(val) => AttributeValue::Address(val), + None => return Err(ConvertError::InvalidAddress), + } + } + read::AttributeValue::UnitRef(val) => { + if !context.unit.header.is_valid_offset(val) { + return Err(ConvertError::InvalidUnitRef); + } + let id = context + .entry_ids + .get(&val.to_unit_section_offset(context.unit)) + .ok_or(ConvertError::InvalidUnitRef)?; + AttributeValue::UnitRef(id.1) + } + read::AttributeValue::DebugInfoRef(val) => { + // TODO: support relocation of this value + let id = context + .entry_ids + .get(&UnitSectionOffset::DebugInfoOffset(val)) + .ok_or(ConvertError::InvalidDebugInfoRef)?; + AttributeValue::DebugInfoRef(Reference::Entry(id.0, id.1)) + } + read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val), + read::AttributeValue::DebugLineRef(val) => { + // There should only be the line program in the CU DIE which we've already + // converted, so check if it matches that. + if Some(val) == context.line_program_offset { + AttributeValue::LineProgramRef + } else { + return Err(ConvertError::InvalidLineRef); + } + } + read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val), + read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val), + read::AttributeValue::LocationListsRef(val) => { + let iter = context + .dwarf + .locations + .raw_locations(val, context.unit.encoding())?; + let loc_list = LocationList::from(iter, context)?; + let loc_id = context.locations.add(loc_list); + AttributeValue::LocationListRef(loc_id) + } + read::AttributeValue::DebugLocListsBase(_base) => { + // We convert all location list indices to offsets, + // so this is unneeded. + return Ok(None); + } + read::AttributeValue::DebugLocListsIndex(index) => { + let offset = context.dwarf.locations_offset(context.unit, index)?; + let iter = context + .dwarf + .locations + .raw_locations(offset, context.unit.encoding())?; + let loc_list = LocationList::from(iter, context)?; + let loc_id = context.locations.add(loc_list); + AttributeValue::LocationListRef(loc_id) + } + read::AttributeValue::RangeListsRef(offset) => { + let offset = context.dwarf.ranges_offset_from_raw(context.unit, offset); + let iter = context.dwarf.raw_ranges(context.unit, offset)?; + let range_list = RangeList::from(iter, context)?; + let range_id = context.ranges.add(range_list); + AttributeValue::RangeListRef(range_id) + } + read::AttributeValue::DebugRngListsBase(_base) => { + // We convert all range list indices to offsets, + // so this is unneeded. + return Ok(None); + } + read::AttributeValue::DebugRngListsIndex(index) => { + let offset = context.dwarf.ranges_offset(context.unit, index)?; + let iter = context + .dwarf + .ranges + .raw_ranges(offset, context.unit.encoding())?; + let range_list = RangeList::from(iter, context)?; + let range_id = context.ranges.add(range_list); + AttributeValue::RangeListRef(range_id) + } + read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val), + read::AttributeValue::DebugStrRef(offset) => { + let r = context.dwarf.string(offset)?; + let id = context.strings.add(r.to_slice()?); + AttributeValue::StringRef(id) + } + read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val), + read::AttributeValue::DebugStrOffsetsBase(_base) => { + // We convert all string offsets to `.debug_str` references, + // so this is unneeded. + return Ok(None); + } + read::AttributeValue::DebugStrOffsetsIndex(index) => { + let offset = context.dwarf.string_offset(context.unit, index)?; + let r = context.dwarf.string(offset)?; + let id = context.strings.add(r.to_slice()?); + AttributeValue::StringRef(id) + } + read::AttributeValue::DebugLineStrRef(offset) => { + let r = context.dwarf.line_string(offset)?; + let id = context.line_strings.add(r.to_slice()?); + AttributeValue::LineStringRef(id) + } + read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()), + read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val), + read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val), + read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val), + read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val), + read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val), + read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val), + read::AttributeValue::Language(val) => AttributeValue::Language(val), + read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val), + read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val), + read::AttributeValue::CallingConvention(val) => { + AttributeValue::CallingConvention(val) + } + read::AttributeValue::Inline(val) => AttributeValue::Inline(val), + read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val), + read::AttributeValue::FileIndex(val) => { + if val == 0 && context.unit.encoding().version <= 4 { + AttributeValue::FileIndex(None) + } else { + match context.line_program_files.get(val as usize) { + Some(id) => AttributeValue::FileIndex(Some(*id)), + None => return Err(ConvertError::InvalidFileIndex), + } + } + } + // Should always be a more specific section reference. + read::AttributeValue::SecOffset(_) => { + return Err(ConvertError::InvalidAttributeValue); + } + read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val), + }; + Ok(Some(to)) + } + } +} + +#[cfg(test)] +#[cfg(feature = "read")] +mod tests { + use super::*; + use crate::common::LineEncoding; + use crate::constants; + use crate::read; + use crate::write::{ + Dwarf, DwarfUnit, EndianVec, LineString, Location, LocationList, Range, RangeList, + }; + use crate::LittleEndian; + use std::mem; + + #[test] + fn test_unit_table() { + let mut dwarf = Dwarf::new(); + let unit_id1 = dwarf.units.add(Unit::new( + Encoding { + version: 4, + address_size: 8, + format: Format::Dwarf32, + }, + LineProgram::none(), + )); + let unit2 = dwarf.units.add(Unit::new( + Encoding { + version: 2, + address_size: 4, + format: Format::Dwarf64, + }, + LineProgram::none(), + )); + let unit3 = dwarf.units.add(Unit::new( + Encoding { + version: 5, + address_size: 4, + format: Format::Dwarf32, + }, + LineProgram::none(), + )); + assert_eq!(dwarf.units.count(), 3); + { + let unit1 = dwarf.units.get_mut(unit_id1); + assert_eq!(unit1.version(), 4); + assert_eq!(unit1.address_size(), 8); + assert_eq!(unit1.format(), Format::Dwarf32); + assert_eq!(unit1.count(), 1); + + let root_id = unit1.root(); + assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0)); + { + let root = unit1.get_mut(root_id); + assert_eq!(root.id(), root_id); + assert!(root.parent().is_none()); + assert_eq!(root.tag(), constants::DW_TAG_compile_unit); + + // Test get/get_mut + assert!(root.get(constants::DW_AT_producer).is_none()); + assert!(root.get_mut(constants::DW_AT_producer).is_none()); + let mut producer = AttributeValue::String(b"root"[..].into()); + root.set(constants::DW_AT_producer, producer.clone()); + assert_eq!(root.get(constants::DW_AT_producer), Some(&producer)); + assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer)); + + // Test attrs + let mut attrs = root.attrs(); + let attr = attrs.next().unwrap(); + assert_eq!(attr.name(), constants::DW_AT_producer); + assert_eq!(attr.get(), &producer); + assert!(attrs.next().is_none()); + } + + let child1 = unit1.add(root_id, constants::DW_TAG_subprogram); + assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1)); + { + let child1 = unit1.get_mut(child1); + assert_eq!(child1.parent(), Some(root_id)); + + let tmp = AttributeValue::String(b"tmp"[..].into()); + child1.set(constants::DW_AT_name, tmp.clone()); + assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp)); + + // Test attrs_mut + let name = AttributeValue::StringRef(dwarf.strings.add(&b"child1"[..])); + { + let attr = child1.attrs_mut().next().unwrap(); + assert_eq!(attr.name(), constants::DW_AT_name); + attr.set(name.clone()); + } + assert_eq!(child1.get(constants::DW_AT_name), Some(&name)); + } + + let child2 = unit1.add(root_id, constants::DW_TAG_subprogram); + assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2)); + { + let child2 = unit1.get_mut(child2); + assert_eq!(child2.parent(), Some(root_id)); + + let tmp = AttributeValue::String(b"tmp"[..].into()); + child2.set(constants::DW_AT_name, tmp.clone()); + assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp)); + + // Test replace + let name = AttributeValue::StringRef(dwarf.strings.add(&b"child2"[..])); + child2.set(constants::DW_AT_name, name.clone()); + assert_eq!(child2.get(constants::DW_AT_name), Some(&name)); + } + + { + let root = unit1.get(root_id); + assert_eq!( + root.children().cloned().collect::>(), + vec![child1, child2] + ); + } + } + { + let unit2 = dwarf.units.get(unit2); + assert_eq!(unit2.version(), 2); + assert_eq!(unit2.address_size(), 4); + assert_eq!(unit2.format(), Format::Dwarf64); + assert_eq!(unit2.count(), 1); + + let root = unit2.root(); + assert_eq!(root, UnitEntryId::new(unit2.base_id, 0)); + let root = unit2.get(root); + assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0)); + assert!(root.parent().is_none()); + assert_eq!(root.tag(), constants::DW_TAG_compile_unit); + } + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + println!("{:?}", sections.debug_str); + println!("{:?}", sections.debug_info); + println!("{:?}", sections.debug_abbrev); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + + { + let read_unit1 = read_units.next().unwrap().unwrap(); + let unit1 = dwarf.units.get(unit_id1); + assert_eq!(unit1.version(), read_unit1.version()); + assert_eq!(unit1.address_size(), read_unit1.address_size()); + assert_eq!(unit1.format(), read_unit1.format()); + + let read_unit1 = read_dwarf.unit(read_unit1).unwrap(); + let mut read_entries = read_unit1.entries(); + + let root = unit1.get(unit1.root()); + { + let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(depth, 0); + assert_eq!(root.tag(), read_root.tag()); + assert!(read_root.has_children()); + + let producer = match root.get(constants::DW_AT_producer).unwrap() { + AttributeValue::String(ref producer) => &**producer, + otherwise => panic!("unexpected {:?}", otherwise), + }; + assert_eq!(producer, b"root"); + let read_producer = read_root + .attr_value(constants::DW_AT_producer) + .unwrap() + .unwrap(); + assert_eq!( + read_dwarf + .attr_string(&read_unit1, read_producer) + .unwrap() + .slice(), + producer + ); + } + + let mut children = root.children().cloned(); + + { + let child = children.next().unwrap(); + assert_eq!(child, UnitEntryId::new(unit1.base_id, 1)); + let child = unit1.get(child); + let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(depth, 1); + assert_eq!(child.tag(), read_child.tag()); + assert!(!read_child.has_children()); + + let name = match child.get(constants::DW_AT_name).unwrap() { + AttributeValue::StringRef(name) => *name, + otherwise => panic!("unexpected {:?}", otherwise), + }; + let name = dwarf.strings.get(name); + assert_eq!(name, b"child1"); + let read_name = read_child + .attr_value(constants::DW_AT_name) + .unwrap() + .unwrap(); + assert_eq!( + read_dwarf + .attr_string(&read_unit1, read_name) + .unwrap() + .slice(), + name + ); + } + + { + let child = children.next().unwrap(); + assert_eq!(child, UnitEntryId::new(unit1.base_id, 2)); + let child = unit1.get(child); + let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(depth, 0); + assert_eq!(child.tag(), read_child.tag()); + assert!(!read_child.has_children()); + + let name = match child.get(constants::DW_AT_name).unwrap() { + AttributeValue::StringRef(name) => *name, + otherwise => panic!("unexpected {:?}", otherwise), + }; + let name = dwarf.strings.get(name); + assert_eq!(name, b"child2"); + let read_name = read_child + .attr_value(constants::DW_AT_name) + .unwrap() + .unwrap(); + assert_eq!( + read_dwarf + .attr_string(&read_unit1, read_name) + .unwrap() + .slice(), + name + ); + } + + assert!(read_entries.next_dfs().unwrap().is_none()); + } + + { + let read_unit2 = read_units.next().unwrap().unwrap(); + let unit2 = dwarf.units.get(unit2); + assert_eq!(unit2.version(), read_unit2.version()); + assert_eq!(unit2.address_size(), read_unit2.address_size()); + assert_eq!(unit2.format(), read_unit2.format()); + + let abbrevs = read_dwarf.abbreviations(&read_unit2).unwrap(); + let mut read_entries = read_unit2.entries(&abbrevs); + + { + let root = unit2.get(unit2.root()); + let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(depth, 0); + assert_eq!(root.tag(), read_root.tag()); + assert!(!read_root.has_children()); + } + + assert!(read_entries.next_dfs().unwrap().is_none()); + } + + { + let read_unit3 = read_units.next().unwrap().unwrap(); + let unit3 = dwarf.units.get(unit3); + assert_eq!(unit3.version(), read_unit3.version()); + assert_eq!(unit3.address_size(), read_unit3.address_size()); + assert_eq!(unit3.format(), read_unit3.format()); + + let abbrevs = read_dwarf.abbreviations(&read_unit3).unwrap(); + let mut read_entries = read_unit3.entries(&abbrevs); + + { + let root = unit3.get(unit3.root()); + let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap(); + assert_eq!(depth, 0); + assert_eq!(root.tag(), read_root.tag()); + assert!(!read_root.has_children()); + } + + assert!(read_entries.next_dfs().unwrap().is_none()); + } + + assert!(read_units.next().unwrap().is_none()); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap(); + assert_eq!(convert_dwarf.units.count(), dwarf.units.count()); + + for i in 0..convert_dwarf.units.count() { + let unit_id = dwarf.units.id(i); + let unit = dwarf.units.get(unit_id); + let convert_unit_id = convert_dwarf.units.id(i); + let convert_unit = convert_dwarf.units.get(convert_unit_id); + assert_eq!(convert_unit.version(), unit.version()); + assert_eq!(convert_unit.address_size(), unit.address_size()); + assert_eq!(convert_unit.format(), unit.format()); + assert_eq!(convert_unit.count(), unit.count()); + + let root = unit.get(unit.root()); + let convert_root = convert_unit.get(convert_unit.root()); + assert_eq!(convert_root.tag(), root.tag()); + for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) { + assert_eq!(convert_attr, attr); + } + } + } + + #[test] + fn test_attribute_value() { + let string_data = "string data"; + let line_string_data = "line string data"; + + let data = vec![1, 2, 3, 4]; + let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian); + + let mut expression = Expression::new(); + expression.op_constu(57); + let read_expression = read::Expression(read::EndianSlice::new( + &[constants::DW_OP_constu.0, 57], + LittleEndian, + )); + + let range = RangeList(vec![Range::StartEnd { + begin: Address::Constant(0x1234), + end: Address::Constant(0x2345), + }]); + + let location = LocationList(vec![Location::StartEnd { + begin: Address::Constant(0x1234), + end: Address::Constant(0x2345), + data: expression.clone(), + }]); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + let mut dwarf = Dwarf::new(); + let unit = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit); + let loc_id = unit.locations.add(location.clone()); + let range_id = unit.ranges.add(range.clone()); + // Create a string with a non-zero id/offset. + dwarf.strings.add("dummy string"); + let string_id = dwarf.strings.add(string_data); + dwarf.line_strings.add("dummy line string"); + let line_string_id = dwarf.line_strings.add(line_string_data); + + let attributes = &[ + ( + constants::DW_AT_name, + AttributeValue::Address(Address::Constant(0x1234)), + read::AttributeValue::Addr(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Block(data.clone()), + read::AttributeValue::Block(read_data), + ), + ( + constants::DW_AT_name, + AttributeValue::Data1(0x12), + read::AttributeValue::Data1(0x12), + ), + ( + constants::DW_AT_name, + AttributeValue::Data2(0x1234), + read::AttributeValue::Data2(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Data4(0x1234), + read::AttributeValue::Data4(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Data8(0x1234), + read::AttributeValue::Data8(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Sdata(0x1234), + read::AttributeValue::Sdata(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Udata(0x1234), + read::AttributeValue::Udata(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::Exprloc(expression.clone()), + read::AttributeValue::Exprloc(read_expression), + ), + ( + constants::DW_AT_name, + AttributeValue::Flag(false), + read::AttributeValue::Flag(false), + ), + /* + ( + constants::DW_AT_name, + AttributeValue::FlagPresent, + read::AttributeValue::Flag(true), + ), + */ + ( + constants::DW_AT_name, + AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)), + read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)), + ), + ( + constants::DW_AT_macro_info, + AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)), + read::AttributeValue::SecOffset(0x1234), + ), + ( + constants::DW_AT_macros, + AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)), + read::AttributeValue::SecOffset(0x1234), + ), + ( + constants::DW_AT_name, + AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)), + read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)), + ), + ( + constants::DW_AT_name, + AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)), + read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)), + ), + ( + constants::DW_AT_name, + AttributeValue::String(data.clone()), + read::AttributeValue::String(read_data), + ), + ( + constants::DW_AT_encoding, + AttributeValue::Encoding(constants::DwAte(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_decimal_sign, + AttributeValue::DecimalSign(constants::DwDs(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_endianity, + AttributeValue::Endianity(constants::DwEnd(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_accessibility, + AttributeValue::Accessibility(constants::DwAccess(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_visibility, + AttributeValue::Visibility(constants::DwVis(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_virtuality, + AttributeValue::Virtuality(constants::DwVirtuality(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_language, + AttributeValue::Language(constants::DwLang(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_address_class, + AttributeValue::AddressClass(constants::DwAddr(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_identifier_case, + AttributeValue::IdentifierCase(constants::DwId(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_calling_convention, + AttributeValue::CallingConvention(constants::DwCc(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_ordering, + AttributeValue::Ordering(constants::DwOrd(0x12)), + read::AttributeValue::Udata(0x12), + ), + ( + constants::DW_AT_inline, + AttributeValue::Inline(constants::DwInl(0x12)), + read::AttributeValue::Udata(0x12), + ), + ]; + + let mut add_attribute = |name, value| { + let entry_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + let entry = unit.get_mut(entry_id); + entry.set(name, value); + }; + for (name, value, _) in attributes { + add_attribute(*name, value.clone()); + } + add_attribute( + constants::DW_AT_location, + AttributeValue::LocationListRef(loc_id), + ); + add_attribute( + constants::DW_AT_ranges, + AttributeValue::RangeListRef(range_id), + ); + add_attribute(constants::DW_AT_name, AttributeValue::StringRef(string_id)); + add_attribute( + constants::DW_AT_name, + AttributeValue::LineStringRef(line_string_id), + ); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + let read_unit = read_units.next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let mut read_entries = read_unit.entries(); + let (_, _root) = read_entries.next_dfs().unwrap().unwrap(); + + let mut get_attribute = |name| { + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + entry.attr(name).unwrap().unwrap() + }; + for (name, _, expect_value) in attributes { + let read_value = &get_attribute(*name).raw_value(); + // read::AttributeValue is invariant in the lifetime of R. + // The lifetimes here are all okay, so transmute it. + let read_value = unsafe { + mem::transmute::< + &read::AttributeValue>, + &read::AttributeValue>, + >(read_value) + }; + assert_eq!(read_value, expect_value); + } + + let read_attr = get_attribute(constants::DW_AT_location).value(); + let read::AttributeValue::LocationListsRef(read_loc_offset) = read_attr else { + panic!("unexpected {:?}", read_attr); + }; + let mut read_locations = read_unit.locations(read_loc_offset).unwrap(); + let read_location = read_locations.next().unwrap().unwrap(); + assert_eq!(read_location.range.begin, 0x1234); + assert_eq!(read_location.range.end, 0x2345); + assert_eq!(read_location.data, read_expression); + + let read_attr = get_attribute(constants::DW_AT_ranges).value(); + let read::AttributeValue::RangeListsRef(read_range_offset) = read_attr else { + panic!("unexpected {:?}", read_attr); + }; + let read_range_offset = read_unit.ranges_offset_from_raw(read_range_offset); + let mut read_ranges = read_unit.ranges(read_range_offset).unwrap(); + let read_range = read_ranges.next().unwrap().unwrap(); + assert_eq!(read_range.begin, 0x1234); + assert_eq!(read_range.end, 0x2345); + + let read_string = get_attribute(constants::DW_AT_name).raw_value(); + let read::AttributeValue::DebugStrRef(read_string_offset) = read_string else { + panic!("unexpected {:?}", read_string); + }; + assert_eq!( + read_dwarf.string(read_string_offset).unwrap().slice(), + string_data.as_bytes() + ); + + let read_line_string = get_attribute(constants::DW_AT_name).raw_value(); + let read::AttributeValue::DebugLineStrRef(read_line_string_offset) = + read_line_string + else { + panic!("unexpected {:?}", read_line_string); + }; + assert_eq!( + read_dwarf + .line_string(read_line_string_offset) + .unwrap() + .slice(), + line_string_data.as_bytes() + ); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0)); + let convert_root = convert_unit.get(convert_unit.root()); + let mut convert_entries = convert_root.children(); + + let mut get_convert_attr = |name| { + let convert_entry = convert_unit.get(*convert_entries.next().unwrap()); + convert_entry.get(name).unwrap() + }; + for (name, attr, _) in attributes { + let convert_attr = get_convert_attr(*name); + assert_eq!(convert_attr, attr); + } + + let convert_attr = get_convert_attr(constants::DW_AT_location); + let AttributeValue::LocationListRef(convert_loc_id) = convert_attr else { + panic!("unexpected {:?}", convert_attr); + }; + let convert_location = convert_unit.locations.get(*convert_loc_id); + assert_eq!(*convert_location, location); + + let convert_attr = get_convert_attr(constants::DW_AT_ranges); + let AttributeValue::RangeListRef(convert_range_id) = convert_attr else { + panic!("unexpected {:?}", convert_attr); + }; + let convert_range = convert_unit.ranges.get(*convert_range_id); + assert_eq!(*convert_range, range); + + let convert_attr = get_convert_attr(constants::DW_AT_name); + let AttributeValue::StringRef(convert_string_id) = convert_attr else { + panic!("unexpected {:?}", convert_attr); + }; + let convert_string = convert_dwarf.strings.get(*convert_string_id); + assert_eq!(convert_string, string_data.as_bytes()); + + let convert_attr = get_convert_attr(constants::DW_AT_name); + let AttributeValue::LineStringRef(convert_line_string_id) = convert_attr else { + panic!("unexpected {:?}", convert_attr); + }; + let convert_line_string = + convert_dwarf.line_strings.get(*convert_line_string_id); + assert_eq!(convert_line_string, line_string_data.as_bytes()); + } + } + } + } + + #[test] + fn test_unit_ref() { + let mut dwarf = Dwarf::new(); + let unit_id1 = dwarf.units.add(Unit::new( + Encoding { + version: 4, + address_size: 8, + format: Format::Dwarf32, + }, + LineProgram::none(), + )); + assert_eq!(unit_id1, dwarf.units.id(0)); + let unit_id2 = dwarf.units.add(Unit::new( + Encoding { + version: 2, + address_size: 4, + format: Format::Dwarf64, + }, + LineProgram::none(), + )); + assert_eq!(unit_id2, dwarf.units.id(1)); + let unit1_child1 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 1); + let unit1_child2 = UnitEntryId::new(dwarf.units.get(unit_id1).base_id, 2); + let unit2_child1 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 1); + let unit2_child2 = UnitEntryId::new(dwarf.units.get(unit_id2).base_id, 2); + { + let unit1 = dwarf.units.get_mut(unit_id1); + let root = unit1.root(); + let child_id1 = unit1.add(root, constants::DW_TAG_subprogram); + assert_eq!(child_id1, unit1_child1); + let child_id2 = unit1.add(root, constants::DW_TAG_subprogram); + assert_eq!(child_id2, unit1_child2); + { + let child1 = unit1.get_mut(child_id1); + child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2)); + } + { + let child2 = unit1.get_mut(child_id2); + child2.set( + constants::DW_AT_type, + AttributeValue::DebugInfoRef(Reference::Entry(unit_id2, unit2_child1)), + ); + } + } + { + let unit2 = dwarf.units.get_mut(unit_id2); + let root = unit2.root(); + let child_id1 = unit2.add(root, constants::DW_TAG_subprogram); + assert_eq!(child_id1, unit2_child1); + let child_id2 = unit2.add(root, constants::DW_TAG_subprogram); + assert_eq!(child_id2, unit2_child2); + { + let child1 = unit2.get_mut(child_id1); + child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2)); + } + { + let child2 = unit2.get_mut(child_id2); + child2.set( + constants::DW_AT_type, + AttributeValue::DebugInfoRef(Reference::Entry(unit_id1, unit1_child1)), + ); + } + } + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + println!("{:?}", sections.debug_info); + println!("{:?}", sections.debug_abbrev); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + + let read_unit = read_units.next().unwrap().unwrap(); + let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap(); + let mut read_entries = read_unit.entries(&abbrevs); + let (_, _root) = read_entries.next_dfs().unwrap().unwrap(); + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + let read_unit1_child1_attr = entry.attr_value(constants::DW_AT_type).unwrap(); + let read_unit1_child1_section_offset = + entry.offset().to_debug_info_offset(&read_unit).unwrap(); + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + let read_unit1_child2_attr = entry.attr_value(constants::DW_AT_type).unwrap(); + let read_unit1_child2_offset = entry.offset(); + + let read_unit = read_units.next().unwrap().unwrap(); + let abbrevs = read_dwarf.abbreviations(&read_unit).unwrap(); + let mut read_entries = read_unit.entries(&abbrevs); + let (_, _root) = read_entries.next_dfs().unwrap().unwrap(); + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + let read_unit2_child1_attr = entry.attr_value(constants::DW_AT_type).unwrap(); + let read_unit2_child1_section_offset = + entry.offset().to_debug_info_offset(&read_unit).unwrap(); + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + let read_unit2_child2_attr = entry.attr_value(constants::DW_AT_type).unwrap(); + let read_unit2_child2_offset = entry.offset(); + + assert_eq!( + read_unit1_child1_attr, + Some(read::AttributeValue::UnitRef(read_unit1_child2_offset)) + ); + assert_eq!( + read_unit1_child2_attr, + Some(read::AttributeValue::DebugInfoRef( + read_unit2_child1_section_offset + )) + ); + assert_eq!( + read_unit2_child1_attr, + Some(read::AttributeValue::UnitRef(read_unit2_child2_offset)) + ); + assert_eq!( + read_unit2_child2_attr, + Some(read::AttributeValue::DebugInfoRef( + read_unit1_child1_section_offset + )) + ); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))).unwrap(); + let convert_units = &convert_dwarf.units; + assert_eq!(convert_units.count(), dwarf.units.count()); + + for i in 0..convert_units.count() { + let unit = dwarf.units.get(dwarf.units.id(i)); + let convert_unit = convert_units.get(convert_units.id(i)); + assert_eq!(convert_unit.version(), unit.version()); + assert_eq!(convert_unit.address_size(), unit.address_size()); + assert_eq!(convert_unit.format(), unit.format()); + assert_eq!(convert_unit.count(), unit.count()); + + let root = unit.get(unit.root()); + let convert_root = convert_unit.get(convert_unit.root()); + assert_eq!(convert_root.tag(), root.tag()); + for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) { + assert_eq!(convert_attr, attr); + } + + let child1 = unit.get(UnitEntryId::new(unit.base_id, 1)); + let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1)); + assert_eq!(convert_child1.tag(), child1.tag()); + for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) { + assert_eq!(convert_attr.name, attr.name); + match (convert_attr.value.clone(), attr.value.clone()) { + ( + AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)), + AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)), + ) => { + assert_eq!(convert_unit.index, unit.index); + assert_eq!(convert_entry.index, entry.index); + } + (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => { + assert_eq!(convert_id.index, id.index); + } + (convert_value, value) => assert_eq!(convert_value, value), + } + } + + let child2 = unit.get(UnitEntryId::new(unit.base_id, 2)); + let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2)); + assert_eq!(convert_child2.tag(), child2.tag()); + for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) { + assert_eq!(convert_attr.name, attr.name); + match (convert_attr.value.clone(), attr.value.clone()) { + ( + AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)), + AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)), + ) => { + assert_eq!(convert_unit.index, unit.index); + assert_eq!(convert_entry.index, entry.index); + } + (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => { + assert_eq!(convert_id.index, id.index); + } + (convert_value, value) => assert_eq!(convert_value, value), + } + } + } + } + + #[test] + fn test_sibling() { + fn add_child( + unit: &mut Unit, + parent: UnitEntryId, + tag: constants::DwTag, + name: &str, + ) -> UnitEntryId { + let id = unit.add(parent, tag); + let child = unit.get_mut(id); + child.set(constants::DW_AT_name, AttributeValue::String(name.into())); + child.set_sibling(true); + id + } + + fn add_children(unit: &mut Unit) { + let root = unit.root(); + let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1"); + add_child(unit, child1, constants::DW_TAG_variable, "grandchild1"); + add_child(unit, root, constants::DW_TAG_subprogram, "child2"); + add_child(unit, root, constants::DW_TAG_subprogram, "child3"); + } + + fn next_child>( + entries: &mut read::EntriesCursor<'_, '_, R>, + ) -> (read::UnitOffset, Option) { + let (_, entry) = entries.next_dfs().unwrap().unwrap(); + let offset = entry.offset(); + let sibling = + entry + .attr_value(constants::DW_AT_sibling) + .unwrap() + .map(|attr| match attr { + read::AttributeValue::UnitRef(offset) => offset, + _ => panic!("bad sibling value"), + }); + (offset, sibling) + } + + fn check_sibling>( + unit: read::UnitHeader, + dwarf: &read::Dwarf, + ) { + let unit = dwarf.unit(unit).unwrap(); + let mut entries = unit.entries(); + // root + entries.next_dfs().unwrap().unwrap(); + // child1 + let (_, sibling1) = next_child(&mut entries); + // grandchild1 + entries.next_dfs().unwrap().unwrap(); + // child2 + let (offset2, sibling2) = next_child(&mut entries); + // child3 + let (_, _) = next_child(&mut entries); + assert_eq!(sibling1, Some(offset2)); + assert_eq!(sibling2, None); + } + + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 8, + }; + let mut dwarf = Dwarf::new(); + let unit_id1 = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + add_children(dwarf.units.get_mut(unit_id1)); + let unit_id2 = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + add_children(dwarf.units.get_mut(unit_id2)); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + println!("{:?}", sections.debug_info); + println!("{:?}", sections.debug_abbrev); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf); + check_sibling(read_units.next().unwrap().unwrap(), &read_dwarf); + } + + #[test] + fn test_line_ref() { + let dir_bytes = b"dir"; + let file_bytes1 = b"file1"; + let file_bytes2 = b"file2"; + let file_string1 = LineString::String(file_bytes1.to_vec()); + let file_string2 = LineString::String(file_bytes2.to_vec()); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + + // The line program we'll be referencing. + let mut line_program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(dir_bytes.to_vec()), + None, + file_string1.clone(), + None, + ); + let dir = line_program.default_directory(); + // For version >= 5, this will reuse the existing file at index 0. + let file1 = line_program.add_file(file_string1.clone(), dir, None); + let file2 = line_program.add_file(file_string2.clone(), dir, None); + + let mut unit = Unit::new(encoding, line_program); + let root = unit.get_mut(unit.root()); + root.set( + constants::DW_AT_name, + AttributeValue::String(file_bytes1.to_vec()), + ); + root.set( + constants::DW_AT_comp_dir, + AttributeValue::String(dir_bytes.to_vec()), + ); + root.set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef); + + let child = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(child).set( + constants::DW_AT_decl_file, + AttributeValue::FileIndex(Some(file1)), + ); + + let child = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(child).set( + constants::DW_AT_call_file, + AttributeValue::FileIndex(Some(file2)), + ); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let mut read_units = read_dwarf.units(); + let read_unit = read_units.next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let read_line_program = read_unit.line_program.as_ref().unwrap().header(); + let mut read_entries = read_unit.entries(); + let (_, _root) = read_entries.next_dfs().unwrap().unwrap(); + + let mut get_path = |name| { + let (_, entry) = read_entries.next_dfs().unwrap().unwrap(); + let read_attr = entry.attr(name).unwrap().unwrap(); + let read::AttributeValue::FileIndex(read_file_index) = read_attr.value() + else { + panic!("unexpected {:?}", read_attr); + }; + let read_file = read_line_program.file(read_file_index).unwrap(); + let read_path = read_unit + .attr_string(read_file.path_name()) + .unwrap() + .slice(); + (read_file_index, read_path) + }; + + let (read_index, read_path) = get_path(constants::DW_AT_decl_file); + assert_eq!(read_index, if version >= 5 { 0 } else { 1 }); + assert_eq!(read_path, file_bytes1); + + let (read_index, read_path) = get_path(constants::DW_AT_call_file); + assert_eq!(read_index, if version >= 5 { 1 } else { 2 }); + assert_eq!(read_path, file_bytes2); + + let convert_dwarf = + Dwarf::from(&read_dwarf, &|address| Some(Address::Constant(address))) + .unwrap(); + let convert_unit = convert_dwarf.units.get(convert_dwarf.units.id(0)); + let convert_root = convert_unit.get(convert_unit.root()); + let mut convert_entries = convert_root.children(); + + let mut get_convert_path = |name| { + let convert_entry = convert_unit.get(*convert_entries.next().unwrap()); + let convert_attr = convert_entry.get(name).unwrap(); + let AttributeValue::FileIndex(Some(convert_file_index)) = convert_attr + else { + panic!("unexpected {:?}", convert_attr); + }; + convert_unit.line_program.get_file(*convert_file_index).0 + }; + + let convert_path = get_convert_path(constants::DW_AT_decl_file); + assert_eq!(convert_path, &file_string1); + + let convert_path = get_convert_path(constants::DW_AT_call_file); + assert_eq!(convert_path, &file_string2); + } + } + } + } + + #[test] + fn test_line_program_used() { + for used in [false, true] { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let line_program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(b"comp_dir".to_vec()), + None, + LineString::String(b"comp_name".to_vec()), + None, + ); + + let mut unit = Unit::new(encoding, line_program); + let file_id = if used { Some(FileId::new(0)) } else { None }; + let root = unit.root(); + unit.get_mut(root).set( + constants::DW_AT_decl_file, + AttributeValue::FileIndex(file_id), + ); + + let mut dwarf = Dwarf::new(); + dwarf.units.add(unit); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + dwarf.write(&mut sections).unwrap(); + assert_eq!(!used, sections.debug_line.slice().is_empty()); + } + } + + #[test] + fn test_delete_child() { + fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) { + let entry = unit.get_mut(id); + entry.set(constants::DW_AT_name, AttributeValue::String(name.into())); + } + fn check_name( + entry: &read::DebuggingInformationEntry<'_, '_, R>, + unit: read::UnitRef<'_, R>, + name: &str, + ) { + let name_attr = entry.attr(constants::DW_AT_name).unwrap().unwrap(); + let entry_name = unit.attr_string(name_attr.value()).unwrap(); + let entry_name_str = entry_name.to_string().unwrap(); + assert_eq!(entry_name_str, name); + } + let encoding = Encoding { + format: Format::Dwarf32, + version: 4, + address_size: 8, + }; + let mut dwarf = DwarfUnit::new(encoding); + let root = dwarf.unit.root(); + + // Add and delete entries in the root unit + let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram); + set_name(&mut dwarf.unit, child1, "child1"); + let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable); + set_name(&mut dwarf.unit, grandchild1, "grandchild1"); + let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram); + set_name(&mut dwarf.unit, child2, "child2"); + // This deletes both `child1` and its child `grandchild1` + dwarf.unit.get_mut(root).delete_child(child1); + let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram); + set_name(&mut dwarf.unit, child3, "child3"); + let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram); + set_name(&mut dwarf.unit, child4, "child4"); + let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable); + set_name(&mut dwarf.unit, grandchild4, "grandchild4"); + dwarf.unit.get_mut(child4).delete_child(grandchild4); + + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + + // Write DWARF data which should only include `child2`, `child3` and `child4` + dwarf.write(&mut sections).unwrap(); + + let read_dwarf = sections.read(LittleEndian); + let read_unit = read_dwarf.units().next().unwrap().unwrap(); + let read_unit = read_dwarf.unit(read_unit).unwrap(); + let read_unit = read_unit.unit_ref(&read_dwarf); + let mut entries = read_unit.entries(); + // root + entries.next_dfs().unwrap().unwrap(); + // child2 + let (_, read_child2) = entries.next_dfs().unwrap().unwrap(); + check_name(read_child2, read_unit, "child2"); + // child3 + let (_, read_child3) = entries.next_dfs().unwrap().unwrap(); + check_name(read_child3, read_unit, "child3"); + // child4 + let (_, read_child4) = entries.next_dfs().unwrap().unwrap(); + check_name(read_child4, read_unit, "child4"); + // There should be no more entries + assert!(entries.next_dfs().unwrap().is_none()); + } + + #[test] + fn test_missing_unit_ref() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // Create the entry to be referenced. + let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type); + // And delete it so that it is not available when writing. + unit.get_mut(unit.root()).delete_child(entry_id); + + // Create a reference to the deleted entry. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(subprogram_id) + .set(constants::DW_AT_type, AttributeValue::UnitRef(entry_id)); + + // Writing the DWARF should fail. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference)); + } + + #[test] + fn test_missing_debuginfo_ref() { + let encoding = Encoding { + format: Format::Dwarf32, + version: 5, + address_size: 8, + }; + + let mut dwarf = Dwarf::new(); + let unit_id = dwarf.units.add(Unit::new(encoding, LineProgram::none())); + let unit = dwarf.units.get_mut(unit_id); + + // Create the entry to be referenced. + let entry_id = unit.add(unit.root(), constants::DW_TAG_const_type); + // And delete it so that it is not available when writing. + unit.get_mut(unit.root()).delete_child(entry_id); + + // Create a reference to the deleted entry. + let subprogram_id = unit.add(unit.root(), constants::DW_TAG_subprogram); + unit.get_mut(subprogram_id).set( + constants::DW_AT_type, + AttributeValue::DebugInfoRef(Reference::Entry(unit_id, entry_id)), + ); + + // Writing the DWARF should fail. + let mut sections = Sections::new(EndianVec::new(LittleEndian)); + assert_eq!(dwarf.write(&mut sections), Err(Error::InvalidReference)); + } +} diff --git a/anneal/v2/vendor/gimli/src/write/writer.rs b/anneal/v2/vendor/gimli/src/write/writer.rs new file mode 100644 index 0000000000..9ee071bf61 --- /dev/null +++ b/anneal/v2/vendor/gimli/src/write/writer.rs @@ -0,0 +1,493 @@ +use crate::common::{Format, SectionId}; +use crate::constants; +use crate::endianity::Endianity; +use crate::leb128; +use crate::write::{Address, Error, Result}; + +/// A trait for writing the data to a DWARF section. +/// +/// All write operations append to the section unless otherwise specified. +#[allow(clippy::len_without_is_empty)] +pub trait Writer { + /// The endianity of bytes that are written. + type Endian: Endianity; + + /// Return the endianity of bytes that are written. + fn endian(&self) -> Self::Endian; + + /// Return the current section length. + /// + /// This may be used as an offset for future `write_at` calls. + fn len(&self) -> usize; + + /// Write a slice. + fn write(&mut self, bytes: &[u8]) -> Result<()>; + + /// Write a slice at a given offset. + /// + /// The write must not extend past the current section length. + fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>; + + /// Write an address. + /// + /// If the writer supports relocations, then it must provide its own implementation + /// of this method. + // TODO: use write_reference instead? + fn write_address(&mut self, address: Address, size: u8) -> Result<()> { + match address { + Address::Constant(val) => self.write_udata(val, size), + Address::Symbol { .. } => Err(Error::InvalidAddress), + } + } + + /// Write an address with a `.eh_frame` pointer encoding. + /// + /// The given size is only used for `DW_EH_PE_absptr` formats. + /// + /// If the writer supports relocations, then it must provide its own implementation + /// of this method. + fn write_eh_pointer( + &mut self, + address: Address, + eh_pe: constants::DwEhPe, + size: u8, + ) -> Result<()> { + match address { + Address::Constant(val) => { + // Indirect doesn't matter here. + let val = match eh_pe.application() { + constants::DW_EH_PE_absptr => val, + constants::DW_EH_PE_pcrel => { + // TODO: better handling of sign + let offset = self.len() as u64; + val.wrapping_sub(offset) + } + _ => { + return Err(Error::UnsupportedPointerEncoding(eh_pe)); + } + }; + self.write_eh_pointer_data(val, eh_pe.format(), size) + } + Address::Symbol { .. } => Err(Error::InvalidAddress), + } + } + + /// Write a value with a `.eh_frame` pointer format. + /// + /// The given size is only used for `DW_EH_PE_absptr` formats. + /// + /// This must not be used directly for values that may require relocation. + fn write_eh_pointer_data( + &mut self, + val: u64, + format: constants::DwEhPe, + size: u8, + ) -> Result<()> { + match format { + constants::DW_EH_PE_absptr => self.write_udata(val, size), + constants::DW_EH_PE_uleb128 => self.write_uleb128(val), + constants::DW_EH_PE_udata2 => self.write_udata(val, 2), + constants::DW_EH_PE_udata4 => self.write_udata(val, 4), + constants::DW_EH_PE_udata8 => self.write_udata(val, 8), + constants::DW_EH_PE_sleb128 => self.write_sleb128(val as i64), + constants::DW_EH_PE_sdata2 => self.write_sdata(val as i64, 2), + constants::DW_EH_PE_sdata4 => self.write_sdata(val as i64, 4), + constants::DW_EH_PE_sdata8 => self.write_sdata(val as i64, 8), + _ => Err(Error::UnsupportedPointerEncoding(format)), + } + } + + /// Write an offset that is relative to the start of the given section. + /// + /// If the writer supports relocations, then it must provide its own implementation + /// of this method. + fn write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()> { + self.write_udata(val as u64, size) + } + + /// Write an offset that is relative to the start of the given section. + /// + /// If the writer supports relocations, then it must provide its own implementation + /// of this method. + fn write_offset_at( + &mut self, + offset: usize, + val: usize, + _section: SectionId, + size: u8, + ) -> Result<()> { + self.write_udata_at(offset, val as u64, size) + } + + /// Write a reference to a symbol. + /// + /// If the writer supports symbols, then it must provide its own implementation + /// of this method. + fn write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()> { + Err(Error::InvalidReference) + } + + /// Write a u8. + fn write_u8(&mut self, val: u8) -> Result<()> { + let bytes = [val]; + self.write(&bytes) + } + + /// Write a u16. + fn write_u16(&mut self, val: u16) -> Result<()> { + let mut bytes = [0; 2]; + self.endian().write_u16(&mut bytes, val); + self.write(&bytes) + } + + /// Write a u32. + fn write_u32(&mut self, val: u32) -> Result<()> { + let mut bytes = [0; 4]; + self.endian().write_u32(&mut bytes, val); + self.write(&bytes) + } + + /// Write a u64. + fn write_u64(&mut self, val: u64) -> Result<()> { + let mut bytes = [0; 8]; + self.endian().write_u64(&mut bytes, val); + self.write(&bytes) + } + + /// Write a u8 at the given offset. + fn write_u8_at(&mut self, offset: usize, val: u8) -> Result<()> { + let bytes = [val]; + self.write_at(offset, &bytes) + } + + /// Write a u16 at the given offset. + fn write_u16_at(&mut self, offset: usize, val: u16) -> Result<()> { + let mut bytes = [0; 2]; + self.endian().write_u16(&mut bytes, val); + self.write_at(offset, &bytes) + } + + /// Write a u32 at the given offset. + fn write_u32_at(&mut self, offset: usize, val: u32) -> Result<()> { + let mut bytes = [0; 4]; + self.endian().write_u32(&mut bytes, val); + self.write_at(offset, &bytes) + } + + /// Write a u64 at the given offset. + fn write_u64_at(&mut self, offset: usize, val: u64) -> Result<()> { + let mut bytes = [0; 8]; + self.endian().write_u64(&mut bytes, val); + self.write_at(offset, &bytes) + } + + /// Write unsigned data of the given size. + /// + /// Returns an error if the value is too large for the size. + /// This must not be used directly for values that may require relocation. + fn write_udata(&mut self, val: u64, size: u8) -> Result<()> { + match size { + 1 => { + let write_val = val as u8; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u8(write_val) + } + 2 => { + let write_val = val as u16; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u16(write_val) + } + 4 => { + let write_val = val as u32; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u32(write_val) + } + 8 => self.write_u64(val), + otherwise => Err(Error::UnsupportedWordSize(otherwise)), + } + } + + /// Write signed data of the given size. + /// + /// Returns an error if the value is too large for the size. + /// This must not be used directly for values that may require relocation. + fn write_sdata(&mut self, val: i64, size: u8) -> Result<()> { + match size { + 1 => { + let write_val = val as i8; + if val != i64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u8(write_val as u8) + } + 2 => { + let write_val = val as i16; + if val != i64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u16(write_val as u16) + } + 4 => { + let write_val = val as i32; + if val != i64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u32(write_val as u32) + } + 8 => self.write_u64(val as u64), + otherwise => Err(Error::UnsupportedWordSize(otherwise)), + } + } + + /// Write a word of the given size at the given offset. + /// + /// Returns an error if the value is too large for the size. + /// This must not be used directly for values that may require relocation. + fn write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()> { + match size { + 1 => { + let write_val = val as u8; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u8_at(offset, write_val) + } + 2 => { + let write_val = val as u16; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u16_at(offset, write_val) + } + 4 => { + let write_val = val as u32; + if val != u64::from(write_val) { + return Err(Error::ValueTooLarge); + } + self.write_u32_at(offset, write_val) + } + 8 => self.write_u64_at(offset, val), + otherwise => Err(Error::UnsupportedWordSize(otherwise)), + } + } + + /// Write an unsigned LEB128 encoded integer. + fn write_uleb128(&mut self, val: u64) -> Result<()> { + let mut bytes = [0u8; 10]; + // bytes is long enough so this will never fail. + let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap(); + self.write(&bytes[..len]) + } + + /// Read an unsigned LEB128 encoded integer. + fn write_sleb128(&mut self, val: i64) -> Result<()> { + let mut bytes = [0u8; 10]; + // bytes is long enough so this will never fail. + let len = leb128::write::signed(&mut { &mut bytes[..] }, val).unwrap(); + self.write(&bytes[..len]) + } + + /// Write an initial length according to the given DWARF format. + /// + /// This will only write a length of zero, since the length isn't + /// known yet, and a subsequent call to `write_initial_length_at` + /// will write the actual length. + fn write_initial_length(&mut self, format: Format) -> Result { + if format == Format::Dwarf64 { + self.write_u32(0xffff_ffff)?; + } + let offset = InitialLengthOffset(self.len()); + self.write_udata(0, format.word_size())?; + Ok(offset) + } + + /// Write an initial length at the given offset according to the given DWARF format. + /// + /// `write_initial_length` must have previously returned the offset. + fn write_initial_length_at( + &mut self, + offset: InitialLengthOffset, + length: u64, + format: Format, + ) -> Result<()> { + self.write_udata_at(offset.0, length, format.word_size()) + } +} + +/// The offset at which an initial length should be written. +#[derive(Debug, Clone, Copy)] +pub struct InitialLengthOffset(usize); + +#[cfg(test)] +mod tests { + use super::*; + use crate::write; + use crate::{BigEndian, LittleEndian}; + + #[test] + fn test_writer() { + let mut w = write::EndianVec::new(LittleEndian); + w.write_address(Address::Constant(0x1122_3344), 4).unwrap(); + assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]); + assert_eq!( + w.write_address( + Address::Symbol { + symbol: 0, + addend: 0 + }, + 4 + ), + Err(Error::InvalidAddress) + ); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_offset(0x1122_3344, SectionId::DebugInfo, 4) + .unwrap(); + assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]); + w.write_offset_at(1, 0x5566, SectionId::DebugInfo, 2) + .unwrap(); + assert_eq!(w.slice(), &[0x44, 0x66, 0x55, 0x11]); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_u8(0x11).unwrap(); + w.write_u16(0x2233).unwrap(); + w.write_u32(0x4455_6677).unwrap(); + w.write_u64(0x8081_8283_8485_8687).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x11, + 0x33, 0x22, + 0x77, 0x66, 0x55, 0x44, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + ]); + w.write_u8_at(14, 0x11).unwrap(); + w.write_u16_at(12, 0x2233).unwrap(); + w.write_u32_at(8, 0x4455_6677).unwrap(); + w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x77, 0x66, 0x55, 0x44, + 0x33, 0x22, + 0x11, + ]); + + let mut w = write::EndianVec::new(BigEndian); + w.write_u8(0x11).unwrap(); + w.write_u16(0x2233).unwrap(); + w.write_u32(0x4455_6677).unwrap(); + w.write_u64(0x8081_8283_8485_8687).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x11, + 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + ]); + w.write_u8_at(14, 0x11).unwrap(); + w.write_u16_at(12, 0x2233).unwrap(); + w.write_u32_at(8, 0x4455_6677).unwrap(); + w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x44, 0x55, 0x66, 0x77, + 0x22, 0x33, + 0x11, + ]); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_udata(0x11, 1).unwrap(); + w.write_udata(0x2233, 2).unwrap(); + w.write_udata(0x4455_6677, 4).unwrap(); + w.write_udata(0x8081_8283_8485_8687, 8).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x11, + 0x33, 0x22, + 0x77, 0x66, 0x55, 0x44, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + ]); + assert_eq!(w.write_udata(0x100, 1), Err(Error::ValueTooLarge)); + assert_eq!(w.write_udata(0x1_0000, 2), Err(Error::ValueTooLarge)); + assert_eq!(w.write_udata(0x1_0000_0000, 4), Err(Error::ValueTooLarge)); + assert_eq!(w.write_udata(0x00, 3), Err(Error::UnsupportedWordSize(3))); + w.write_udata_at(14, 0x11, 1).unwrap(); + w.write_udata_at(12, 0x2233, 2).unwrap(); + w.write_udata_at(8, 0x4455_6677, 4).unwrap(); + w.write_udata_at(0, 0x8081_8283_8485_8687, 8).unwrap(); + #[rustfmt::skip] + assert_eq!(w.slice(), &[ + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x77, 0x66, 0x55, 0x44, + 0x33, 0x22, + 0x11, + ]); + assert_eq!(w.write_udata_at(0, 0x100, 1), Err(Error::ValueTooLarge)); + assert_eq!(w.write_udata_at(0, 0x1_0000, 2), Err(Error::ValueTooLarge)); + assert_eq!( + w.write_udata_at(0, 0x1_0000_0000, 4), + Err(Error::ValueTooLarge) + ); + assert_eq!( + w.write_udata_at(0, 0x00, 3), + Err(Error::UnsupportedWordSize(3)) + ); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_uleb128(0).unwrap(); + assert_eq!(w.slice(), &[0]); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_uleb128(u64::MAX).unwrap(); + assert_eq!( + w.slice(), + &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1] + ); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_sleb128(0).unwrap(); + assert_eq!(w.slice(), &[0]); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_sleb128(i64::MAX).unwrap(); + assert_eq!( + w.slice(), + &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0] + ); + + let mut w = write::EndianVec::new(LittleEndian); + w.write_sleb128(i64::MIN).unwrap(); + assert_eq!( + w.slice(), + &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f] + ); + + let mut w = write::EndianVec::new(LittleEndian); + let offset = w.write_initial_length(Format::Dwarf32).unwrap(); + assert_eq!(w.slice(), &[0, 0, 0, 0]); + w.write_initial_length_at(offset, 0x1122_3344, Format::Dwarf32) + .unwrap(); + assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]); + assert_eq!( + w.write_initial_length_at(offset, 0x1_0000_0000, Format::Dwarf32), + Err(Error::ValueTooLarge) + ); + + let mut w = write::EndianVec::new(LittleEndian); + let offset = w.write_initial_length(Format::Dwarf64).unwrap(); + assert_eq!(w.slice(), &[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0]); + w.write_initial_length_at(offset, 0x1122_3344_5566_7788, Format::Dwarf64) + .unwrap(); + assert_eq!( + w.slice(), + &[0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11] + ); + } +} diff --git a/anneal/v2/vendor/indicatif/.cargo-checksum.json b/anneal/v2/vendor/indicatif/.cargo-checksum.json new file mode 100644 index 0000000000..f62b74c746 --- /dev/null +++ b/anneal/v2/vendor/indicatif/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"1e20f63b732e91b2b177e3e7495408726663de47055edd88eec4b173f39fbed3",".github/dependabot.yml":"601e819a72581b0db06f31d262ab1b7f76d78504052739d7bfb0c1f8ec549a1d",".github/workflows/rust.yml":"acfc24d17b1379994ac97e05939a69d87771e3d248e6be13a3940b1f36e2fc4f","Cargo.lock":"efad8c4cac0313e734b7e4e3747c1f5d95925cbd42c674c3ce15d5810aaa1f82","Cargo.toml":"734208048021e18805dc0b3993ea6e70399c363c35c3126554dec2d7c1c290d8","Cargo.toml.orig":"022d2366e30cf4143efb2a0fc744ff2aa347332523caefad17e418c384de40d0","LICENSE":"2022c11b24fc1e50fa06a5959e40198a3464f560729ad3d00139abb8a328362d","README.md":"8cb15d644b9fd7ab5affc2f9005b79b90484dac566ec5aabd90f2f6c223111c1","deny.toml":"ad015d5bc132d679b86f1519c1879d85da93aa8a7eda230dc35019c64e5fb39d","examples/cargo.rs":"5ef2f7bff13e8ef9f53d30fb7979519136e92cbcfc0ef3feaf031071a37fc63d","examples/cargowrap.rs":"6341fc972a8ef36354d12a2a17eb3d0a2ff2a43e4c73410ce9570d9a139041c2","examples/download-continued.rs":"a4d78fe65f8b83e23edabe2b4d4da1cba0d88ae7c8eb73efec11dd33dab57524","examples/download-speed.rs":"694ad313c33a8ffe13f6db9b8b84c74a32ca2397b047fa38e488c74100753ea5","examples/download.rs":"ba7a8b6979a7c98aaee3770792956646b8d6570424e94695afee69a89d3d34d9","examples/fastbar.rs":"15fd733b7e058544005e68399d93550e7eb46c90a7c2248804887c5c521710c5","examples/finebars.rs":"c9a2cf88e4643718be03401c19b3c379287d57841b088342fc47eade44426bc0","examples/iterator.rs":"9d3d965d81f1c7bed4247205e4f8978cdce870de8c8b0ed93097a403351360ba","examples/log.rs":"fd88f4d8a56726c1e3f91e2a3b7b68262dd6a48c7f30f4af5184a6efe177736c","examples/long-spinner.rs":"f753a118d0e553a0fd74bc875dc691804db32fbdad8119d53ea5e304f39cfaad","examples/message.rs":"9b6c19bb19bebce185ab23a54bc90e74ced6ea09d5aac7cc082e4fc55b5126d4","examples/morebars.rs":"a073505554dc477b509f351bb82c703d70ac256407ce32cd41a734da5604d6f9","examples/multi-tree-ext.rs":"bb8897e1d071b6ecfb97ac44d3d71a3f5df57eb893257bbbfe8176326d8b43cc","examples/multi-tree.rs":"60613ceaeaa2d8be1ca38ed4b4e8a52ab63c111c682bd0467b452fb9ce6bbfa0","examples/multi.rs":"4cf84a59785370a94ca690d943ac35d42ec621a1b8b67392de3766af6abd87f8","examples/single.rs":"576c342c93b5493cd78257d0eecc8abd24b2bd4a3ad3d674d1023f2a3cad833d","examples/slow.rs":"f0152c6c35bbdfcbad44153b63c895bcd1e6929cb98ee49a67fefd942e2a2631","examples/spinner-loop.rs":"fc1084ac258a096d5f71e316e7a19523a5ab6376c83fb4ff71d43c76b86c9e14","examples/steady.rs":"981338f2fbf3ec3967fabde198ab973c8dc8926e6cae1a8acf53494cb47e9c89","examples/tokio.rs":"ef637f87461db3cd14de36498ad05ec3bf30f77cc67ea9315766ccbe84a96884","examples/yarnish.rs":"83073569a338edb202e947b086610c9f6a56c4c9abc46010e514a79ced7595ea","src/draw_target.rs":"741b11002cd5e3e1744f7d6f900f1f012a93c3091400c3eff8dd43d3b90dbf7e","src/format.rs":"9b840640c61769f1fc79a8bc132f4e98e2e4bb9cac1de0412a328a3e46a5afea","src/in_memory.rs":"fa920e7ed034ea2af4c1adc36558384e609e34702765885de697c4db36ff943c","src/iter.rs":"2a578de917f8fdac30f786f80b24147e993a2dc5d267d14080ef15c43a77edb0","src/lib.rs":"7f150b7472dff358ef9b43c3781bbb898987a01601588856474d84a6bd0ce2d2","src/multi.rs":"98fb6333565e3e4b8d2061cea100caf1c2cb7512ab15749431a248010d018998","src/progress_bar.rs":"b6e023fff702fabd782938f795cc45fbde53497b0ffdd6ff8ccc9e6b80843e8b","src/rayon.rs":"75371d526d7ea56695dcddcefc2051aa3bdede837b9d3193cb55d201aa43b95b","src/state.rs":"3db28bbb225b500cf56c8fec42d6e63eef249a3df63c5c4d2a185c766aad31e5","src/style.rs":"b161041e4cd193ffce2287183ec962137aa6ad0a09c3f3707b5280ad565a6eca","src/term_like.rs":"4605e937c63c5da9e0ab0afd49fd0466c21fdf76e99973139cec985ced25ed5d","tests/multi-autodrop.rs":"c453259d8b84e48b504b27ad0c729aa09a90acc9bfe35814f8216efbc3a98b1c","tests/render.rs":"f787cac80743d1b396d79378d0cdd7922081845dd1d6bc386b2602b784fe69a6"},"package":"25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb"} \ No newline at end of file diff --git a/anneal/v2/vendor/indicatif/.cargo_vcs_info.json b/anneal/v2/vendor/indicatif/.cargo_vcs_info.json new file mode 100644 index 0000000000..032b451a6b --- /dev/null +++ b/anneal/v2/vendor/indicatif/.cargo_vcs_info.json @@ -0,0 +1,7 @@ +{ + "git": { + "sha1": "4de2f604c3f5af5556db0a1d15e296102879c8d9", + "dirty": true + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/indicatif/.github/dependabot.yml b/anneal/v2/vendor/indicatif/.github/dependabot.yml new file mode 100644 index 0000000000..8ef5278d08 --- /dev/null +++ b/anneal/v2/vendor/indicatif/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff --git a/anneal/v2/vendor/indicatif/.github/workflows/rust.yml b/anneal/v2/vendor/indicatif/.github/workflows/rust.yml new file mode 100644 index 0000000000..1e1e17c463 --- /dev/null +++ b/anneal/v2/vendor/indicatif/.github/workflows/rust.yml @@ -0,0 +1,89 @@ +name: CI + +on: + push: + branches: ['main'] + pull_request: + schedule: + - cron: "43 6 * * 5" + +env: + CLICOLOR_FORCE: 1 + +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + rust: [stable] + features: [--all-features] + target: [""] + include: + - os: ubuntu-latest + rust: stable + features: "" + - os: ubuntu-latest + rust: stable + features: --no-default-features + - os: ubuntu-latest + rust: beta + features: --all-features + - os: ubuntu-latest + rust: stable + features: --all-features + target: --target armv5te-unknown-linux-gnueabi + use-cross: true + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - run: cargo test ${{ matrix.features }} + + cross: + runs-on: ubuntu-latest + + strategy: + matrix: + target: [armv5te-unknown-linux-gnueabi] + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + target: ${{ matrix.target }} + - uses: taiki-e/install-action@cross + - run: cross build --target ${{ matrix.target }} --all-features + + msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: "1.71" + - run: cargo check --lib --all-features + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt, clippy + - run: cargo fmt --all -- --check + - run: cargo clippy --all-targets --all-features -- -D warnings + - name: doc + run: cargo doc --no-deps --document-private-items + env: + RUSTDOCFLAGS: -Dwarnings + + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v2 diff --git a/anneal/v2/vendor/indicatif/Cargo.lock b/anneal/v2/vendor/indicatif/Cargo.lock new file mode 100644 index 0000000000..1314c2a429 --- /dev/null +++ b/anneal/v2/vendor/indicatif/Cargo.lock @@ -0,0 +1,664 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clap" +version = "4.5.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "console" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[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 = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indicatif" +version = "0.18.4" +dependencies = [ + "clap", + "console", + "futures", + "futures-core", + "once_cell", + "portable-atomic", + "pretty_assertions", + "rand", + "rayon", + "tokio", + "unicode-segmentation", + "unicode-width", + "unit-prefix", + "vt100", + "web-time", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "pin-project-lite", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vt100" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ff75fb8fa83e609e685106df4faeffdf3a735d3c74ebce97ec557d5d36fd9" +dependencies = [ + "itoa", + "unicode-width", + "vte", +] + +[[package]] +name = "vte" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd" +dependencies = [ + "arrayvec", + "memchr", +] + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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 = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.8.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57cf3aa6855b23711ee9852dfc97dfaa51c45feaba5b645d0c777414d494a961" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a616990af1a287837c4fe6596ad77ef57948f787e46ce28e166facc0cc1cb75" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/anneal/v2/vendor/indicatif/Cargo.toml b/anneal/v2/vendor/indicatif/Cargo.toml new file mode 100644 index 0000000000..3cd28aadda --- /dev/null +++ b/anneal/v2/vendor/indicatif/Cargo.toml @@ -0,0 +1,227 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.71" +name = "indicatif" +version = "0.18.4" +build = false +exclude = ["screenshots/*"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A progress bar and cli reporting library for Rust" +documentation = "https://docs.rs/indicatif" +readme = "README.md" +keywords = [ + "cli", + "progress", + "pb", + "colors", + "progressbar", +] +categories = ["command-line-interface"] +license = "MIT" +repository = "https://github.com/console-rs/indicatif" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +default = [ + "unicode-width", + "wasmbind", +] +futures = ["dep:futures-core"] +improved_unicode = [ + "unicode-segmentation", + "unicode-width", +] +in_memory = ["vt100"] +unicode-width = [ + "dep:unicode-width", + "console/unicode-width", +] +wasmbind = ["dep:web-time"] + +[lib] +name = "indicatif" +path = "src/lib.rs" + +[[example]] +name = "cargo" +path = "examples/cargo.rs" + +[[example]] +name = "cargowrap" +path = "examples/cargowrap.rs" + +[[example]] +name = "download" +path = "examples/download.rs" + +[[example]] +name = "download-continued" +path = "examples/download-continued.rs" + +[[example]] +name = "download-speed" +path = "examples/download-speed.rs" + +[[example]] +name = "fastbar" +path = "examples/fastbar.rs" + +[[example]] +name = "finebars" +path = "examples/finebars.rs" + +[[example]] +name = "iterator" +path = "examples/iterator.rs" + +[[example]] +name = "log" +path = "examples/log.rs" + +[[example]] +name = "long-spinner" +path = "examples/long-spinner.rs" + +[[example]] +name = "message" +path = "examples/message.rs" + +[[example]] +name = "morebars" +path = "examples/morebars.rs" + +[[example]] +name = "multi" +path = "examples/multi.rs" + +[[example]] +name = "multi-tree" +path = "examples/multi-tree.rs" + +[[example]] +name = "multi-tree-ext" +path = "examples/multi-tree-ext.rs" + +[[example]] +name = "single" +path = "examples/single.rs" + +[[example]] +name = "slow" +path = "examples/slow.rs" + +[[example]] +name = "spinner-loop" +path = "examples/spinner-loop.rs" + +[[example]] +name = "steady" +path = "examples/steady.rs" + +[[example]] +name = "tokio" +path = "examples/tokio.rs" + +[[example]] +name = "yarnish" +path = "examples/yarnish.rs" + +[[test]] +name = "multi-autodrop" +path = "tests/multi-autodrop.rs" + +[[test]] +name = "render" +path = "tests/render.rs" + +[dependencies.console] +version = "0.16" +features = [ + "ansi-parsing", + "std", +] +default-features = false + +[dependencies.futures-core] +version = "0.3" +optional = true +default-features = false + +[dependencies.portable-atomic] +version = "1.12.0" + +[dependencies.rayon] +version = "1.1" +optional = true + +[dependencies.tokio] +version = "1" +features = ["io-util"] +optional = true + +[dependencies.unicode-segmentation] +version = "1" +optional = true + +[dependencies.unicode-width] +version = "0.2" +optional = true + +[dependencies.unit-prefix] +version = "0.5.1" + +[dependencies.vt100] +version = "0.16.1" +optional = true + +[dev-dependencies.clap] +version = "4" +features = [ + "color", + "derive", +] + +[dev-dependencies.futures] +version = "0.3" + +[dev-dependencies.once_cell] +version = "1" + +[dev-dependencies.pretty_assertions] +version = "1.4.0" + +[dev-dependencies.rand] +version = "0.9" + +[dev-dependencies.tokio] +version = "1" +features = [ + "fs", + "time", + "rt", +] + +[target.'cfg(target_arch = "wasm32")'.dependencies.web-time] +version = "1.1.0" +optional = true diff --git a/anneal/v2/vendor/indicatif/Cargo.toml.orig b/anneal/v2/vendor/indicatif/Cargo.toml.orig new file mode 100644 index 0000000000..8d03330cf9 --- /dev/null +++ b/anneal/v2/vendor/indicatif/Cargo.toml.orig @@ -0,0 +1,47 @@ +[package] +name = "indicatif" +version = "0.18.4" +edition = "2021" +rust-version = "1.71" +description = "A progress bar and cli reporting library for Rust" +keywords = ["cli", "progress", "pb", "colors", "progressbar"] +categories = ["command-line-interface"] +license = "MIT" +repository = "https://github.com/console-rs/indicatif" +documentation = "https://docs.rs/indicatif" +readme = "README.md" +exclude = ["screenshots/*"] + +[dependencies] +console = { version = "0.16", default-features = false, features = ["ansi-parsing", "std"] } +futures-core = { version = "0.3", default-features = false, optional = true } +unit-prefix = "0.5.1" +portable-atomic = "1.12.0" +rayon = { version = "1.1", optional = true } +tokio = { version = "1", optional = true, features = ["io-util"] } +unicode-segmentation = { version = "1", optional = true } +unicode-width = { version = "0.2", optional = true } +vt100 = { version = "0.16.1", optional = true } + +[dev-dependencies] +clap = { version = "4", features = ["color", "derive"] } +once_cell = "1" +rand = "0.9" +tokio = { version = "1", features = ["fs", "time", "rt"] } +futures = "0.3" # so the doctest for wrap_stream is nice +pretty_assertions = "1.4.0" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +web-time = { version = "1.1.0", optional = true } + +[features] +default = ["unicode-width", "wasmbind"] +unicode-width = ["dep:unicode-width", "console/unicode-width"] +improved_unicode = ["unicode-segmentation", "unicode-width"] +in_memory = ["vt100"] +futures = ["dep:futures-core"] +wasmbind = ["dep:web-time"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/anneal/v2/vendor/indicatif/LICENSE b/anneal/v2/vendor/indicatif/LICENSE new file mode 100644 index 0000000000..dc9a85c1ee --- /dev/null +++ b/anneal/v2/vendor/indicatif/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 Armin Ronacher + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/anneal/v2/vendor/indicatif/README.md b/anneal/v2/vendor/indicatif/README.md new file mode 100644 index 0000000000..1126a56a87 --- /dev/null +++ b/anneal/v2/vendor/indicatif/README.md @@ -0,0 +1,35 @@ +# indicatif + +[![Documentation](https://docs.rs/indicatif/badge.svg)](https://docs.rs/indicatif/) +[![Crates.io](https://img.shields.io/crates/v/indicatif.svg)](https://crates.io/crates/indicatif) +[![Build status](https://github.com/console-rs/indicatif/workflows/CI/badge.svg)](https://github.com/console-rs/indicatif/actions/workflows/rust.yml) +[![Chat](https://img.shields.io/discord/976380008299917365?logo=discord)](https://discord.gg/YHmNA3De4W) + +A Rust library for indicating progress in command line applications to users. + +This currently primarily provides progress bars and spinners as well as basic +color support, but there are bigger plans for the future of this! + +## Examples + +[examples/yarnish.rs](examples/yarnish.rs) + + +[examples/download.rs](examples/download.rs) + + +[examples/multi.rs](examples/multi.rs) + + +[examples/single.rs](examples/single.rs) + + +## Integrations + +You can use [indicatif-log-bridge](https://crates.io/crates/indicatif-log-bridge) to integrate with the +[log crate](https://crates.io/crates/log) and avoid having both fight for your terminal. + +You can use [tracing-indicatif](https://crates.io/crates/tracing-indicatif) to integrate with the +[tracing crate](https://crates.io/crates/tracing) with automatic progress bar management +for active tracing spans, as well as ensure that tracing +log events do not interfere with active progress bars. diff --git a/anneal/v2/vendor/indicatif/deny.toml b/anneal/v2/vendor/indicatif/deny.toml new file mode 100644 index 0000000000..df58056572 --- /dev/null +++ b/anneal/v2/vendor/indicatif/deny.toml @@ -0,0 +1,2 @@ +[licenses] +allow = ["Apache-2.0", "MIT", "Unicode-3.0"] diff --git a/anneal/v2/vendor/indicatif/examples/cargo.rs b/anneal/v2/vendor/indicatif/examples/cargo.rs new file mode 100644 index 0000000000..e29f7fe7ec --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/cargo.rs @@ -0,0 +1,122 @@ +use std::sync::{mpsc, Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant}; + +use console::{Style, Term}; +use indicatif::{HumanDuration, ProgressBar, ProgressStyle}; +use rand::Rng; + +static CRATES: &[(&str, &str)] = &[ + ("console", "v0.14.1"), + ("lazy_static", "v1.4.0"), + ("libc", "v0.2.93"), + ("regex", "v1.4.6"), + ("regex-syntax", "v0.6.23"), + ("terminal_size", "v0.1.16"), + ("libc", "v0.2.93"), + ("unicode-width", "v0.1.8"), + ("lazy_static", "v1.4.0"), + ("number_prefix", "v0.4.0"), + ("regex", "v1.4.6"), + ("rand", "v0.8.3"), + ("getrandom", "v0.2.2"), + ("cfg-if", "v1.0.0"), + ("libc", "v0.2.93"), + ("rand_chacha", "v0.3.0"), + ("ppv-lite86", "v0.2.10"), + ("rand_core", "v0.6.2"), + ("getrandom", "v0.2.2"), + ("rand_core", "v0.6.2"), + ("tokio", "v1.5.0"), + ("bytes", "v1.0.1"), + ("pin-project-lite", "v0.2.6"), + ("slab", "v0.4.3"), + ("indicatif", "v0.15.0"), +]; + +fn main() { + // number of cpus + const NUM_CPUS: usize = 4; + let start = Instant::now(); + + // mimic cargo progress bar although it behaves a bit different + let pb = ProgressBar::new(CRATES.len() as u64); + pb.set_style( + ProgressStyle::with_template( + // note that bar size is fixed unlike cargo which is dynamic + // and also the truncation in cargo uses trailers (`...`) + if Term::stdout().size().1 > 80 { + "{prefix:>12.cyan.bold} [{bar:57}] {pos}/{len} {wide_msg}" + } else { + "{prefix:>12.cyan.bold} [{bar:57}] {pos}/{len}" + }, + ) + .unwrap() + .progress_chars("=> "), + ); + pb.set_prefix("Building"); + + // process in another thread + // crates to be iterated but not exactly a tree + let crates = Arc::new(Mutex::new(CRATES.iter())); + let (tx, rx) = mpsc::channel(); + for n in 0..NUM_CPUS { + let tx = tx.clone(); + let crates = crates.clone(); + thread::spawn(move || { + let mut rng = rand::rng(); + loop { + let krate = crates.lock().unwrap().next(); + // notify main thread if n thread is processing a crate + tx.send((n, krate)).unwrap(); + if let Some(krate) = krate { + thread::sleep(Duration::from_millis( + // last compile and linking is always slow, let's mimic that + if CRATES.last() == Some(krate) { + rng.random_range(1_000..2_000) + } else { + rng.random_range(250..1_000) + }, + )); + } else { + break; + } + } + }); + } + // drop tx to stop waiting + drop(tx); + + let green_bold = Style::new().green().bold(); + + // do progress drawing in main thread + let mut processing = [None; NUM_CPUS]; + while let Ok((n, krate)) = rx.recv() { + processing[n] = krate; + let crates: Vec<&str> = processing + .iter() + .filter_map(|t| t.copied().map(|(name, _)| name)) + .collect(); + pb.set_message(crates.join(", ")); + if let Some((name, version)) = krate { + // crate is being built + let line = format!( + "{:>12} {} {}", + green_bold.apply_to("Compiling"), + name, + version + ); + pb.println(line); + + pb.inc(1); + } + } + pb.finish_and_clear(); + + // compilation is finished + println!( + "{:>12} dev [unoptimized + debuginfo] target(s) in {}", + green_bold.apply_to("Finished"), + HumanDuration(start.elapsed()) + ); +} diff --git a/anneal/v2/vendor/indicatif/examples/cargowrap.rs b/anneal/v2/vendor/indicatif/examples/cargowrap.rs new file mode 100644 index 0000000000..354b6e0f62 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/cargowrap.rs @@ -0,0 +1,41 @@ +use std::io::{BufRead, BufReader}; +use std::process; +use std::time::{Duration, Instant}; + +use indicatif::{HumanDuration, ProgressBar, ProgressStyle}; + +pub fn main() { + let started = Instant::now(); + + println!("Compiling package in release mode..."); + + let pb = ProgressBar::new_spinner(); + pb.enable_steady_tick(Duration::from_millis(200)); + pb.set_style( + ProgressStyle::with_template("{spinner:.dim.bold} cargo: {wide_msg}") + .unwrap() + .tick_chars("/|\\- "), + ); + + let mut p = process::Command::new("cargo") + .arg("build") + .arg("--release") + .stderr(process::Stdio::piped()) + .spawn() + .unwrap(); + + for line in BufReader::new(p.stderr.take().unwrap()).lines() { + let line = line.unwrap(); + let stripped_line = line.trim(); + if !stripped_line.is_empty() { + pb.set_message(stripped_line.to_owned()); + } + pb.tick(); + } + + p.wait().unwrap(); + + pb.finish_and_clear(); + + println!("Done in {}", HumanDuration(started.elapsed())); +} diff --git a/anneal/v2/vendor/indicatif/examples/download-continued.rs b/anneal/v2/vendor/indicatif/examples/download-continued.rs new file mode 100644 index 0000000000..c9a76b6cf4 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/download-continued.rs @@ -0,0 +1,29 @@ +use std::cmp::min; +use std::thread; +use std::time::Duration; + +use indicatif::{ProgressBar, ProgressStyle}; + +fn main() { + let mut downloaded = 69369369; + let total_size = 231231231; + + let pb = ProgressBar::new(total_size); + pb.set_style( + ProgressStyle::with_template( + "{spinner:.green} [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})", + ) + .unwrap() + .progress_chars("#>-"), + ); + pb.set_position(downloaded); + pb.reset_eta(); + + while downloaded < total_size { + downloaded = min(downloaded + 123211, total_size); + pb.set_position(downloaded); + thread::sleep(Duration::from_millis(12)); + } + + pb.finish_with_message("downloaded"); +} diff --git a/anneal/v2/vendor/indicatif/examples/download-speed.rs b/anneal/v2/vendor/indicatif/examples/download-speed.rs new file mode 100644 index 0000000000..da5a80fa3a --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/download-speed.rs @@ -0,0 +1,24 @@ +use std::cmp::min; +use std::thread; +use std::time::Duration; + +use indicatif::{ProgressBar, ProgressStyle}; + +fn main() { + let mut downloaded = 0; + let total_size = 231231231; + + let pb = ProgressBar::new(total_size); + pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})") + .unwrap() + .progress_chars("#>-")); + + while downloaded < total_size { + let new = min(downloaded + 223211, total_size); + downloaded = new; + pb.set_position(new); + thread::sleep(Duration::from_millis(12)); + } + + pb.finish_with_message("downloaded"); +} diff --git a/anneal/v2/vendor/indicatif/examples/download.rs b/anneal/v2/vendor/indicatif/examples/download.rs new file mode 100644 index 0000000000..c3f92027a3 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/download.rs @@ -0,0 +1,25 @@ +use std::thread; +use std::time::Duration; +use std::{cmp::min, fmt::Write}; + +use indicatif::{ProgressBar, ProgressState, ProgressStyle}; + +fn main() { + let mut downloaded = 0; + let total_size = 231231231; + + let pb = ProgressBar::new(total_size); + pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})") + .unwrap() + .with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()) + .progress_chars("#>-")); + + while downloaded < total_size { + let new = min(downloaded + 223211, total_size); + downloaded = new; + pb.set_position(new); + thread::sleep(Duration::from_millis(12)); + } + + pb.finish_with_message("downloaded"); +} diff --git a/anneal/v2/vendor/indicatif/examples/fastbar.rs b/anneal/v2/vendor/indicatif/examples/fastbar.rs new file mode 100644 index 0000000000..1b71f0ca3a --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/fastbar.rs @@ -0,0 +1,23 @@ +use indicatif::ProgressBar; + +fn many_units_of_easy_work(n: u64, label: &str) { + let pb = ProgressBar::new(n); + + let mut sum = 0; + for i in 0..n { + // Any quick computation, followed by an update to the progress bar. + sum += 2 * i + 3; + pb.inc(1); + } + pb.finish(); + + println!("[{}] Sum ({}) calculated in {:?}", label, sum, pb.elapsed()); +} + +fn main() { + const N: u64 = 1 << 20; + + // Perform a long sequence of many simple computations monitored by a + // default progress bar. + many_units_of_easy_work(N, "Default progress bar "); +} diff --git a/anneal/v2/vendor/indicatif/examples/finebars.rs b/anneal/v2/vendor/indicatif/examples/finebars.rs new file mode 100644 index 0000000000..06a1a2dc34 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/finebars.rs @@ -0,0 +1,43 @@ +use std::thread; +use std::time::Duration; + +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use rand::Rng; + +fn main() { + let styles = [ + ("Rough bar:", "█ ", "red"), + ("Fine bar: ", "█▉▊▋▌▍▎▏ ", "yellow"), + ("Vertical: ", "█▇▆▅▄▃▂▁ ", "green"), + ("Fade in: ", "█▓▒░ ", "blue"), + ("Blocky: ", "█▛▌▖ ", "magenta"), + ]; + + let m = MultiProgress::new(); + + let handles: Vec<_> = styles + .iter() + .map(|s| { + let pb = m.add(ProgressBar::new(512)); + pb.set_style( + ProgressStyle::with_template(&format!("{{prefix:.bold}}▕{{bar:.{}}}▏{{msg}}", s.2)) + .unwrap() + .progress_chars(s.1), + ); + pb.set_prefix(s.0); + let wait = Duration::from_millis(rand::rng().random_range(10..30)); + thread::spawn(move || { + for i in 0..512 { + thread::sleep(wait); + pb.inc(1); + pb.set_message(format!("{:3}%", 100 * i / 512)); + } + pb.finish_with_message("100%"); + }) + }) + .collect(); + + for h in handles { + let _ = h.join(); + } +} diff --git a/anneal/v2/vendor/indicatif/examples/iterator.rs b/anneal/v2/vendor/indicatif/examples/iterator.rs new file mode 100644 index 0000000000..8f4004720b --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/iterator.rs @@ -0,0 +1,31 @@ +use std::thread; +use std::time::Duration; + +use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; + +fn main() { + // Default styling, attempt to use Iterator::size_hint to count input size + for _ in (0..1000).progress() { + // ... + thread::sleep(Duration::from_millis(5)); + } + + // Provide explicit number of elements in iterator + for _ in (0..1000).progress_count(1000) { + // ... + thread::sleep(Duration::from_millis(5)); + } + + // Provide a custom bar style + let pb = ProgressBar::new(1000); + pb.set_style( + ProgressStyle::with_template( + "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] ({pos}/{len}, ETA {eta})", + ) + .unwrap(), + ); + for _ in (0..1000).progress_with(pb) { + // ... + thread::sleep(Duration::from_millis(5)); + } +} diff --git a/anneal/v2/vendor/indicatif/examples/log.rs b/anneal/v2/vendor/indicatif/examples/log.rs new file mode 100644 index 0000000000..26d506cd00 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/log.rs @@ -0,0 +1,14 @@ +use std::thread; +use std::time::Duration; + +use indicatif::ProgressBar; + +fn main() { + let pb = ProgressBar::new(100); + for i in 0..100 { + thread::sleep(Duration::from_millis(25)); + pb.println(format!("[+] finished #{i}")); + pb.inc(1); + } + pb.finish_with_message("done"); +} diff --git a/anneal/v2/vendor/indicatif/examples/long-spinner.rs b/anneal/v2/vendor/indicatif/examples/long-spinner.rs new file mode 100644 index 0000000000..6b145487b8 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/long-spinner.rs @@ -0,0 +1,27 @@ +use std::thread; +use std::time::Duration; + +use indicatif::{ProgressBar, ProgressStyle}; + +fn main() { + let pb = ProgressBar::new_spinner(); + pb.enable_steady_tick(Duration::from_millis(120)); + pb.set_style( + ProgressStyle::with_template("{spinner:.blue} {msg}") + .unwrap() + // For more spinners check out the cli-spinners project: + // https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json + .tick_strings(&[ + "▹▹▹▹▹", + "▸▹▹▹▹", + "▹▸▹▹▹", + "▹▹▸▹▹", + "▹▹▹▸▹", + "▹▹▹▹▸", + "▪▪▪▪▪", + ]), + ); + pb.set_message("Calculating..."); + thread::sleep(Duration::from_secs(5)); + pb.finish_with_message("Done"); +} diff --git a/anneal/v2/vendor/indicatif/examples/message.rs b/anneal/v2/vendor/indicatif/examples/message.rs new file mode 100644 index 0000000000..d15781ae95 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/message.rs @@ -0,0 +1,11 @@ +use std::{thread, time::Duration}; + +use indicatif::ProgressBar; + +fn main() { + let pb = ProgressBar::new(100).with_message("Frobbing the widget"); + for _ in 0..100 { + thread::sleep(Duration::from_millis(30)); + pb.inc(1); + } +} diff --git a/anneal/v2/vendor/indicatif/examples/morebars.rs b/anneal/v2/vendor/indicatif/examples/morebars.rs new file mode 100644 index 0000000000..30b664f00d --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/morebars.rs @@ -0,0 +1,28 @@ +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; + +fn main() { + let m = Arc::new(MultiProgress::new()); + let sty = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>7}/{len:7}").unwrap(); + + let pb = m.add(ProgressBar::new(5)); + pb.set_style(sty.clone()); + + // make sure we show up at all. otherwise no rendering + // event. + pb.tick(); + for _ in 0..5 { + let pb2 = m.add(ProgressBar::new(128)); + pb2.set_style(sty.clone()); + for _ in 0..128 { + thread::sleep(Duration::from_millis(5)); + pb2.inc(1); + } + pb2.finish(); + pb.inc(1); + } + pb.finish_with_message("done"); +} diff --git a/anneal/v2/vendor/indicatif/examples/multi-tree-ext.rs b/anneal/v2/vendor/indicatif/examples/multi-tree-ext.rs new file mode 100644 index 0000000000..b769f38123 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/multi-tree-ext.rs @@ -0,0 +1,280 @@ +use clap::Parser; +use std::fmt::Debug; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +use console::style; +use indicatif::{MultiProgress, MultiProgressAlignment, ProgressBar, ProgressStyle}; +use once_cell::sync::Lazy; +use rand::rngs::ThreadRng; +use rand::{Rng, RngCore}; + +#[derive(Debug, Clone)] +enum Action { + ModifyTree(usize), + IncProgressBar(usize), + Stop, +} + +#[derive(Clone, Debug)] +enum Elem { + AddItem(Item), + RemoveItem(Index), +} + +#[derive(Clone, Debug)] +struct Item { + key: String, + index: usize, + indent: usize, + progress_bar: ProgressBar, +} + +#[derive(Clone, Debug)] +struct Index(usize); + +const PB_LEN: u64 = 32; +static ELEM_IDX: AtomicUsize = AtomicUsize::new(0); + +static ELEMENTS: Lazy<[Elem; 27]> = Lazy::new(|| { + [ + Elem::AddItem(Item { + indent: 9, + index: 0, + progress_bar: ProgressBar::new(PB_LEN), + key: "dog".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 0, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_1".to_string(), + }), + Elem::AddItem(Item { + indent: 8, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "lazy".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_2".to_string(), + }), + Elem::AddItem(Item { + indent: 1, + index: 0, + progress_bar: ProgressBar::new(PB_LEN), + key: "the".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 0, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_3".to_string(), + }), + Elem::AddItem(Item { + indent: 7, + index: 3, + progress_bar: ProgressBar::new(PB_LEN), + key: "a".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 3, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_4".to_string(), + }), + Elem::AddItem(Item { + indent: 6, + index: 2, + progress_bar: ProgressBar::new(PB_LEN), + key: "over".to_string(), + }), + Elem::RemoveItem(Index(6)), + Elem::RemoveItem(Index(4)), + Elem::RemoveItem(Index(3)), + Elem::RemoveItem(Index(0)), + Elem::AddItem(Item { + indent: 0, + index: 2, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_5".to_string(), + }), + Elem::AddItem(Item { + indent: 4, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "fox".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_6".to_string(), + }), + Elem::AddItem(Item { + indent: 2, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "quick".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 1, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_7".to_string(), + }), + Elem::AddItem(Item { + indent: 5, + index: 5, + progress_bar: ProgressBar::new(PB_LEN), + key: "jumps".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 5, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_8".to_string(), + }), + Elem::AddItem(Item { + indent: 3, + index: 4, + progress_bar: ProgressBar::new(PB_LEN), + key: "brown".to_string(), + }), + Elem::AddItem(Item { + indent: 0, + index: 3, + progress_bar: ProgressBar::new(PB_LEN), + key: "temp_9".to_string(), + }), + Elem::RemoveItem(Index(10)), + Elem::RemoveItem(Index(7)), + Elem::RemoveItem(Index(4)), + Elem::RemoveItem(Index(3)), + Elem::RemoveItem(Index(1)), + ] +}); + +#[derive(Debug, Parser)] +pub struct Config { + #[clap(long)] + bottom_alignment: bool, +} + +/// The example demonstrates the usage of `MultiProgress` and further extends `multi-tree` example. +/// Now the example has 3 different actions implemented, and the item tree can be modified +/// by inserting or removing progress bars. The progress bars to be removed eventually +/// have messages with pattern `"temp_*"`. +/// +/// Also the command option `--bottom-alignment` is used to control the vertical alignment of the +/// `MultiProgress`. To enable this run it with +/// ```ignore +/// cargo run --example multi-tree-ext -- --bottom-alignment +/// ``` +pub fn main() { + let conf: Config = Config::parse(); + let mp = Arc::new(MultiProgress::new()); + let alignment = if conf.bottom_alignment { + MultiProgressAlignment::Bottom + } else { + MultiProgressAlignment::Top + }; + mp.set_alignment(alignment); + let sty_main = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>4}/{len:4}").unwrap(); + let sty_aux = + ProgressStyle::with_template("[{pos:>2}/{len:2}] {prefix}{spinner:.green} {msg}").unwrap(); + let sty_fin = ProgressStyle::with_template("[{pos:>2}/{len:2}] {prefix}{msg}").unwrap(); + + let pb_main = mp.add(ProgressBar::new( + ELEMENTS + .iter() + .map(|e| match e { + Elem::AddItem(item) => item.progress_bar.length().unwrap(), + Elem::RemoveItem(_) => 1, + }) + .sum(), + )); + + pb_main.set_style(sty_main); + for e in ELEMENTS.iter() { + match e { + Elem::AddItem(item) => item.progress_bar.set_style(sty_aux.clone()), + Elem::RemoveItem(_) => {} + } + } + + let mut items: Vec<&Item> = Vec::with_capacity(ELEMENTS.len()); + + let mp2 = Arc::clone(&mp); + let mut rng = ThreadRng::default(); + pb_main.tick(); + loop { + match get_action(&mut rng, &items) { + Action::Stop => { + // all elements were exhausted + pb_main.finish(); + return; + } + Action::ModifyTree(elem_idx) => match &ELEMENTS[elem_idx] { + Elem::AddItem(item) => { + let pb = mp2.insert(item.index, item.progress_bar.clone()); + pb.set_prefix(" ".repeat(item.indent)); + pb.set_message(&item.key); + items.insert(item.index, item); + } + Elem::RemoveItem(Index(index)) => { + let item = items.remove(*index); + let pb = &item.progress_bar; + mp2.remove(pb); + pb_main.inc(pb.length().unwrap() - pb.position()); + } + }, + Action::IncProgressBar(item_idx) => { + let item = &items[item_idx]; + item.progress_bar.inc(1); + let pos = item.progress_bar.position(); + if pos >= item.progress_bar.length().unwrap() { + item.progress_bar.set_style(sty_fin.clone()); + item.progress_bar.finish_with_message(format!( + "{} {}", + style("✔").green(), + item.key + )); + } + pb_main.inc(1); + } + } + thread::sleep(Duration::from_millis(20)); + } +} + +/// The function guarantees to return the action, that is valid for the current tree. +fn get_action(rng: &mut dyn RngCore, items: &[&Item]) -> Action { + let elem_idx = ELEM_IDX.load(Ordering::SeqCst); + // the indices of those items, that not completed yet + let uncompleted = items + .iter() + .enumerate() + .filter(|(_, item)| { + let pos = item.progress_bar.position(); + pos < item.progress_bar.length().unwrap() + }) + .map(|(idx, _)| idx) + .collect::>(); + let k = rng.random_range(0..16); + if (k > 0 || k == 0 && elem_idx == ELEMENTS.len()) && !uncompleted.is_empty() { + let idx = rng.random_range(0..uncompleted.len() as u64) as usize; + Action::IncProgressBar(uncompleted[idx]) + } else if elem_idx < ELEMENTS.len() { + ELEM_IDX.fetch_add(1, Ordering::SeqCst); + Action::ModifyTree(elem_idx) + } else { + // nothing to do more + Action::Stop + } +} diff --git a/anneal/v2/vendor/indicatif/examples/multi-tree.rs b/anneal/v2/vendor/indicatif/examples/multi-tree.rs new file mode 100644 index 0000000000..ac1f06093e --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/multi-tree.rs @@ -0,0 +1,189 @@ +use std::fmt::Debug; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; + +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use once_cell::sync::Lazy; +use rand::rngs::ThreadRng; +use rand::{Rng, RngCore}; + +#[derive(Debug, Clone)] +enum Action { + AddProgressBar(usize), + IncProgressBar(usize), +} + +#[derive(Clone, Debug)] +struct Elem { + key: String, + index: usize, + indent: usize, + progress_bar: ProgressBar, +} + +static ELEMENTS: Lazy<[Elem; 9]> = Lazy::new(|| { + [ + Elem { + indent: 1, + index: 0, + progress_bar: ProgressBar::new(32), + key: "jumps".to_string(), + }, + Elem { + indent: 2, + index: 1, + progress_bar: ProgressBar::new(32), + key: "lazy".to_string(), + }, + Elem { + indent: 0, + index: 0, + progress_bar: ProgressBar::new(32), + key: "the".to_string(), + }, + Elem { + indent: 3, + index: 3, + progress_bar: ProgressBar::new(32), + key: "dog".to_string(), + }, + Elem { + indent: 2, + index: 2, + progress_bar: ProgressBar::new(32), + key: "over".to_string(), + }, + Elem { + indent: 2, + index: 1, + progress_bar: ProgressBar::new(32), + key: "brown".to_string(), + }, + Elem { + indent: 1, + index: 1, + progress_bar: ProgressBar::new(32), + key: "quick".to_string(), + }, + Elem { + indent: 3, + index: 5, + progress_bar: ProgressBar::new(32), + key: "a".to_string(), + }, + Elem { + indent: 3, + index: 3, + progress_bar: ProgressBar::new(32), + key: "fox".to_string(), + }, + ] +}); + +/// The example implements the tree-like collection of progress bars, where elements are +/// added on the fly and progress bars get incremented until all elements is added and +/// all progress bars finished. +/// On each iteration `get_action` function returns some action, and when the tree gets +/// complete, the function returns `None`, which finishes the loop. +fn main() { + let mp = Arc::new(MultiProgress::new()); + let sty_main = ProgressStyle::with_template("{bar:40.green/yellow} {pos:>4}/{len:4}").unwrap(); + let sty_aux = ProgressStyle::with_template("{spinner:.green} {msg} {pos:>4}/{len:4}").unwrap(); + + let pb_main = mp.add(ProgressBar::new( + ELEMENTS + .iter() + .map(|e| e.progress_bar.length().unwrap()) + .sum(), + )); + pb_main.set_style(sty_main); + for elem in ELEMENTS.iter() { + elem.progress_bar.set_style(sty_aux.clone()); + } + + let tree: Arc>> = Arc::new(Mutex::new(Vec::with_capacity(ELEMENTS.len()))); + let tree2 = Arc::clone(&tree); + + let mp2 = Arc::clone(&mp); + let _ = thread::spawn(move || { + let mut rng = ThreadRng::default(); + pb_main.tick(); + loop { + thread::sleep(Duration::from_millis(15)); + match get_action(&mut rng, &tree) { + None => { + // all elements were exhausted + pb_main.finish(); + return; + } + Some(Action::AddProgressBar(el_idx)) => { + let elem = &ELEMENTS[el_idx]; + let pb = mp2.insert(elem.index + 1, elem.progress_bar.clone()); + pb.set_message(format!("{} {}", " ".repeat(elem.indent), elem.key)); + tree.lock().unwrap().insert(elem.index, elem); + } + Some(Action::IncProgressBar(el_idx)) => { + let elem = &tree.lock().unwrap()[el_idx]; + elem.progress_bar.inc(1); + let pos = elem.progress_bar.position(); + if pos >= elem.progress_bar.length().unwrap() { + elem.progress_bar.finish_with_message(format!( + "{}{} {}", + " ".repeat(elem.indent), + "✔", + elem.key + )); + } + pb_main.inc(1); + } + } + } + }) + .join(); + + println!("==============================="); + println!("the tree should be the same as:"); + for elem in tree2.lock().unwrap().iter() { + println!("{} {}", " ".repeat(elem.indent), elem.key); + } +} + +/// The function guarantees to return the action, that is valid for the current tree. +fn get_action(rng: &mut dyn RngCore, tree: &Mutex>) -> Option { + let elem_len = ELEMENTS.len() as u64; + let list_len = tree.lock().unwrap().len() as u64; + let sum_free = tree + .lock() + .unwrap() + .iter() + .map(|e| { + let pos = e.progress_bar.position(); + let len = e.progress_bar.length().unwrap(); + len - pos + }) + .sum::(); + + if sum_free == 0 && list_len == elem_len { + // nothing to do more + None + } else if sum_free == 0 && list_len < elem_len { + // there is no place to make an increment + Some(Action::AddProgressBar(tree.lock().unwrap().len())) + } else { + loop { + let list = tree.lock().unwrap(); + let k = rng.random_range(0..17); + if k == 0 && list_len < elem_len { + return Some(Action::AddProgressBar(list.len())); + } else { + let l = (k % list_len) as usize; + let pos = list[l].progress_bar.position(); + let len = list[l].progress_bar.length(); + if pos < len.unwrap() { + return Some(Action::IncProgressBar(l)); + } + } + } + } +} diff --git a/anneal/v2/vendor/indicatif/examples/multi.rs b/anneal/v2/vendor/indicatif/examples/multi.rs new file mode 100644 index 0000000000..4a7eb5366b --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/multi.rs @@ -0,0 +1,62 @@ +use std::thread; +use std::time::Duration; + +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; + +use rand::Rng; + +fn main() { + let m = MultiProgress::new(); + let sty = ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", + ) + .unwrap() + .progress_chars("##-"); + + let n = 200; + let pb = m.add(ProgressBar::new(n)); + pb.set_style(sty.clone()); + pb.set_message("todo"); + let pb2 = m.add(ProgressBar::new(n)); + pb2.set_style(sty.clone()); + pb2.set_message("finished"); + + let pb3 = m.insert_after(&pb2, ProgressBar::new(1024)); + pb3.set_style(sty); + + m.println("starting!").unwrap(); + + let mut threads = vec![]; + + let m_clone = m.clone(); + let h3 = thread::spawn(move || { + for i in 0..1024 { + thread::sleep(Duration::from_millis(2)); + pb3.set_message(format!("item #{}", i + 1)); + pb3.inc(1); + } + m_clone.println("pb3 is done!").unwrap(); + pb3.finish_with_message("done"); + }); + + for i in 0..n { + thread::sleep(Duration::from_millis(15)); + if i == n / 3 { + thread::sleep(Duration::from_secs(2)); + } + pb.inc(1); + let pb2 = pb2.clone(); + threads.push(thread::spawn(move || { + thread::sleep(rand::rng().random_range(Duration::from_secs(1)..Duration::from_secs(5))); + pb2.inc(1); + })); + } + pb.finish_with_message("all jobs started"); + + for thread in threads { + let _ = thread.join(); + } + let _ = h3.join(); + pb2.finish_with_message("all jobs done"); + m.clear().unwrap(); +} diff --git a/anneal/v2/vendor/indicatif/examples/single.rs b/anneal/v2/vendor/indicatif/examples/single.rs new file mode 100644 index 0000000000..6e921e54f5 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/single.rs @@ -0,0 +1,13 @@ +use std::thread; +use std::time::Duration; + +use indicatif::ProgressBar; + +fn main() { + let pb = ProgressBar::new(1024); + for _ in 0..1024 { + thread::sleep(Duration::from_millis(5)); + pb.inc(1); + } + pb.finish_with_message("done"); +} diff --git a/anneal/v2/vendor/indicatif/examples/slow.rs b/anneal/v2/vendor/indicatif/examples/slow.rs new file mode 100644 index 0000000000..91a8e7e607 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/slow.rs @@ -0,0 +1,12 @@ +use indicatif::{ProgressBar, ProgressStyle}; +use std::time::Duration; + +fn main() { + let progress = + ProgressBar::new(10).with_style(ProgressStyle::default_bar().progress_chars("🔐🔑🕓")); + for _ in 0..10 { + progress.inc(1); + std::thread::sleep(Duration::from_secs(1)); + } + progress.finish(); +} diff --git a/anneal/v2/vendor/indicatif/examples/spinner-loop.rs b/anneal/v2/vendor/indicatif/examples/spinner-loop.rs new file mode 100644 index 0000000000..7ecc9463c3 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/spinner-loop.rs @@ -0,0 +1,20 @@ +use std::thread; +use std::time::Duration; + +use indicatif::{ProgressBar, ProgressFinish}; + +fn main() { + let mut spinner: Option = None; + + for i in 0..3 { + let new_spinner = ProgressBar::new_spinner() + .with_message(format!("doing stuff {}", i)) + .with_finish(ProgressFinish::AndLeave); + new_spinner.enable_steady_tick(Duration::from_millis(10)); + thread::sleep(Duration::from_millis(500)); + println!("\n\nreplace {}\n\n", i); + if let Some(t) = spinner.replace(new_spinner) { + t.finish() + } + } +} diff --git a/anneal/v2/vendor/indicatif/examples/steady.rs b/anneal/v2/vendor/indicatif/examples/steady.rs new file mode 100644 index 0000000000..4515ce97b6 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/steady.rs @@ -0,0 +1,50 @@ +use std::{ + thread::sleep, + time::{Duration, Instant}, +}; + +use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; + +fn main() { + let iterations = 1000; + // Set the array with all the blocksizes to test + let blocksizes: [usize; 7] = [16, 64, 256, 1024, 4096, 16384, 65536]; + + // Set the array with all the durations to save + let mut elapsed: [Duration; 7] = [Duration::ZERO; 7]; + + for (pos, blocksize) in blocksizes.iter().enumerate() { + // Set up the style for the progressbar + let sty = ProgressStyle::default_spinner() + .tick_strings(&[ + "▹▹▹▹▹", + "▸▹▹▹▹", + "▹▸▹▹▹", + "▹▹▸▹▹", + "▹▹▹▸▹", + "▹▹▹▹▸", + "▪▪▪▪▪", + ]) + .template("{prefix} {pos:>4}/{len:4} Iterations per second: {per_sec} {spinner} {msg}") + .unwrap(); + + // Set up the progress bar and apply the style + let pb = ProgressBar::new(iterations); + pb.set_style(sty); + pb.enable_steady_tick(Duration::from_millis(120)); + pb.set_prefix(format!("Doing test with Blocksize {:5?}:", blocksize)); + + // Iterate for the given number of iterations + // for _ in (0..iterations) { + for _ in (0..iterations).progress_with(pb) { + // pb.inc(1); + // Take a timestamp for timemeasurement later on + let now = Instant::now(); + sleep(Duration::from_millis(1)); + // Save the elapsed time for later evaluation + elapsed[pos] += now.elapsed(); + } + + // pb.finish_using_style(); + } +} diff --git a/anneal/v2/vendor/indicatif/examples/tokio.rs b/anneal/v2/vendor/indicatif/examples/tokio.rs new file mode 100644 index 0000000000..17ac2b1fff --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/tokio.rs @@ -0,0 +1,34 @@ +use std::time::Duration; + +use indicatif::ProgressBar; +use tokio::runtime; +use tokio::time::interval; + +fn main() { + // Plain progress bar, totaling 1024 steps. + let steps = 1024; + let pb = ProgressBar::new(steps); + + // Stream of events, triggering every 5ms. + let rt = runtime::Builder::new_current_thread() + .enable_time() + .build() + .expect("failed to create runtime"); + + // Future computation which runs for `steps` interval events, + // incrementing one step of the progress bar each time. + let future = async { + let mut intv = interval(Duration::from_millis(5)); + + for _ in 0..steps { + intv.tick().await; + pb.inc(1); + } + }; + + // Drive the future to completion, blocking until done. + rt.block_on(future); + + // Mark the progress bar as finished. + pb.finish(); +} diff --git a/anneal/v2/vendor/indicatif/examples/yarnish.rs b/anneal/v2/vendor/indicatif/examples/yarnish.rs new file mode 100644 index 0000000000..129c0f5b66 --- /dev/null +++ b/anneal/v2/vendor/indicatif/examples/yarnish.rs @@ -0,0 +1,97 @@ +use std::thread; +use std::time::{Duration, Instant}; + +use console::{style, Emoji}; +use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressStyle}; +use rand::prelude::IndexedRandom; +use rand::Rng; + +static PACKAGES: &[&str] = &[ + "fs-events", + "my-awesome-module", + "emoji-speaker", + "wrap-ansi", + "stream-browserify", + "acorn-dynamic-import", +]; + +static COMMANDS: &[&str] = &[ + "cmake .", + "make", + "make clean", + "gcc foo.c -o foo", + "gcc bar.c -o bar", + "./helper.sh rebuild-cache", + "make all-clean", + "make test", +]; + +static LOOKING_GLASS: Emoji<'_, '_> = Emoji("🔍 ", ""); +static TRUCK: Emoji<'_, '_> = Emoji("🚚 ", ""); +static CLIP: Emoji<'_, '_> = Emoji("🔗 ", ""); +static PAPER: Emoji<'_, '_> = Emoji("📃 ", ""); +static SPARKLE: Emoji<'_, '_> = Emoji("✨ ", ":-)"); + +pub fn main() { + let mut rng = rand::rng(); + let started = Instant::now(); + let spinner_style = ProgressStyle::with_template("{prefix:.bold.dim} {spinner} {wide_msg}") + .unwrap() + .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "); + + println!( + "{} {}Resolving packages...", + style("[1/4]").bold().dim(), + LOOKING_GLASS + ); + println!( + "{} {}Fetching packages...", + style("[2/4]").bold().dim(), + TRUCK + ); + + println!( + "{} {}Linking dependencies...", + style("[3/4]").bold().dim(), + CLIP + ); + let deps = 1232; + let pb = ProgressBar::new(deps); + for _ in 0..deps { + thread::sleep(Duration::from_millis(3)); + pb.inc(1); + } + pb.finish_and_clear(); + + println!( + "{} {}Building fresh packages...", + style("[4/4]").bold().dim(), + PAPER + ); + let m = MultiProgress::new(); + let handles: Vec<_> = (0..4u32) + .map(|i| { + let count = rng.random_range(30..80); + let pb = m.add(ProgressBar::new(count)); + pb.set_style(spinner_style.clone()); + pb.set_prefix(format!("[{}/?]", i + 1)); + thread::spawn(move || { + let mut rng = rand::rng(); + let pkg = PACKAGES.choose(&mut rng).unwrap(); + for _ in 0..count { + let cmd = COMMANDS.choose(&mut rng).unwrap(); + thread::sleep(Duration::from_millis(rng.random_range(25..200))); + pb.set_message(format!("{pkg}: {cmd}")); + pb.inc(1); + } + pb.finish_with_message("waiting..."); + }) + }) + .collect(); + for h in handles { + let _ = h.join(); + } + m.clear().unwrap(); + + println!("{} Done in {}", SPARKLE, HumanDuration(started.elapsed())); +} diff --git a/anneal/v2/vendor/indicatif/src/draw_target.rs b/anneal/v2/vendor/indicatif/src/draw_target.rs new file mode 100644 index 0000000000..b49728086b --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/draw_target.rs @@ -0,0 +1,805 @@ +use std::io; +use std::ops::{Add, AddAssign, Sub}; +use std::slice::SliceIndex; +use std::sync::{Arc, RwLock, RwLockWriteGuard}; +use std::thread::panicking; +use std::time::Duration; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; + +use console::{Term, TermTarget}; +#[cfg(all(target_arch = "wasm32", feature = "wasmbind"))] +use web_time::Instant; + +use crate::multi::{MultiProgressAlignment, MultiState}; +use crate::TermLike; + +/// Target for draw operations +/// +/// This tells a [`ProgressBar`](crate::ProgressBar) or a +/// [`MultiProgress`](crate::MultiProgress) object where to paint to. +/// The draw target is a stateful wrapper over a drawing destination and +/// internally optimizes how often the state is painted to the output +/// device. +#[derive(Debug)] +pub struct ProgressDrawTarget { + kind: TargetKind, +} + +impl ProgressDrawTarget { + /// Draw to a buffered stdout terminal at a max of 20 times a second. + /// + /// For more information see [`ProgressDrawTarget::term`]. + pub fn stdout() -> Self { + Self::term(Term::buffered_stdout(), 20) + } + + /// Draw to a buffered stderr terminal at a max of 20 times a second. + /// + /// This is the default draw target for progress bars. For more + /// information see [`ProgressDrawTarget::term`]. + pub fn stderr() -> Self { + Self::term(Term::buffered_stderr(), 20) + } + + /// Draw to a buffered stdout terminal at a max of `refresh_rate` times a second. + /// + /// For more information see [`ProgressDrawTarget::term`]. + pub fn stdout_with_hz(refresh_rate: u8) -> Self { + Self::term(Term::buffered_stdout(), refresh_rate) + } + + /// Draw to a buffered stderr terminal at a max of `refresh_rate` times a second. + /// + /// For more information see [`ProgressDrawTarget::term`]. + pub fn stderr_with_hz(refresh_rate: u8) -> Self { + Self::term(Term::buffered_stderr(), refresh_rate) + } + + pub(crate) fn new_remote(state: Arc>, idx: usize) -> Self { + Self { + kind: TargetKind::Multi { state, idx }, + } + } + + /// Draw to a terminal, with a specific refresh rate. + /// + /// Progress bars are by default drawn to terminals however if the + /// terminal is not user attended the entire progress bar will be + /// hidden. This is done so that piping to a file will not produce + /// useless escape codes in that file. + /// + /// Progress bars will also be hidden if `NO_COLOR` is set or `TERM` is unset/`dumb`. + /// + /// Will panic if `refresh_rate` is `0`. + pub fn term(term: Term, refresh_rate: u8) -> Self { + if !term.features().colors_supported() { + return Self::hidden(); + } + Self { + kind: TargetKind::Term { + term, + last_line_count: VisualLines::default(), + rate_limiter: RateLimiter::new(refresh_rate), + draw_state: DrawState::default(), + }, + } + } + + /// Draw to a boxed object that implements the [`TermLike`] trait. + /// + /// Warning: unlike `stdout()`, `stderr()` and `term()`, this method does not set a default + /// refresh rate. For most uses, consider using `term_like_with_hz()` instead. + /// + /// (indicatif defaults to a refresh rate of 20 times per second in other methods.) + pub fn term_like(term_like: Box) -> Self { + Self { + kind: TargetKind::TermLike { + inner: term_like, + last_line_count: VisualLines::default(), + rate_limiter: None, + draw_state: DrawState::default(), + }, + } + } + + /// Draw to a boxed object that implements the [`TermLike`] trait, + /// with a specific refresh rate. + pub fn term_like_with_hz(term_like: Box, refresh_rate: u8) -> Self { + Self { + kind: TargetKind::TermLike { + inner: term_like, + last_line_count: VisualLines::default(), + rate_limiter: Option::from(RateLimiter::new(refresh_rate)), + draw_state: DrawState::default(), + }, + } + } + + /// A hidden draw target. + /// + /// This forces a progress bar to be not rendered at all. + pub fn hidden() -> Self { + Self { + kind: TargetKind::Hidden, + } + } + + /// Returns true if the draw target is hidden. + /// + /// This is internally used in progress bars to figure out if overhead + /// from drawing can be prevented. + pub fn is_hidden(&self) -> bool { + match self.kind { + TargetKind::Hidden => true, + TargetKind::Term { ref term, .. } => !term.is_term(), + TargetKind::Multi { ref state, .. } => state.read().unwrap().is_hidden(), + _ => false, + } + } + + /// This is used in progress bars to determine whether to use stdout or stderr + /// for detecting color support. + pub(crate) fn is_stderr(&self) -> bool { + match &self.kind { + TargetKind::Term { term, .. } => matches!(term.target(), TermTarget::Stderr), + _ => false, + } + } + + /// Returns the current width of the draw target. + pub(crate) fn width(&self) -> Option { + match self.kind { + TargetKind::Term { ref term, .. } => Some(term.size().1), + TargetKind::Multi { ref state, .. } => state.read().unwrap().width(), + TargetKind::TermLike { ref inner, .. } => Some(inner.width()), + TargetKind::Hidden => None, + } + } + + /// Notifies the backing `MultiProgress` (if applicable) that the associated progress bar should + /// be marked a zombie. + pub(crate) fn mark_zombie(&self) { + if let TargetKind::Multi { idx, state } = &self.kind { + state.write().unwrap().mark_zombie(*idx); + } + } + + /// Set whether or not to just move cursor instead of clearing lines + pub(crate) fn set_move_cursor(&mut self, move_cursor: bool) { + match &mut self.kind { + TargetKind::Term { draw_state, .. } => draw_state.move_cursor = move_cursor, + TargetKind::TermLike { draw_state, .. } => draw_state.move_cursor = move_cursor, + _ => {} + } + } + + /// Apply the given draw state (draws it). + pub(crate) fn drawable(&mut self, force_draw: bool, now: Instant) -> Option> { + match &mut self.kind { + TargetKind::Term { + term, + last_line_count, + rate_limiter, + draw_state, + } => { + match force_draw || rate_limiter.allow(now) { + true => Some(Drawable::Term { + term, + last_line_count, + draw_state, + }), + false => None, // rate limited + } + } + TargetKind::Multi { idx, state, .. } => { + let state = state.write().unwrap(); + Some(Drawable::Multi { + idx: *idx, + state, + force_draw, + now, + }) + } + TargetKind::TermLike { + inner, + last_line_count, + rate_limiter, + draw_state, + } => match force_draw || rate_limiter.as_mut().map_or(true, |r| r.allow(now)) { + true => Some(Drawable::TermLike { + term_like: &**inner, + last_line_count, + draw_state, + }), + false => None, // rate limited + }, + // Hidden, finished, or no need to refresh yet + _ => None, + } + } + + /// Properly disconnects from the draw target + pub(crate) fn disconnect(&self, now: Instant) { + match self.kind { + TargetKind::Term { .. } => {} + TargetKind::Multi { idx, ref state, .. } => { + let state = state.write().unwrap(); + let _ = Drawable::Multi { + state, + idx, + force_draw: true, + now, + } + .clear(); + } + TargetKind::Hidden => {} + TargetKind::TermLike { .. } => {} + }; + } + + pub(crate) fn remote(&self) -> Option<(&Arc>, usize)> { + match &self.kind { + TargetKind::Multi { state, idx } => Some((state, *idx)), + _ => None, + } + } + + pub(crate) fn adjust_last_line_count(&mut self, adjust: LineAdjust) { + self.kind.adjust_last_line_count(adjust); + } +} + +#[derive(Debug)] +enum TargetKind { + Term { + term: Term, + last_line_count: VisualLines, + rate_limiter: RateLimiter, + draw_state: DrawState, + }, + Multi { + state: Arc>, + idx: usize, + }, + Hidden, + TermLike { + inner: Box, + last_line_count: VisualLines, + rate_limiter: Option, + draw_state: DrawState, + }, +} + +impl TargetKind { + /// Adjust `last_line_count` such that the next draw operation keeps/clears additional lines + fn adjust_last_line_count(&mut self, adjust: LineAdjust) { + let last_line_count = match self { + Self::Term { + last_line_count, .. + } => last_line_count, + Self::TermLike { + last_line_count, .. + } => last_line_count, + _ => return, + }; + + match adjust { + LineAdjust::Clear(count) => *last_line_count = last_line_count.saturating_add(count), + LineAdjust::Keep(count) => *last_line_count = last_line_count.saturating_sub(count), + } + } +} + +pub(crate) enum Drawable<'a> { + Term { + term: &'a Term, + last_line_count: &'a mut VisualLines, + draw_state: &'a mut DrawState, + }, + Multi { + state: RwLockWriteGuard<'a, MultiState>, + idx: usize, + force_draw: bool, + now: Instant, + }, + TermLike { + term_like: &'a dyn TermLike, + last_line_count: &'a mut VisualLines, + draw_state: &'a mut DrawState, + }, +} + +impl Drawable<'_> { + /// Adjust `last_line_count` such that the next draw operation keeps/clears additional lines + pub(crate) fn adjust_last_line_count(&mut self, adjust: LineAdjust) { + let last_line_count: &mut VisualLines = match self { + Drawable::Term { + last_line_count, .. + } => last_line_count, + Drawable::TermLike { + last_line_count, .. + } => last_line_count, + _ => return, + }; + + match adjust { + LineAdjust::Clear(count) => *last_line_count = last_line_count.saturating_add(count), + LineAdjust::Keep(count) => *last_line_count = last_line_count.saturating_sub(count), + } + } + + pub(crate) fn state(&mut self) -> DrawStateWrapper<'_> { + let mut state = match self { + Drawable::Term { draw_state, .. } => DrawStateWrapper::for_term(draw_state), + Drawable::Multi { state, idx, .. } => state.draw_state(*idx), + Drawable::TermLike { draw_state, .. } => DrawStateWrapper::for_term(draw_state), + }; + + state.reset(); + state + } + + pub(crate) fn clear(mut self) -> io::Result<()> { + let state = self.state(); + drop(state); + self.draw() + } + + pub(crate) fn draw(self) -> io::Result<()> { + match self { + Drawable::Term { + term, + last_line_count, + draw_state, + } => draw_state.draw_to_term(term, last_line_count), + Drawable::Multi { + mut state, + force_draw, + now, + .. + } => state.draw(force_draw, None, now), + Drawable::TermLike { + term_like, + last_line_count, + draw_state, + } => draw_state.draw_to_term(term_like, last_line_count), + } + } + + pub(crate) fn width(&self) -> Option { + match self { + Self::Term { term, .. } => Some(term.size().1), + Self::Multi { state, .. } => state.width(), + Self::TermLike { term_like, .. } => Some(term_like.width()), + } + } +} + +pub(crate) enum LineAdjust { + /// Adds to `last_line_count` so that the next draw also clears those lines + Clear(VisualLines), + /// Subtracts from `last_line_count` so that the next draw retains those lines + Keep(VisualLines), +} + +pub(crate) struct DrawStateWrapper<'a> { + state: &'a mut DrawState, + orphan_lines: Option<&'a mut Vec>, +} + +impl<'a> DrawStateWrapper<'a> { + pub(crate) fn for_term(state: &'a mut DrawState) -> Self { + Self { + state, + orphan_lines: None, + } + } + + pub(crate) fn for_multi(state: &'a mut DrawState, orphan_lines: &'a mut Vec) -> Self { + Self { + state, + orphan_lines: Some(orphan_lines), + } + } +} + +impl std::ops::Deref for DrawStateWrapper<'_> { + type Target = DrawState; + + fn deref(&self) -> &Self::Target { + self.state + } +} + +impl std::ops::DerefMut for DrawStateWrapper<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.state + } +} + +impl Drop for DrawStateWrapper<'_> { + fn drop(&mut self) { + if let Some(text_lines) = &mut self.orphan_lines { + // Filter out the lines that do not contain progress information + // Store the filtered out lines in orphaned + let mut lines = Vec::new(); + + for line in self.state.lines.drain(..) { + match &line { + LineType::Text(_) | LineType::Empty => text_lines.push(line), + _ => lines.push(line), + } + } + + self.state.lines = lines; + } + } +} + +#[derive(Debug)] +struct RateLimiter { + interval: u16, // in milliseconds + capacity: u8, + prev: Instant, +} + +/// Rate limit but allow occasional bursts above desired rate +impl RateLimiter { + fn new(rate: u8) -> Self { + Self { + interval: 1000 / (rate as u16), // between 3 and 1000 milliseconds + capacity: MAX_BURST, + prev: Instant::now(), + } + } + + fn allow(&mut self, now: Instant) -> bool { + if now < self.prev { + return false; + } + + let elapsed = now - self.prev; + // If `capacity` is 0 and not enough time (`self.interval` ms) has passed since + // `self.prev` to add new capacity, return `false`. The goal of this method is to + // make this decision as efficient as possible. + if self.capacity == 0 && elapsed < Duration::from_millis(self.interval as u64) { + return false; + } + + // We now calculate `new`, the number of ms, since we last returned `true`, + // and `remainder`, which represents a number of ns less than 1ms which we cannot + // convert into capacity now, so we're saving it for later. + let (new, remainder) = ( + elapsed.as_millis() / self.interval as u128, + elapsed.as_nanos() % (self.interval as u128 * 1_000_000), + ); + + // We add `new` to `capacity`, subtract one for returning `true` from here, + // then make sure it does not exceed a maximum of `MAX_BURST`, then store it. + self.capacity = Ord::min(MAX_BURST as u128, (self.capacity as u128) + new - 1) as u8; + // Store `prev` for the next iteration after subtracting the `remainder`. + // Just use `unwrap` here because it shouldn't be possible for this to underflow. + self.prev = now + .checked_sub(Duration::from_nanos(remainder as u64)) + .unwrap(); + true + } +} + +const MAX_BURST: u8 = 20; + +/// The drawn state of an element. +#[derive(Clone, Debug, Default)] +pub(crate) struct DrawState { + /// The lines to print (can contain ANSI codes) + pub(crate) lines: Vec, + /// True if we should move the cursor up when possible instead of clearing lines. + pub(crate) move_cursor: bool, + /// Controls how the multi progress is aligned if some of its progress bars get removed, default is `Top` + pub(crate) alignment: MultiProgressAlignment, +} + +impl DrawState { + /// Draw the current state to the terminal + /// We expect a few things: + /// - self.lines contains n lines of text/empty then m lines of bars + /// - None of those lines contain newlines + fn draw_to_term( + &mut self, + term: &(impl TermLike + ?Sized), + bar_count: &mut VisualLines, // The number of dynamic lines printed at the previous tick + ) -> io::Result<()> { + if panicking() { + return Ok(()); + } + + if !self.lines.is_empty() && self.move_cursor { + // Move up to first line (assuming the last line doesn't contain a '\n') and then move to then front of the line + term.move_cursor_up(bar_count.as_usize().saturating_sub(1))?; + term.write_str("\r")?; + } else { + // Fork of console::clear_last_lines that assumes that the last line doesn't contain a '\n' + let n = bar_count.as_usize(); + term.move_cursor_up(n.saturating_sub(1))?; + for i in 0..n { + term.clear_line()?; + if i + 1 != n { + term.move_cursor_down(1)?; + } + } + term.move_cursor_up(n.saturating_sub(1))?; + } + + let term_width = term.width() as usize; + + // Here we calculate the terminal vertical real estate that the state requires + let full_height = self.visual_line_count(.., term_width); + + let shift = match self.alignment { + // If we align to the bottom and the new height is less than before, clear the lines + // that are not used by the new content. + MultiProgressAlignment::Bottom if full_height < *bar_count => { + let shift = *bar_count - full_height; + for _ in 0..shift.as_usize() { + term.write_line("")?; + } + shift + } + _ => VisualLines::default(), + }; + + // Accumulate the displayed height in here. This differs from `full_height` in that it will + // accurately reflect the number of lines that have been displayed on the terminal, if the + // full height exceeds the terminal height. + let mut real_height = VisualLines::default(); + + for (idx, line) in self.lines.iter().enumerate() { + let line_height = line.wrapped_height(term_width); + + // Check here for bar lines that exceed the terminal height + if matches!(line, LineType::Bar(_)) { + // Stop here if printing this bar would exceed the terminal height + if real_height + line_height > term.height().into() { + break; + } + + real_height += line_height; + } + + // Print a new line if this is not the first line printed this tick + // the first line will automatically wrap due to the filler below + if idx != 0 { + term.write_line("")?; + } + + term.write_str(line.as_ref())?; + + if idx + 1 == self.lines.len() { + // For the last line of the output, keep the cursor on the right terminal + // side so that next user writes/prints will happen on the next line + let last_line_filler = line_height.as_usize() * term_width - line.console_width(); + term.write_str(&" ".repeat(last_line_filler))?; + } + } + + term.flush()?; + *bar_count = real_height + shift; + + Ok(()) + } + + fn reset(&mut self) { + self.lines.clear(); + } + + pub(crate) fn visual_line_count( + &self, + range: impl SliceIndex<[LineType], Output = [LineType]>, + width: usize, + ) -> VisualLines { + visual_line_count(&self.lines[range], width) + } +} + +#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] +pub(crate) struct VisualLines(usize); + +impl VisualLines { + pub(crate) fn saturating_add(&self, other: Self) -> Self { + Self(self.0.saturating_add(other.0)) + } + + pub(crate) fn saturating_sub(&self, other: Self) -> Self { + Self(self.0.saturating_sub(other.0)) + } + + pub(crate) fn as_usize(&self) -> usize { + self.0 + } +} + +impl Add for VisualLines { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +impl AddAssign for VisualLines { + fn add_assign(&mut self, rhs: Self) { + self.0 += rhs.0; + } +} + +impl> From for VisualLines { + fn from(value: T) -> Self { + Self(value.into()) + } +} + +impl Sub for VisualLines { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +/// Calculate the number of visual lines in the given lines, after +/// accounting for line wrapping and non-printable characters. +pub(crate) fn visual_line_count(lines: &[LineType], width: usize) -> VisualLines { + lines.iter().fold(VisualLines::default(), |acc, line| { + acc.saturating_add(line.wrapped_height(width)) + }) +} + +#[derive(Clone, Debug)] +pub(crate) enum LineType { + Text(String), + Bar(String), + Empty, +} + +impl LineType { + fn wrapped_height(&self, width: usize) -> VisualLines { + // Calculate real length based on terminal width + // This take in account linewrap from terminal + let terminal_len = (self.console_width() as f64 / width as f64).ceil() as usize; + + // If the line is effectively empty (for example when it consists + // solely of ANSI color code sequences, count it the same as a + // new line. If the line is measured to be len = 0, we will + // subtract with overflow later. + usize::max(terminal_len, 1).into() + } + + fn console_width(&self) -> usize { + console::measure_text_width(self.as_ref()) + } +} + +impl AsRef for LineType { + fn as_ref(&self) -> &str { + match self { + LineType::Text(s) | LineType::Bar(s) => s, + LineType::Empty => "", + } + } +} + +impl PartialEq for LineType { + fn eq(&self, other: &str) -> bool { + self.as_ref() == other + } +} + +#[cfg(test)] +mod tests { + use crate::draw_target::LineType; + use crate::{MultiProgress, ProgressBar, ProgressDrawTarget}; + + #[test] + fn multi_is_hidden() { + let mp = MultiProgress::with_draw_target(ProgressDrawTarget::hidden()); + + let pb = mp.add(ProgressBar::new(100)); + assert!(mp.is_hidden()); + assert!(pb.is_hidden()); + } + + #[test] + fn real_line_count_test() { + #[derive(Debug)] + struct Case { + lines: &'static [&'static str], + expectation: usize, + width: usize, + } + + let lines_and_expectations = [ + Case { + lines: &["1234567890"], + expectation: 1, + width: 10, + }, + Case { + lines: &["1234567890"], + expectation: 2, + width: 5, + }, + Case { + lines: &["1234567890"], + expectation: 3, + width: 4, + }, + Case { + lines: &["1234567890"], + expectation: 4, + width: 3, + }, + Case { + lines: &["1234567890", "", "1234567890"], + expectation: 3, + width: 10, + }, + Case { + lines: &["1234567890", "", "1234567890"], + expectation: 5, + width: 5, + }, + Case { + lines: &["1234567890", "", "1234567890"], + expectation: 7, + width: 4, + }, + Case { + lines: &["aaaaaaaaaaaaa", "", "bbbbbbbbbbbbbbbbb", "", "ccccccc"], + expectation: 8, + width: 7, + }, + Case { + lines: &["", "", "", "", ""], + expectation: 5, + width: 6, + }, + Case { + // These lines contain only ANSI escape sequences, so they should only count as 1 line + lines: &["\u{1b}[1m\u{1b}[1m\u{1b}[1m", "\u{1b}[1m\u{1b}[1m\u{1b}[1m"], + expectation: 2, + width: 5, + }, + Case { + // These lines contain ANSI escape sequences and two effective chars, so they should only count as 1 line still + lines: &[ + "a\u{1b}[1m\u{1b}[1m\u{1b}[1ma", + "a\u{1b}[1m\u{1b}[1m\u{1b}[1ma", + ], + expectation: 2, + width: 5, + }, + Case { + // These lines contain ANSI escape sequences and six effective chars, so they should count as 2 lines each + lines: &[ + "aa\u{1b}[1m\u{1b}[1m\u{1b}[1mabcd", + "aa\u{1b}[1m\u{1b}[1m\u{1b}[1mabcd", + ], + expectation: 4, + width: 5, + }, + ]; + + for case in lines_and_expectations.iter() { + let result = super::visual_line_count( + &case + .lines + .iter() + .map(|s| LineType::Text(s.to_string())) + .collect::>(), + case.width, + ); + assert_eq!(result, case.expectation.into(), "case: {case:?}"); + } + } +} diff --git a/anneal/v2/vendor/indicatif/src/format.rs b/anneal/v2/vendor/indicatif/src/format.rs new file mode 100644 index 0000000000..e4d5b5adbd --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/format.rs @@ -0,0 +1,381 @@ +use std::fmt; +use std::time::Duration; + +use unit_prefix::NumberPrefix; + +const SECOND: Duration = Duration::from_secs(1); +const MINUTE: Duration = Duration::from_secs(60); +const HOUR: Duration = Duration::from_secs(60 * 60); +const DAY: Duration = Duration::from_secs(24 * 60 * 60); +const WEEK: Duration = Duration::from_secs(7 * 24 * 60 * 60); +const YEAR: Duration = Duration::from_secs(365 * 24 * 60 * 60); + +/// Wraps an std duration for human basic formatting. +#[derive(Debug)] +pub struct FormattedDuration(pub Duration); + +/// Wraps an std duration for human readable formatting. +#[derive(Debug)] +pub struct HumanDuration(pub Duration); + +/// Formats bytes for human readability +/// +/// # Examples +/// ```rust +/// # use indicatif::HumanBytes; +/// assert_eq!("15 B", format!("{}", HumanBytes(15))); +/// assert_eq!("1.46 KiB", format!("{}", HumanBytes(1_500))); +/// assert_eq!("1.43 MiB", format!("{}", HumanBytes(1_500_000))); +/// assert_eq!("1.40 GiB", format!("{}", HumanBytes(1_500_000_000))); +/// assert_eq!("1.36 TiB", format!("{}", HumanBytes(1_500_000_000_000))); +/// assert_eq!("1.33 PiB", format!("{}", HumanBytes(1_500_000_000_000_000))); +/// ``` +#[derive(Debug)] +pub struct HumanBytes(pub u64); + +/// Formats bytes for human readability using SI prefixes +/// +/// # Examples +/// ```rust +/// # use indicatif::DecimalBytes; +/// assert_eq!("15 B", format!("{}", DecimalBytes(15))); +/// assert_eq!("1.50 kB", format!("{}", DecimalBytes(1_500))); +/// assert_eq!("1.50 MB", format!("{}", DecimalBytes(1_500_000))); +/// assert_eq!("1.50 GB", format!("{}", DecimalBytes(1_500_000_000))); +/// assert_eq!("1.50 TB", format!("{}", DecimalBytes(1_500_000_000_000))); +/// assert_eq!("1.50 PB", format!("{}", DecimalBytes(1_500_000_000_000_000))); +/// ``` +#[derive(Debug)] +pub struct DecimalBytes(pub u64); + +/// Formats bytes for human readability using ISO/IEC prefixes +/// +/// # Examples +/// ```rust +/// # use indicatif::BinaryBytes; +/// assert_eq!("15 B", format!("{}", BinaryBytes(15))); +/// assert_eq!("1.46 KiB", format!("{}", BinaryBytes(1_500))); +/// assert_eq!("1.43 MiB", format!("{}", BinaryBytes(1_500_000))); +/// assert_eq!("1.40 GiB", format!("{}", BinaryBytes(1_500_000_000))); +/// assert_eq!("1.36 TiB", format!("{}", BinaryBytes(1_500_000_000_000))); +/// assert_eq!("1.33 PiB", format!("{}", BinaryBytes(1_500_000_000_000_000))); +/// ``` +#[derive(Debug)] +pub struct BinaryBytes(pub u64); + +/// Formats counts for human readability using commas +#[derive(Debug)] +pub struct HumanCount(pub u64); + +/// Formats counts for human readability using commas for floats +#[derive(Debug)] +pub struct HumanFloatCount(pub f64); + +impl fmt::Display for FormattedDuration { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut t = self.0.as_secs(); + let seconds = t % 60; + t /= 60; + let minutes = t % 60; + t /= 60; + let hours = t % 24; + t /= 24; + if t > 0 { + let days = t; + write!(f, "{days}d {hours:02}:{minutes:02}:{seconds:02}") + } else { + write!(f, "{hours:02}:{minutes:02}:{seconds:02}") + } + } +} + +// `HumanDuration` should be as intuitively understandable as possible. +// So we want to round, not truncate: otherwise 1 hour and 59 minutes +// would display an ETA of "1 hour" which underestimates the time +// remaining by a factor 2. +// +// To make the precision more uniform, we avoid displaying "1 unit" +// (except for seconds), because it would be displayed for a relatively +// long duration compared to the unit itself. Instead, when we arrive +// around 1.5 unit, we change from "2 units" to the next smaller unit +// (e.g. "89 seconds"). +// +// Formally: +// * for n >= 2, we go from "n+1 units" to "n units" exactly at (n + 1/2) units +// * we switch from "2 units" to the next smaller unit at (1.5 unit minus half of the next smaller unit) + +impl fmt::Display for HumanDuration { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut idx = 0; + for (i, &(cur, _, _)) in UNITS.iter().enumerate() { + idx = i; + match UNITS.get(i + 1) { + Some(&next) if self.0.saturating_add(next.0 / 2) >= cur + cur / 2 => break, + _ => continue, + } + } + + let (unit, name, alt) = UNITS[idx]; + // FIXME when `div_duration_f64` is stable + let mut t = (self.0.as_secs_f64() / unit.as_secs_f64()).round() as usize; + if idx < UNITS.len() - 1 { + t = Ord::max(t, 2); + } + + match (f.alternate(), t) { + (true, _) => write!(f, "{t}{alt}"), + (false, 1) => write!(f, "{t} {name}"), + (false, _) => write!(f, "{t} {name}s"), + } + } +} + +const UNITS: &[(Duration, &str, &str)] = &[ + (YEAR, "year", "y"), + (WEEK, "week", "w"), + (DAY, "day", "d"), + (HOUR, "hour", "h"), + (MINUTE, "minute", "m"), + (SECOND, "second", "s"), +]; + +impl fmt::Display for HumanBytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match NumberPrefix::binary(self.0 as f64) { + NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), + NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), + } + } +} + +impl fmt::Display for DecimalBytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match NumberPrefix::decimal(self.0 as f64) { + NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), + NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), + } + } +} + +impl fmt::Display for BinaryBytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match NumberPrefix::binary(self.0 as f64) { + NumberPrefix::Standalone(number) => write!(f, "{number:.0} B"), + NumberPrefix::Prefixed(prefix, number) => write!(f, "{number:.2} {prefix}B"), + } + } +} + +impl fmt::Display for HumanCount { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use fmt::Write; + + let num = self.0.to_string(); + let len = num.len(); + for (idx, c) in num.chars().enumerate() { + let pos = len - idx - 1; + f.write_char(c)?; + if pos > 0 && pos % 3 == 0 { + f.write_char(',')?; + } + } + Ok(()) + } +} + +impl fmt::Display for HumanFloatCount { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use fmt::Write; + + // Use formatter's precision if provided, otherwise default to 4 + let precision = f.precision().unwrap_or(4); + let num = format!("{:.*}", precision, self.0); + + let (int_part, frac_part) = match num.split_once('.') { + Some((int_str, fract_str)) => (int_str.to_string(), fract_str), + None => (self.0.trunc().to_string(), ""), + }; + let len = int_part.len(); + for (idx, c) in int_part.chars().enumerate() { + let pos = len - idx - 1; + f.write_char(c)?; + if pos > 0 && pos % 3 == 0 { + f.write_char(',')?; + } + } + let frac_trimmed = frac_part.trim_end_matches('0'); + if !frac_trimmed.is_empty() { + f.write_char('.')?; + f.write_str(frac_trimmed)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const MILLI: Duration = Duration::from_millis(1); + + #[test] + fn human_duration_alternate() { + for (unit, _, alt) in UNITS { + assert_eq!(format!("2{alt}"), format!("{:#}", HumanDuration(2 * *unit))); + } + } + + #[test] + fn human_duration_less_than_one_second() { + assert_eq!( + "0 seconds", + format!("{}", HumanDuration(Duration::from_secs(0))) + ); + assert_eq!("0 seconds", format!("{}", HumanDuration(MILLI))); + assert_eq!("0 seconds", format!("{}", HumanDuration(499 * MILLI))); + assert_eq!("1 second", format!("{}", HumanDuration(500 * MILLI))); + assert_eq!("1 second", format!("{}", HumanDuration(999 * MILLI))); + } + + #[test] + fn human_duration_less_than_two_seconds() { + assert_eq!("1 second", format!("{}", HumanDuration(1499 * MILLI))); + assert_eq!("2 seconds", format!("{}", HumanDuration(1500 * MILLI))); + assert_eq!("2 seconds", format!("{}", HumanDuration(1999 * MILLI))); + } + + #[test] + fn human_duration_one_unit() { + assert_eq!("1 second", format!("{}", HumanDuration(SECOND))); + assert_eq!("60 seconds", format!("{}", HumanDuration(MINUTE))); + assert_eq!("60 minutes", format!("{}", HumanDuration(HOUR))); + assert_eq!("24 hours", format!("{}", HumanDuration(DAY))); + assert_eq!("7 days", format!("{}", HumanDuration(WEEK))); + assert_eq!("52 weeks", format!("{}", HumanDuration(YEAR))); + } + + #[test] + fn human_duration_less_than_one_and_a_half_unit() { + // this one is actually done at 1.5 unit - half of the next smaller unit - epsilon + // and should display the next smaller unit + let d = HumanDuration(MINUTE + MINUTE / 2 - SECOND / 2 - MILLI); + assert_eq!("89 seconds", format!("{d}")); + let d = HumanDuration(HOUR + HOUR / 2 - MINUTE / 2 - MILLI); + assert_eq!("89 minutes", format!("{d}")); + let d = HumanDuration(DAY + DAY / 2 - HOUR / 2 - MILLI); + assert_eq!("35 hours", format!("{d}")); + let d = HumanDuration(WEEK + WEEK / 2 - DAY / 2 - MILLI); + assert_eq!("10 days", format!("{d}")); + let d = HumanDuration(YEAR + YEAR / 2 - WEEK / 2 - MILLI); + assert_eq!("78 weeks", format!("{d}")); + } + + #[test] + fn human_duration_one_and_a_half_unit() { + // this one is actually done at 1.5 unit - half of the next smaller unit + // and should still display "2 units" + let d = HumanDuration(MINUTE + MINUTE / 2 - SECOND / 2); + assert_eq!("2 minutes", format!("{d}")); + let d = HumanDuration(HOUR + HOUR / 2 - MINUTE / 2); + assert_eq!("2 hours", format!("{d}")); + let d = HumanDuration(DAY + DAY / 2 - HOUR / 2); + assert_eq!("2 days", format!("{d}")); + let d = HumanDuration(WEEK + WEEK / 2 - DAY / 2); + assert_eq!("2 weeks", format!("{d}")); + let d = HumanDuration(YEAR + YEAR / 2 - WEEK / 2); + assert_eq!("2 years", format!("{d}")); + } + + #[test] + fn human_duration_two_units() { + assert_eq!("2 seconds", format!("{}", HumanDuration(2 * SECOND))); + assert_eq!("2 minutes", format!("{}", HumanDuration(2 * MINUTE))); + assert_eq!("2 hours", format!("{}", HumanDuration(2 * HOUR))); + assert_eq!("2 days", format!("{}", HumanDuration(2 * DAY))); + assert_eq!("2 weeks", format!("{}", HumanDuration(2 * WEEK))); + assert_eq!("2 years", format!("{}", HumanDuration(2 * YEAR))); + } + + #[test] + fn human_duration_less_than_two_and_a_half_units() { + let d = HumanDuration(2 * SECOND + SECOND / 2 - MILLI); + assert_eq!("2 seconds", format!("{d}")); + let d = HumanDuration(2 * MINUTE + MINUTE / 2 - MILLI); + assert_eq!("2 minutes", format!("{d}")); + let d = HumanDuration(2 * HOUR + HOUR / 2 - MILLI); + assert_eq!("2 hours", format!("{d}")); + let d = HumanDuration(2 * DAY + DAY / 2 - MILLI); + assert_eq!("2 days", format!("{d}")); + let d = HumanDuration(2 * WEEK + WEEK / 2 - MILLI); + assert_eq!("2 weeks", format!("{d}")); + let d = HumanDuration(2 * YEAR + YEAR / 2 - MILLI); + assert_eq!("2 years", format!("{d}")); + } + + #[test] + fn human_duration_two_and_a_half_units() { + let d = HumanDuration(2 * SECOND + SECOND / 2); + assert_eq!("3 seconds", format!("{d}")); + let d = HumanDuration(2 * MINUTE + MINUTE / 2); + assert_eq!("3 minutes", format!("{d}")); + let d = HumanDuration(2 * HOUR + HOUR / 2); + assert_eq!("3 hours", format!("{d}")); + let d = HumanDuration(2 * DAY + DAY / 2); + assert_eq!("3 days", format!("{d}")); + let d = HumanDuration(2 * WEEK + WEEK / 2); + assert_eq!("3 weeks", format!("{d}")); + let d = HumanDuration(2 * YEAR + YEAR / 2); + assert_eq!("3 years", format!("{d}")); + } + + #[test] + fn human_duration_three_units() { + assert_eq!("3 seconds", format!("{}", HumanDuration(3 * SECOND))); + assert_eq!("3 minutes", format!("{}", HumanDuration(3 * MINUTE))); + assert_eq!("3 hours", format!("{}", HumanDuration(3 * HOUR))); + assert_eq!("3 days", format!("{}", HumanDuration(3 * DAY))); + assert_eq!("3 weeks", format!("{}", HumanDuration(3 * WEEK))); + assert_eq!("3 years", format!("{}", HumanDuration(3 * YEAR))); + } + + #[test] + fn human_count() { + assert_eq!("42", format!("{}", HumanCount(42))); + assert_eq!("7,654", format!("{}", HumanCount(7654))); + assert_eq!("12,345", format!("{}", HumanCount(12345))); + assert_eq!("1,234,567,890", format!("{}", HumanCount(1234567890))); + } + + #[test] + fn human_float_count() { + assert_eq!("42", format!("{}", HumanFloatCount(42.0))); + assert_eq!("7,654", format!("{}", HumanFloatCount(7654.0))); + assert_eq!("12,345", format!("{}", HumanFloatCount(12345.0))); + assert_eq!( + "1,234,567,890", + format!("{}", HumanFloatCount(1234567890.0)) + ); + assert_eq!("42.5", format!("{}", HumanFloatCount(42.5))); + assert_eq!("42.5", format!("{}", HumanFloatCount(42.500012345))); + assert_eq!("42.502", format!("{}", HumanFloatCount(42.502012345))); + assert_eq!("7,654.321", format!("{}", HumanFloatCount(7654.321))); + assert_eq!("7,654.321", format!("{}", HumanFloatCount(7654.3210123456))); + assert_eq!("12,345.6789", format!("{}", HumanFloatCount(12345.6789))); + assert_eq!( + "1,234,567,890.1235", + format!("{}", HumanFloatCount(1234567890.1234567)) + ); + assert_eq!( + "1,234,567,890.1234", + format!("{}", HumanFloatCount(1234567890.1234321)) + ); + assert_eq!("1,234", format!("{:.0}", HumanFloatCount(1234.1234321))); + assert_eq!("1,234.1", format!("{:.1}", HumanFloatCount(1234.1234321))); + assert_eq!("1,234.12", format!("{:.2}", HumanFloatCount(1234.1234321))); + assert_eq!("1,234.123", format!("{:.3}", HumanFloatCount(1234.1234321))); + assert_eq!( + "1,234.1234320999999454215867445", + format!("{:.25}", HumanFloatCount(1234.1234321)) + ); + } +} diff --git a/anneal/v2/vendor/indicatif/src/in_memory.rs b/anneal/v2/vendor/indicatif/src/in_memory.rs new file mode 100644 index 0000000000..046ae14a09 --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/in_memory.rs @@ -0,0 +1,399 @@ +use std::fmt::{Debug, Formatter, Write as _}; +use std::io::Write as _; +use std::sync::{Arc, Mutex}; + +use vt100::Parser; + +use crate::TermLike; + +/// A thin wrapper around [`vt100::Parser`]. +/// +/// This is just an [`Arc`] around its internal state, so it can be freely cloned. +#[cfg_attr(docsrs, doc(cfg(feature = "in_memory")))] +#[derive(Debug, Clone)] +pub struct InMemoryTerm { + state: Arc>, +} + +impl InMemoryTerm { + pub fn new(rows: u16, cols: u16) -> InMemoryTerm { + assert!(rows > 0, "rows must be > 0"); + assert!(cols > 0, "cols must be > 0"); + InMemoryTerm { + state: Arc::new(Mutex::new(InMemoryTermState::new(rows, cols))), + } + } + + pub fn reset(&self) { + let mut state = self.state.lock().unwrap(); + *state = InMemoryTermState::new(state.height, state.width); + } + + pub fn contents(&self) -> String { + let state = self.state.lock().unwrap(); + + // For some reason, the `Screen::contents` method doesn't include newlines in what it + // returns, making it useless for our purposes. So we need to manually reconstruct the + // contents by iterating over the rows in the terminal buffer. + let mut rows = state + .parser + .screen() + .rows(0, state.width) + .collect::>(); + + // Reverse the rows and trim empty lines from the end + rows = rows + .into_iter() + .rev() + .skip_while(|line| line.is_empty()) + .map(|line| line.trim_end().to_string()) + .collect(); + + // Un-reverse the rows and join them up with newlines + rows.reverse(); + rows.join("\n") + } + + pub fn contents_formatted(&self) -> Vec { + let state = self.state.lock().unwrap(); + + // For some reason, the `Screen::contents` method doesn't include newlines in what it + // returns, making it useless for our purposes. So we need to manually reconstruct the + // contents by iterating over the rows in the terminal buffer. + let mut rows = state + .parser + .screen() + .rows_formatted(0, state.width) + .collect::>(); + + // Reverse the rows and trim empty lines from the end + rows = rows + .into_iter() + .rev() + .skip_while(|line| line.is_empty()) + .collect(); + + // Un-reverse the rows + rows.reverse(); + + // Calculate buffer size + let reset = b""; + let len = rows.iter().map(|line| line.len() + reset.len() + 1).sum(); + + // Join rows up with reset codes and newlines + let mut contents = rows.iter().fold(Vec::with_capacity(len), |mut acc, cur| { + acc.extend_from_slice(cur); + acc.extend_from_slice(reset); + acc.push(b'\n'); + acc + }); + + // Remove last newline again, but leave the reset code + contents.truncate(len.saturating_sub(1)); + contents + } + + pub fn moves_since_last_check(&self) -> String { + let mut s = String::new(); + for line in std::mem::take(&mut self.state.lock().unwrap().history) { + writeln!(s, "{line:?}").unwrap(); + } + s + } +} + +impl TermLike for InMemoryTerm { + fn width(&self) -> u16 { + self.state.lock().unwrap().width + } + + fn height(&self) -> u16 { + self.state.lock().unwrap().height + } + + fn move_cursor_up(&self, n: usize) -> std::io::Result<()> { + match n { + 0 => Ok(()), + _ => { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Up(n)); + state.write_str(&format!("\x1b[{n}A")) + } + } + } + + fn move_cursor_down(&self, n: usize) -> std::io::Result<()> { + match n { + 0 => Ok(()), + _ => { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Down(n)); + state.write_str(&format!("\x1b[{n}B")) + } + } + } + + fn move_cursor_right(&self, n: usize) -> std::io::Result<()> { + match n { + 0 => Ok(()), + _ => { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Right(n)); + state.write_str(&format!("\x1b[{n}C")) + } + } + } + + fn move_cursor_left(&self, n: usize) -> std::io::Result<()> { + match n { + 0 => Ok(()), + _ => { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Left(n)); + state.write_str(&format!("\x1b[{n}D")) + } + } + } + + fn write_line(&self, s: &str) -> std::io::Result<()> { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Str(s.into())); + state.history.push(Move::NewLine); + + // Don't try to handle writing lines with additional newlines embedded in them - it's not + // worth the extra code for something that indicatif doesn't even do. May revisit in future. + debug_assert!( + s.lines().count() <= 1, + "calling write_line with embedded newlines is not allowed" + ); + + // vte100 needs the full \r\n sequence to jump to the next line and reset the cursor to + // the beginning of the line. Be flexible and take either \n or \r\n + state.write_str(s)?; + state.write_str("\r\n") + } + + fn write_str(&self, s: &str) -> std::io::Result<()> { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Str(s.into())); + state.write_str(s) + } + + fn clear_line(&self) -> std::io::Result<()> { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Clear); + state.write_str("\r\x1b[2K") + } + + fn flush(&self) -> std::io::Result<()> { + let mut state = self.state.lock().unwrap(); + state.history.push(Move::Flush); + state.parser.flush() + } +} + +struct InMemoryTermState { + width: u16, + height: u16, + parser: vt100::Parser, + history: Vec, +} + +impl InMemoryTermState { + pub(crate) fn new(rows: u16, cols: u16) -> InMemoryTermState { + InMemoryTermState { + width: cols, + height: rows, + parser: Parser::new(rows, cols, 0), + history: vec![], + } + } + + pub(crate) fn write_str(&mut self, s: &str) -> std::io::Result<()> { + self.parser.write_all(s.as_bytes()) + } +} + +impl Debug for InMemoryTermState { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InMemoryTermState").finish_non_exhaustive() + } +} + +#[derive(Debug, PartialEq, Clone)] +enum Move { + Up(usize), + Down(usize), + Left(usize), + Right(usize), + Str(String), + NewLine, + Clear, + Flush, +} + +#[cfg(test)] +mod test { + use super::*; + + fn cursor_pos(in_mem: &InMemoryTerm) -> (u16, u16) { + in_mem + .state + .lock() + .unwrap() + .parser + .screen() + .cursor_position() + } + + #[test] + fn line_wrapping() { + let in_mem = InMemoryTerm::new(10, 5); + assert_eq!(cursor_pos(&in_mem), (0, 0)); + + in_mem.write_str("ABCDE").unwrap(); + assert_eq!(in_mem.contents(), "ABCDE"); + assert_eq!(cursor_pos(&in_mem), (0, 5)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("ABCDE") +"# + ); + + // Should wrap onto next line + in_mem.write_str("FG").unwrap(); + assert_eq!(in_mem.contents(), "ABCDE\nFG"); + assert_eq!(cursor_pos(&in_mem), (1, 2)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("FG") +"# + ); + + in_mem.write_str("HIJ").unwrap(); + assert_eq!(in_mem.contents(), "ABCDE\nFGHIJ"); + assert_eq!(cursor_pos(&in_mem), (1, 5)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("HIJ") +"# + ); + } + + #[test] + fn write_line() { + let in_mem = InMemoryTerm::new(10, 5); + assert_eq!(cursor_pos(&in_mem), (0, 0)); + + in_mem.write_line("A").unwrap(); + assert_eq!(in_mem.contents(), "A"); + assert_eq!(cursor_pos(&in_mem), (1, 0)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("A") +NewLine +"# + ); + + in_mem.write_line("B").unwrap(); + assert_eq!(in_mem.contents(), "A\nB"); + assert_eq!(cursor_pos(&in_mem), (2, 0)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("B") +NewLine +"# + ); + + in_mem.write_line("Longer than cols").unwrap(); + assert_eq!(in_mem.contents(), "A\nB\nLonge\nr tha\nn col\ns"); + assert_eq!(cursor_pos(&in_mem), (6, 0)); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("Longer than cols") +NewLine +"# + ); + } + + #[test] + fn basic_functionality() { + let in_mem = InMemoryTerm::new(10, 80); + + in_mem.write_line("This is a test line").unwrap(); + assert_eq!(in_mem.contents(), "This is a test line"); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("This is a test line") +NewLine +"# + ); + + in_mem.write_line("And another line!").unwrap(); + assert_eq!(in_mem.contents(), "This is a test line\nAnd another line!"); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("And another line!") +NewLine +"# + ); + + in_mem.move_cursor_up(1).unwrap(); + in_mem.write_str("TEST").unwrap(); + + assert_eq!(in_mem.contents(), "This is a test line\nTESTanother line!"); + assert_eq!( + in_mem.moves_since_last_check(), + r#"Up(1) +Str("TEST") +"# + ); + } + + #[test] + fn newlines() { + let in_mem = InMemoryTerm::new(10, 10); + in_mem.write_line("LINE ONE").unwrap(); + in_mem.write_line("LINE TWO").unwrap(); + in_mem.write_line("").unwrap(); + in_mem.write_line("LINE FOUR").unwrap(); + + assert_eq!(in_mem.contents(), "LINE ONE\nLINE TWO\n\nLINE FOUR"); + + assert_eq!( + in_mem.moves_since_last_check(), + r#"Str("LINE ONE") +NewLine +Str("LINE TWO") +NewLine +Str("") +NewLine +Str("LINE FOUR") +NewLine +"# + ); + } + + #[test] + fn cursor_zero_movement() { + let in_mem = InMemoryTerm::new(10, 80); + in_mem.write_line("LINE ONE").unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 0)); + + // Check that moving zero rows/cols does not actually move cursor + in_mem.move_cursor_up(0).unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 0)); + + in_mem.move_cursor_down(0).unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 0)); + + in_mem.move_cursor_right(1).unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 1)); + + in_mem.move_cursor_left(0).unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 1)); + + in_mem.move_cursor_right(0).unwrap(); + assert_eq!(cursor_pos(&in_mem), (1, 1)); + } +} diff --git a/anneal/v2/vendor/indicatif/src/iter.rs b/anneal/v2/vendor/indicatif/src/iter.rs new file mode 100644 index 0000000000..d8468e0c4f --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/iter.rs @@ -0,0 +1,506 @@ +use std::borrow::Cow; +use std::io::{self, IoSliceMut}; +use std::iter::FusedIterator; +#[cfg(feature = "tokio")] +use std::pin::Pin; +#[cfg(feature = "tokio")] +use std::task::{Context, Poll}; +use std::time::Duration; + +#[cfg(feature = "tokio")] +use tokio::io::{ReadBuf, SeekFrom}; + +use crate::progress_bar::ProgressBar; +use crate::state::ProgressFinish; +use crate::style::ProgressStyle; + +/// Wraps an iterator to display its progress. +pub trait ProgressIterator +where + Self: Sized + Iterator, +{ + /// Wrap an iterator with default styling. Uses [`Iterator::size_hint()`] to get length. + /// Returns `Some(..)` only if `size_hint.1` is [`Some`]. If you want to create a progress bar + /// even if `size_hint.1` returns [`None`] use [`progress_count()`](ProgressIterator::progress_count) + /// or [`progress_with()`](ProgressIterator::progress_with) instead. + fn try_progress(self) -> Option> { + self.size_hint() + .1 + .map(|len| self.progress_count(u64::try_from(len).unwrap())) + } + + /// Wrap an iterator with default styling. + fn progress(self) -> ProgressBarIter + where + Self: ExactSizeIterator, + { + let len = u64::try_from(self.len()).unwrap(); + self.progress_count(len) + } + + /// Wrap an iterator with an explicit element count. + fn progress_count(self, len: u64) -> ProgressBarIter { + self.progress_with(ProgressBar::new(len)) + } + + /// Wrap an iterator with a custom progress bar. + fn progress_with(self, progress: ProgressBar) -> ProgressBarIter; + + /// Wrap an iterator with a progress bar and style it. + fn progress_with_style(self, style: crate::ProgressStyle) -> ProgressBarIter + where + Self: ExactSizeIterator, + { + let len = u64::try_from(self.len()).unwrap(); + let bar = ProgressBar::new(len).with_style(style); + self.progress_with(bar) + } +} + +/// Wraps an iterator to display its progress. +#[derive(Debug)] +pub struct ProgressBarIter { + pub(crate) it: T, + pub progress: ProgressBar, + pub(crate) seek_max: SeekMax, +} + +impl ProgressBarIter { + /// Builder-like function for setting underlying progress bar's style. + /// + /// See [`ProgressBar::with_style()`]. + pub fn with_style(mut self, style: ProgressStyle) -> Self { + self.progress = self.progress.with_style(style); + self + } + + /// Builder-like function for setting underlying progress bar's prefix. + /// + /// See [`ProgressBar::with_prefix()`]. + pub fn with_prefix(mut self, prefix: impl Into>) -> Self { + self.progress = self.progress.with_prefix(prefix); + self + } + + /// Builder-like function for setting underlying progress bar's message. + /// + /// See [`ProgressBar::with_message()`]. + pub fn with_message(mut self, message: impl Into>) -> Self { + self.progress = self.progress.with_message(message); + self + } + + /// Builder-like function for setting underlying progress bar's position. + /// + /// See [`ProgressBar::with_position()`]. + pub fn with_position(mut self, position: u64) -> Self { + self.progress = self.progress.with_position(position); + self + } + + /// Builder-like function for setting underlying progress bar's elapsed time. + /// + /// See [`ProgressBar::with_elapsed()`]. + pub fn with_elapsed(mut self, elapsed: Duration) -> Self { + self.progress = self.progress.with_elapsed(elapsed); + self + } + + /// Builder-like function for setting underlying progress bar's finish behavior. + /// + /// See [`ProgressBar::with_finish()`]. + pub fn with_finish(mut self, finish: ProgressFinish) -> Self { + self.progress = self.progress.with_finish(finish); + self + } +} + +impl> Iterator for ProgressBarIter { + type Item = S; + + fn next(&mut self) -> Option { + let item = self.it.next(); + + if item.is_some() { + self.progress.inc(1); + } else if !self.progress.is_finished() { + self.progress.finish_using_style(); + } + + item + } +} + +impl ExactSizeIterator for ProgressBarIter { + fn len(&self) -> usize { + self.it.len() + } +} + +impl DoubleEndedIterator for ProgressBarIter { + fn next_back(&mut self) -> Option { + let item = self.it.next_back(); + + if item.is_some() { + self.progress.inc(1); + } else if !self.progress.is_finished() { + self.progress.finish_using_style(); + } + + item + } +} + +impl FusedIterator for ProgressBarIter {} + +impl io::Read for ProgressBarIter { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let inc = self.it.read(buf)?; + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), inc as u64), + ); + Ok(inc) + } + + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + let inc = self.it.read_vectored(bufs)?; + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), inc as u64), + ); + Ok(inc) + } + + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + let inc = self.it.read_to_string(buf)?; + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), inc as u64), + ); + Ok(inc) + } + + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.it.read_exact(buf)?; + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), buf.len() as u64), + ); + Ok(()) + } +} + +impl io::BufRead for ProgressBarIter { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.it.fill_buf() + } + + fn consume(&mut self, amt: usize) { + self.it.consume(amt); + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), amt.try_into().unwrap()), + ); + } +} + +impl io::Seek for ProgressBarIter { + fn seek(&mut self, f: io::SeekFrom) -> io::Result { + self.it.seek(f).map(|pos| { + if f != io::SeekFrom::Current(0) { + // this kind of seek is used to find the current position, but does not alter it + // generally equivalent to stream_position() + self.progress.set_position(self.seek_max.update_seek(pos)); + } + + pos + }) + } + // Pass this through to preserve optimizations that the inner I/O object may use here + // Also avoid sending a set_position update when the position hasn't changed + fn stream_position(&mut self) -> io::Result { + self.it.stream_position() + } +} + +/// Calculates a more stable visual position from jittery seeks to show to the user. +/// +/// Holds the maximum position encountered out of the last HISTORY read/write positions. +/// Drops history when only sequential operations are performed RESET times in a row. +#[derive(Debug, Default)] +pub(crate) struct SeekMax { + buf: Option<(Box>, u8)>, +} + +impl SeekMax { + fn update_seq(&mut self, prev_pos: u64, delta: u64) -> u64 { + let new_pos = prev_pos + delta; + let Some((buf, seq)) = &mut self.buf else { + return new_pos; + }; + + *seq += 1; + if *seq >= RESET { + self.buf = None; + return new_pos; + } + + buf.update(new_pos); + buf.max() + } + + fn update_seek(&mut self, newpos: u64) -> u64 { + let (b, seq) = self + .buf + .get_or_insert_with(|| (Box::new(MaxRingBuf::::default()), 0)); + *seq = 0; + b.update(newpos); + b.max() + } +} + +/// Ring buffer that remembers the maximum contained value. +#[derive(Debug)] +struct MaxRingBuf { + history: [u64; HISTORY], + head: u8, // must be < HISTORY + max_pos: u8, // must be < HISTORY +} + +impl MaxRingBuf { + /// Updates internal bookkeeping to remember the maximum value + /// + /// Updates that overwrite the position the maximum was stored in with a smaller number do a + /// seek of the buffer, searching for the new maximum. This only happens on average each + /// 1 / HISTORY and has a cost of HISTORY, therefore amortizing to O(1). + /// + /// In case there is some linear increase with jitter, as expected in this specific use-case, + /// as long as there is one bigger update each HISTORY updates the scan is never triggered at all. + /// + /// Worst case would be linearly decreasing values, which is still O(1). + fn update(&mut self, new: u64) { + let head = usize::from(self.head) % self.history.len(); + let max_pos = usize::from(self.max_pos) % self.history.len(); + let prev_max = self.history[max_pos]; + self.history[head] = new; + + if new > prev_max { + // This is now the new maximum + self.max_pos = self.head; + } else if self.max_pos == self.head && new < prev_max { + // This was the maximum and may not be anymore + // do a linear seek to find the new maximum + let (idx, _val) = self + .history + .iter() + .enumerate() + .max_by_key(|(_, v)| *v) + .expect("array has fixded size > 0"); + // invariant_m: idx is from an enumeration of history + self.max_pos = idx as u8; + } + + self.head = (self.head + 1) % (self.history.len() as u8); + } + + fn max(&self) -> u64 { + // exploit invariant_m to eliminate bounds checks & panic code path + self.history[self.max_pos as usize % self.history.len()] + } +} + +impl Default for MaxRingBuf { + fn default() -> Self { + assert!(HISTORY <= u8::MAX.into()); + assert!(HISTORY > 0); + Self { + history: [0; HISTORY], + head: 0, + max_pos: 0, + } + } +} + +#[cfg(feature = "tokio")] +#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] +impl tokio::io::AsyncWrite for ProgressBarIter { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Pin::new(&mut self.it).poll_write(cx, buf).map(|poll| { + poll.map(|inc| { + let pos = self.progress.position(); + let new = self.seek_max.update_seq(pos, inc as u64); + self.progress.set_position(new); + inc + }) + }) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.it).poll_flush(cx) + } + + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.it).poll_shutdown(cx) + } +} + +#[cfg(feature = "tokio")] +#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] +impl tokio::io::AsyncRead for ProgressBarIter { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { + let prev_len = buf.filled().len() as u64; + let poll = Pin::new(&mut self.it).poll_read(cx, buf); + if let Poll::Ready(_e) = &poll { + let inc = buf.filled().len() as u64 - prev_len; + let pos = self.progress.position(); + let new = self.seek_max.update_seq(pos, inc); + self.progress.set_position(new); + } + poll + } +} + +#[cfg(feature = "tokio")] +#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] +impl tokio::io::AsyncSeek for ProgressBarIter { + fn start_seek(mut self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()> { + Pin::new(&mut self.it).start_seek(position) + } + + fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let poll = Pin::new(&mut self.it).poll_complete(cx); + if let Poll::Ready(Ok(pos)) = &poll { + let new = self.seek_max.update_seek(*pos); + self.progress.set_position(new); + } + + poll + } +} + +#[cfg(feature = "tokio")] +#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] +impl tokio::io::AsyncBufRead + for ProgressBarIter +{ + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.get_mut(); + Pin::new(&mut this.it).poll_fill_buf(cx) + } + + fn consume(mut self: Pin<&mut Self>, amt: usize) { + Pin::new(&mut self.it).consume(amt); + let pos = self.progress.position(); + let new = self.seek_max.update_seq(pos, amt as u64); + self.progress.set_position(new); + } +} + +#[cfg(feature = "futures")] +#[cfg_attr(docsrs, doc(cfg(feature = "futures")))] +impl futures_core::Stream for ProgressBarIter { + type Item = S::Item; + + fn poll_next( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + let this = self.get_mut(); + let item = std::pin::Pin::new(&mut this.it).poll_next(cx); + match &item { + std::task::Poll::Ready(Some(_)) => this.progress.inc(1), + std::task::Poll::Ready(None) => this.progress.finish_using_style(), + std::task::Poll::Pending => {} + } + item + } +} + +impl io::Write for ProgressBarIter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.it.write(buf).map(|inc| { + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), inc as u64), + ); + inc + }) + } + + fn write_vectored(&mut self, bufs: &[io::IoSlice]) -> io::Result { + self.it.write_vectored(bufs).map(|inc| { + self.progress.set_position( + self.seek_max + .update_seq(self.progress.position(), inc as u64), + ); + inc + }) + } + + fn flush(&mut self) -> io::Result<()> { + self.it.flush() + } + + // write_fmt can not be captured with reasonable effort. + // as it uses write_all internally by default that should not be a problem. + // fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()>; +} + +impl> ProgressIterator for T { + fn progress_with(self, progress: ProgressBar) -> ProgressBarIter { + ProgressBarIter { + it: self, + progress, + seek_max: SeekMax::default(), + } + } +} + +#[cfg(test)] +mod test { + use crate::iter::{ProgressBarIter, ProgressIterator}; + use crate::progress_bar::ProgressBar; + use crate::ProgressStyle; + + #[test] + fn it_can_wrap_an_iterator() { + let v = [1, 2, 3]; + let wrap = |it: ProgressBarIter<_>| { + assert_eq!(it.map(|x| x * 2).collect::>(), vec![2, 4, 6]); + }; + + wrap(v.iter().progress()); + wrap(v.iter().progress_count(3)); + wrap({ + let pb = ProgressBar::new(v.len() as u64); + v.iter().progress_with(pb) + }); + wrap({ + let style = ProgressStyle::default_bar() + .template("{wide_bar:.red} {percent}/100%") + .unwrap(); + v.iter().progress_with_style(style) + }); + } + + #[test] + fn test_max_ring_buf() { + use crate::iter::MaxRingBuf; + let mut max = MaxRingBuf::<10>::default(); + max.update(100); + assert_eq!(max.max(), 100); + for i in 0..10 { + max.update(99 - i); + } + assert_eq!(max.max(), 99); + } +} diff --git a/anneal/v2/vendor/indicatif/src/lib.rs b/anneal/v2/vendor/indicatif/src/lib.rs new file mode 100644 index 0000000000..0378f09177 --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/lib.rs @@ -0,0 +1,295 @@ +//! indicatif is a library for Rust that helps you build command line +//! interfaces that report progress to users. It comes with various +//! tools and utilities for formatting anything that indicates progress. +//! +//! Platform support: +//! +//! * Linux +//! * macOS +//! * Windows (colors require Windows 10) +//! +//! Best paired with other libraries in the family: +//! +//! * [console](https://docs.rs/console) +//! * [dialoguer](https://docs.rs/dialoguer) +//! +//! # Crate Contents +//! +//! * **Progress bars** +//! * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners +//! * [`MultiProgress`](struct.MultiProgress.html) for multiple bars +//! * **Data Formatting** +//! * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes +//! * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes +//! * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes +//! * [`HumanDuration`](struct.HumanDuration.html) for formatting durations +//! * [`HumanCount`](struct.HumanCount.html) for formatting large counts +//! * [`HumanFloatCount`](struct.HumanFloatCount.html) for formatting large float counts +//! +//! # Progress Bars and Spinners +//! +//! indicatif comes with a [`ProgressBar`] type that supports both bounded +//! progress bar uses as well as unbounded "spinner" type progress reports. +//! Progress bars are [`Sync`] and [`Send`] objects which means that they are +//! internally locked and can be passed from thread to thread. +//! +//! Additionally a [`MultiProgress`] utility is provided that can manage +//! rendering multiple progress bars at once (eg: from multiple threads). +//! +//! To whet your appetite, this is what this can look like: +//! +//! +//! +//! Progress bars are manually advanced and by default draw to stderr. +//! When you are done, the progress bar can be finished either visibly +//! (eg: the progress bar stays on the screen) or cleared (the progress +//! bar will be removed). +//! +//! ```rust +//! use indicatif::ProgressBar; +//! +//! let bar = ProgressBar::new(1000); +//! for _ in 0..1000 { +//! bar.inc(1); +//! // ... +//! } +//! bar.finish(); +//! ``` +//! +//! Spinners can be manually advanced with [`tick`](ProgressBar::tick), or you can set them up +//! to spin automatically with [`enable_steady_tick`](ProgressBar::enable_steady_tick): +//! +//! ```rust +//! use std::time::Duration; +//! use indicatif::ProgressBar; +//! +//! let bar = ProgressBar::new_spinner(); +//! bar.enable_steady_tick(Duration::from_millis(100)); +//! // ... do some work +//! bar.finish(); +//! ``` +//! +//! General progress bar behaviors: +//! +//! * if a non terminal is detected the progress bar will be completely +//! hidden. This makes piping programs to logfiles make sense out of +//! the box. +//! * a progress bar only starts drawing when [`set_message`](ProgressBar::set_message), +//! [`inc`](ProgressBar::inc), [`set_position`](ProgressBar::set_position) +//! or [`tick`](ProgressBar::tick) are called. In some situations you +//! might have to call [`tick`](ProgressBar::tick) once to draw it. +//! * progress bars should be explicitly finished to reset the rendering +//! for others. Either by also clearing them or by replacing them with +//! a new message / retaining the current message. +//! * the default template renders neither message nor prefix. +//! +//! # Iterators +//! +//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be +//! associated with an iterator. For example: +//! +//! ```rust +//! use indicatif::ProgressIterator; +//! +//! for _ in (0..1000).progress() { +//! // ... +//! } +//! ``` +//! +//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more +//! methods to configure the number of elements in the iterator or change +//! the progress bar style. Indicatif also has optional support for parallel +//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your +//! `Cargo.toml`, use the "rayon" feature: +//! +//! ```toml +//! [dependencies] +//! indicatif = {version = "*", features = ["rayon"]} +//! ``` +//! +//! And then use it like this: +//! +//! ```rust,ignore +//! # extern crate rayon; +//! use indicatif::ParallelProgressIterator; +//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator}; +//! +//! let v: Vec<_> = (0..100000).collect(); +//! let v2: Vec<_> = v.par_iter().progress_count(v.len() as u64).map(|i| i + 1).collect(); +//! assert_eq!(v2[0], 1); +//! ``` +//! +//! Or if you'd like to customize the progress bar: +//! +//! ```rust,ignore +//! # extern crate rayon; +//! use indicatif::{ProgressBar, ParallelProgressIterator, ProgressStyle}; +//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator}; +//! +//! // Alternatively, use `ProgressBar::new().with_style()` +//! let style = ProgressStyle::default_bar(); +//! let v: Vec<_> = (0..100000).collect(); +//! let v2: Vec<_> = v.par_iter().progress_with_style(style).map(|i| i + 1).collect(); +//! assert_eq!(v2[0], 1); +//! ``` +//! +//! # Templates +//! +//! Progress bars can be styled with simple format strings similar to the +//! ones in Rust itself. The format for a placeholder is `{key:options}` +//! where the `options` part is optional. If provided the format is this: +//! +//! ```text +//! <^> for an optional alignment specification (left, center and right respectively) +//! WIDTH an optional width as positive integer +//! ! an optional exclamation mark to enable truncation +//! .STYLE an optional dot separated style string +//! /STYLE an optional dot separated alternative style string +//! ``` +//! +//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str) +//! for more information. Indicatif uses the `console` base crate for all +//! colorization and formatting options. +//! +//! Some examples for templates: +//! +//! ```text +//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg} +//! ``` +//! +//! This sets a progress bar that is 40 characters wide and has cyan +//! as primary style color and blue as alternative style color. +//! Alternative styles are currently only used for progress bars. +//! +//! Example configuration: +//! +//! ```rust +//! # use indicatif::{ProgressBar, ProgressStyle}; +//! # let bar = ProgressBar::new(0); +//! bar.set_style(ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}") +//! .unwrap() +//! .progress_chars("##-")); +//! ``` +//! +//! The following keys exist: +//! +//! * `bar`: renders a progress bar. By default 20 characters wide. The +//! style string is used to color the elapsed part, the alternative +//! style is used for the bar that is yet to render. +//! * `wide_bar`: like `bar` but always fills the remaining space. It should not be used with `wide_msg`. +//! * `spinner`: renders the spinner (current tick string). Note that spinners do not automatically tick by default. You either +//! need to call `enable_steady_tick` or manually call `tick`. +//! * `prefix`: renders the prefix set on the progress bar. +//! * `msg`: renders the currently set message on the progress bar. +//! * `wide_msg`: like `msg` but always fills the remaining space and truncates. It should not be used +//! with `wide_bar`. +//! * `pos`: renders the current position of the bar as integer +//! * `human_pos`: renders the current position of the bar as an integer, with commas as the +//! thousands separator. +//! * `len`: renders the amount of work to be done as an integer +//! * `human_len`: renders the total length of the bar as an integer, with commas as the thousands +//! separator. +//! * `percent`: renders the current position of the bar as a percentage of the total length (as an integer). +//! * `percent_precise`: renders the current position of the bar as a percentage of the total length (with 3 fraction digits). +//! * `bytes`: renders the current position of the bar as bytes (alias of `binary_bytes`). +//! * `total_bytes`: renders the total length of the bar as bytes (alias of `binary_total_bytes`). +//! * `decimal_bytes`: renders the current position of the bar as bytes using +//! power-of-10 units, i.e. `MB`, `kB`, etc. +//! * `decimal_total_bytes`: renders the total length of the bar as bytes using +//! power-of-10 units, i.e. `MB`, `kB`, etc. +//! * `binary_bytes`: renders the current position of the bar as bytes using +//! power-of-two units, i.e. `MiB`, `KiB`, etc. +//! * `binary_total_bytes`: renders the total length of the bar as bytes using +//! power-of-two units, i.e. `MiB`, `KiB`, etc. +//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`. +//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc. +//! * `per_sec`: renders the speed in steps per second. +//! * `bytes_per_sec`: renders the speed in bytes per second (alias of `binary_bytes_per_sec`). +//! * `decimal_bytes_per_sec`: renders the speed in bytes per second using +//! power-of-10 units, i.e. `MB`, `kB`, etc. +//! * `binary_bytes_per_sec`: renders the speed in bytes per second using +//! power-of-two units, i.e. `MiB`, `KiB`, etc. +//! * `eta_precise`: the remaining time (like `elapsed_precise`). +//! * `eta`: the remaining time (like `elapsed`). +//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`). +//! * `duration`: the extrapolated total duration time (like `elapsed`). +//! +//! If the list above does not contain the value you need, consider creating a custom +//! [`ProgressTracker`][crate::style::ProgressTracker] implementation. +//! +//! The design of the progress bar can be altered with the integrated +//! template functionality. The template can be set by changing a +//! [`ProgressStyle`] and attaching it to the progress bar. +//! +//! # Human Readable Formatting +//! +//! There are some formatting wrappers for showing elapsed time and +//! file sizes for human users: +//! +//! ```rust +//! # use std::time::Duration; +//! use indicatif::{HumanBytes, HumanCount, HumanDuration, HumanFloatCount}; +//! +//! assert_eq!("3.00 MiB", HumanBytes(3*1024*1024).to_string()); +//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string()); +//! assert_eq!("33,857,009", HumanCount(33857009).to_string()); +//! assert_eq!("33,857,009.1235", HumanFloatCount(33857009.123456).to_string()); +//! ``` +//! +//! # Feature Flags +//! +//! * `rayon`: adds rayon support +//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation) + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn(unreachable_pub)] + +#[cfg(all(target_arch = "wasm32", not(feature = "wasmbind")))] +compile_error!("The 'wasmbind' feature must be enabled when compiling for wasm32."); + +mod draw_target; +mod format; +#[cfg(feature = "in_memory")] +mod in_memory; +mod iter; +mod multi; +mod progress_bar; +#[cfg(feature = "rayon")] +mod rayon; +mod state; +pub mod style; +mod term_like; + +pub use crate::draw_target::ProgressDrawTarget; +pub use crate::format::{ + BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration, + HumanFloatCount, +}; +#[cfg(feature = "in_memory")] +pub use crate::in_memory::InMemoryTerm; +pub use crate::iter::{ProgressBarIter, ProgressIterator}; +pub use crate::multi::{MultiProgress, MultiProgressAlignment}; +pub use crate::progress_bar::{ProgressBar, WeakProgressBar}; +#[cfg(feature = "rayon")] +pub use crate::rayon::ParallelProgressIterator; +pub use crate::state::{ProgressFinish, ProgressState}; +pub use crate::style::ProgressStyle; +pub use crate::term_like::TermLike; + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(dead_code)] + trait MustBeThreadSafe: Send + Sync {} + + // Ensure that the following types are `Send + Sync` + impl MustBeThreadSafe for MultiProgress {} + impl MustBeThreadSafe for MultiProgressAlignment {} + impl MustBeThreadSafe for ProgressBar {} + impl MustBeThreadSafe for ProgressBarIter<()> {} + impl MustBeThreadSafe for ProgressFinish {} + impl MustBeThreadSafe for ProgressState {} + impl MustBeThreadSafe for ProgressStyle {} + impl MustBeThreadSafe for WeakProgressBar {} +} diff --git a/anneal/v2/vendor/indicatif/src/multi.rs b/anneal/v2/vendor/indicatif/src/multi.rs new file mode 100644 index 0000000000..195c9f9d98 --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/multi.rs @@ -0,0 +1,690 @@ +use std::fmt::{Debug, Formatter}; +use std::io; +use std::sync::{Arc, RwLock}; +use std::thread::panicking; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; + +use crate::draw_target::{ + visual_line_count, DrawState, DrawStateWrapper, LineAdjust, LineType, ProgressDrawTarget, + VisualLines, +}; +use crate::progress_bar::ProgressBar; +#[cfg(all(target_arch = "wasm32", feature = "wasmbind"))] +use web_time::Instant; + +/// Manages multiple progress bars from different threads +#[derive(Debug, Clone)] +pub struct MultiProgress { + pub(crate) state: Arc>, +} + +impl Default for MultiProgress { + fn default() -> Self { + Self::with_draw_target(ProgressDrawTarget::stderr()) + } +} + +impl MultiProgress { + /// Creates a new multi progress object. + /// + /// Progress bars added to this object by default draw directly to stderr, and refresh + /// a maximum of 15 times a second. To change the refresh rate [set] the [draw target] to + /// one with a different refresh rate. + /// + /// [set]: MultiProgress::set_draw_target + /// [draw target]: ProgressDrawTarget + pub fn new() -> Self { + Self::default() + } + + /// Creates a new multi progress object with the given draw target. + pub fn with_draw_target(draw_target: ProgressDrawTarget) -> Self { + Self { + state: Arc::new(RwLock::new(MultiState::new(draw_target))), + } + } + + /// Sets a different draw target for the multiprogress bar. + /// + /// Use [`MultiProgress::with_draw_target`] to set the draw target during creation. + pub fn set_draw_target(&self, target: ProgressDrawTarget) { + let mut state = self.state.write().unwrap(); + state.draw_target.disconnect(Instant::now()); + state.draw_target = target; + } + + /// Set whether we should try to move the cursor when possible instead of clearing lines. + /// + /// This can reduce flickering, but do not enable it if you intend to change the number of + /// progress bars. + pub fn set_move_cursor(&self, move_cursor: bool) { + self.state + .write() + .unwrap() + .draw_target + .set_move_cursor(move_cursor); + } + + /// Set alignment flag + pub fn set_alignment(&self, alignment: MultiProgressAlignment) { + self.state.write().unwrap().alignment = alignment; + } + + /// Adds a progress bar. + /// + /// The progress bar added will have the draw target changed to a + /// remote draw target that is intercepted by the multi progress + /// object overriding custom [`ProgressDrawTarget`] settings. + /// + /// The progress bar will be positioned below all other bars currently + /// in the [`MultiProgress`]. + /// + /// Adding a progress bar that is already a member of the [`MultiProgress`] + /// will have no effect. + pub fn add(&self, pb: ProgressBar) -> ProgressBar { + self.internalize(InsertLocation::End, pb) + } + + /// Inserts a progress bar. + /// + /// The progress bar inserted at position `index` will have the draw + /// target changed to a remote draw target that is intercepted by the + /// multi progress object overriding custom [`ProgressDrawTarget`] settings. + /// + /// If `index >= MultiProgressState::objects.len()`, the progress bar + /// is added to the end of the list. + /// + /// Inserting a progress bar that is already a member of the [`MultiProgress`] + /// will have no effect. + pub fn insert(&self, index: usize, pb: ProgressBar) -> ProgressBar { + self.internalize(InsertLocation::Index(index), pb) + } + + /// Inserts a progress bar from the back. + /// + /// The progress bar inserted at position `MultiProgressState::objects.len() - index` + /// will have the draw target changed to a remote draw target that is + /// intercepted by the multi progress object overriding custom + /// [`ProgressDrawTarget`] settings. + /// + /// If `index >= MultiProgressState::objects.len()`, the progress bar + /// is added to the start of the list. + /// + /// Inserting a progress bar that is already a member of the [`MultiProgress`] + /// will have no effect. + pub fn insert_from_back(&self, index: usize, pb: ProgressBar) -> ProgressBar { + self.internalize(InsertLocation::IndexFromBack(index), pb) + } + + /// Inserts a progress bar before an existing one. + /// + /// The progress bar added will have the draw target changed to a + /// remote draw target that is intercepted by the multi progress + /// object overriding custom [`ProgressDrawTarget`] settings. + /// + /// Inserting a progress bar that is already a member of the [`MultiProgress`] + /// will have no effect. + pub fn insert_before(&self, before: &ProgressBar, pb: ProgressBar) -> ProgressBar { + self.internalize(InsertLocation::Before(before.index().unwrap()), pb) + } + + /// Inserts a progress bar after an existing one. + /// + /// The progress bar added will have the draw target changed to a + /// remote draw target that is intercepted by the multi progress + /// object overriding custom [`ProgressDrawTarget`] settings. + /// + /// Inserting a progress bar that is already a member of the [`MultiProgress`] + /// will have no effect. + pub fn insert_after(&self, after: &ProgressBar, pb: ProgressBar) -> ProgressBar { + self.internalize(InsertLocation::After(after.index().unwrap()), pb) + } + + /// Removes a progress bar. + /// + /// The progress bar is removed only if it was previously inserted or added + /// by the methods [`MultiProgress::insert`] or [`MultiProgress::add`]. + /// If the passed progress bar does not satisfy the condition above, + /// the `remove` method does nothing. + pub fn remove(&self, pb: &ProgressBar) { + let mut state = pb.state(); + let idx = match &state.draw_target.remote() { + Some((state, idx)) => { + // Check that this progress bar is owned by the current MultiProgress. + assert!(Arc::ptr_eq(&self.state, state)); + *idx + } + _ => return, + }; + + state.draw_target = ProgressDrawTarget::hidden(); + self.state.write().unwrap().remove_idx(idx); + } + + fn internalize(&self, location: InsertLocation, pb: ProgressBar) -> ProgressBar { + let mut state = self.state.write().unwrap(); + let idx = state.insert(location); + drop(state); + + pb.set_draw_target(ProgressDrawTarget::new_remote(self.state.clone(), idx)); + pb + } + + /// Print a log line above all progress bars in the [`MultiProgress`] + /// + /// If the draw target is hidden (e.g. when standard output is not a terminal), `println()` + /// will not do anything. + pub fn println>(&self, msg: I) -> io::Result<()> { + let mut state = self.state.write().unwrap(); + state.println(msg, Instant::now()) + } + + /// Hide all progress bars temporarily, execute `f`, then redraw the [`MultiProgress`] + /// + /// Executes 'f' even if the draw target is hidden. + /// + /// Useful for external code that writes to the standard output. + /// + /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print + /// anything on the progress bar will be blocked until `f` finishes. + /// Therefore, it is recommended to avoid long-running operations in `f`. + pub fn suspend R, R>(&self, f: F) -> R { + let mut state = self.state.write().unwrap(); + state.suspend(f, Instant::now()) + } + + pub fn clear(&self) -> io::Result<()> { + self.state.write().unwrap().clear(Instant::now()) + } + + pub fn is_hidden(&self) -> bool { + self.state.read().unwrap().is_hidden() + } +} + +#[derive(Debug)] +pub(crate) struct MultiState { + /// The collection of states corresponding to progress bars + members: Vec, + /// Set of removed bars, should have corresponding members in the `members` vector with a + /// `draw_state` of `None`. + free_set: Vec, + /// Indices to the `draw_states` to maintain correct visual order + ordering: Vec, + /// Target for draw operation for MultiProgress + draw_target: ProgressDrawTarget, + /// Controls how the multi progress is aligned if some of its progress bars get removed, default is `Top` + alignment: MultiProgressAlignment, + /// Lines to be drawn above everything else in the MultiProgress. These specifically come from + /// calling `ProgressBar::println` on a pb that is connected to a `MultiProgress`. + orphan_lines: Vec, + /// The count of currently visible zombie lines. + zombie_lines_count: VisualLines, +} + +impl MultiState { + fn new(draw_target: ProgressDrawTarget) -> Self { + Self { + members: vec![], + free_set: vec![], + ordering: vec![], + draw_target, + alignment: MultiProgressAlignment::default(), + orphan_lines: Vec::new(), + zombie_lines_count: VisualLines::default(), + } + } + + pub(crate) fn mark_zombie(&mut self, index: usize) { + let width = self.width().map(usize::from); + + let member = &mut self.members[index]; + + // If the zombie is the first visual bar then we can reap it right now instead of + // deferring it to the next draw. + if index != self.ordering.first().copied().unwrap() { + member.is_zombie = true; + return; + } + + let line_count = member + .draw_state + .as_ref() + .zip(width) + .map(|(d, width)| d.visual_line_count(.., width)) + .unwrap_or_default(); + + // Track the total number of zombie lines on the screen + self.zombie_lines_count = self.zombie_lines_count.saturating_add(line_count); + + // Make `DrawTarget` forget about the zombie lines so that they aren't cleared on next draw. + self.draw_target + .adjust_last_line_count(LineAdjust::Keep(line_count)); + + self.remove_idx(index); + } + + pub(crate) fn draw( + &mut self, + mut force_draw: bool, + extra_lines: Option>, + now: Instant, + ) -> io::Result<()> { + if panicking() { + return Ok(()); + } + + let width = match self.width() { + Some(width) => width as usize, + None => return Ok(()), + }; + + // Assumption: if extra_lines is not None, then it has at least one line + debug_assert_eq!( + extra_lines.is_some(), + extra_lines.as_ref().map(Vec::len).unwrap_or_default() > 0 + ); + + let mut reap_indices = vec![]; + + // Reap all consecutive 'zombie' progress bars from head of the list. + let mut adjust = VisualLines::default(); + for &index in &self.ordering { + let member = &self.members[index]; + if !member.is_zombie { + break; + } + + let line_count = member + .draw_state + .as_ref() + .map(|d| d.visual_line_count(.., width)) + .unwrap_or_default(); + // Track the total number of zombie lines on the screen. + self.zombie_lines_count += line_count; + + // Track the number of zombie lines that will be drawn by this call to draw. + adjust += line_count; + + reap_indices.push(index); + } + + // If this draw is due to a `println`, then we need to erase all the zombie lines. + // This is because `println` is supposed to appear above all other elements in the + // `MultiProgress`. + if extra_lines.is_some() { + self.draw_target + .adjust_last_line_count(LineAdjust::Clear(self.zombie_lines_count)); + self.zombie_lines_count = VisualLines::default(); + } + + let orphan_visual_line_count = visual_line_count(&self.orphan_lines, width); + force_draw |= orphan_visual_line_count > VisualLines::default(); + let mut drawable = match self.draw_target.drawable(force_draw, now) { + Some(drawable) => drawable, + None => return Ok(()), + }; + + let mut draw_state = drawable.state(); + draw_state.alignment = self.alignment; + + if let Some(extra_lines) = &extra_lines { + draw_state.lines.extend_from_slice(extra_lines.as_slice()); + } + + // Add lines from `ProgressBar::println` call. + draw_state.lines.append(&mut self.orphan_lines); + + for index in &self.ordering { + let member = &self.members[*index]; + if let Some(state) = &member.draw_state { + draw_state.lines.extend_from_slice(&state.lines[..]); + } + } + + drop(draw_state); + let drawable = drawable.draw(); + + for index in reap_indices { + self.remove_idx(index); + } + + // The zombie lines were drawn for the last time, so make `DrawTarget` forget about them + // so they aren't cleared on next draw. + if extra_lines.is_none() { + self.draw_target + .adjust_last_line_count(LineAdjust::Keep(adjust)); + } + + drawable + } + + pub(crate) fn println>(&mut self, msg: I, now: Instant) -> io::Result<()> { + let msg = msg.as_ref(); + + // If msg is "", make sure a line is still printed + let lines: Vec = match msg.is_empty() { + false => msg.lines().map(|l| LineType::Text(Into::into(l))).collect(), + true => vec![LineType::Empty], + }; + + self.draw(true, Some(lines), now) + } + + pub(crate) fn draw_state(&mut self, idx: usize) -> DrawStateWrapper<'_> { + let member = self.members.get_mut(idx).unwrap(); + // alignment is handled by the `MultiProgress`'s underlying draw target, so there is no + // point in propagating it here. + let state = member.draw_state.get_or_insert(DrawState::default()); + + DrawStateWrapper::for_multi(state, &mut self.orphan_lines) + } + + pub(crate) fn is_hidden(&self) -> bool { + self.draw_target.is_hidden() + } + + pub(crate) fn suspend R, R>(&mut self, f: F, now: Instant) -> R { + self.clear(now).unwrap(); + let ret = f(); + self.draw(true, None, Instant::now()).unwrap(); + ret + } + + pub(crate) fn width(&self) -> Option { + self.draw_target.width() + } + + fn insert(&mut self, location: InsertLocation) -> usize { + let idx = if let Some(idx) = self.free_set.pop() { + self.members[idx] = MultiStateMember::default(); + idx + } else { + self.members.push(MultiStateMember::default()); + self.members.len() - 1 + }; + + match location { + InsertLocation::End => self.ordering.push(idx), + InsertLocation::Index(pos) => { + let pos = Ord::min(pos, self.ordering.len()); + self.ordering.insert(pos, idx); + } + InsertLocation::IndexFromBack(pos) => { + let pos = self.ordering.len().saturating_sub(pos); + self.ordering.insert(pos, idx); + } + InsertLocation::After(after_idx) => { + let pos = self.ordering.iter().position(|i| *i == after_idx).unwrap(); + self.ordering.insert(pos + 1, idx); + } + InsertLocation::Before(before_idx) => { + let pos = self.ordering.iter().position(|i| *i == before_idx).unwrap(); + self.ordering.insert(pos, idx); + } + } + + assert_eq!( + self.len(), + self.ordering.len(), + "Draw state is inconsistent" + ); + + idx + } + + fn clear(&mut self, now: Instant) -> io::Result<()> { + match self.draw_target.drawable(true, now) { + Some(mut drawable) => { + // Make the clear operation also wipe out zombie lines + drawable.adjust_last_line_count(LineAdjust::Clear(self.zombie_lines_count)); + self.zombie_lines_count = VisualLines::default(); + drawable.clear() + } + None => Ok(()), + } + } + + fn remove_idx(&mut self, idx: usize) { + if self.free_set.contains(&idx) { + return; + } + + self.members[idx] = MultiStateMember::default(); + self.free_set.push(idx); + self.ordering.retain(|&x| x != idx); + + assert_eq!( + self.len(), + self.ordering.len(), + "Draw state is inconsistent" + ); + } + + fn len(&self) -> usize { + self.members.len() - self.free_set.len() + } +} + +#[derive(Default)] +struct MultiStateMember { + /// Draw state will be `None` for members that haven't been drawn before, or for entries that + /// correspond to something in the free set. + draw_state: Option, + /// Whether the corresponding progress bar (more precisely, `BarState`) has been dropped. + is_zombie: bool, +} + +impl Debug for MultiStateMember { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("MultiStateElement") + .field("draw_state", &self.draw_state) + .field("is_zombie", &self.is_zombie) + .finish_non_exhaustive() + } +} + +/// Vertical alignment of a multi progress. +/// +/// The alignment controls how the multi progress is aligned if some of its progress bars get removed. +/// E.g. [`Top`](MultiProgressAlignment::Top) alignment (default), when _progress bar 2_ is removed: +/// ```ignore +/// [0/100] progress bar 1 [0/100] progress bar 1 +/// [0/100] progress bar 2 => [0/100] progress bar 3 +/// [0/100] progress bar 3 +/// ``` +/// +/// [`Bottom`](MultiProgressAlignment::Bottom) alignment +/// ```ignore +/// [0/100] progress bar 1 +/// [0/100] progress bar 2 => [0/100] progress bar 1 +/// [0/100] progress bar 3 [0/100] progress bar 3 +/// ``` +#[derive(Debug, Copy, Clone, Default)] +pub enum MultiProgressAlignment { + #[default] + Top, + Bottom, +} + +enum InsertLocation { + End, + Index(usize), + IndexFromBack(usize), + After(usize), + Before(usize), +} + +#[cfg(test)] +mod tests { + use crate::{MultiProgress, ProgressBar, ProgressDrawTarget}; + + #[test] + fn late_pb_drop() { + let pb = ProgressBar::new(10); + let mpb = MultiProgress::new(); + // This clone call is required to trigger a now fixed bug. + // See for context + #[allow(clippy::redundant_clone)] + mpb.add(pb.clone()); + } + + #[test] + fn progress_bar_sync_send() { + let _: Box = Box::new(ProgressBar::new(1)); + let _: Box = Box::new(ProgressBar::new(1)); + let _: Box = Box::new(MultiProgress::new()); + let _: Box = Box::new(MultiProgress::new()); + } + + #[test] + fn multi_progress_hidden() { + let mpb = MultiProgress::with_draw_target(ProgressDrawTarget::hidden()); + let pb = mpb.add(ProgressBar::new(123)); + pb.finish(); + } + + #[test] + fn multi_progress_modifications() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + let p2 = mp.add(ProgressBar::new(1)); + let p3 = mp.add(ProgressBar::new(1)); + mp.remove(&p2); + mp.remove(&p1); + let p4 = mp.insert(1, ProgressBar::new(1)); + + let state = mp.state.read().unwrap(); + // the removed place for p1 is reused + assert_eq!(state.members.len(), 4); + assert_eq!(state.len(), 3); + + // free_set may contain 1 or 2 + match state.free_set.last() { + Some(1) => { + assert_eq!(state.ordering, vec![0, 2, 3]); + assert!(state.members[1].draw_state.is_none()); + assert_eq!(p4.index().unwrap(), 2); + } + Some(2) => { + assert_eq!(state.ordering, vec![0, 1, 3]); + assert!(state.members[2].draw_state.is_none()); + assert_eq!(p4.index().unwrap(), 1); + } + _ => unreachable!(), + } + + assert_eq!(p0.index().unwrap(), 0); + assert_eq!(p1.index(), None); + assert_eq!(p2.index(), None); + assert_eq!(p3.index().unwrap(), 3); + } + + #[test] + fn multi_progress_insert_from_back() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + let p2 = mp.add(ProgressBar::new(1)); + let p3 = mp.insert_from_back(1, ProgressBar::new(1)); + let p4 = mp.insert_from_back(10, ProgressBar::new(1)); + + let state = mp.state.read().unwrap(); + assert_eq!(state.ordering, vec![4, 0, 1, 3, 2]); + assert_eq!(p0.index().unwrap(), 0); + assert_eq!(p1.index().unwrap(), 1); + assert_eq!(p2.index().unwrap(), 2); + assert_eq!(p3.index().unwrap(), 3); + assert_eq!(p4.index().unwrap(), 4); + } + + #[test] + fn multi_progress_insert_after() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + let p2 = mp.add(ProgressBar::new(1)); + let p3 = mp.insert_after(&p2, ProgressBar::new(1)); + let p4 = mp.insert_after(&p0, ProgressBar::new(1)); + + let state = mp.state.read().unwrap(); + assert_eq!(state.ordering, vec![0, 4, 1, 2, 3]); + assert_eq!(p0.index().unwrap(), 0); + assert_eq!(p1.index().unwrap(), 1); + assert_eq!(p2.index().unwrap(), 2); + assert_eq!(p3.index().unwrap(), 3); + assert_eq!(p4.index().unwrap(), 4); + } + + #[test] + fn multi_progress_insert_before() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + let p2 = mp.add(ProgressBar::new(1)); + let p3 = mp.insert_before(&p0, ProgressBar::new(1)); + let p4 = mp.insert_before(&p2, ProgressBar::new(1)); + + let state = mp.state.read().unwrap(); + assert_eq!(state.ordering, vec![3, 0, 1, 4, 2]); + assert_eq!(p0.index().unwrap(), 0); + assert_eq!(p1.index().unwrap(), 1); + assert_eq!(p2.index().unwrap(), 2); + assert_eq!(p3.index().unwrap(), 3); + assert_eq!(p4.index().unwrap(), 4); + } + + #[test] + fn multi_progress_insert_before_and_after() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + let p2 = mp.add(ProgressBar::new(1)); + let p3 = mp.insert_before(&p0, ProgressBar::new(1)); + let p4 = mp.insert_after(&p3, ProgressBar::new(1)); + let p5 = mp.insert_after(&p3, ProgressBar::new(1)); + let p6 = mp.insert_before(&p1, ProgressBar::new(1)); + + let state = mp.state.read().unwrap(); + assert_eq!(state.ordering, vec![3, 5, 4, 0, 6, 1, 2]); + assert_eq!(p0.index().unwrap(), 0); + assert_eq!(p1.index().unwrap(), 1); + assert_eq!(p2.index().unwrap(), 2); + assert_eq!(p3.index().unwrap(), 3); + assert_eq!(p4.index().unwrap(), 4); + assert_eq!(p5.index().unwrap(), 5); + assert_eq!(p6.index().unwrap(), 6); + } + + #[test] + fn multi_progress_multiple_remove() { + let mp = MultiProgress::new(); + let p0 = mp.add(ProgressBar::new(1)); + let p1 = mp.add(ProgressBar::new(1)); + // double remove beyond the first one have no effect + mp.remove(&p0); + mp.remove(&p0); + mp.remove(&p0); + + let state = mp.state.read().unwrap(); + // the removed place for p1 is reused + assert_eq!(state.members.len(), 2); + assert_eq!(state.free_set.len(), 1); + assert_eq!(state.len(), 1); + assert!(state.members[0].draw_state.is_none()); + assert_eq!(state.free_set.last(), Some(&0)); + + assert_eq!(state.ordering, vec![1]); + assert_eq!(p0.index(), None); + assert_eq!(p1.index().unwrap(), 1); + } + + #[test] + fn mp_no_crash_double_add() { + let mp = MultiProgress::new(); + let pb = mp.add(ProgressBar::new(10)); + mp.add(pb); + } +} diff --git a/anneal/v2/vendor/indicatif/src/progress_bar.rs b/anneal/v2/vendor/indicatif/src/progress_bar.rs new file mode 100644 index 0000000000..61a5990ebf --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/progress_bar.rs @@ -0,0 +1,876 @@ +#[cfg(test)] +use portable_atomic::{AtomicBool, Ordering}; +use std::borrow::Cow; +use std::sync::{Arc, Condvar, Mutex, MutexGuard, Weak}; +use std::time::Duration; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; +use std::{fmt, io, thread}; + +#[cfg(test)] +use once_cell::sync::Lazy; +#[cfg(all(target_arch = "wasm32", feature = "wasmbind"))] +use web_time::Instant; + +use crate::draw_target::ProgressDrawTarget; +use crate::state::{AtomicPosition, BarState, ProgressFinish, Reset, TabExpandedString}; +use crate::style::ProgressStyle; +use crate::{iter, ProgressBarIter, ProgressIterator, ProgressState}; + +/// A progress bar or spinner +/// +/// The progress bar is an [`Arc`] around its internal state. When the progress bar is cloned it +/// just increments the refcount (so the original and its clone share the same state). +#[derive(Clone)] +pub struct ProgressBar { + state: Arc>, + pos: Arc, + ticker: Arc>>, +} + +impl fmt::Debug for ProgressBar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ProgressBar").finish() + } +} + +impl ProgressBar { + /// Creates a new progress bar with a given length + /// + /// This progress bar by default draws directly to stderr, and refreshes a maximum of 20 times + /// a second. To change the refresh rate, [set] the [draw target] to one with a different refresh + /// rate. + /// + /// [set]: ProgressBar::set_draw_target + /// [draw target]: ProgressDrawTarget + pub fn new(len: u64) -> Self { + Self::with_draw_target(Some(len), ProgressDrawTarget::stderr()) + } + + /// Creates a new progress bar without a specified length + /// + /// This progress bar by default draws directly to stderr, and refreshes a maximum of 20 times + /// a second. To change the refresh rate, [set] the [draw target] to one with a different refresh + /// rate. + /// + /// [set]: ProgressBar::set_draw_target + /// [draw target]: ProgressDrawTarget + pub fn no_length() -> Self { + Self::with_draw_target(None, ProgressDrawTarget::stderr()) + } + + /// Creates a completely hidden progress bar + /// + /// This progress bar still responds to API changes but it does not have a length or render in + /// any way. + pub fn hidden() -> Self { + Self::with_draw_target(None, ProgressDrawTarget::hidden()) + } + + /// Creates a new progress bar with a given length and draw target + pub fn with_draw_target(len: Option, draw_target: ProgressDrawTarget) -> Self { + let pos = Arc::new(AtomicPosition::new()); + Self { + state: Arc::new(Mutex::new(BarState::new(len, draw_target, pos.clone()))), + pos, + ticker: Arc::new(Mutex::new(None)), + } + } + + /// Get a clone of the current progress bar style. + pub fn style(&self) -> ProgressStyle { + self.state().style.clone() + } + + /// A convenience builder-like function for a progress bar with a given style + pub fn with_style(self, style: ProgressStyle) -> Self { + self.set_style(style); + self + } + + /// A convenience builder-like function for a progress bar with a given tab width + pub fn with_tab_width(self, tab_width: usize) -> Self { + self.state().set_tab_width(tab_width); + self + } + + /// A convenience builder-like function for a progress bar with a given prefix + /// + /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template + /// (see [`ProgressStyle`]). + pub fn with_prefix(self, prefix: impl Into>) -> Self { + let mut state = self.state(); + state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width); + drop(state); + self + } + + /// A convenience builder-like function for a progress bar with a given message + /// + /// For the message to be visible, the `{msg}` placeholder must be present in the template (see + /// [`ProgressStyle`]). + pub fn with_message(self, message: impl Into>) -> Self { + let mut state = self.state(); + state.state.message = TabExpandedString::new(message.into(), state.tab_width); + drop(state); + self + } + + /// A convenience builder-like function for a progress bar with a given position + pub fn with_position(self, pos: u64) -> Self { + self.state().state.set_pos(pos); + self + } + + /// A convenience builder-like function for a progress bar with a given elapsed time + pub fn with_elapsed(self, elapsed: Duration) -> Self { + self.state().state.started = Instant::now().checked_sub(elapsed).unwrap(); + self + } + + /// Sets the finish behavior for the progress bar + /// + /// This behavior is invoked when [`ProgressBar`] or + /// [`ProgressBarIter`] completes and + /// [`ProgressBar::is_finished()`] is false. + /// If you don't want the progress bar to be automatically finished then + /// call `with_finish(Abandon)`. + /// + /// [`ProgressBar`]: crate::ProgressBar + /// [`ProgressBarIter`]: crate::ProgressBarIter + /// [`ProgressBar::is_finished()`]: crate::ProgressBar::is_finished + pub fn with_finish(self, finish: ProgressFinish) -> Self { + self.state().on_finish = finish; + self + } + + /// Creates a new spinner + /// + /// This spinner by default draws directly to stderr. This adds the default spinner style to it. + pub fn new_spinner() -> Self { + let rv = Self::with_draw_target(None, ProgressDrawTarget::stderr()); + rv.set_style(ProgressStyle::default_spinner()); + rv + } + + /// Overrides the stored style + /// + /// This does not redraw the bar. Call [`ProgressBar::tick()`] to force it. + pub fn set_style(&self, mut style: ProgressStyle) { + let mut state = self.state(); + if state.draw_target.is_stderr() { + style.set_for_stderr() + }; + state.set_style(style); + } + + /// Sets the tab width (default: 8). All tabs will be expanded to this many spaces. + pub fn set_tab_width(&self, tab_width: usize) { + let mut state = self.state(); + state.set_tab_width(tab_width); + state.draw(true, Instant::now()).unwrap(); + } + + /// Spawns a background thread to tick the progress bar + /// + /// When this is enabled a background thread will regularly tick the progress bar in the given + /// interval. This is useful to advance progress bars that are very slow by themselves. + /// + /// When steady ticks are enabled, calling [`ProgressBar::tick()`] on a progress bar does not + /// have any effect. + pub fn enable_steady_tick(&self, interval: Duration) { + // The way we test for ticker termination is with a single static `AtomicBool`. Since cargo + // runs tests concurrently, we have a `TICKER_TEST` lock to make sure tests using ticker + // don't step on each other. This check catches attempts to use tickers in tests without + // acquiring the lock. + #[cfg(test)] + { + let guard = TICKER_TEST.try_lock(); + let lock_acquired = guard.is_ok(); + // Drop the guard before panicking to avoid poisoning the lock (which would cause other + // ticker tests to fail) + drop(guard); + if lock_acquired { + panic!("you must acquire the TICKER_TEST lock in your test to use this method"); + } + } + + if interval.is_zero() { + return; + } + + self.stop_and_replace_ticker(Some(interval)); + } + + /// Undoes [`ProgressBar::enable_steady_tick()`] + pub fn disable_steady_tick(&self) { + self.stop_and_replace_ticker(None); + } + + fn stop_and_replace_ticker(&self, interval: Option) { + let mut ticker_state = self.ticker.lock().unwrap(); + if let Some(ticker) = ticker_state.take() { + ticker.stop(); + } + + *ticker_state = interval.map(|interval| Ticker::new(interval, &self.state)); + } + + /// Manually ticks the spinner or progress bar + /// + /// This automatically happens on any other change to a progress bar. + pub fn tick(&self) { + self.tick_inner(Instant::now()); + } + + fn tick_inner(&self, now: Instant) { + // Only tick if a `Ticker` isn't installed + if self.ticker.lock().unwrap().is_none() { + self.state().tick(now); + } + } + + /// Advances the position of the progress bar by `delta` + pub fn inc(&self, delta: u64) { + self.pos.inc(delta); + let now = Instant::now(); + if self.pos.allow(now) { + self.tick_inner(now); + } + } + + /// Decrease the position of the progress bar by `delta` + pub fn dec(&self, delta: u64) { + self.pos.dec(delta); + let now = Instant::now(); + if self.pos.allow(now) { + self.tick_inner(now); + } + } + + /// A quick convenience check if the progress bar is hidden + pub fn is_hidden(&self) -> bool { + self.state().draw_target.is_hidden() + } + + /// Indicates that the progress bar finished + pub fn is_finished(&self) -> bool { + self.state().state.is_finished() + } + + /// Print a log line above the progress bar + /// + /// If the progress bar is hidden (e.g. when standard output is not a terminal), `println()` + /// will not do anything. If you want to write to the standard output in such cases as well, use + /// [`ProgressBar::suspend()`] instead. + /// + /// If the progress bar was added to a [`MultiProgress`], the log line will be + /// printed above all other progress bars. + /// + /// [`ProgressBar::suspend()`]: ProgressBar::suspend + /// [`MultiProgress`]: crate::MultiProgress + pub fn println>(&self, msg: I) { + self.state().println(Instant::now(), msg.as_ref()); + } + + /// Update the `ProgressBar`'s inner [`ProgressState`] + pub fn update(&self, f: impl FnOnce(&mut ProgressState)) { + self.state() + .update(Instant::now(), f, self.ticker.lock().unwrap().is_none()); + } + + /// Sets the position of the progress bar + pub fn set_position(&self, pos: u64) { + self.pos.set(pos); + let now = Instant::now(); + if self.pos.allow(now) { + self.tick_inner(now); + } + } + + /// Sets the length of the progress bar to `None` + pub fn unset_length(&self) { + self.state().unset_length(Instant::now()); + } + + /// Sets the length of the progress bar + pub fn set_length(&self, len: u64) { + self.state().set_length(Instant::now(), len); + } + + /// Increase the length of the progress bar + pub fn inc_length(&self, delta: u64) { + self.state().inc_length(Instant::now(), delta); + } + + /// Decrease the length of the progress bar + pub fn dec_length(&self, delta: u64) { + self.state().dec_length(Instant::now(), delta); + } + + /// Sets the current prefix of the progress bar + /// + /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template + /// (see [`ProgressStyle`]). + pub fn set_prefix(&self, prefix: impl Into>) { + let mut state = self.state(); + state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width); + state.update_estimate_and_draw(Instant::now()); + } + + /// Sets the current message of the progress bar + /// + /// For the message to be visible, the `{msg}` placeholder must be present in the template (see + /// [`ProgressStyle`]). + pub fn set_message(&self, msg: impl Into>) { + let mut state = self.state(); + state.state.message = TabExpandedString::new(msg.into(), state.tab_width); + state.update_estimate_and_draw(Instant::now()); + } + + /// Sets the elapsed time for the progress bar + pub fn set_elapsed(&self, elapsed: Duration) { + self.state().state.started = Instant::now().checked_sub(elapsed).unwrap(); + } + + /// Creates a new weak reference to this [`ProgressBar`] + pub fn downgrade(&self) -> WeakProgressBar { + WeakProgressBar { + state: Arc::downgrade(&self.state), + pos: Arc::downgrade(&self.pos), + ticker: Arc::downgrade(&self.ticker), + } + } + + /// Resets the ETA calculation + /// + /// This can be useful if the progress bars made a large jump or was paused for a prolonged + /// time. + pub fn reset_eta(&self) { + self.state().reset(Instant::now(), Reset::Eta); + } + + /// Resets elapsed time and the ETA calculation + pub fn reset_elapsed(&self) { + self.state().reset(Instant::now(), Reset::Elapsed); + } + + /// Resets all of the progress bar state + pub fn reset(&self) { + self.state().reset(Instant::now(), Reset::All); + } + + /// Finishes the progress bar and leaves the current message + pub fn finish(&self) { + self.state() + .finish_using_style(Instant::now(), ProgressFinish::AndLeave); + } + + /// Finishes the progress bar and sets a message + /// + /// For the message to be visible, the `{msg}` placeholder must be present in the template (see + /// [`ProgressStyle`]). + pub fn finish_with_message(&self, msg: impl Into>) { + self.state() + .finish_using_style(Instant::now(), ProgressFinish::WithMessage(msg.into())); + } + + /// Finishes the progress bar and completely clears it + pub fn finish_and_clear(&self) { + self.state() + .finish_using_style(Instant::now(), ProgressFinish::AndClear); + } + + /// Finishes the progress bar and leaves the current message and progress + pub fn abandon(&self) { + self.state() + .finish_using_style(Instant::now(), ProgressFinish::Abandon); + } + + /// Finishes the progress bar and sets a message, and leaves the current progress + /// + /// For the message to be visible, the `{msg}` placeholder must be present in the template (see + /// [`ProgressStyle`]). + pub fn abandon_with_message(&self, msg: impl Into>) { + self.state().finish_using_style( + Instant::now(), + ProgressFinish::AbandonWithMessage(msg.into()), + ); + } + + /// Finishes the progress bar using the behavior stored in the [`ProgressStyle`] + /// + /// See [`ProgressBar::with_finish()`]. + pub fn finish_using_style(&self) { + let mut state = self.state(); + let finish = state.on_finish.clone(); + state.finish_using_style(Instant::now(), finish); + } + + /// Sets a different draw target for the progress bar + /// + /// This can be used to draw the progress bar to stderr (this is the default): + /// + /// ```rust,no_run + /// # use indicatif::{ProgressBar, ProgressDrawTarget}; + /// let pb = ProgressBar::new(100); + /// pb.set_draw_target(ProgressDrawTarget::stderr()); + /// ``` + /// + /// **Note:** Calling this method on a [`ProgressBar`] linked with a [`MultiProgress`] (after + /// running [`MultiProgress::add()`]) will unlink this progress bar. If you don't want this + /// behavior, call [`MultiProgress::set_draw_target()`] instead. + /// + /// Use [`ProgressBar::with_draw_target()`] to set the draw target during creation. + /// + /// [`MultiProgress`]: crate::MultiProgress + /// [`MultiProgress::add()`]: crate::MultiProgress::add + /// [`MultiProgress::set_draw_target()`]: crate::MultiProgress::set_draw_target + pub fn set_draw_target(&self, target: ProgressDrawTarget) { + let mut state = self.state(); + state.draw_target.disconnect(Instant::now()); + state.draw_target = target; + } + + /// Force a redraw of the progress bar to be in sync with its state + /// + /// For performance reasons the progress bar is not redrawn on each state update. + /// This is normally not an issue, since new updates will eventually trigger rendering. + /// + /// For slow running tasks it is recommended to rely on [`ProgressBar::enable_steady_tick()`] + /// to ensure continued rendering of the progress bar. + pub fn force_draw(&self) { + let _ = self.state().draw(true, Instant::now()); + } + + /// Hide the progress bar temporarily, execute `f`, then redraw the progress bar + /// + /// Useful for external code that writes to the standard output. + /// + /// If the progress bar was added to a [`MultiProgress`], it will suspend the entire [`MultiProgress`]. + /// + /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print + /// anything on the progress bar will be blocked until `f` finishes. + /// Therefore, it is recommended to avoid long-running operations in `f`. + /// + /// ```rust,no_run + /// # use indicatif::ProgressBar; + /// let mut pb = ProgressBar::new(3); + /// pb.suspend(|| { + /// println!("Log message"); + /// }) + /// ``` + /// + /// [`MultiProgress`]: crate::MultiProgress + pub fn suspend R, R>(&self, f: F) -> R { + self.state().suspend(Instant::now(), f) + } + + /// Wraps an [`Iterator`] with the progress bar + /// + /// ```rust,no_run + /// # use indicatif::ProgressBar; + /// let v = vec![1, 2, 3]; + /// let pb = ProgressBar::new(3); + /// for item in pb.wrap_iter(v.iter()) { + /// // ... + /// } + /// ``` + pub fn wrap_iter(&self, it: It) -> ProgressBarIter { + it.progress_with(self.clone()) + } + + /// Wraps an [`io::Read`] with the progress bar + /// + /// ```rust,no_run + /// # use std::fs::File; + /// # use std::io; + /// # use indicatif::ProgressBar; + /// # fn test () -> io::Result<()> { + /// let source = File::open("work.txt")?; + /// let mut target = File::create("done.txt")?; + /// let pb = ProgressBar::new(source.metadata()?.len()); + /// io::copy(&mut pb.wrap_read(source), &mut target); + /// # Ok(()) + /// # } + /// ``` + pub fn wrap_read(&self, read: R) -> ProgressBarIter { + ProgressBarIter { + progress: self.clone(), + it: read, + seek_max: iter::SeekMax::default(), + } + } + + /// Wraps an [`io::Write`] with the progress bar + /// + /// ```rust,no_run + /// # use std::fs::File; + /// # use std::io; + /// # use indicatif::ProgressBar; + /// # fn test () -> io::Result<()> { + /// let mut source = File::open("work.txt")?; + /// let target = File::create("done.txt")?; + /// let pb = ProgressBar::new(source.metadata()?.len()); + /// io::copy(&mut source, &mut pb.wrap_write(target)); + /// # Ok(()) + /// # } + /// ``` + pub fn wrap_write(&self, write: W) -> ProgressBarIter { + ProgressBarIter { + progress: self.clone(), + it: write, + seek_max: iter::SeekMax::default(), + } + } + + #[cfg(feature = "tokio")] + #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] + /// Wraps an [`tokio::io::AsyncWrite`] with the progress bar + /// + /// ```rust,no_run + /// # use tokio::fs::File; + /// # use tokio::io; + /// # use indicatif::ProgressBar; + /// # async fn test() -> io::Result<()> { + /// let mut source = File::open("work.txt").await?; + /// let mut target = File::open("done.txt").await?; + /// let pb = ProgressBar::new(source.metadata().await?.len()); + /// io::copy(&mut source, &mut pb.wrap_async_write(target)).await?; + /// # Ok(()) + /// # } + /// ``` + pub fn wrap_async_write( + &self, + write: W, + ) -> ProgressBarIter { + ProgressBarIter { + progress: self.clone(), + it: write, + seek_max: iter::SeekMax::default(), + } + } + + #[cfg(feature = "tokio")] + #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] + /// Wraps an [`tokio::io::AsyncRead`] with the progress bar + /// + /// ```rust,no_run + /// # use tokio::fs::File; + /// # use tokio::io; + /// # use indicatif::ProgressBar; + /// # async fn test() -> io::Result<()> { + /// let mut source = File::open("work.txt").await?; + /// let mut target = File::open("done.txt").await?; + /// let pb = ProgressBar::new(source.metadata().await?.len()); + /// io::copy(&mut pb.wrap_async_read(source), &mut target).await?; + /// # Ok(()) + /// # } + /// ``` + pub fn wrap_async_read(&self, read: R) -> ProgressBarIter { + ProgressBarIter { + progress: self.clone(), + it: read, + seek_max: iter::SeekMax::default(), + } + } + + /// Wraps a [`futures::Stream`](https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html) with the progress bar + /// + /// ``` + /// # use indicatif::ProgressBar; + /// # futures::executor::block_on(async { + /// use futures::stream::{self, StreamExt}; + /// let pb = ProgressBar::new(10); + /// let mut stream = pb.wrap_stream(stream::iter('a'..='z')); + /// + /// assert_eq!(stream.next().await, Some('a')); + /// assert_eq!(stream.count().await, 25); + /// # }); // block_on + /// ``` + #[cfg(feature = "futures")] + #[cfg_attr(docsrs, doc(cfg(feature = "futures")))] + pub fn wrap_stream(&self, stream: S) -> ProgressBarIter { + ProgressBarIter { + progress: self.clone(), + it: stream, + seek_max: iter::SeekMax::default(), + } + } + + /// Returns the current position + pub fn position(&self) -> u64 { + self.state().state.pos() + } + + /// Returns the current length + pub fn length(&self) -> Option { + self.state().state.len() + } + + /// Returns the current ETA + pub fn eta(&self) -> Duration { + self.state().state.eta() + } + + /// Returns the current rate of progress + pub fn per_sec(&self) -> f64 { + self.state().state.per_sec() + } + + /// Returns the current expected duration + pub fn duration(&self) -> Duration { + self.state().state.duration() + } + + /// Returns the current elapsed time + pub fn elapsed(&self) -> Duration { + self.state().state.elapsed() + } + + /// Returns the current tab width + pub fn tab_width(&self) -> usize { + self.state().tab_width + } + + /// Index in the `MultiState` + pub(crate) fn index(&self) -> Option { + self.state().draw_target.remote().map(|(_, idx)| idx) + } + + /// Current message + pub fn message(&self) -> String { + self.state().state.message.expanded().to_string() + } + + /// Current prefix + pub fn prefix(&self) -> String { + self.state().state.prefix.expanded().to_string() + } + + #[inline] + pub(crate) fn state(&self) -> MutexGuard<'_, BarState> { + self.state.lock().unwrap() + } +} + +/// A weak reference to a [`ProgressBar`]. +/// +/// Useful for creating custom steady tick implementations +#[derive(Clone, Default)] +pub struct WeakProgressBar { + state: Weak>, + pos: Weak, + ticker: Weak>>, +} + +impl WeakProgressBar { + /// Create a new [`WeakProgressBar`] that returns `None` when [`upgrade()`] is called. + /// + /// [`upgrade()`]: WeakProgressBar::upgrade + pub fn new() -> Self { + Self::default() + } + + /// Attempts to upgrade the Weak pointer to a [`ProgressBar`], delaying dropping of the inner + /// value if successful. Returns [`None`] if the inner value has since been dropped. + /// + /// [`ProgressBar`]: struct.ProgressBar.html + pub fn upgrade(&self) -> Option { + let state = self.state.upgrade()?; + let pos = self.pos.upgrade()?; + let ticker = self.ticker.upgrade()?; + Some(ProgressBar { state, pos, ticker }) + } +} + +pub(crate) struct Ticker { + stopping: Arc<(Mutex, Condvar)>, + join_handle: Option>, +} + +impl Drop for Ticker { + fn drop(&mut self) { + self.stop(); + self.join_handle.take().map(|handle| handle.join()); + } +} + +#[cfg(test)] +static TICKER_RUNNING: AtomicBool = AtomicBool::new(false); + +impl Ticker { + pub(crate) fn new(interval: Duration, bar_state: &Arc>) -> Self { + debug_assert!(!interval.is_zero()); + + // A `Mutex` is used as a flag to indicate whether the ticker was requested to stop. + // The `Condvar` is used a notification mechanism: when the ticker is dropped, we notify + // the thread and interrupt the ticker wait. + #[allow(clippy::mutex_atomic)] + let stopping = Arc::new((Mutex::new(false), Condvar::new())); + let control = TickerControl { + stopping: stopping.clone(), + state: Arc::downgrade(bar_state), + }; + + let join_handle = thread::spawn(move || control.run(interval)); + Self { + stopping, + join_handle: Some(join_handle), + } + } + + pub(crate) fn stop(&self) { + *self.stopping.0.lock().unwrap() = true; + self.stopping.1.notify_one(); + } +} + +struct TickerControl { + stopping: Arc<(Mutex, Condvar)>, + state: Weak>, +} + +impl TickerControl { + fn run(&self, interval: Duration) { + #[cfg(test)] + TICKER_RUNNING.store(true, Ordering::SeqCst); + + while let Some(arc) = self.state.upgrade() { + let mut state = arc.lock().unwrap(); + if state.state.is_finished() { + break; + } + + state.tick(Instant::now()); + + drop(state); // Don't forget to drop the lock before sleeping + drop(arc); // Also need to drop Arc otherwise BarState won't be dropped + + // Wait for `interval` but return early if we are notified to stop + let result = self + .stopping + .1 + .wait_timeout_while(self.stopping.0.lock().unwrap(), interval, |stopped| { + !*stopped + }) + .unwrap(); + + // If the wait didn't time out, it means we were notified to stop + if !result.1.timed_out() { + break; + } + } + + #[cfg(test)] + TICKER_RUNNING.store(false, Ordering::SeqCst); + } +} + +// Tests using the global TICKER_RUNNING flag need to be serialized +#[cfg(test)] +pub(crate) static TICKER_TEST: Lazy> = Lazy::new(Mutex::default); + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(clippy::float_cmp)] + #[test] + fn test_pbar_zero() { + let pb = ProgressBar::new(0); + assert_eq!(pb.state().state.fraction(), 1.0); + } + + #[allow(clippy::float_cmp)] + #[test] + fn test_pbar_maxu64() { + let pb = ProgressBar::new(!0); + assert_eq!(pb.state().state.fraction(), 0.0); + } + + #[test] + fn test_pbar_overflow() { + let pb = ProgressBar::new(1); + pb.set_draw_target(ProgressDrawTarget::hidden()); + pb.inc(2); + pb.finish(); + } + + #[test] + fn test_get_position() { + let pb = ProgressBar::new(1); + pb.set_draw_target(ProgressDrawTarget::hidden()); + pb.inc(2); + let pos = pb.position(); + assert_eq!(pos, 2); + } + + #[test] + fn test_weak_pb() { + let pb = ProgressBar::new(0); + let weak = pb.downgrade(); + assert!(weak.upgrade().is_some()); + ::std::mem::drop(pb); + assert!(weak.upgrade().is_none()); + } + + #[test] + fn it_can_wrap_a_reader() { + let bytes = &b"I am an implementation of io::Read"[..]; + let pb = ProgressBar::new(bytes.len() as u64); + let mut reader = pb.wrap_read(bytes); + let mut writer = Vec::new(); + io::copy(&mut reader, &mut writer).unwrap(); + assert_eq!(writer, bytes); + } + + #[test] + fn it_can_wrap_a_writer() { + let bytes = b"implementation of io::Read"; + let mut reader = &bytes[..]; + let pb = ProgressBar::new(bytes.len() as u64); + let writer = Vec::new(); + let mut writer = pb.wrap_write(writer); + io::copy(&mut reader, &mut writer).unwrap(); + assert_eq!(writer.it, bytes); + } + + #[test] + fn ticker_thread_terminates_on_drop() { + let _guard = TICKER_TEST.lock().unwrap(); + assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); + + let pb = ProgressBar::new_spinner(); + pb.enable_steady_tick(Duration::from_millis(50)); + + // Give the thread time to start up + thread::sleep(Duration::from_millis(250)); + + assert!(TICKER_RUNNING.load(Ordering::SeqCst)); + + drop(pb); + assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); + } + + #[test] + fn ticker_thread_terminates_on_drop_2() { + let _guard = TICKER_TEST.lock().unwrap(); + assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); + + let pb = ProgressBar::new_spinner(); + pb.enable_steady_tick(Duration::from_millis(50)); + let pb2 = pb.clone(); + + // Give the thread time to start up + thread::sleep(Duration::from_millis(250)); + + assert!(TICKER_RUNNING.load(Ordering::SeqCst)); + + drop(pb); + assert!(TICKER_RUNNING.load(Ordering::SeqCst)); + + drop(pb2); + assert!(!TICKER_RUNNING.load(Ordering::SeqCst)); + } +} diff --git a/anneal/v2/vendor/indicatif/src/rayon.rs b/anneal/v2/vendor/indicatif/src/rayon.rs new file mode 100644 index 0000000000..0d63561d79 --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/rayon.rs @@ -0,0 +1,240 @@ +use rayon::iter::plumbing::{Consumer, Folder, Producer, ProducerCallback, UnindexedConsumer}; +use rayon::iter::{IndexedParallelIterator, ParallelIterator}; + +use crate::{iter::SeekMax, ProgressBar, ProgressBarIter}; + +/// Wraps a Rayon parallel iterator. +/// +/// See [`ProgressIterator`](trait.ProgressIterator.html) for method +/// documentation. +#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] +pub trait ParallelProgressIterator +where + Self: Sized + ParallelIterator, +{ + /// Wrap an iterator with a custom progress bar. + fn progress_with(self, progress: ProgressBar) -> ProgressBarIter; + + /// Wrap an iterator with an explicit element count. + fn progress_count(self, len: u64) -> ProgressBarIter { + self.progress_with(ProgressBar::new(len)) + } + + fn progress(self) -> ProgressBarIter + where + Self: IndexedParallelIterator, + { + let len = u64::try_from(self.len()).unwrap(); + self.progress_count(len) + } + + /// Wrap an iterator with a progress bar and style it. + fn progress_with_style(self, style: crate::ProgressStyle) -> ProgressBarIter + where + Self: IndexedParallelIterator, + { + let len = u64::try_from(self.len()).unwrap(); + let bar = ProgressBar::new(len).with_style(style); + self.progress_with(bar) + } +} + +impl> ParallelProgressIterator for T { + fn progress_with(self, progress: ProgressBar) -> ProgressBarIter { + ProgressBarIter { + it: self, + progress, + seek_max: SeekMax::default(), + } + } +} + +impl> IndexedParallelIterator for ProgressBarIter { + fn len(&self) -> usize { + self.it.len() + } + + fn drive>(self, consumer: C) -> >::Result { + let consumer = ProgressConsumer::new(consumer, self.progress); + self.it.drive(consumer) + } + + fn with_producer>( + self, + callback: CB, + ) -> >::Output { + return self.it.with_producer(Callback { + callback, + progress: self.progress, + }); + + struct Callback { + callback: CB, + progress: ProgressBar, + } + + impl> ProducerCallback for Callback { + type Output = CB::Output; + + fn callback

(self, base: P) -> CB::Output + where + P: Producer, + { + let producer = ProgressProducer { + base, + progress: self.progress, + }; + self.callback.callback(producer) + } + } + } +} + +struct ProgressProducer { + base: T, + progress: ProgressBar, +} + +impl> Producer for ProgressProducer

{ + type Item = T; + type IntoIter = ProgressBarIter; + + fn into_iter(self) -> Self::IntoIter { + ProgressBarIter { + it: self.base.into_iter(), + progress: self.progress, + seek_max: SeekMax::default(), + } + } + + fn min_len(&self) -> usize { + self.base.min_len() + } + + fn max_len(&self) -> usize { + self.base.max_len() + } + + fn split_at(self, index: usize) -> (Self, Self) { + let (left, right) = self.base.split_at(index); + ( + ProgressProducer { + base: left, + progress: self.progress.clone(), + }, + ProgressProducer { + base: right, + progress: self.progress, + }, + ) + } +} + +struct ProgressConsumer { + base: C, + progress: ProgressBar, +} + +impl ProgressConsumer { + fn new(base: C, progress: ProgressBar) -> Self { + ProgressConsumer { base, progress } + } +} + +impl> Consumer for ProgressConsumer { + type Folder = ProgressFolder; + type Reducer = C::Reducer; + type Result = C::Result; + + fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { + let (left, right, reducer) = self.base.split_at(index); + ( + ProgressConsumer::new(left, self.progress.clone()), + ProgressConsumer::new(right, self.progress), + reducer, + ) + } + + fn into_folder(self) -> Self::Folder { + ProgressFolder { + base: self.base.into_folder(), + progress: self.progress, + } + } + + fn full(&self) -> bool { + self.base.full() + } +} + +impl> UnindexedConsumer for ProgressConsumer { + fn split_off_left(&self) -> Self { + ProgressConsumer::new(self.base.split_off_left(), self.progress.clone()) + } + + fn to_reducer(&self) -> Self::Reducer { + self.base.to_reducer() + } +} + +struct ProgressFolder { + base: C, + progress: ProgressBar, +} + +impl> Folder for ProgressFolder { + type Result = C::Result; + + fn consume(self, item: T) -> Self { + self.progress.inc(1); + ProgressFolder { + base: self.base.consume(item), + progress: self.progress, + } + } + + fn complete(self) -> C::Result { + self.base.complete() + } + + fn full(&self) -> bool { + self.base.full() + } +} + +impl> ParallelIterator for ProgressBarIter { + type Item = S; + + fn drive_unindexed>(self, consumer: C) -> C::Result { + let consumer1 = ProgressConsumer::new(consumer, self.progress.clone()); + self.it.drive_unindexed(consumer1) + } +} + +#[cfg(test)] +mod test { + use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; + + use crate::{ParallelProgressIterator, ProgressBar, ProgressBarIter, ProgressStyle}; + + #[test] + fn it_can_wrap_a_parallel_iterator() { + let v = vec![1, 2, 3]; + fn wrap<'a, T: ParallelIterator>(it: ProgressBarIter) { + assert_eq!(it.map(|x| x * 2).collect::>(), vec![2, 4, 6]); + } + + wrap(v.par_iter().progress_count(3)); + wrap({ + let pb = ProgressBar::new(v.len() as u64); + v.par_iter().progress_with(pb) + }); + + wrap({ + let style = ProgressStyle::default_bar() + .template("{wide_bar:.red} {percent}/100%") + .unwrap(); + v.par_iter().progress_with_style(style) + }); + } +} diff --git a/anneal/v2/vendor/indicatif/src/state.rs b/anneal/v2/vendor/indicatif/src/state.rs new file mode 100644 index 0000000000..92bac64cc1 --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/state.rs @@ -0,0 +1,884 @@ +use std::borrow::Cow; +use std::io; +use std::sync::{Arc, OnceLock}; +use std::time::Duration; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; + +use portable_atomic::{AtomicU64, AtomicU8, Ordering}; +#[cfg(all(target_arch = "wasm32", feature = "wasmbind"))] +use web_time::Instant; + +use crate::draw_target::{LineType, ProgressDrawTarget}; +use crate::style::ProgressStyle; + +pub(crate) struct BarState { + pub(crate) draw_target: ProgressDrawTarget, + pub(crate) on_finish: ProgressFinish, + pub(crate) style: ProgressStyle, + pub(crate) state: ProgressState, + pub(crate) tab_width: usize, +} + +impl BarState { + pub(crate) fn new( + len: Option, + draw_target: ProgressDrawTarget, + pos: Arc, + ) -> Self { + Self { + draw_target, + on_finish: ProgressFinish::default(), + style: ProgressStyle::default_bar(), + state: ProgressState::new(len, pos), + tab_width: DEFAULT_TAB_WIDTH, + } + } + + /// Finishes the progress bar using the [`ProgressFinish`] behavior stored + /// in the [`ProgressStyle`]. + pub(crate) fn finish_using_style(&mut self, now: Instant, finish: ProgressFinish) { + let duration = now.duration_since(self.state.started); + self.state.status = Status::DoneVisible(duration); + match finish { + ProgressFinish::AndLeave => { + if let Some(len) = self.state.len { + self.state.pos.set(len); + } + } + ProgressFinish::WithMessage(msg) => { + if let Some(len) = self.state.len { + self.state.pos.set(len); + } + self.state.message = TabExpandedString::new(msg, self.tab_width); + } + ProgressFinish::AndClear => { + if let Some(len) = self.state.len { + self.state.pos.set(len); + } + self.state.status = Status::DoneHidden(duration); + } + ProgressFinish::Abandon => {} + ProgressFinish::AbandonWithMessage(msg) => { + self.state.message = TabExpandedString::new(msg, self.tab_width); + } + } + + // There's no need to update the estimate here; once the `status` is no longer + // `InProgress`, we will use the length and elapsed time to estimate. + let _ = self.draw(true, now); + } + + pub(crate) fn reset(&mut self, now: Instant, mode: Reset) { + // Always reset the estimator; this is the only reset that will occur if mode is + // `Reset::Eta`. + self.state.est.reset(now); + + if let Reset::Elapsed | Reset::All = mode { + self.state.started = now; + } + + if let Reset::All = mode { + self.state.pos.reset(now); + self.state.status = Status::InProgress; + + for tracker in self.style.format_map.values_mut() { + tracker.reset(&self.state, now); + } + + let _ = self.draw(false, now); + } + } + + pub(crate) fn update(&mut self, now: Instant, f: impl FnOnce(&mut ProgressState), tick: bool) { + f(&mut self.state); + if tick { + self.tick(now); + } + } + + pub(crate) fn unset_length(&mut self, now: Instant) { + self.state.len = None; + self.update_estimate_and_draw(now); + } + + pub(crate) fn set_length(&mut self, now: Instant, len: u64) { + self.state.len = Some(len); + self.update_estimate_and_draw(now); + } + + pub(crate) fn inc_length(&mut self, now: Instant, delta: u64) { + if let Some(len) = self.state.len { + self.state.len = Some(len.saturating_add(delta)); + } + self.update_estimate_and_draw(now); + } + + pub(crate) fn dec_length(&mut self, now: Instant, delta: u64) { + if let Some(len) = self.state.len { + self.state.len = Some(len.saturating_sub(delta)); + } + self.update_estimate_and_draw(now); + } + + pub(crate) fn set_tab_width(&mut self, tab_width: usize) { + self.tab_width = tab_width; + self.state.message.set_tab_width(tab_width); + self.state.prefix.set_tab_width(tab_width); + self.style.set_tab_width(tab_width); + } + + pub(crate) fn set_style(&mut self, style: ProgressStyle) { + self.style = style; + self.style.set_tab_width(self.tab_width); + } + + pub(crate) fn tick(&mut self, now: Instant) { + self.state.tick = self.state.tick.saturating_add(1); + self.update_estimate_and_draw(now); + } + + pub(crate) fn update_estimate_and_draw(&mut self, now: Instant) { + let pos = self.state.pos.pos.load(Ordering::Relaxed); + self.state.est.record(pos, now); + + for tracker in self.style.format_map.values_mut() { + tracker.tick(&self.state, now); + } + + let _ = self.draw(false, now); + } + + pub(crate) fn println(&mut self, now: Instant, msg: &str) { + let width = self.draw_target.width(); + let mut drawable = match self.draw_target.drawable(true, now) { + Some(drawable) => drawable, + None => return, + }; + + let mut draw_state = drawable.state(); + let lines: Vec = msg.lines().map(|l| LineType::Text(Into::into(l))).collect(); + // Empty msg should trigger newline as we are in println + if lines.is_empty() { + draw_state.lines.push(LineType::Empty); + } else { + draw_state.lines.extend(lines); + } + + if let Some(width) = width { + if !matches!(self.state.status, Status::DoneHidden(_)) { + self.style + .format_state(&self.state, &mut draw_state.lines, width); + } + } + + drop(draw_state); + let _ = drawable.draw(); + } + + pub(crate) fn suspend R, R>(&mut self, now: Instant, f: F) -> R { + if let Some((state, _)) = self.draw_target.remote() { + return state.write().unwrap().suspend(f, now); + } + + if let Some(drawable) = self.draw_target.drawable(true, now) { + let _ = drawable.clear(); + } + + let ret = f(); + let _ = self.draw(true, Instant::now()); + ret + } + + pub(crate) fn draw(&mut self, mut force_draw: bool, now: Instant) -> io::Result<()> { + // `|= self.is_finished()` should not be needed here, but we used to always draw for + // finished progress bars, so it's kept as to not cause compatibility issues in weird cases. + force_draw |= self.state.is_finished(); + let mut drawable = match self.draw_target.drawable(force_draw, now) { + Some(drawable) => drawable, + None => return Ok(()), + }; + + // Getting the width can be expensive; thus this should happen after checking drawable. + let width = drawable.width(); + + let mut draw_state = drawable.state(); + + if let Some(width) = width { + if !matches!(self.state.status, Status::DoneHidden(_)) { + self.style + .format_state(&self.state, &mut draw_state.lines, width); + } + } + + drop(draw_state); + drawable.draw() + } +} + +impl Drop for BarState { + fn drop(&mut self) { + // Progress bar is already finished. Do not need to do anything other than notify + // the `MultiProgress` that we're now a zombie. + if self.state.is_finished() { + self.draw_target.mark_zombie(); + return; + } + + self.finish_using_style(Instant::now(), self.on_finish.clone()); + + // Notify the `MultiProgress` that we're now a zombie. + self.draw_target.mark_zombie(); + } +} + +pub(crate) enum Reset { + Eta, + Elapsed, + All, +} + +/// The state of a progress bar at a moment in time. +#[non_exhaustive] +pub struct ProgressState { + pos: Arc, + len: Option, + pub(crate) tick: u64, + pub(crate) started: Instant, + status: Status, + est: Estimator, + pub(crate) message: TabExpandedString, + pub(crate) prefix: TabExpandedString, +} + +impl ProgressState { + pub(crate) fn new(len: Option, pos: Arc) -> Self { + let now = Instant::now(); + Self { + pos, + len, + tick: 0, + status: Status::InProgress, + started: now, + est: Estimator::new(now), + message: TabExpandedString::NoTabs("".into()), + prefix: TabExpandedString::NoTabs("".into()), + } + } + + /// Indicates that the progress bar finished. + pub fn is_finished(&self) -> bool { + match self.status { + Status::InProgress => false, + Status::DoneVisible(_) => true, + Status::DoneHidden(_) => true, + } + } + + /// Returns the completion as a floating-point number between 0 and 1 + pub fn fraction(&self) -> f32 { + let pos = self.pos.pos.load(Ordering::Relaxed); + let pct = match (pos, self.len) { + (_, None) => 0.0, + (_, Some(0)) => 1.0, + (0, _) => 0.0, + (pos, Some(len)) => pos as f32 / len as f32, + }; + pct.clamp(0.0, 1.0) + } + + /// The expected ETA + pub fn eta(&self) -> Duration { + if self.is_finished() { + return Duration::new(0, 0); + } + + let len = match self.len { + Some(len) => len, + None => return Duration::new(0, 0), + }; + + let pos = self.pos.pos.load(Ordering::Relaxed); + + let sps = self.est.steps_per_second(Instant::now()); + + // Infinite duration should only ever happen at the beginning, so in this case it's okay to + // just show an ETA of 0 until progress starts to occur. + if sps == 0.0 { + return Duration::new(0, 0); + } + + secs_to_duration(len.saturating_sub(pos) as f64 / sps) + } + + /// The expected total duration (that is, elapsed time + expected ETA) + pub fn duration(&self) -> Duration { + match (self.status, self.len) { + (Status::DoneVisible(duration) | Status::DoneHidden(duration), _) => duration, + (Status::InProgress, Some(_)) => self.started.elapsed().saturating_add(self.eta()), + (Status::InProgress, None) => Duration::ZERO, + } + } + + /// The number of steps per second + pub fn per_sec(&self) -> f64 { + if let Status::InProgress = self.status { + self.est.steps_per_second(Instant::now()) + } else { + self.pos() as f64 / self.started.elapsed().as_secs_f64() + } + } + + pub fn elapsed(&self) -> Duration { + self.started.elapsed() + } + + pub fn pos(&self) -> u64 { + self.pos.pos.load(Ordering::Relaxed) + } + + pub fn set_pos(&mut self, pos: u64) { + self.pos.set(pos); + } + + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> Option { + self.len + } + + pub fn set_len(&mut self, len: u64) { + self.len = Some(len); + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub(crate) enum TabExpandedString { + NoTabs(Cow<'static, str>), + WithTabs { + original: Cow<'static, str>, + expanded: OnceLock, + tab_width: usize, + }, +} + +impl TabExpandedString { + pub(crate) fn new(s: Cow<'static, str>, tab_width: usize) -> Self { + if !s.contains('\t') { + Self::NoTabs(s) + } else { + Self::WithTabs { + original: s, + tab_width, + expanded: OnceLock::new(), + } + } + } + + pub(crate) fn expanded(&self) -> &str { + match &self { + Self::NoTabs(s) => { + debug_assert!(!s.contains('\t')); + s + } + Self::WithTabs { + original, + tab_width, + expanded, + } => expanded.get_or_init(|| original.replace('\t', &" ".repeat(*tab_width))), + } + } + + pub(crate) fn set_tab_width(&mut self, new_tab_width: usize) { + if let Self::WithTabs { + expanded, + tab_width, + .. + } = self + { + if *tab_width != new_tab_width { + *tab_width = new_tab_width; + expanded.take(); + } + } + } +} + +/// Double-smoothed exponentially weighted estimator +/// +/// This uses an exponentially weighted *time-based* estimator, meaning that it exponentially +/// downweights old data based on its age. The rate at which this occurs is currently a constant +/// value of 15 seconds for 90% weighting. This means that all data older than 15 seconds has a +/// collective weight of 0.1 in the estimate, and all data older than 30 seconds has a collective +/// weight of 0.01, and so on. +/// +/// The primary value exposed by `Estimator` is `steps_per_second`. This value is doubly-smoothed, +/// meaning that is the result of using an exponentially weighted estimator (as described above) to +/// estimate the value of another exponentially weighted estimator, which estimates the value of +/// the raw data. +/// +/// The purpose of this extra smoothing step is to reduce instantaneous fluctations in the estimate +/// when large updates are received. Without this, estimates might have a large spike followed by a +/// slow asymptotic approach to zero (until the next spike). +#[derive(Debug)] +pub(crate) struct Estimator { + smoothed_steps_per_sec: f64, + double_smoothed_steps_per_sec: f64, + prev_steps: u64, + prev_time: Instant, + start_time: Instant, +} + +impl Estimator { + fn new(now: Instant) -> Self { + Self { + smoothed_steps_per_sec: 0.0, + double_smoothed_steps_per_sec: 0.0, + prev_steps: 0, + prev_time: now, + start_time: now, + } + } + + fn record(&mut self, new_steps: u64, now: Instant) { + // sanity check: don't record data if time or steps have not advanced + if new_steps <= self.prev_steps || now <= self.prev_time { + // Reset on backwards seek to prevent breakage from seeking to the end for length determination + // See https://github.com/console-rs/indicatif/issues/480 + if new_steps < self.prev_steps { + self.prev_steps = new_steps; + self.reset(now); + } + return; + } + + let delta_steps = new_steps - self.prev_steps; + let delta_t = duration_to_secs(now - self.prev_time); + + // the rate of steps we saw in this update + let new_steps_per_second = delta_steps as f64 / delta_t; + + // update the estimate: a weighted average of the old estimate and new data + let weight = estimator_weight(delta_t); + self.smoothed_steps_per_sec = + self.smoothed_steps_per_sec * weight + new_steps_per_second * (1.0 - weight); + + // An iterative estimate like `smoothed_steps_per_sec` is supposed to be an exponentially + // weighted average from t=0 back to t=-inf; Since we initialize it to 0, we neglect the + // (non-existent) samples in the weighted average prior to the first one, so the resulting + // average must be normalized. We normalize the single estimate here in order to use it as + // a source for the double smoothed estimate. See comment on normalization in + // `steps_per_second` for details. + let delta_t_start = duration_to_secs(now - self.start_time); + let total_weight = 1.0 - estimator_weight(delta_t_start); + let normalized_smoothed_steps_per_sec = self.smoothed_steps_per_sec / total_weight; + + // determine the double smoothed value (EWA smoothing of the single EWA) + self.double_smoothed_steps_per_sec = self.double_smoothed_steps_per_sec * weight + + normalized_smoothed_steps_per_sec * (1.0 - weight); + + self.prev_steps = new_steps; + self.prev_time = now; + } + + /// Reset the state of the estimator. Once reset, estimates will not depend on any data prior + /// to `now`. This does not reset the stored position of the progress bar. + pub(crate) fn reset(&mut self, now: Instant) { + self.smoothed_steps_per_sec = 0.0; + self.double_smoothed_steps_per_sec = 0.0; + + // only reset prev_time, not prev_steps + self.prev_time = now; + self.start_time = now; + } + + /// Average time per step in seconds, using double exponential smoothing + fn steps_per_second(&self, now: Instant) -> f64 { + // Because the value stored in the Estimator is only updated when the Estimator receives an + // update, this value will become stuck if progress stalls. To return an accurate estimate, + // we determine how much time has passed since the last update, and treat this as a + // pseudo-update with 0 steps. + let delta_t = duration_to_secs(now - self.prev_time); + let reweight = estimator_weight(delta_t); + + // Normalization of estimates: + // + // The raw estimate is a single value (smoothed_steps_per_second) that is iteratively + // updated. At each update, the previous value of the estimate is downweighted according to + // its age, receiving the iterative weight W(t) = 0.1 ^ (t/15). + // + // Since W(Sum(t_n)) = Prod(W(t_n)), the total weight of a sample after a series of + // iterative steps is simply W(t_e) - W(t_b), where t_e is the time since the end of the + // sample, and t_b is the time since the beginning. The resulting estimate is therefore a + // weighted average with sample weights W(t_e) - W(t_b). + // + // Notice that the weighting function generates sample weights that sum to 1 only when the + // sample times span from t=0 to t=inf; but this is not the case. We have a first sample + // with finite, positive t_b = t_f. In the raw estimate, we handle times prior to t_f by + // setting an initial value of 0, meaning that these (non-existent) samples have no weight. + // + // Therefore, the raw estimate must be normalized by dividing it by the sum of the weights + // in the weighted average. This sum is just W(0) - W(t_f), where t_f is the time since the + // first sample, and W(0) = 1. + let delta_t_start = duration_to_secs(now - self.start_time); + let total_weight = 1.0 - estimator_weight(delta_t_start); + + // Generate updated values for `smoothed_steps_per_sec` and `double_smoothed_steps_per_sec` + // (sps and dsps) without storing them. Note that we normalize sps when using it as a + // source to update dsps, and then normalize dsps itself before returning it. + let sps = self.smoothed_steps_per_sec * reweight / total_weight; + let dsps = self.double_smoothed_steps_per_sec * reweight + sps * (1.0 - reweight); + dsps / total_weight + } +} + +pub(crate) struct AtomicPosition { + pub(crate) pos: AtomicU64, + capacity: AtomicU8, + prev: AtomicU64, + start: Instant, +} + +impl AtomicPosition { + pub(crate) fn new() -> Self { + Self { + pos: AtomicU64::new(0), + capacity: AtomicU8::new(MAX_BURST), + prev: AtomicU64::new(0), + start: Instant::now(), + } + } + + pub(crate) fn allow(&self, now: Instant) -> bool { + if now < self.start { + return false; + } + + let mut capacity = self.capacity.load(Ordering::Acquire); + // `prev` is the number of ns after `self.started` we last returned `true` + let prev = self.prev.load(Ordering::Acquire); + // `elapsed` is the number of ns since `self.started` + let elapsed = (now - self.start).as_nanos() as u64; + // `diff` is the number of ns since we last returned `true` + let diff = elapsed.saturating_sub(prev); + + // If `capacity` is 0 and not enough time (1ms) has passed since `prev` + // to add new capacity, return `false`. The goal of this method is to + // make this decision as efficient as possible. + if capacity == 0 && diff < INTERVAL { + return false; + } + + // We now calculate `new`, the number of INTERVALs since we last returned `true`, + // and `remainder`, which represents a number of ns less than INTERVAL which we cannot + // convert into capacity now, so we're saving it for later. We do this by + // subtracting this from `elapsed` before storing it into `self.prev`. + let (new, remainder) = ((diff / INTERVAL), (diff % INTERVAL)); + // We add `new` to `capacity`, subtract one for returning `true` from here, + // then make sure it does not exceed a maximum of `MAX_BURST`. + capacity = Ord::min(MAX_BURST as u128, (capacity as u128) + (new as u128) - 1) as u8; + + // Then, we just store `capacity` and `prev` atomically for the next iteration + self.capacity.store(capacity, Ordering::Release); + self.prev.store(elapsed - remainder, Ordering::Release); + true + } + + fn reset(&self, now: Instant) { + self.set(0); + let elapsed = (now.saturating_duration_since(self.start)).as_nanos() as u64; + self.prev.store(elapsed, Ordering::Release); + } + + pub(crate) fn inc(&self, delta: u64) { + self.pos.fetch_add(delta, Ordering::SeqCst); + } + + pub(crate) fn dec(&self, delta: u64) { + self.pos.fetch_sub(delta, Ordering::SeqCst); + } + + pub(crate) fn set(&self, pos: u64) { + self.pos.store(pos, Ordering::Release); + } +} + +const INTERVAL: u64 = 1_000_000; +const MAX_BURST: u8 = 10; + +/// Behavior of a progress bar when it is finished +/// +/// This is invoked when a [`ProgressBar`] or [`ProgressBarIter`] completes and +/// [`ProgressBar::is_finished`] is false. +/// +/// [`ProgressBar`]: crate::ProgressBar +/// [`ProgressBarIter`]: crate::ProgressBarIter +/// [`ProgressBar::is_finished`]: crate::ProgressBar::is_finished +#[derive(Clone, Debug, Default)] +pub enum ProgressFinish { + /// Finishes the progress bar and leaves the current message + /// + /// Same behavior as calling [`ProgressBar::finish()`](crate::ProgressBar::finish). + AndLeave, + /// Finishes the progress bar and sets a message + /// + /// Same behavior as calling [`ProgressBar::finish_with_message()`](crate::ProgressBar::finish_with_message). + WithMessage(Cow<'static, str>), + /// Finishes the progress bar and completely clears it (this is the default) + /// + /// Same behavior as calling [`ProgressBar::finish_and_clear()`](crate::ProgressBar::finish_and_clear). + #[default] + AndClear, + /// Finishes the progress bar and leaves the current message and progress + /// + /// Same behavior as calling [`ProgressBar::abandon()`](crate::ProgressBar::abandon). + Abandon, + /// Finishes the progress bar and sets a message, and leaves the current progress + /// + /// Same behavior as calling [`ProgressBar::abandon_with_message()`](crate::ProgressBar::abandon_with_message). + AbandonWithMessage(Cow<'static, str>), +} + +/// Get the appropriate dilution weight for Estimator data given the data's age (in seconds) +/// +/// Whenever an update occurs, we will create a new estimate using a weight `w_i` like so: +/// +/// ```math +/// = * w_i + * (1 - w_i) +/// ``` +/// +/// In other words, the new estimate is a weighted average of the previous estimate and the new +/// data. We want to choose weights such that for any set of samples where `t_0, t_1, ...` are +/// the durations of the samples: +/// +/// ```math +/// Sum(t_i) = ews ==> Prod(w_i) = 0.1 +/// ``` +/// +/// With this constraint it is easy to show that +/// +/// ```math +/// w_i = 0.1 ^ (t_i / ews) +/// ``` +/// +/// Notice that the constraint implies that estimates are independent of the durations of the +/// samples, a very useful feature. +fn estimator_weight(age: f64) -> f64 { + const EXPONENTIAL_WEIGHTING_SECONDS: f64 = 15.0; + 0.1_f64.powf(age / EXPONENTIAL_WEIGHTING_SECONDS) +} + +fn duration_to_secs(d: Duration) -> f64 { + d.as_secs() as f64 + f64::from(d.subsec_nanos()) / 1_000_000_000f64 +} + +fn secs_to_duration(s: f64) -> Duration { + let secs = s.trunc() as u64; + let nanos = (s.fract() * 1_000_000_000f64) as u32; + Duration::new(secs, nanos) +} + +#[derive(Debug, Clone, Copy)] +pub(crate) enum Status { + InProgress, + DoneVisible(Duration), + DoneHidden(Duration), +} + +pub(crate) const DEFAULT_TAB_WIDTH: usize = 8; + +#[cfg(test)] +mod tests { + use super::*; + use crate::ProgressBar; + + // https://github.com/rust-lang/rust-clippy/issues/10281 + #[allow(clippy::uninlined_format_args)] + #[test] + fn test_steps_per_second() { + let test_rate = |items_per_second| { + let mut now = Instant::now(); + let mut est = Estimator::new(now); + let mut pos = 0; + + for _ in 0..20 { + pos += items_per_second; + now += Duration::from_secs(1); + est.record(pos, now); + } + let avg_steps_per_second = est.steps_per_second(now); + + assert!(avg_steps_per_second > 0.0); + assert!(avg_steps_per_second.is_finite()); + + let absolute_error = (avg_steps_per_second - items_per_second as f64).abs(); + let relative_error = absolute_error / items_per_second as f64; + assert!( + relative_error < 1.0 / 1e9, + "Expected rate: {}, actual: {}, relative error: {}", + items_per_second, + avg_steps_per_second, + relative_error + ); + }; + + test_rate(1); + test_rate(1_000); + test_rate(1_000_000); + test_rate(1_000_000_000); + test_rate(1_000_000_001); + test_rate(100_000_000_000); + test_rate(1_000_000_000_000); + test_rate(100_000_000_000_000); + test_rate(1_000_000_000_000_000); + } + + #[test] + fn test_double_exponential_ave() { + let mut now = Instant::now(); + let mut est = Estimator::new(now); + let mut pos = 0; + + // note: this is the default weight set in the Estimator + let weight = 15; + + for _ in 0..weight { + pos += 1; + now += Duration::from_secs(1); + est.record(pos, now); + } + now += Duration::from_secs(weight); + + // The first level EWA: + // -> 90% weight @ 0 eps, 9% weight @ 1 eps, 1% weight @ 0 eps + // -> then normalized by deweighting the 1% weight (before -30 seconds) + let single_target = 0.09 / 0.99; + + // The second level EWA: + // -> same logic as above, but using the first level EWA as the source + let double_target = (0.9 * single_target + 0.09) / 0.99; + assert_eq!(est.steps_per_second(now), double_target); + } + + #[test] + fn test_estimator_rewind_position() { + let mut now = Instant::now(); + let mut est = Estimator::new(now); + + now += Duration::from_secs(1); + est.record(1, now); + + // should not panic + now += Duration::from_secs(1); + est.record(0, now); + + // check that reset occurred (estimator at 1 event per sec) + now += Duration::from_secs(1); + est.record(1, now); + assert_eq!(est.steps_per_second(now), 1.0); + + // check that progress bar handles manual seeking + let pb = ProgressBar::hidden(); + pb.set_length(10); + pb.set_position(1); + pb.tick(); + // Should not panic. + pb.set_position(0); + } + + #[test] + fn test_reset_eta() { + let mut now = Instant::now(); + let mut est = Estimator::new(now); + + // two per second, then reset + now += Duration::from_secs(1); + est.record(2, now); + est.reset(now); + + // now one per second, and verify + now += Duration::from_secs(1); + est.record(3, now); + assert_eq!(est.steps_per_second(now), 1.0); + } + + #[test] + fn test_duration_stuff() { + let duration = Duration::new(42, 100_000_000); + let secs = duration_to_secs(duration); + assert_eq!(secs_to_duration(secs), duration); + } + + #[test] + fn test_duration_after_finish_and_leave() { + let duration = Duration::from_secs(42); + let now = Instant::now(); + + let mut state = state_started_at(now - duration); + state.finish_using_style(now, ProgressFinish::AndLeave); + + assert_eq!( + state.state.duration(), + duration, + "Expected duration: {}, actual: {}", + duration_to_secs(duration), + duration_to_secs(state.state.duration()) + ); + } + + #[test] + fn test_duration_after_finish_and_clear() { + let duration = Duration::from_secs(42); + let now = Instant::now(); + + let mut state = state_started_at(now - duration); + state.finish_using_style(now, ProgressFinish::AndClear); + + assert_eq!( + state.state.duration(), + duration, + "Expected duration: {}, actual: {}", + duration_to_secs(duration), + duration_to_secs(state.state.duration()) + ); + } + + fn state_started_at(started: Instant) -> BarState { + BarState { + draw_target: ProgressDrawTarget::hidden(), + on_finish: ProgressFinish::default(), + style: ProgressStyle::default_bar(), + state: { + ProgressState { + pos: Arc::new(AtomicPosition::new()), + len: None, + tick: 0, + status: Status::InProgress, + started, + est: Estimator::new(started), + message: TabExpandedString::NoTabs("".into()), + prefix: TabExpandedString::NoTabs("".into()), + } + }, + tab_width: DEFAULT_TAB_WIDTH, + } + } + + #[test] + fn test_atomic_position_large_time_difference() { + let atomic_position = AtomicPosition::new(); + let later = atomic_position.start + Duration::from_nanos(INTERVAL * u64::from(u8::MAX)); + // Should not panic. + atomic_position.allow(later); + } + + #[test] + fn test_atomic_position_reset() { + const ELAPSE_TIME: Duration = Duration::from_millis(20); + let mut pos = AtomicPosition::new(); + pos.reset(pos.start + ELAPSE_TIME); + + // prev should be exactly ELAPSE_TIME after reset + assert_eq!(*pos.pos.get_mut(), 0); + assert_eq!(*pos.prev.get_mut(), ELAPSE_TIME.as_nanos() as u64); + } +} diff --git a/anneal/v2/vendor/indicatif/src/style.rs b/anneal/v2/vendor/indicatif/src/style.rs new file mode 100644 index 0000000000..939fa4e67b --- /dev/null +++ b/anneal/v2/vendor/indicatif/src/style.rs @@ -0,0 +1,1181 @@ +use std::collections::HashMap; +use std::fmt::{self, Formatter, Write}; +use std::mem; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; +#[cfg(feature = "unicode-width")] +use unicode_width::UnicodeWidthChar; + +use console::{measure_text_width, AnsiCodeIterator, Style}; +#[cfg(feature = "unicode-segmentation")] +use unicode_segmentation::UnicodeSegmentation; +#[cfg(all(target_arch = "wasm32", feature = "wasmbind"))] +use web_time::Instant; + +use crate::draw_target::LineType; +use crate::format::{ + BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration, + HumanFloatCount, +}; +use crate::state::{ProgressState, TabExpandedString, DEFAULT_TAB_WIDTH}; + +#[derive(Clone)] +pub struct ProgressStyle { + tick_strings: Vec>, + progress_chars: Vec>, + template: Template, + // how unicode-big each char in progress_chars is + char_width: usize, + tab_width: usize, + pub(crate) format_map: HashMap<&'static str, Box>, +} + +#[cfg(feature = "unicode-segmentation")] +fn segment(s: &str) -> Vec> { + UnicodeSegmentation::graphemes(s, true) + .map(|s| s.into()) + .collect() +} + +#[cfg(not(feature = "unicode-segmentation"))] +fn segment(s: &str) -> Vec> { + s.chars().map(|x| x.to_string().into()).collect() +} + +#[cfg(feature = "unicode-width")] +fn measure(s: &str) -> usize { + unicode_width::UnicodeWidthStr::width(s) +} + +#[cfg(not(feature = "unicode-width"))] +fn measure(s: &str) -> usize { + s.chars().count() +} + +/// finds the unicode-aware width of the passed grapheme cluters +/// panics on an empty parameter, or if the characters are not equal-width +fn width(c: &[Box]) -> usize { + c.iter() + .map(|s| measure(s.as_ref())) + .fold(None, |acc, new| { + match acc { + None => return Some(new), + Some(old) => assert_eq!(old, new, "got passed un-equal width progress characters"), + } + acc + }) + .unwrap() +} + +impl ProgressStyle { + /// Returns the default progress bar style for bars + pub fn default_bar() -> Self { + Self::new(Template::from_str("{wide_bar} {pos}/{len}").unwrap()) + } + + /// Returns the default progress bar style for spinners + pub fn default_spinner() -> Self { + Self::new(Template::from_str("{spinner} {msg}").unwrap()) + } + + /// Sets the template string for the progress bar + /// + /// Review the [list of template keys](../index.html#templates) for more information. + pub fn with_template(template: &str) -> Result { + Ok(Self::new(Template::from_str(template)?)) + } + + pub(crate) fn set_tab_width(&mut self, new_tab_width: usize) { + self.tab_width = new_tab_width; + self.template.set_tab_width(new_tab_width); + } + + /// Specifies that the progress bar is intended to be printed to stderr + /// + /// The progress bar will determine whether to enable/disable colors based on stderr + /// instead of stdout. Under the hood, this uses [`console::colors_enabled_stderr`]. + pub(crate) fn set_for_stderr(&mut self) { + for part in &mut self.template.parts { + let (style, alt_style) = match part { + TemplatePart::Placeholder { + style, alt_style, .. + } => (style, alt_style), + _ => continue, + }; + if let Some(s) = style.take() { + *style = Some(s.for_stderr()) + } + if let Some(s) = alt_style.take() { + *alt_style = Some(s.for_stderr()) + } + } + } + + fn new(template: Template) -> Self { + let progress_chars = segment("█░"); + let char_width = width(&progress_chars); + Self { + tick_strings: "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈ " + .chars() + .map(|c| c.to_string().into()) + .collect(), + progress_chars, + char_width, + template, + format_map: HashMap::default(), + tab_width: DEFAULT_TAB_WIDTH, + } + } + + /// Sets the tick character sequence for spinners + /// + /// Note that the last character is used as the [final tick string][Self::get_final_tick_str()]. + /// At least two characters are required to provide a non-final and final state. + pub fn tick_chars(mut self, s: &str) -> Self { + self.tick_strings = s.chars().map(|c| c.to_string().into()).collect(); + // Format bar will panic with some potentially confusing message, better to panic here + // with a message explicitly informing of the problem + assert!( + self.tick_strings.len() >= 2, + "at least 2 tick chars required" + ); + self + } + + /// Sets the tick string sequence for spinners + /// + /// Note that the last string is used as the [final tick string][Self::get_final_tick_str()]. + /// At least two strings are required to provide a non-final and final state. + pub fn tick_strings(mut self, s: &[&str]) -> Self { + self.tick_strings = s.iter().map(|s| s.to_string().into()).collect(); + // Format bar will panic with some potentially confusing message, better to panic here + // with a message explicitly informing of the problem + assert!( + self.progress_chars.len() >= 2, + "at least 2 tick strings required" + ); + self + } + + /// Sets the progress characters `(filled, current, to do)` + /// + /// You can pass more than three for a more detailed display. + /// All passed grapheme clusters need to be of equal width. + pub fn progress_chars(mut self, s: &str) -> Self { + self.progress_chars = segment(s); + // Format bar will panic with some potentially confusing message, better to panic here + // with a message explicitly informing of the problem + assert!( + self.progress_chars.len() >= 2, + "at least 2 progress chars required" + ); + self.char_width = width(&self.progress_chars); + self + } + + /// Adds a custom key that owns a [`ProgressTracker`] to the template + pub fn with_key(mut self, key: &'static str, f: S) -> Self { + self.format_map.insert(key, Box::new(f)); + self + } + + /// Sets the template string for the progress bar + /// + /// Review the [list of template keys](../index.html#templates) for more information. + pub fn template(mut self, s: &str) -> Result { + self.template = Template::from_str(s)?; + Ok(self) + } + + fn current_tick_str(&self, state: &ProgressState) -> &str { + match state.is_finished() { + true => self.get_final_tick_str(), + false => self.get_tick_str(state.tick), + } + } + + /// Returns the tick string for a given number + pub fn get_tick_str(&self, idx: u64) -> &str { + &self.tick_strings[(idx as usize) % (self.tick_strings.len() - 1)] + } + + /// Returns the tick string for the finished state + pub fn get_final_tick_str(&self) -> &str { + &self.tick_strings[self.tick_strings.len() - 1] + } + + fn format_bar(&self, fract: f32, width: usize, alt_style: Option<&Style>) -> BarDisplay<'_> { + // The number of clusters from progress_chars to write (rounding down). + let width = width / self.char_width; + // The number of full clusters (including a fractional component for a partially-full one). + let fill = fract * width as f32; + // The number of entirely full clusters (by truncating `fill`). + let entirely_filled = fill as usize; + + // if the bar is not entirely empty or full (meaning we need to draw the "current" + // character between the filled and "to do" segment) + let cur = if fill > 0.0 && entirely_filled < width { + // Number of fine-grained progress entries in progress_chars. + let n = self.progress_chars.len().saturating_sub(2); + match n { + // We have no "current" entries, so simply skip drawing it + 0 => None, + // We only have a single "current" entry, so choose this one + 1 => Some(1), + // Pick a fine-grained entry, ranging from the last one (n) if the fractional part + // of fill is 0 to the first one (1) if the fractional part of fill is almost 1. + _ => Some(n.saturating_sub((fill.fract() * n as f32) as usize)), + } + } else { + None + }; + + // Number of entirely empty clusters needed to fill the bar up to `width`. + let bg = width + .saturating_sub(entirely_filled) + .saturating_sub(cur.is_some() as usize); + let rest = RepeatedStringDisplay { + str: &self.progress_chars[self.progress_chars.len() - 1], + num: bg, + }; + + BarDisplay { + chars: &self.progress_chars, + filled: entirely_filled, + cur, + rest: alt_style.unwrap_or(&Style::new()).apply_to(rest), + } + } + + pub(crate) fn format_state( + &self, + state: &ProgressState, + lines: &mut Vec, + target_width: u16, + ) { + let mut cur = String::new(); + let mut buf = String::new(); + let mut wide = None; + + let pos = state.pos(); + let len = state.len().unwrap_or(pos); + for part in &self.template.parts { + match part { + TemplatePart::Placeholder { + key, + align, + width, + truncate, + style, + alt_style, + } => { + buf.clear(); + if let Some(tracker) = self.format_map.get(key.as_str()) { + tracker.write(state, &mut TabRewriter(&mut buf, self.tab_width)); + } else { + match key.as_str() { + "wide_bar" => { + wide = Some(WideElement::Bar { alt_style }); + buf.push('\x00'); + } + "bar" => buf + .write_fmt(format_args!( + "{}", + self.format_bar( + state.fraction(), + width.unwrap_or(20) as usize, + alt_style.as_ref(), + ) + )) + .unwrap(), + "spinner" => buf.push_str(self.current_tick_str(state)), + "wide_msg" => { + wide = Some(WideElement::Message { align }); + buf.push('\x00'); + } + "msg" => buf.push_str(state.message.expanded()), + "prefix" => buf.push_str(state.prefix.expanded()), + "pos" => buf.write_fmt(format_args!("{pos}")).unwrap(), + "human_pos" => { + buf.write_fmt(format_args!("{}", HumanCount(pos))).unwrap(); + } + "len" => buf.write_fmt(format_args!("{len}")).unwrap(), + "human_len" => { + buf.write_fmt(format_args!("{}", HumanCount(len))).unwrap(); + } + "percent" => buf + .write_fmt(format_args!("{:.*}", 0, state.fraction() * 100f32)) + .unwrap(), + "percent_precise" => buf + .write_fmt(format_args!("{:.*}", 3, state.fraction() * 100f32)) + .unwrap(), + "bytes" => buf.write_fmt(format_args!("{}", HumanBytes(pos))).unwrap(), + "total_bytes" => { + buf.write_fmt(format_args!("{}", HumanBytes(len))).unwrap(); + } + "decimal_bytes" => buf + .write_fmt(format_args!("{}", DecimalBytes(pos))) + .unwrap(), + "decimal_total_bytes" => buf + .write_fmt(format_args!("{}", DecimalBytes(len))) + .unwrap(), + "binary_bytes" => { + buf.write_fmt(format_args!("{}", BinaryBytes(pos))).unwrap(); + } + "binary_total_bytes" => { + buf.write_fmt(format_args!("{}", BinaryBytes(len))).unwrap(); + } + "elapsed_precise" => buf + .write_fmt(format_args!("{}", FormattedDuration(state.elapsed()))) + .unwrap(), + "elapsed" => buf + .write_fmt(format_args!("{:#}", HumanDuration(state.elapsed()))) + .unwrap(), + "per_sec" => { + if let Some(width) = width { + buf.write_fmt(format_args!( + "{:.1$}/s", + HumanFloatCount(state.per_sec()), + *width as usize + )) + .unwrap(); + } else { + buf.write_fmt(format_args!( + "{}/s", + HumanFloatCount(state.per_sec()) + )) + .unwrap(); + } + } + "bytes_per_sec" => buf + .write_fmt(format_args!("{}/s", HumanBytes(state.per_sec() as u64))) + .unwrap(), + "decimal_bytes_per_sec" => buf + .write_fmt(format_args!( + "{}/s", + DecimalBytes(state.per_sec() as u64) + )) + .unwrap(), + "binary_bytes_per_sec" => buf + .write_fmt(format_args!( + "{}/s", + BinaryBytes(state.per_sec() as u64) + )) + .unwrap(), + "eta_precise" => buf + .write_fmt(format_args!("{}", FormattedDuration(state.eta()))) + .unwrap(), + "eta" => buf + .write_fmt(format_args!("{:#}", HumanDuration(state.eta()))) + .unwrap(), + "duration_precise" => buf + .write_fmt(format_args!("{}", FormattedDuration(state.duration()))) + .unwrap(), + "duration" => buf + .write_fmt(format_args!("{:#}", HumanDuration(state.duration()))) + .unwrap(), + _ => (), + } + }; + + match width { + Some(width) => { + let padded = PaddedStringDisplay { + str: &buf, + width: *width as usize, + align: *align, + truncate: *truncate, + }; + match style { + Some(s) => cur + .write_fmt(format_args!("{}", s.apply_to(padded))) + .unwrap(), + None => cur.write_fmt(format_args!("{padded}")).unwrap(), + } + } + None => match style { + Some(s) => cur.write_fmt(format_args!("{}", s.apply_to(&buf))).unwrap(), + None => cur.push_str(&buf), + }, + } + } + TemplatePart::Literal(s) => cur.push_str(s.expanded()), + TemplatePart::NewLine => { + self.push_line(lines, &mut cur, state, &mut buf, target_width, &wide); + } + } + } + + if !cur.is_empty() { + self.push_line(lines, &mut cur, state, &mut buf, target_width, &wide); + } + } + + /// This is used exclusively to add the bars built above to the lines to print + fn push_line( + &self, + lines: &mut Vec, + cur: &mut String, + state: &ProgressState, + buf: &mut String, + target_width: u16, + wide: &Option, + ) { + let expanded = match wide { + Some(inner) => inner.expand(mem::take(cur), self, state, buf, target_width), + None => mem::take(cur), + }; + + // If there are newlines, we need to split them up + // and add the lines separately so that they're counted + // correctly on re-render. + for (i, line) in expanded.split('\n').enumerate() { + // No newlines found in this case + if i == 0 && line.len() == expanded.len() { + lines.push(LineType::Bar(expanded)); + break; + } + + lines.push(LineType::Bar(line.to_string())); + } + } +} + +struct TabRewriter<'a>(&'a mut dyn fmt::Write, usize); + +impl Write for TabRewriter<'_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0 + .write_str(s.replace('\t', &" ".repeat(self.1)).as_str()) + } +} + +#[derive(Clone, Copy)] +enum WideElement<'a> { + Bar { alt_style: &'a Option

for Utf8PathBuf { + fn from_iter>(iter: I) -> Utf8PathBuf { + let mut buf = Utf8PathBuf::new(); + buf.extend(iter); + buf + } +} + +// --- +// [Partial]Eq, [Partial]Ord, Hash +// --- + +impl PartialEq for Utf8PathBuf { + #[inline] + fn eq(&self, other: &Utf8PathBuf) -> bool { + self.components() == other.components() + } +} + +impl Eq for Utf8PathBuf {} + +impl Hash for Utf8PathBuf { + #[inline] + fn hash(&self, state: &mut H) { + self.as_path().hash(state) + } +} + +impl PartialOrd for Utf8PathBuf { + #[inline] + fn partial_cmp(&self, other: &Utf8PathBuf) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Utf8PathBuf { + fn cmp(&self, other: &Utf8PathBuf) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl PartialEq for Utf8Path { + #[inline] + fn eq(&self, other: &Utf8Path) -> bool { + self.components().eq(other.components()) + } +} + +impl Eq for Utf8Path {} + +impl Hash for Utf8Path { + fn hash(&self, state: &mut H) { + for component in self.components() { + component.hash(state) + } + } +} + +impl PartialOrd for Utf8Path { + #[inline] + fn partial_cmp(&self, other: &Utf8Path) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Utf8Path { + fn cmp(&self, other: &Utf8Path) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl<'a> IntoIterator for &'a Utf8PathBuf { + type Item = &'a str; + type IntoIter = Iter<'a>; + #[inline] + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +impl<'a> IntoIterator for &'a Utf8Path { + type Item = &'a str; + type IntoIter = Iter<'a>; + #[inline] + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +macro_rules! impl_cmp { + ($lhs:ty, $rhs: ty) => { + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + ::eq(self, other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + ::eq(self, other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + ::partial_cmp(self, other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + ::partial_cmp(self, other) + } + } + }; +} + +impl_cmp!(Utf8PathBuf, Utf8Path); +impl_cmp!(Utf8PathBuf, &'a Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, &'b Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8PathBuf); + +macro_rules! impl_cmp_std_path { + ($lhs:ty, $rhs: ty) => { + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + ::eq(self.as_ref(), other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + ::eq(self, other.as_ref()) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + ::partial_cmp(self.as_ref(), other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + ::partial_cmp(self, other.as_ref()) + } + } + }; +} + +impl_cmp_std_path!(Utf8PathBuf, Path); +impl_cmp_std_path!(Utf8PathBuf, &'a Path); +impl_cmp_std_path!(Utf8PathBuf, Cow<'a, Path>); +impl_cmp_std_path!(Utf8PathBuf, PathBuf); +impl_cmp_std_path!(Utf8Path, Path); +impl_cmp_std_path!(Utf8Path, &'a Path); +impl_cmp_std_path!(Utf8Path, Cow<'a, Path>); +impl_cmp_std_path!(Utf8Path, PathBuf); +impl_cmp_std_path!(&'a Utf8Path, Path); +impl_cmp_std_path!(&'a Utf8Path, Cow<'b, Path>); +impl_cmp_std_path!(&'a Utf8Path, PathBuf); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_str { + ($lhs:ty, $rhs: ty) => { + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + ::eq(self, Utf8Path::new(other)) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + ::eq(Utf8Path::new(self), other) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + ::partial_cmp(self, Utf8Path::new(other)) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + ::partial_cmp(Utf8Path::new(self), other) + } + } + }; +} + +impl_cmp_str!(Utf8PathBuf, str); +impl_cmp_str!(Utf8PathBuf, &'a str); +impl_cmp_str!(Utf8PathBuf, Cow<'a, str>); +impl_cmp_str!(Utf8PathBuf, String); +impl_cmp_str!(Utf8Path, str); +impl_cmp_str!(Utf8Path, &'a str); +impl_cmp_str!(Utf8Path, Cow<'a, str>); +impl_cmp_str!(Utf8Path, String); +impl_cmp_str!(&'a Utf8Path, str); +impl_cmp_str!(&'a Utf8Path, Cow<'b, str>); +impl_cmp_str!(&'a Utf8Path, String); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_os_str { + ($lhs:ty, $rhs: ty) => { + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + ::eq(self.as_ref(), other.as_ref()) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + ::eq(self.as_ref(), other.as_ref()) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option { + ::partial_cmp(self.as_ref(), other.as_ref()) + } + } + + #[allow(clippy::extra_unused_lifetimes)] + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option { + ::partial_cmp(self.as_ref(), other.as_ref()) + } + } + }; +} + +impl_cmp_os_str!(Utf8PathBuf, OsStr); +impl_cmp_os_str!(Utf8PathBuf, &'a OsStr); +impl_cmp_os_str!(Utf8PathBuf, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8PathBuf, OsString); +impl_cmp_os_str!(Utf8Path, OsStr); +impl_cmp_os_str!(Utf8Path, &'a OsStr); +impl_cmp_os_str!(Utf8Path, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8Path, OsString); +impl_cmp_os_str!(&'a Utf8Path, OsStr); +impl_cmp_os_str!(&'a Utf8Path, Cow<'b, OsStr>); +impl_cmp_os_str!(&'a Utf8Path, OsString); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +/// Makes the path absolute without accessing the filesystem, converting it to a [`Utf8PathBuf`]. +/// +/// If the path is relative, the current directory is used as the base directory. All intermediate +/// components will be resolved according to platform-specific rules, but unlike +/// [`canonicalize`][Utf8Path::canonicalize] or [`canonicalize_utf8`](Utf8Path::canonicalize_utf8), +/// this does not resolve symlinks and may succeed even if the path does not exist. +/// +/// *Requires Rust 1.79 or newer.* +/// +/// # Errors +/// +/// Errors if: +/// +/// * The path is empty. +/// * The [current directory][std::env::current_dir] cannot be determined. +/// * The path is not valid UTF-8. +/// +/// # Examples +/// +/// ## POSIX paths +/// +/// ``` +/// # #[cfg(unix)] +/// fn main() -> std::io::Result<()> { +/// use camino::Utf8Path; +/// +/// // Relative to absolute +/// let absolute = camino::absolute_utf8("foo/./bar")?; +/// assert!(absolute.ends_with("foo/bar")); +/// +/// // Absolute to absolute +/// let absolute = camino::absolute_utf8("/foo//test/.././bar.rs")?; +/// assert_eq!(absolute, Utf8Path::new("/foo/test/../bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(unix))] +/// # fn main() {} +/// ``` +/// +/// The path is resolved using [POSIX semantics][posix-semantics] except that it stops short of +/// resolving symlinks. This means it will keep `..` components and trailing slashes. +/// +/// ## Windows paths +/// +/// ``` +/// # #[cfg(windows)] +/// fn main() -> std::io::Result<()> { +/// use camino::Utf8Path; +/// +/// // Relative to absolute +/// let absolute = camino::absolute_utf8("foo/./bar")?; +/// assert!(absolute.ends_with(r"foo\bar")); +/// +/// // Absolute to absolute +/// let absolute = camino::absolute_utf8(r"C:\foo//test\..\./bar.rs")?; +/// +/// assert_eq!(absolute, Utf8Path::new(r"C:\foo\bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(windows))] +/// # fn main() {} +/// ``` +/// +/// For verbatim paths this will simply return the path as given. For other paths this is currently +/// equivalent to calling [`GetFullPathNameW`][windows-path]. +/// +/// Note that this [may change in the future][changes]. +/// +/// [changes]: io#platform-specific-behavior +/// [posix-semantics]: +/// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 +/// [windows-path]: +/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew +#[cfg(absolute_path)] +pub fn absolute_utf8>(path: P) -> io::Result { + // Note that even if the passed in path is valid UTF-8, it is not guaranteed + // that the absolute path will be valid UTF-8. For example, the current + // directory may not be valid UTF-8. + // + // That's why we take `AsRef` instead of `AsRef` here -- we + // have to pay the cost of checking for valid UTF-8 anyway. + let path = path.as_ref(); + #[allow(clippy::incompatible_msrv)] + Utf8PathBuf::try_from(std::path::absolute(path)?).map_err(|error| error.into_io_error()) +} + +// invariant: OsStr must be guaranteed to be utf8 data +#[inline] +unsafe fn str_assume_utf8(string: &OsStr) -> &str { + #[cfg(os_str_bytes)] + { + // SAFETY: OsStr is guaranteed to be utf8 data from the invariant + unsafe { + std::str::from_utf8_unchecked( + #[allow(clippy::incompatible_msrv)] + string.as_encoded_bytes(), + ) + } + } + #[cfg(not(os_str_bytes))] + { + // Adapted from the source code for Option::unwrap_unchecked. + match string.to_str() { + Some(val) => val, + None => std::hint::unreachable_unchecked(), + } + } +} diff --git a/anneal/v2/vendor/camino/src/proptest_impls.rs b/anneal/v2/vendor/camino/src/proptest_impls.rs new file mode 100644 index 0000000000..64dbe25670 --- /dev/null +++ b/anneal/v2/vendor/camino/src/proptest_impls.rs @@ -0,0 +1,60 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! [proptest::Arbitrary](Arbitrary) implementation for `Utf8PathBuf` and `Box`. Note +//! that implementations for `Rc` and `Arc` are not currently possible due to +//! orphan rules - this crate doesn't define `Rc`/`Arc` nor `Arbitrary`, so it can't define those +//! implementations. + +// NOTE: #[cfg(feature = "proptest1")] is specified here to work with `doc_cfg`. + +use crate::{Utf8Path, Utf8PathBuf}; +use proptest::{arbitrary::StrategyFor, prelude::*, strategy::MapInto}; + +/// The [`Arbitrary`] impl for `Utf8PathBuf` returns a path with between 0 and 8 components, +/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is +/// randomly generated, and may itself contain one or more separators.) +/// +/// On Unix, this generates an absolute path half of the time and a relative path the other half. +/// +/// On Windows, this implementation doesn't currently generate +/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might. +#[cfg(feature = "proptest1")] +impl Arbitrary for Utf8PathBuf { + type Parameters = ::Parameters; + type Strategy = BoxedStrategy; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + ( + any::(), + prop::collection::vec(any_with::(args), 0..8), + ) + .prop_map(|(is_relative, components)| { + let initial_component = if is_relative { + Some(format!("{}", std::path::MAIN_SEPARATOR)) + } else { + None + }; + initial_component.into_iter().chain(components).collect() + }) + .boxed() + } +} + +/// The [`Arbitrary`] impl for `Box` returns a path with between 0 and 8 components, +/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is +/// randomly generated, and may itself contain one or more separators.) +/// +/// On Unix, this generates an absolute path half of the time and a relative path the other half. +/// +/// On Windows, this implementation doesn't currently generate +/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might. +#[cfg(feature = "proptest1")] +impl Arbitrary for Box { + type Parameters = ::Parameters; + type Strategy = MapInto, Self>; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + any_with::(args).prop_map_into() + } +} diff --git a/anneal/v2/vendor/camino/src/serde_impls.rs b/anneal/v2/vendor/camino/src/serde_impls.rs new file mode 100644 index 0000000000..4e838bbd83 --- /dev/null +++ b/anneal/v2/vendor/camino/src/serde_impls.rs @@ -0,0 +1,276 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Serde implementations for the types in this crate. +//! +//! * `Utf8Path` is an unsized type which the derive impls can't handle. +//! * `Utf8PathBuf` could be derived, but we don't depend on serde_derive to +//! improve compile times. It's also very straightforward to implement. + +use crate::{Utf8Path, Utf8PathBuf}; +use serde_core::{Deserialize, Deserializer, Serialize, Serializer, de}; +use std::fmt; + +struct Utf8PathBufVisitor; + +impl<'a> de::Visitor<'a> for Utf8PathBufVisitor { + type Value = Utf8PathBuf; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a UTF-8 path string") + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(v.into()) + } + + fn visit_string(self, v: String) -> Result + where + E: de::Error, + { + Ok(v.into()) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + std::str::from_utf8(v) + .map(Into::into) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self)) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: de::Error, + { + String::from_utf8(v) + .map(Into::into) + .map_err(|e| de::Error::invalid_value(de::Unexpected::Bytes(&e.into_bytes()), &self)) + } +} + +impl<'de> Deserialize<'de> for Utf8PathBuf { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_string(Utf8PathBufVisitor) + } +} + +impl Serialize for Utf8PathBuf { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_str().serialize(serializer) + } +} + +struct Utf8PathVisitor; + +impl<'a> de::Visitor<'a> for Utf8PathVisitor { + type Value = &'a Utf8Path; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed UTF-8 path") + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: de::Error, + { + Ok(v.as_ref()) + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: de::Error, + { + std::str::from_utf8(v) + .map(AsRef::as_ref) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self)) + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a Utf8Path { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(Utf8PathVisitor) + } +} + +impl Serialize for Utf8Path { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_str().serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Box { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Utf8PathBuf::deserialize(deserializer)?.into()) + } +} + +// impl Serialize for Box comes from impl Serialize for Utf8Path. + +// Can't provide impls for Arc/Rc due to orphan rule issues, but we could provide +// `with` impls in the future as requested. + +#[cfg(test)] +mod tests { + use super::*; + use crate::Utf8PathBuf; + use serde::{Deserialize, Serialize}; + use serde_bytes::ByteBuf; + + #[test] + fn valid_utf8() { + let valid_utf8 = &["", "bar", "💩"]; + for input in valid_utf8 { + let encode = Encode { + path: ByteBuf::from(*input), + }; + let encoded = bincode::serialize(&encode).expect("encoded correctly"); + + assert_valid_utf8::(input, &encoded); + assert_valid_utf8::(input, &encoded); + assert_valid_utf8::(input, &encoded); + } + } + + fn assert_valid_utf8<'de, T: TestTrait<'de>>(input: &str, encoded: &'de [u8]) { + let output = bincode::deserialize::(encoded).expect("valid UTF-8 should be fine"); + assert_eq!( + output.path(), + input, + "for input, with {}, paths should match", + T::description() + ); + let roundtrip = bincode::serialize(&output).expect("message should roundtrip"); + assert_eq!(roundtrip, encoded, "encoded path matches"); + } + + #[test] + fn invalid_utf8() { + let invalid_utf8: &[(&[u8], _, _)] = &[ + (b"\xff", 0, 1), + (b"foo\xfe", 3, 1), + (b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9", 4, 1), + ]; + + for (input, valid_up_to, error_len) in invalid_utf8 { + let encode = Encode { + path: ByteBuf::from(*input), + }; + let encoded = bincode::serialize(&encode).expect("encoded correctly"); + + assert_invalid_utf8::(input, &encoded, *valid_up_to, *error_len); + assert_invalid_utf8::(input, &encoded, *valid_up_to, *error_len); + assert_invalid_utf8::(input, &encoded, *valid_up_to, *error_len); + } + } + + fn assert_invalid_utf8<'de, T: TestTrait<'de>>( + input: &[u8], + encoded: &'de [u8], + valid_up_to: usize, + error_len: usize, + ) { + let error = bincode::deserialize::(encoded).expect_err("invalid UTF-8 should error out"); + let utf8_error = match *error { + bincode::ErrorKind::InvalidUtf8Encoding(utf8_error) => utf8_error, + other => panic!( + "for input {:?}, with {}, expected ErrorKind::InvalidUtf8Encoding, found: {}", + input, + T::description(), + other + ), + }; + assert_eq!( + utf8_error.valid_up_to(), + valid_up_to, + "for input {:?}, with {}, valid_up_to didn't match", + input, + T::description(), + ); + assert_eq!( + utf8_error.error_len(), + Some(error_len), + "for input {:?}, with {}, error_len didn't match", + input, + T::description(), + ); + } + + #[derive(Serialize, Debug)] + struct Encode { + path: ByteBuf, + } + + trait TestTrait<'de>: Serialize + Deserialize<'de> + fmt::Debug { + fn description() -> &'static str; + fn path(&self) -> &Utf8Path; + } + + #[derive(Serialize, Deserialize, Debug)] + #[allow(unused)] + struct DecodeOwned { + path: Utf8PathBuf, + } + + impl TestTrait<'_> for DecodeOwned { + fn description() -> &'static str { + "DecodeOwned" + } + + fn path(&self) -> &Utf8Path { + &self.path + } + } + + #[derive(Serialize, Deserialize, Debug)] + #[allow(unused)] + struct DecodeBorrowed<'a> { + #[serde(borrow)] + path: &'a Utf8Path, + } + + impl<'de> TestTrait<'de> for DecodeBorrowed<'de> { + fn description() -> &'static str { + "DecodeBorrowed" + } + + fn path(&self) -> &Utf8Path { + self.path + } + } + + #[derive(Serialize, Deserialize, Debug)] + #[allow(unused)] + struct DecodeBoxed { + path: Box, + } + + impl TestTrait<'_> for DecodeBoxed { + fn description() -> &'static str { + "DecodeBoxed" + } + + fn path(&self) -> &Utf8Path { + &self.path + } + } +} diff --git a/anneal/v2/vendor/camino/src/tests.rs b/anneal/v2/vendor/camino/src/tests.rs new file mode 100644 index 0000000000..e84c227af9 --- /dev/null +++ b/anneal/v2/vendor/camino/src/tests.rs @@ -0,0 +1,54 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +// Test that all required impls exist. + +use crate::{Utf8Path, Utf8PathBuf}; +use std::{ + borrow::Cow, + path::{Path, PathBuf}, + rc::Rc, + sync::Arc, +}; + +macro_rules! all_into { + ($t:ty, $x:ident) => { + test_into::<$t, Utf8PathBuf>($x.clone()); + test_into::<$t, Box>($x.clone()); + test_into::<$t, Arc>($x.clone()); + test_into::<$t, Rc>($x.clone()); + test_into::<$t, Cow<'_, Utf8Path>>($x.clone()); + test_into::<$t, PathBuf>($x.clone()); + test_into::<$t, Box>($x.clone()); + test_into::<$t, Arc>($x.clone()); + test_into::<$t, Rc>($x.clone()); + test_into::<$t, Cow<'_, Path>>($x.clone()); + }; +} + +#[test] +fn test_borrowed_into() { + let utf8_path = Utf8Path::new("test/path"); + all_into!(&Utf8Path, utf8_path); +} + +#[test] +fn test_owned_into() { + let utf8_path_buf = Utf8PathBuf::from("test/path"); + all_into!(Utf8PathBuf, utf8_path_buf); +} + +fn test_into(orig: T) +where + T: Into, +{ + let _ = orig.into(); +} + +#[cfg(path_buf_deref_mut)] +#[test] +fn test_deref_mut() { + // This test is mostly for miri. + let mut path_buf = Utf8PathBuf::from("foobar"); + let _: &mut Utf8Path = &mut path_buf; +} diff --git a/anneal/v2/vendor/camino/tests/integration_tests.rs b/anneal/v2/vendor/camino/tests/integration_tests.rs new file mode 100644 index 0000000000..190ba82bab --- /dev/null +++ b/anneal/v2/vendor/camino/tests/integration_tests.rs @@ -0,0 +1,115 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use camino::{Utf8Path, Utf8PathBuf}; +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + path::Path, +}; + +static PATH_CORPUS: &[&str] = &[ + "", + "foo", + "foo/bar", + "foo//bar", + "foo/bar/baz", + "foo/bar/./baz", + "foo/bar/../baz", + "../foo/bar/./../baz", + "/foo", + "/foo/bar", + "/", + "///", + // --- + // Windows-only paths + // --- + #[cfg(windows)] + "foo\\bar", + #[cfg(windows)] + "\\foo\\bar", + #[cfg(windows)] + "C:\\foo", + #[cfg(windows)] + "C:foo\\bar", + #[cfg(windows)] + "C:\\foo\\..\\.\\bar", + #[cfg(windows)] + "\\\\server\\foo\\bar", + #[cfg(windows)] + "\\\\.\\C:\\foo\\bar.txt", +]; + +#[test] +fn test_borrow_eq_ord() { + // Utf8PathBuf implements Borrow so equality and ordering comparisons should + // match. + for (idx, &path1) in PATH_CORPUS.iter().enumerate() { + for &path2 in &PATH_CORPUS[idx..] { + let borrowed1 = Utf8Path::new(path1); + let borrowed2 = Utf8Path::new(path2); + let owned1 = Utf8PathBuf::from(path1); + let owned2 = Utf8PathBuf::from(path2); + + assert_eq!( + borrowed1 == borrowed2, + owned1 == owned2, + "Eq impls match: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + owned1.cmp(&owned2), + "Ord impls match: {} and {}", + borrowed1, + borrowed2 + ); + + // Also check against std paths. + let std1 = Path::new(path1); + let std2 = Path::new(path2); + assert_eq!( + borrowed1, std1, + "Eq between Path and Utf8Path: {}", + borrowed1 + ); + assert_eq!( + borrowed1 == borrowed2, + std1 == std2, + "Eq impl matches Path: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + std1.cmp(std2), + "Ord impl matches Path: {} and {}", + borrowed1, + borrowed2 + ); + } + } +} + +#[test] +fn test_borrow_hash() { + // Utf8PathBuf implements Borrow so hash comparisons should match. + fn hash_output(x: impl Hash) -> u64 { + let mut hasher = DefaultHasher::new(); + x.hash(&mut hasher); + hasher.finish() + } + + for &path in PATH_CORPUS { + let borrowed = Utf8Path::new(path); + let owned = Utf8PathBuf::from(path); + + assert_eq!( + hash_output(owned), + hash_output(borrowed), + "consistent Hash: {}", + borrowed + ); + } +} diff --git a/anneal/v2/vendor/cargo-platform/.cargo-checksum.json b/anneal/v2/vendor/cargo-platform/.cargo-checksum.json new file mode 100644 index 0000000000..21b94fc5bd --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"10f8a9b5b9721e7cc00e0092b54effd6ed8a5d58f57bffc906b1a3ca230fec5c","Cargo.lock":"5e72bdf1ac733320a000f121866c65fda086c24703fd8fd962680cbc242875e8","Cargo.toml":"869332b4f2c865859ab8a09690fc954717ffc8c8dea64b10719c77dd2daf5fe8","Cargo.toml.orig":"5157bff10a516056e4805abd72768f0d8f06450c8716d41c221f29c07e63468e","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"23bb153e6c8585dfac13913a49606eacbb54a44afec4db95b6aafee9f51449dc","examples/matches.rs":"760a95d8b32b7c9d1413e3317e6401c3190c5f42e6fe67790de471abf62f46af","src/cfg.rs":"f0fa5f12226c9358e4838d228f647a1efce72a84c3ae2d4310ce204ddcc21e95","src/error.rs":"1229940c1cd6dde6f56363f787c27007ba62135371bd3c2a3b671172cf0b6d6b","src/lib.rs":"acb0fab77b936f964bdf663fdf7d59565f0419d95a379cf75452dc01cf55c425","tests/test_cfg.rs":"fe366780d02d22ffcbef280fe4c2a27d340a94d8a4f7991990bb98992218d21c"},"package":"dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"} \ No newline at end of file diff --git a/anneal/v2/vendor/cargo-platform/.cargo_vcs_info.json b/anneal/v2/vendor/cargo-platform/.cargo_vcs_info.json new file mode 100644 index 0000000000..a9ad0e4afd --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f2d3ce0bd7f24a49f8f72d9000448f8838c4e850" + }, + "path_in_vcs": "crates/cargo-platform" +} \ No newline at end of file diff --git a/anneal/v2/vendor/cargo-platform/Cargo.lock b/anneal/v2/vendor/cargo-platform/Cargo.lock new file mode 100644 index 0000000000..607dd31b49 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/Cargo.lock @@ -0,0 +1,75 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cargo-platform" +version = "0.3.3" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" diff --git a/anneal/v2/vendor/cargo-platform/Cargo.toml b/anneal/v2/vendor/cargo-platform/Cargo.toml new file mode 100644 index 0000000000..d7d6333cfa --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/Cargo.toml @@ -0,0 +1,67 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +rust-version = "1.91" +name = "cargo-platform" +version = "0.3.3" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Cargo's representation of a target platform." +documentation = "https://docs.rs/cargo-platform" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/cargo" +resolver = "2" + +[lib] +name = "cargo_platform" +path = "src/lib.rs" + +[[example]] +name = "matches" +path = "examples/matches.rs" + +[[test]] +name = "test_cfg" +path = "tests/test_cfg.rs" + +[dependencies.serde_core] +version = "1.0.228" + +[target."cfg(any())".dependencies.serde] +version = "1.0.228" + +[lints.clippy] +dbg_macro = "warn" +disallowed_methods = "warn" +print_stderr = "warn" +print_stdout = "warn" +self_named_module_files = "warn" + +[lints.clippy.all] +level = "allow" +priority = -2 + +[lints.clippy.correctness] +level = "warn" +priority = -1 + +[lints.rust] +rust_2018_idioms = "warn" + +[lints.rustdoc] +private_intra_doc_links = "allow" diff --git a/anneal/v2/vendor/cargo-platform/Cargo.toml.orig b/anneal/v2/vendor/cargo-platform/Cargo.toml.orig new file mode 100644 index 0000000000..16f9b4bcd0 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/Cargo.toml.orig @@ -0,0 +1,20 @@ +[package] +name = "cargo-platform" +version = "0.3.3" +edition.workspace = true +license.workspace = true +rust-version.workspace = true +repository.workspace = true +documentation = "https://docs.rs/cargo-platform" +description = "Cargo's representation of a target platform." + +[dependencies] +serde_core.workspace = true + +# serde v1.0.220 is the first version that released with `serde_core`. +# This is required to avoid conflict with other `serde` users which may require an older version. +[target.'cfg(any())'.dependencies] +serde.workspace = true + +[lints] +workspace = true diff --git a/anneal/v2/vendor/cargo-platform/LICENSE-APACHE b/anneal/v2/vendor/cargo-platform/LICENSE-APACHE new file mode 100644 index 0000000000..c98d27d4f3 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/cargo-platform/LICENSE-MIT b/anneal/v2/vendor/cargo-platform/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/cargo-platform/README.md b/anneal/v2/vendor/cargo-platform/README.md new file mode 100644 index 0000000000..844bc081f7 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/README.md @@ -0,0 +1,2 @@ +> This crate is maintained by the Cargo team for use by the wider +> ecosystem. This crate follows semver compatibility for its APIs. diff --git a/anneal/v2/vendor/cargo-platform/examples/matches.rs b/anneal/v2/vendor/cargo-platform/examples/matches.rs new file mode 100644 index 0000000000..11318a7df5 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/examples/matches.rs @@ -0,0 +1,57 @@ +//! This example demonstrates how to filter a Platform based on the current +//! host target. + +#![allow(clippy::print_stdout)] + +use cargo_platform::{Cfg, Platform}; +use std::process::Command; +use std::str::FromStr; + +static EXAMPLES: &[&str] = &[ + "cfg(windows)", + "cfg(unix)", + "cfg(target_os=\"macos\")", + "cfg(target_os=\"linux\")", + "cfg(any(target_arch=\"x86\", target_arch=\"x86_64\"))", +]; + +fn main() { + let target = get_target(); + let cfgs = get_cfgs(); + println!("host target={} cfgs:", target); + for cfg in &cfgs { + println!(" {}", cfg); + } + let mut examples: Vec<&str> = EXAMPLES.iter().copied().collect(); + examples.push(target.as_str()); + for example in examples { + let p = Platform::from_str(example).unwrap(); + println!("{:?} matches: {:?}", example, p.matches(&target, &cfgs)); + } +} + +fn get_target() -> String { + let output = Command::new("rustc") + .arg("-Vv") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + for line in stdout.lines() { + if let Some(line) = line.strip_prefix("host: ") { + return String::from(line); + } + } + panic!("Failed to find host: {}", stdout); +} + +fn get_cfgs() -> Vec { + let output = Command::new("rustc") + .arg("--print=cfg") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + stdout + .lines() + .map(|line| Cfg::from_str(line).unwrap()) + .collect() +} diff --git a/anneal/v2/vendor/cargo-platform/src/cfg.rs b/anneal/v2/vendor/cargo-platform/src/cfg.rs new file mode 100644 index 0000000000..6b87fd9bd0 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/src/cfg.rs @@ -0,0 +1,429 @@ +use crate::error::{ParseError, ParseErrorKind::*}; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::iter; +use std::str::{self, FromStr}; + +/// A cfg expression. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum CfgExpr { + Not(Box), + All(Vec), + Any(Vec), + Value(Cfg), + True, + False, +} + +/// A cfg value. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Cfg { + /// A named cfg value, like `unix`. + Name(Ident), + /// A key/value cfg pair, like `target_os = "linux"`. + KeyPair(Ident, String), +} + +/// A identifier +#[derive(Eq, Ord, PartialOrd, Clone, Debug)] +pub struct Ident { + /// The identifier + pub name: String, + /// Is this a raw ident: `r#async` + /// + /// It's mainly used for display and doesn't take + /// part in the hash or equality (`foo` == `r#foo`). + pub raw: bool, +} + +#[derive(PartialEq)] +enum Token<'a> { + LeftParen, + RightParen, + Ident(bool, &'a str), + Comma, + Equals, + String(&'a str), +} + +/// The list of keywords. +/// +/// We should consider all the keywords, but some are conditional on +/// the edition so for now we just consider true/false. +/// +/// +pub(crate) const KEYWORDS: &[&str; 2] = &["true", "false"]; + +#[derive(Clone)] +struct Tokenizer<'a> { + s: iter::Peekable>, + orig: &'a str, +} + +struct Parser<'a> { + t: Tokenizer<'a>, +} + +impl Ident { + pub fn as_str(&self) -> &str { + &self.name + } +} + +impl Hash for Ident { + fn hash(&self, state: &mut H) { + self.name.hash(state); + } +} + +impl PartialEq for Ident { + fn eq(&self, other: &str) -> bool { + self.name == other + } +} + +impl PartialEq<&str> for Ident { + fn eq(&self, other: &&str) -> bool { + self.name == *other + } +} + +impl PartialEq for Ident { + fn eq(&self, other: &Ident) -> bool { + self.name == other.name + } +} + +impl fmt::Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.raw { + f.write_str("r#")?; + } + f.write_str(&*self.name) + } +} + +impl FromStr for Cfg { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + let mut p = Parser::new(s); + let e = p.cfg()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for Cfg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Cfg::Name(ref s) => s.fmt(f), + Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v), + } + } +} + +impl CfgExpr { + /// Utility function to check if the key, "cfg(..)" matches the `target_cfg` + pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool { + if key.starts_with("cfg(") && key.ends_with(')') { + let cfg = &key[4..key.len() - 1]; + + CfgExpr::from_str(cfg) + .ok() + .map(|ce| ce.matches(target_cfg)) + .unwrap_or(false) + } else { + false + } + } + + pub fn matches(&self, cfg: &[Cfg]) -> bool { + match *self { + CfgExpr::Not(ref e) => !e.matches(cfg), + CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)), + CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)), + CfgExpr::Value(ref e) => cfg.contains(e), + CfgExpr::True => true, + CfgExpr::False => false, + } + } +} + +impl FromStr for CfgExpr { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + let mut p = Parser::new(s); + let e = p.expr()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for CfgExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + CfgExpr::Not(ref e) => write!(f, "not({})", e), + CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)), + CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)), + CfgExpr::Value(ref e) => write!(f, "{}", e), + CfgExpr::True => write!(f, "true"), + CfgExpr::False => write!(f, "false"), + } + } +} + +struct CommaSep<'a, T>(&'a [T]); + +impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, v) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", v)?; + } + Ok(()) + } +} + +impl<'a> Parser<'a> { + fn new(s: &'a str) -> Parser<'a> { + Parser { + t: Tokenizer { + s: s.char_indices().peekable(), + orig: s, + }, + } + } + + fn expr(&mut self) -> Result { + match self.peek() { + Some(Ok(Token::Ident(false, op @ "all"))) + | Some(Ok(Token::Ident(false, op @ "any"))) => { + self.t.next(); + let mut e = Vec::new(); + self.eat(&Token::LeftParen)?; + while !self.r#try(&Token::RightParen) { + e.push(self.expr()?); + if !self.r#try(&Token::Comma) { + self.eat(&Token::RightParen)?; + break; + } + } + if op == "all" { + Ok(CfgExpr::All(e)) + } else { + Ok(CfgExpr::Any(e)) + } + } + Some(Ok(Token::Ident(false, "not"))) => { + self.t.next(); + self.eat(&Token::LeftParen)?; + let e = self.expr()?; + self.eat(&Token::RightParen)?; + Ok(CfgExpr::Not(Box::new(e))) + } + Some(Ok(..)) => self.cfg().map(|v| match v { + Cfg::Name(n) if n == "true" => CfgExpr::True, + Cfg::Name(n) if n == "false" => CfgExpr::False, + v => CfgExpr::Value(v), + }), + Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr("start of a cfg expression"), + )), + } + } + + fn cfg(&mut self) -> Result { + match self.t.next() { + Some(Ok(Token::Ident(raw, name))) => { + let e = if self.r#try(&Token::Equals) { + let val = match self.t.next() { + Some(Ok(Token::String(s))) => s, + Some(Ok(t)) => { + return Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "a string", + found: t.classify(), + }, + )); + } + Some(Err(e)) => return Err(e), + None => { + return Err(ParseError::new(self.t.orig, IncompleteExpr("a string"))); + } + }; + Cfg::KeyPair( + Ident { + name: name.to_string(), + raw, + }, + val.to_string(), + ) + } else { + Cfg::Name(Ident { + name: name.to_string(), + raw, + }) + }; + Ok(e) + } + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "identifier", + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))), + } + } + + fn peek(&mut self) -> Option, ParseError>> { + self.t.clone().next() + } + + fn r#try(&mut self, token: &Token<'a>) -> bool { + match self.peek() { + Some(Ok(ref t)) if token == t => {} + _ => return false, + } + self.t.next(); + true + } + + fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> { + match self.t.next() { + Some(Ok(ref t)) if token == t => Ok(()), + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: token.classify(), + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr(token.classify()), + )), + } + } + + /// Returns the rest of the input from the current location. + fn rest(&self) -> Option<&str> { + let mut s = self.t.s.clone(); + loop { + match s.next() { + Some((_, ' ')) => {} + Some((start, _ch)) => return Some(&self.t.orig[start..]), + None => return None, + } + } + } +} + +impl<'a> Iterator for Tokenizer<'a> { + type Item = Result, ParseError>; + + fn next(&mut self) -> Option, ParseError>> { + loop { + match self.s.next() { + Some((_, ' ')) => {} + Some((_, '(')) => return Some(Ok(Token::LeftParen)), + Some((_, ')')) => return Some(Ok(Token::RightParen)), + Some((_, ',')) => return Some(Ok(Token::Comma)), + Some((_, '=')) => return Some(Ok(Token::Equals)), + Some((start, '"')) => { + while let Some((end, ch)) = self.s.next() { + if ch == '"' { + return Some(Ok(Token::String(&self.orig[start + 1..end]))); + } + } + return Some(Err(ParseError::new(self.orig, UnterminatedString))); + } + Some((start, ch)) if is_ident_start(ch) => { + let (start, raw) = if ch == 'r' { + if let Some(&(_pos, '#')) = self.s.peek() { + // starts with `r#` is a raw ident + self.s.next(); + if let Some((start, ch)) = self.s.next() { + if is_ident_start(ch) { + (start, true) + } else { + // not a starting ident character + return Some(Err(ParseError::new( + self.orig, + UnexpectedChar(ch), + ))); + } + } else { + // not followed by a ident, error out + return Some(Err(ParseError::new( + self.orig, + IncompleteExpr("identifier"), + ))); + } + } else { + // starts with `r` but not does continue with `#` + // cannot be a raw ident + (start, false) + } + } else { + // do not start with `r`, cannot be a raw ident + (start, false) + }; + while let Some(&(end, ch)) = self.s.peek() { + if !is_ident_rest(ch) { + return Some(Ok(Token::Ident(raw, &self.orig[start..end]))); + } else { + self.s.next(); + } + } + return Some(Ok(Token::Ident(raw, &self.orig[start..]))); + } + Some((_, ch)) => { + return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch)))); + } + None => return None, + } + } + } +} + +fn is_ident_start(ch: char) -> bool { + ch == '_' || ch.is_ascii_alphabetic() +} + +fn is_ident_rest(ch: char) -> bool { + is_ident_start(ch) || ch.is_ascii_digit() +} + +impl<'a> Token<'a> { + fn classify(&self) -> &'static str { + match *self { + Token::LeftParen => "`(`", + Token::RightParen => "`)`", + Token::Ident(..) => "an identifier", + Token::Comma => "`,`", + Token::Equals => "`=`", + Token::String(..) => "a string", + } + } +} diff --git a/anneal/v2/vendor/cargo-platform/src/error.rs b/anneal/v2/vendor/cargo-platform/src/error.rs new file mode 100644 index 0000000000..2d5b315f9e --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/src/error.rs @@ -0,0 +1,67 @@ +use std::fmt; + +#[derive(Debug)] +pub struct ParseError { + kind: ParseErrorKind, + orig: String, +} + +#[non_exhaustive] +#[derive(Debug)] +pub enum ParseErrorKind { + UnterminatedString, + UnexpectedChar(char), + UnexpectedToken { + expected: &'static str, + found: &'static str, + }, + IncompleteExpr(&'static str), + UnterminatedExpression(String), + InvalidTarget(String), +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "failed to parse `{}` as a cfg expression: {}", + self.orig, self.kind + ) + } +} + +impl fmt::Display for ParseErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use ParseErrorKind::*; + match self { + UnterminatedString => write!(f, "unterminated string in cfg"), + UnexpectedChar(ch) => write!( + f, + "unexpected character `{}` in cfg, expected parens, a comma, \ + an identifier, or a string", + ch + ), + UnexpectedToken { expected, found } => { + write!(f, "expected {}, found {}", expected, found) + } + IncompleteExpr(expected) => { + write!(f, "expected {}, but cfg expression ended", expected) + } + UnterminatedExpression(s) => { + write!(f, "unexpected content `{}` found after cfg expression", s) + } + InvalidTarget(s) => write!(f, "invalid target specifier: {}", s), + } + } +} + +impl std::error::Error for ParseError {} + +impl ParseError { + pub fn new(orig: &str, kind: ParseErrorKind) -> ParseError { + ParseError { + kind, + orig: orig.to_string(), + } + } +} diff --git a/anneal/v2/vendor/cargo-platform/src/lib.rs b/anneal/v2/vendor/cargo-platform/src/lib.rs new file mode 100644 index 0000000000..9585e2ef25 --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/src/lib.rs @@ -0,0 +1,182 @@ +//! Platform definition used by Cargo. +//! +//! This defines a [`Platform`] type which is used in Cargo to specify a target platform. +//! There are two kinds, a named target like `x86_64-apple-darwin`, and a "cfg expression" +//! like `cfg(any(target_os = "macos", target_os = "ios"))`. +//! +//! See `examples/matches.rs` for an example of how to match against a `Platform`. +//! +//! > This crate is maintained by the Cargo team for use by the wider +//! > ecosystem. This crate follows semver compatibility for its APIs. +//! +//! [`Platform`]: enum.Platform.html + +use std::str::FromStr; +use std::{fmt, path::Path}; + +mod cfg; +mod error; + +use cfg::KEYWORDS; +pub use cfg::{Cfg, CfgExpr, Ident}; +pub use error::{ParseError, ParseErrorKind}; + +/// Platform definition. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Platform { + /// A named platform, like `x86_64-apple-darwin`. + Name(String), + /// A cfg expression, like `cfg(windows)`. + Cfg(CfgExpr), +} + +impl Platform { + /// Returns whether the Platform matches the given target and cfg. + /// + /// The named target and cfg values should be obtained from `rustc`. + pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool { + match *self { + Platform::Name(ref p) => p == name, + Platform::Cfg(ref p) => p.matches(cfg), + } + } + + fn validate_named_platform(name: &str) -> Result<(), ParseError> { + if let Some(ch) = name + .chars() + .find(|&c| !(c.is_alphanumeric() || c == '_' || c == '-' || c == '.')) + { + if name.chars().any(|c| c == '(') { + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget( + "unexpected `(` character, cfg expressions must start with `cfg(`" + .to_string(), + ), + )); + } + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget(format!( + "unexpected character {} in target name", + ch + )), + )); + } + Ok(()) + } + + pub fn check_cfg_attributes(&self, warnings: &mut Vec) { + fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec) { + match *expr { + CfgExpr::Not(ref e) => check_cfg_expr(e, warnings), + CfgExpr::All(ref e) | CfgExpr::Any(ref e) => { + for e in e { + check_cfg_expr(e, warnings); + } + } + CfgExpr::Value(ref e) => match e { + Cfg::Name(name) => match name.as_str() { + "test" | "debug_assertions" | "proc_macro" => + warnings.push(format!( + "Found `{}` in `target.'cfg(...)'.dependencies`. \ + This value is not supported for selecting dependencies \ + and will not work as expected. \ + To learn more visit \ + https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies", + name + )), + _ => (), + }, + Cfg::KeyPair(name, _) => if name.as_str() == "feature" { + warnings.push(String::from( + "Found `feature = ...` in `target.'cfg(...)'.dependencies`. \ + This key is not supported for selecting dependencies \ + and will not work as expected. \ + Use the [features] section instead: \ + https://doc.rust-lang.org/cargo/reference/features.html" + )) + }, + } + CfgExpr::True | CfgExpr::False => {}, + } + } + + if let Platform::Cfg(cfg) = self { + check_cfg_expr(cfg, warnings); + } + } + + pub fn check_cfg_keywords(&self, warnings: &mut Vec, path: &Path) { + fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec, path: &Path) { + match *expr { + CfgExpr::Not(ref e) => check_cfg_expr(e, warnings, path), + CfgExpr::All(ref e) | CfgExpr::Any(ref e) => { + for e in e { + check_cfg_expr(e, warnings, path); + } + } + CfgExpr::True | CfgExpr::False => {} + CfgExpr::Value(ref e) => match e { + Cfg::Name(name) | Cfg::KeyPair(name, _) => { + if !name.raw && KEYWORDS.contains(&name.as_str()) { + warnings.push(format!( + "[{}] future-incompatibility: `cfg({e})` is deprecated as `{name}` is a keyword \ + and not an identifier and should not have have been accepted in this position.\n \ + | this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!\n \ + |\n \ + | help: use raw-idents instead: `cfg(r#{name})`", + path.display() + )); + } + } + }, + } + } + + if let Platform::Cfg(cfg) = self { + check_cfg_expr(cfg, warnings, path); + } + } +} + +impl serde_core::Serialize for Platform { + fn serialize(&self, s: S) -> Result + where + S: serde_core::Serializer, + { + self.to_string().serialize(s) + } +} + +impl<'de> serde_core::Deserialize<'de> for Platform { + fn deserialize(deserializer: D) -> Result + where + D: serde_core::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + FromStr::from_str(&s).map_err(serde_core::de::Error::custom) + } +} + +impl FromStr for Platform { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + if let Some(s) = s.strip_prefix("cfg(").and_then(|s| s.strip_suffix(')')) { + s.parse().map(Platform::Cfg) + } else { + Platform::validate_named_platform(s)?; + Ok(Platform::Name(s.to_string())) + } + } +} + +impl fmt::Display for Platform { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Platform::Name(ref n) => n.fmt(f), + Platform::Cfg(ref e) => write!(f, "cfg({})", e), + } + } +} diff --git a/anneal/v2/vendor/cargo-platform/tests/test_cfg.rs b/anneal/v2/vendor/cargo-platform/tests/test_cfg.rs new file mode 100644 index 0000000000..59cb27d54f --- /dev/null +++ b/anneal/v2/vendor/cargo-platform/tests/test_cfg.rs @@ -0,0 +1,292 @@ +use cargo_platform::{Cfg, CfgExpr, Ident, Platform}; +use std::fmt; +use std::str::FromStr; + +macro_rules! c { + ($a:ident) => { + Cfg::Name(Ident { + name: stringify!($a).to_string(), + raw: false, + }) + }; + (r # $a:ident) => { + Cfg::Name(Ident { + name: stringify!($a).to_string(), + raw: true, + }) + }; + ($a:ident = $e:expr) => { + Cfg::KeyPair( + Ident { + name: stringify!($a).to_string(), + raw: false, + }, + $e.to_string(), + ) + }; + (r # $a:ident = $e:expr) => { + Cfg::KeyPair( + Ident { + name: stringify!($a).to_string(), + raw: true, + }, + $e.to_string(), + ) + }; +} + +macro_rules! e { + (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*])); + (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*])); + (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*)))); + (true) => (CfgExpr::True); + (false) => (CfgExpr::False); + (($($t:tt)*)) => (e!($($t)*)); + ($($t:tt)*) => (CfgExpr::Value(c!($($t)*))); +} + +fn good(s: &str, expected: T) +where + T: FromStr + PartialEq + fmt::Debug, + T::Err: fmt::Display, +{ + let c = match T::from_str(s) { + Ok(c) => c, + Err(e) => panic!("failed to parse `{}`: {}", s, e), + }; + assert_eq!(c, expected); +} + +fn bad(s: &str, err: &str) +where + T: FromStr + fmt::Display, + T::Err: fmt::Display, +{ + let e = match T::from_str(s) { + Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg), + Err(e) => e.to_string(), + }; + assert!( + e.contains(err), + "when parsing `{}`,\n\"{}\" not contained \ + inside: {}", + s, + err, + e + ); +} + +#[test] +fn cfg_syntax() { + good("foo", c!(foo)); + good("_bar", c!(_bar)); + good(" foo", c!(foo)); + good(" foo ", c!(foo)); + good("r#foo", c!(r # foo)); + good(" foo = \"bar\"", c!(foo = "bar")); + good("foo=\"\"", c!(foo = "")); + good("r#foo=\"\"", c!(r # foo = "")); + good(" foo=\"3\" ", c!(foo = "3")); + good("foo = \"3 e\"", c!(foo = "3 e")); + good(" r#foo = \"3 e\"", c!(r # foo = "3 e")); +} + +#[test] +fn cfg_syntax_bad() { + bad::("", "but cfg expression ended"); + bad::(" ", "but cfg expression ended"); + bad::("\t", "unexpected character"); + bad::("7", "unexpected character"); + bad::("=", "expected identifier"); + bad::(",", "expected identifier"); + bad::("(", "expected identifier"); + bad::("foo (", "unexpected content `(` found after cfg expression"); + bad::("bar =", "expected a string"); + bad::("bar = \"", "unterminated string"); + bad::( + "foo, bar", + "unexpected content `, bar` found after cfg expression", + ); + bad::("r# foo", "unexpected character"); + bad::("r #foo", "unexpected content"); + bad::("r#\"foo\"", "unexpected character"); + bad::("foo = r#\"\"", "unexpected character"); +} + +#[test] +fn cfg_expr() { + good("foo", e!(foo)); + good("_bar", e!(_bar)); + good(" foo", e!(foo)); + good(" foo ", e!(foo)); + good(" foo = \"bar\"", e!(foo = "bar")); + good("foo=\"\"", e!(foo = "")); + good(" foo=\"3\" ", e!(foo = "3")); + good("foo = \"3 e\"", e!(foo = "3 e")); + + good("true", e!(true)); + good("false", e!(false)); + + good("all()", e!(all())); + good("all(a)", e!(all(a))); + good("all(a, b)", e!(all(a, b))); + good("all(a, )", e!(all(a))); + good("not(a = \"b\")", e!(not(a = "b"))); + good("not(all(a))", e!(not(all(a)))); +} + +#[test] +fn cfg_expr_bad() { + bad::(" ", "but cfg expression ended"); + bad::(" all", "expected `(`"); + bad::("all(a", "expected `)`"); + bad::("not", "expected `(`"); + bad::("not(a", "expected `)`"); + bad::("a = ", "expected a string"); + bad::("all(not())", "expected identifier"); + bad::( + "foo(a)", + "unexpected content `(a)` found after cfg expression", + ); +} + +#[test] +fn cfg_matches() { + assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo, bar)).matches(&[c!(bar)])); + assert!(e!(any(foo, bar)).matches(&[c!(foo)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(not(foo)).matches(&[c!(bar)])); + assert!(e!(not(foo)).matches(&[])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)])); + assert!(e!(foo).matches(&[c!(r # foo)])); + assert!(e!(r # foo).matches(&[c!(foo)])); + assert!(e!(r # foo).matches(&[c!(r # foo)])); + + assert!(!e!(foo).matches(&[])); + assert!(!e!(foo).matches(&[c!(bar)])); + assert!(!e!(foo).matches(&[c!(fo)])); + assert!(!e!(any(foo)).matches(&[])); + assert!(!e!(any(foo)).matches(&[c!(bar)])); + assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo, bar)).matches(&[c!(bar)])); + assert!(!e!(all(foo, bar)).matches(&[c!(foo)])); + assert!(!e!(all(foo, bar)).matches(&[])); + assert!(!e!(not(bar)).matches(&[c!(bar)])); + assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)])); + assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)])); +} + +#[test] +fn bad_target_name() { + bad::( + "any(cfg(unix), cfg(windows))", + "failed to parse `any(cfg(unix), cfg(windows))` as a cfg expression: \ + invalid target specifier: unexpected `(` character, \ + cfg expressions must start with `cfg(`", + ); + bad::( + "!foo", + "failed to parse `!foo` as a cfg expression: \ + invalid target specifier: unexpected character ! in target name", + ); +} + +#[test] +fn round_trip_platform() { + fn rt(s: &str) { + let p = Platform::from_str(s).unwrap(); + let s2 = p.to_string(); + let p2 = Platform::from_str(&s2).unwrap(); + assert_eq!(p, p2); + } + rt("x86_64-apple-darwin"); + rt("foo"); + rt("cfg(windows)"); + rt("cfg(target_os = \"windows\")"); + rt( + "cfg(any(all(any(target_os = \"android\", target_os = \"linux\"), \ + any(target_arch = \"aarch64\", target_arch = \"arm\", target_arch = \"powerpc64\", \ + target_arch = \"x86\", target_arch = \"x86_64\")), \ + all(target_os = \"freebsd\", target_arch = \"x86_64\")))", + ); +} + +#[test] +fn check_cfg_attributes() { + fn ok(s: &str) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert!( + warnings.is_empty(), + "Expected no warnings but got: {:?}", + warnings, + ); + } + + fn warn(s: &str, names: &[&str]) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert_eq!( + warnings.len(), + names.len(), + "Expecter warnings about {:?} but got {:?}", + names, + warnings, + ); + for (name, warning) in names.iter().zip(warnings.iter()) { + assert!( + warning.contains(name), + "Expected warning about '{}' but got: {}", + name, + warning, + ); + } + } + + ok("unix"); + ok("windows"); + ok("any(not(unix), windows)"); + ok("foo"); + ok("true"); + ok("false"); + + ok("target_arch = \"abc\""); + ok("target_feature = \"abc\""); + ok("target_os = \"abc\""); + ok("target_family = \"abc\""); + ok("target_env = \"abc\""); + ok("target_endian = \"abc\""); + ok("target_pointer_width = \"abc\""); + ok("target_vendor = \"abc\""); + ok("bar = \"def\""); + + warn("test", &["test"]); + warn("debug_assertions", &["debug_assertions"]); + warn("proc_macro", &["proc_macro"]); + warn("feature = \"abc\"", &["feature"]); + + warn("any(not(debug_assertions), windows)", &["debug_assertions"]); + warn( + "any(not(feature = \"def\"), target_arch = \"abc\")", + &["feature"], + ); + warn( + "any(not(target_os = \"windows\"), proc_macro)", + &["proc_macro"], + ); + warn( + "any(not(feature = \"windows\"), proc_macro)", + &["feature", "proc_macro"], + ); + warn( + "all(not(debug_assertions), any(windows, proc_macro))", + &["debug_assertions", "proc_macro"], + ); +} diff --git a/anneal/v2/vendor/cargo_metadata/.cargo-checksum.json b/anneal/v2/vendor/cargo_metadata/.cargo-checksum.json new file mode 100644 index 0000000000..b6f039441b --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"59387e2996b3e898a16e1eaacba3049eabc5938ab9d4c8aa4c3a5c3469153f27",".github/workflows/main.yml":"49111f415ba7e4b1e5dd74a6434d81461522db9ff18a9ec24fd6d2a20cb2df91",".github/workflows/release.yml":"c195a66766f906e59fff767cad2bc848e329969a0b0d28253ccfdf03b63a86a8","CHANGELOG.md":"2299f5639c1014e34cbbff8e09e54e5b784585e5db9f0f581d51f3bedf33a304","Cargo.lock":"efaef17905e83ba11adb049e929bdbbb6bbc52f4a4df67f716780cf066e42d45","Cargo.toml":"d959a912156ea9280cee6b17d34527f22ce2dc6ddc643820053ddb9d0fd3c9f1","Cargo.toml.orig":"bc3d0e03d073b9b0c764ef8c349287f39445bd6c99a3a777af4c17d574b46c88","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"6be7aaba23d8646b470a966eef2f00c9fa04cf4d1de25cfb71680cef562e1574","clippy.toml":"0eb773e1a242ba7e06f0ca5c23be71b5989f4952fe18cae35e5322066e706495","src/dependency.rs":"17b8124fe0b2c2c31de1195e34c09bc696b92bad9c1bf25a006f8caa41390a1a","src/diagnostic.rs":"fee47d27390f1026ff99ffade5dfd2ab3e9b9839c3f33ce91a7dcde875551374","src/errors.rs":"2b995efb03b4c0893ee325a0c200017eca9307005dfc488a41c5669553b00fd5","src/lib.rs":"1bc2fefd936033c31f90d97df2e6dce6df1bea38b14139d24c0ad4300770c5bd","src/libtest.rs":"705519c92f6f1ad1594908b9024d6311777a3c20e23e74a3424e4577850f374c","src/messages.rs":"906f263808f2243172b6b4df1e0776316de1b2e926cd4cf1d9a715045d5b8635","tests/selftest.rs":"fcf0c21dbcf5439fdd9e335b6550902e05b2e2ed63a6d608e6a52224b998f0cc","tests/test_samples.rs":"377581c5b7031e4a842b8e59af66bfe10d6f047f5916f502203526a516881d90"},"package":"ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"} \ No newline at end of file diff --git a/anneal/v2/vendor/cargo_metadata/.cargo_vcs_info.json b/anneal/v2/vendor/cargo_metadata/.cargo_vcs_info.json new file mode 100644 index 0000000000..643095b474 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c08e66cdf534313085ef810ce6f2e0df8a83fc50" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/cargo_metadata/.github/workflows/main.yml b/anneal/v2/vendor/cargo_metadata/.github/workflows/main.yml new file mode 100644 index 0000000000..2fbab0cc8a --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/.github/workflows/main.yml @@ -0,0 +1,52 @@ +name: CI +on: [push, pull_request] + +jobs: + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install rust + run: rustup update --no-self-update stable && rustup default stable && rustup component add rustfmt --toolchain stable + - name: Check formatting + run: cargo fmt -- --check + + clippy: + name: clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install rust + run: rustup update --no-self-update stable && rustup default stable && rustup component add clippy --toolchain stable + - name: Clippy check + run: cargo clippy --all-features -- -Dwarnings + + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + include: + - rust: stable + - rust: beta + - rust: nightly + - rust: 1.86.0 + steps: + - uses: actions/checkout@v2 + - name: Install rust + run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - name: Run tests + run: | + cargo build --verbose + cargo build --verbose --no-default-features + cargo test --verbose + cargo test --verbose --no-default-features + + # Test with all features. But do not use the `unstable` feature on non-nightly toolchains + if [ "${{ matrix.rust }}" = "nightly" ]; then + cargo test --verbose --all-features + else + ALL_FEATURES_EXCEPT_UNSTABLE=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].features | keys | .[]' | grep -v 'unstable' | tr '\n' ' ') + cargo test --features "$ALL_FEATURES_EXCEPT_UNSTABLE" + fi diff --git a/anneal/v2/vendor/cargo_metadata/.github/workflows/release.yml b/anneal/v2/vendor/cargo_metadata/.github/workflows/release.yml new file mode 100644 index 0000000000..1b2d7a7b7f --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/.github/workflows/release.yml @@ -0,0 +1,72 @@ +name: Release new version + +on: + workflow_dispatch: + secrets: + CARGO_REGISTRY_TOKEN: + required: true + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + +jobs: + create-release: + name: Create release + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + persist-credentials: true + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + + - uses: Swatinem/rust-cache@v2 + + # Determine which version we're about to publish, so we can tag it appropriately. + # If the tag already exists, then we've already published this version. + - name: Determine current version + id: version-check + run: | + # Fail on first error, on undefined variables, and on errors in pipes. + set -euo pipefail + export VERSION="$(cargo metadata --format-version 1 | \ + jq --arg crate_name cargo_metadata --exit-status -r \ + '.packages[] | select(.name == $crate_name) | .version')" + echo "version=$VERSION" >> $GITHUB_OUTPUT + if [[ "$(git tag -l "$VERSION")" != '' ]]; then + echo "Aborting: Version $VERSION is already published, we found its tag in the repo." + exit 1 + fi + + - name: Semver-check + uses: obi1kenobi/cargo-semver-checks-action@v2 + with: + rust-toolchain: manual # we've already installed Rust, don't install a new one + + - name: Publish + run: cargo publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + - name: Tag the version + run: | + # Fail on first error, on undefined variables, and on errors in pipes. + set -euo pipefail + git tag "${{ steps.version-check.outputs.version }}" + git push origin "${{ steps.version-check.outputs.version }}" + + - uses: taiki-e/create-gh-release-action@v1 + name: Create GitHub release + with: + branch: main + ref: refs/tags/${{ steps.version-check.outputs.version }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/anneal/v2/vendor/cargo_metadata/CHANGELOG.md b/anneal/v2/vendor/cargo_metadata/CHANGELOG.md new file mode 100644 index 0000000000..c55834e61e --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/CHANGELOG.md @@ -0,0 +1,103 @@ +# Changelog + +## Unreleased + +- n/a + +### Added + +- n/a + +### Changed + +- n/a + +### Removed + +- n/a + +### Fixed + +- n/a + +## [0.23.1] - 2025-11-11 + +### Changed + +- Stabilized `build_directory` + +## [0.23.0] - 2025-09-27 + +### Added + +- Added `FeatureName` and `PackageName` newtype wrappers. + +## [0.22.0] - 2025-08-18 + +### Added + +- Added `pub fn env_remove>(&mut self, key: K) -> &mut MetadataCommand` to `MetadataCommand`. +- Added export of `cargo_platform` at crate's root module. + +### Changed + +- Updated dependencies: + - `camino` from `1.0.7` to `1.1.10` + - `cargo_platform` from `0.2.0` to `0.3.0` + - `derive_builder` from `0.12` to `0.20` + - `semver` from `1.0.7` to `1.0.26` + - `serde_json` from `1.0.118` to `1.0.142` + - `serde` from `1.0.136` to `1.0.219` + - `thiserror` from `2.0.3` to `2.0.12` +- Made `Dependency`'s `source` member the same type as `Package`'s `source` member: `Option`. + +## [0.19.0] - 2024-11-20 + +### Added + +- Re-exported `semver` crate directly. +- Added implementation of `std::ops::Index<&PackageId>` for `Resolve`. +- Added `pub fn is_kind(&self, name: TargetKind) -> bool` to `Target`. +- Added derived implementations of `PartialEq`, `Eq` and `Hash` for `Metadata` and its members' types. +- Added default fields to `PackageBuilder`. +- Added `pub fn new(name:version:id:path:) -> Self` to `PackageBuilder` for providing all required fields upfront. + +### Changed + +- Bumped MSRV from `1.42.0` to `1.56.0`. +- Made `parse_stream` more versatile by accepting anything that implements `Read`. +- Converted `TargetKind` and `CrateType` to an enum representation. + +### Removed + +- Removed re-exports for `BuildMetadata` and `Prerelease` from `semver` crate. +- Removed `.is_lib(…)`, `.is_bin(…)`, `.is_example(…)`, `.is_test(…)`, `.is_bench(…)`, `.is_custom_build(…)`, and `.is_proc_macro(…)` from `Target` (in favor of adding `.is_kind(…)`). + +### Fixed + +- Added missing `manifest_path` field to `Artifact`. Fixes #187. + +## [0.15.0] - 2022-06-22 + +### Added + +- Re-exported `BuildMetadata` and `Prerelease` from `semver` crate. +- Added `workspace_packages` function. +- Added `Edition` enum to better parse edition field. +- Added `rust-version` field to Cargo manifest. + +### Changed + +- Bumped msrv from `1.40.0` to `1.42.0`. + +### Internal Changes + +- Updated `derive_builder` to the latest version. +- Made use of `matches!` macros where possible. +- Fixed some tests + +## [0.15.1] - 2022-10-13 + +### Added + +- Added `TestMessage`, `TestEvent`, `SuiteEvent` for parsing the `cargo test -- --format json` output. diff --git a/anneal/v2/vendor/cargo_metadata/Cargo.lock b/anneal/v2/vendor/cargo_metadata/Cargo.lock new file mode 100644 index 0000000000..0da7fbfd16 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/Cargo.lock @@ -0,0 +1,244 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122ec45a44b270afd1402f351b782c676b173e3c3fb28d86ff7ebfb4d86a4ee4" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +dependencies = [ + "camino", + "cargo-platform", + "derive_builder", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" diff --git a/anneal/v2/vendor/cargo_metadata/Cargo.toml b/anneal/v2/vendor/cargo_metadata/Cargo.toml new file mode 100644 index 0000000000..63049ca991 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/Cargo.toml @@ -0,0 +1,77 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.86.0" +name = "cargo_metadata" +version = "0.23.1" +authors = ["Oliver Schneider "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "structured access to the output of `cargo metadata`" +readme = "README.md" +license = "MIT" +repository = "https://github.com/oli-obk/cargo_metadata" + +[package.metadata.docs.rs] +all-features = true + +[package.metadata.cargo_metadata_test] +some_field = true +other_field = "foo" + +[features] +builder = ["derive_builder"] +default = [] +unstable = [] + +[lib] +name = "cargo_metadata" +path = "src/lib.rs" + +[[test]] +name = "selftest" +path = "tests/selftest.rs" + +[[test]] +name = "test_samples" +path = "tests/test_samples.rs" + +[dependencies.camino] +version = "1.1.10" +features = ["serde1"] + +[dependencies.cargo-platform] +version = "0.3.0" + +[dependencies.derive_builder] +version = "0.20" +optional = true + +[dependencies.semver] +version = "1.0.26" +features = ["serde"] + +[dependencies.serde] +version = "1.0.219" +features = ["derive"] + +[dependencies.serde_json] +version = "1.0.142" +features = ["unbounded_depth"] + +[dependencies.thiserror] +version = "2.0.12" diff --git a/anneal/v2/vendor/cargo_metadata/Cargo.toml.orig b/anneal/v2/vendor/cargo_metadata/Cargo.toml.orig new file mode 100644 index 0000000000..7f77850de7 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/Cargo.toml.orig @@ -0,0 +1,31 @@ +[package] +name = "cargo_metadata" +version = "0.23.1" +authors = ["Oliver Schneider "] +repository = "https://github.com/oli-obk/cargo_metadata" +description = "structured access to the output of `cargo metadata`" +license = "MIT" +readme = "README.md" +edition = "2021" +rust-version = "1.86.0" + +[dependencies] +camino = { version = "1.1.10", features = ["serde1"] } +cargo-platform = "0.3.0" +derive_builder = { version = "0.20", optional = true } +semver = { version = "1.0.26", features = ["serde"] } +serde = { version = "1.0.219", features = ["derive"] } +serde_json = { version = "1.0.142", features = ["unbounded_depth"] } +thiserror = "2.0.12" + +[features] +default = [] +builder = ["derive_builder"] +unstable = [] + +[package.metadata.docs.rs] +all-features = true + +[package.metadata.cargo_metadata_test] +some_field = true +other_field = "foo" diff --git a/anneal/v2/vendor/cargo_metadata/LICENSE-MIT b/anneal/v2/vendor/cargo_metadata/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/cargo_metadata/README.md b/anneal/v2/vendor/cargo_metadata/README.md new file mode 100644 index 0000000000..b54ec48584 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/README.md @@ -0,0 +1,12 @@ +# cargo_metadata + +Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable. + +Also supports serialization to aid in implementing `--message-format=json`-like +output generation in `cargo-*` subcommands, since some of the types in what +`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`. + +[![Build Status](https://github.com/oli-obk/cargo_metadata/workflows/CI/badge.svg?branch=main)](https://github.com/oli-obk/cargo_metadata/actions/workflows/main.yml?query=branch%3Amain) +[![crates.io](https://img.shields.io/crates/v/cargo_metadata.svg)](https://crates.io/crates/cargo_metadata) + +[Documentation](https://docs.rs/cargo_metadata/) diff --git a/anneal/v2/vendor/cargo_metadata/clippy.toml b/anneal/v2/vendor/cargo_metadata/clippy.toml new file mode 100644 index 0000000000..bfb8bfe2d9 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/clippy.toml @@ -0,0 +1,3 @@ +disallowed-types = [ + { path = "std::collections::HashMap", reason = "HashMap's key order is unspecified and thus serializing such a type will result in a random output, use BTreeMap instead." } +] \ No newline at end of file diff --git a/anneal/v2/vendor/cargo_metadata/src/dependency.rs b/anneal/v2/vendor/cargo_metadata/src/dependency.rs new file mode 100644 index 0000000000..09b88501bd --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/dependency.rs @@ -0,0 +1,87 @@ +//! This module contains `Dependency` and the types/functions it uses for deserialization. + +use std::fmt; + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use semver::VersionReq; +use serde::{Deserialize, Deserializer, Serialize}; + +use crate::Source; + +#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash, Serialize, Deserialize, Default)] +/// Dependencies can come in three kinds +pub enum DependencyKind { + #[serde(rename = "normal")] + #[default] + /// The 'normal' kind + Normal, + #[serde(rename = "dev")] + /// Those used in tests only + Development, + #[serde(rename = "build")] + /// Those used in build scripts only + Build, + #[doc(hidden)] + #[serde(other)] + Unknown, +} + +impl fmt::Display for DependencyKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = serde_json::to_string(self).unwrap(); + // skip opening and closing quotes + f.write_str(&s[1..s.len() - 1]) + } +} + +/// The `kind` can be `null`, which is interpreted as the default - `Normal`. +pub(super) fn parse_dependency_kind<'de, D>(d: D) -> Result +where + D: Deserializer<'de>, +{ + Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default()) +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency of the main crate +pub struct Dependency { + /// Name as given in the `Cargo.toml` + pub name: String, + /// The source of dependency + pub source: Option, + /// The required version + pub req: VersionReq, + /// The kind of dependency this is + #[serde(deserialize_with = "parse_dependency_kind")] + pub kind: DependencyKind, + /// Whether this dependency is required or optional + pub optional: bool, + /// Whether the default features in this dependency are used. + pub uses_default_features: bool, + /// The list of features enabled for this dependency. + pub features: Vec, + /// The target this dependency is specific to. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// [`Display`]: std::fmt::Display + pub target: Option, + /// If the dependency is renamed, this is the new name for the dependency + /// as a string. None if it is not renamed. + pub rename: Option, + /// The URL of the index of the registry where this dependency is from. + /// + /// If None, the dependency is from crates.io. + pub registry: Option, + /// The file system path for a local path dependency. + /// + /// Only produced on cargo 1.51+ + pub path: Option, +} + +pub use cargo_platform::Platform; diff --git a/anneal/v2/vendor/cargo_metadata/src/diagnostic.rs b/anneal/v2/vendor/cargo_metadata/src/diagnostic.rs new file mode 100644 index 0000000000..dbe21128a0 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/diagnostic.rs @@ -0,0 +1,160 @@ +//! This module contains `Diagnostic` and the types/functions it uses for deserialization. + +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use std::fmt; + +/// The error code associated to this diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticCode { + /// The code itself. + pub code: String, + /// An explanation for the code + pub explanation: Option, +} + +/// A line of code associated with the Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanLine { + /// The line of code associated with the error + pub text: String, + /// Start of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_start: usize, + /// End of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_end: usize, +} + +/// Macro expansion information associated with a diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanMacroExpansion { + /// span where macro was applied to generate this code; note that + /// this may itself derive from a macro (if + /// `span.expansion.is_some()`) + pub span: DiagnosticSpan, + + /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") + pub macro_decl_name: String, + + /// span where macro was defined (if known) + pub def_site_span: Option, +} + +/// A section of the source code associated with a Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpan { + /// The file name or the macro name this diagnostic comes from. + pub file_name: String, + /// The byte offset in the file where this diagnostic starts from. + pub byte_start: u32, + /// The byte offset in the file where this diagnostic ends. + pub byte_end: u32, + /// 1-based. The line in the file. + pub line_start: usize, + /// 1-based. The line in the file. + pub line_end: usize, + /// 1-based, character offset. + pub column_start: usize, + /// 1-based, character offset. + pub column_end: usize, + /// Is this a "primary" span -- meaning the point, or one of the points, + /// where the error occurred? + /// + /// There are rare cases where multiple spans are marked as primary, + /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can + /// be two separate spans both "primary". Top (parent) messages should + /// always have at least one primary span, unless it has 0 spans. Child + /// messages may have 0 or more primary spans. + pub is_primary: bool, + /// Source text from the start of line_start to the end of line_end. + pub text: Vec, + /// Label that should be placed at this location (if any) + pub label: Option, + /// If we are suggesting a replacement, this will contain text + /// that should be sliced in atop this span. + pub suggested_replacement: Option, + /// If the suggestion is approximate + pub suggestion_applicability: Option, + /// Macro invocations that created the code at this span, if any. + pub expansion: Option>, +} + +/// Whether a suggestion can be safely applied. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum Applicability { + /// The suggested replacement can be applied automatically safely + MachineApplicable, + /// The suggested replacement has placeholders that will need to be manually + /// replaced. + HasPlaceholders, + /// The suggested replacement may be incorrect in some circumstances. Needs + /// human review. + MaybeIncorrect, + /// The suggested replacement will probably not work. + Unspecified, +} + +/// The diagnostic level +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(rename_all = "lowercase")] +pub enum DiagnosticLevel { + /// Internal compiler error + #[serde(rename = "error: internal compiler error")] + Ice, + /// Error + Error, + /// Warning + Warning, + /// Failure note + #[serde(rename = "failure-note")] + FailureNote, + /// Note + Note, + /// Help + Help, +} + +/// A diagnostic message generated by rustc +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Diagnostic { + /// The error message of this diagnostic. + pub message: String, + /// The associated error code for this diagnostic + pub code: Option, + /// "error: internal compiler error", "error", "warning", "note", "help" + pub level: DiagnosticLevel, + /// A list of source code spans this diagnostic is associated with. + pub spans: Vec, + /// Associated diagnostic messages. + pub children: Vec, + /// The message as rustc would render it + pub rendered: Option, +} + +impl fmt::Display for Diagnostic { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref rendered) = self.rendered { + f.write_str(rendered)?; + } else { + f.write_str("cargo didn't render this message")?; + } + Ok(()) + } +} diff --git a/anneal/v2/vendor/cargo_metadata/src/errors.rs b/anneal/v2/vendor/cargo_metadata/src/errors.rs new file mode 100644 index 0000000000..b59f0aba0c --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/errors.rs @@ -0,0 +1,52 @@ +use std::{io, str::Utf8Error, string::FromUtf8Error}; + +/// Custom result type for `cargo_metadata::Error` +pub type Result = ::std::result::Result; + +/// Error returned when executing/parsing `cargo metadata` fails. +/// +/// # Note about Backtraces +/// +/// This error type does not contain backtraces, but each error variant +/// comes from _one_ specific place, so it's not really needed for the +/// inside of this crate. If you need a backtrace down to, but not inside +/// of, a failed call of `cargo_metadata` you can do one of multiple thinks: +/// +/// 1. Convert it to a `failure::Error` (possible using the `?` operator), +/// which is similar to a `Box<::std::error::Error + 'static + Send + Sync>`. +/// 2. Have appropriate variants in your own error type. E.g. you could wrap +/// a `failure::Context` or add a `failure::Backtrace` field (which +/// is empty if `RUST_BACKTRACE` is not set, so it's simple to use). +/// 3. You still can place a failure based error into a `error_chain` if you +/// really want to. (Either through foreign_links or by making it a field +/// value of a `ErrorKind` variant). +/// +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Error during execution of `cargo metadata` + #[error("`cargo metadata` exited with an error: {stderr}")] + CargoMetadata { + /// stderr returned by the `cargo metadata` command + stderr: String, + }, + + /// IO Error during execution of `cargo metadata` + #[error("failed to start `cargo metadata`: {0}")] + Io(#[from] io::Error), + + /// Output of `cargo metadata` was not valid utf8 + #[error("cannot convert the stdout of `cargo metadata`: {0}")] + Utf8(#[from] Utf8Error), + + /// Error output of `cargo metadata` was not valid utf8 + #[error("cannot convert the stderr of `cargo metadata`: {0}")] + ErrUtf8(#[from] FromUtf8Error), + + /// Deserialization error (structure of json did not match expected structure) + #[error("failed to interpret `cargo metadata`'s json: {0}")] + Json(#[from] ::serde_json::Error), + + /// The output did not contain any json + #[error("could not find any json in the output of `cargo metadata`")] + NoJson, +} diff --git a/anneal/v2/vendor/cargo_metadata/src/lib.rs b/anneal/v2/vendor/cargo_metadata/src/lib.rs new file mode 100644 index 0000000000..7fe6321c0b --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/lib.rs @@ -0,0 +1,1330 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] +//! Structured access to the output of `cargo metadata` and `cargo --message-format=json`. +//! Usually used from within a `cargo-*` executable +//! +//! See the [cargo book](https://doc.rust-lang.org/cargo/index.html) for +//! details on cargo itself. +//! +//! ## Examples +//! +//! Get the current crate's metadata without default features but with all dependency information. +//! +//! ```rust +//! # use std::path::Path; +//! # use cargo_metadata::{MetadataCommand, CargoOpt}; +//! let _metadata = MetadataCommand::new().exec().unwrap(); +//! ``` +//! +//! +//! If you have a program that takes `--manifest-path` as an argument, you can forward that +//! to [MetadataCommand]: +//! +//! ```rust +//! # use cargo_metadata::MetadataCommand; +//! # use std::path::Path; +//! let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path")); +//! let mut cmd = MetadataCommand::new(); +//! let manifest_path = match args.next() { +//! Some(ref p) if p == "--manifest-path" => { +//! cmd.manifest_path(args.next().unwrap()); +//! } +//! Some(p) => { +//! cmd.manifest_path(p.trim_start_matches("--manifest-path=")); +//! } +//! None => {} +//! }; +//! +//! let _metadata = cmd.exec().unwrap(); +//! ``` +//! +//! Pass features flags, e.g. `--all-features`. +//! +//! ```rust +//! # use std::path::Path; +//! # use cargo_metadata::{MetadataCommand, CargoOpt}; +//! let _metadata = MetadataCommand::new() +//! .manifest_path("./Cargo.toml") +//! .features(CargoOpt::AllFeatures) +//! .exec() +//! .unwrap(); +//! ``` +//! +//! Parse message-format output produced by other cargo commands. +//! It is recommended to use crates like `escargot` to produce the [Command]. +//! +//! ``` +//! # use std::process::{Stdio, Command}; +//! # use cargo_metadata::Message; +//! let mut command = Command::new("cargo") +//! .args(&["build", "--message-format=json-render-diagnostics"]) +//! .stdout(Stdio::piped()) +//! .spawn() +//! .unwrap(); +//! +//! let reader = std::io::BufReader::new(command.stdout.take().unwrap()); +//! for message in cargo_metadata::Message::parse_stream(reader) { +//! match message.unwrap() { +//! Message::CompilerMessage(msg) => { +//! println!("{:?}", msg); +//! }, +//! Message::CompilerArtifact(artifact) => { +//! println!("{:?}", artifact); +//! }, +//! Message::BuildScriptExecuted(script) => { +//! println!("{:?}", script); +//! }, +//! Message::BuildFinished(finished) => { +//! println!("{:?}", finished); +//! }, +//! _ => () // Unknown message +//! } +//! } +//! +//! let output = command.wait().expect("Couldn't get cargo's exit status"); +//! ``` + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use std::collections::BTreeMap; +use std::env; +use std::ffi::OsString; +use std::fmt; +use std::hash::Hash; +use std::path::PathBuf; +use std::process::{Command, Stdio}; +use std::str::{from_utf8, FromStr}; + +pub use camino; +pub use cargo_platform; +pub use semver; +use semver::Version; + +#[cfg(feature = "builder")] +pub use dependency::DependencyBuilder; +pub use dependency::{Dependency, DependencyKind}; +use diagnostic::Diagnostic; +pub use errors::{Error, Result}; +#[cfg(feature = "unstable")] +pub use libtest::TestMessage; +#[allow(deprecated)] +pub use messages::parse_messages; +pub use messages::{ + Artifact, ArtifactDebuginfo, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, + Message, MessageIter, +}; +#[cfg(feature = "builder")] +pub use messages::{ + ArtifactBuilder, ArtifactProfileBuilder, BuildFinishedBuilder, BuildScriptBuilder, + CompilerMessageBuilder, +}; +use serde::{Deserialize, Deserializer, Serialize}; + +mod dependency; +pub mod diagnostic; +mod errors; +#[cfg(feature = "unstable")] +pub mod libtest; +mod messages; + +macro_rules! str_newtype { + ( + $(#[doc = $docs:literal])* + $name:ident + ) => { + $(#[doc = $docs])* + #[derive(Serialize, Debug, Clone, Eq, PartialOrd, Ord, Hash)] + #[serde(transparent)] + pub struct $name = String>(T); + + impl> $name { + /// Convert the wrapped string into its inner type `T` + pub fn into_inner(self) -> T { + self.0 + } + } + + impl> AsRef for $name { + fn as_ref(&self) -> &str { + self.0.as_ref() + } + } + + impl> std::ops::Deref for $name { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl> std::borrow::Borrow for $name { + fn borrow(&self) -> &str { + self.0.as_ref() + } + } + + impl<'a> std::str::FromStr for $name { + type Err = std::convert::Infallible; + + fn from_str(value: &str) -> Result { + Ok(Self::new(value.to_owned())) + } + } + + impl<'de, T: AsRef + serde::Deserialize<'de>> serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = T::deserialize(deserializer)?; + Ok(Self::new(inner)) + } + } + + impl> fmt::Display for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.as_ref().fmt(f) + } + } + + // Note: The next two implementations are not based on Cargo string newtype implementations. + + impl> $name { + /// Create a new wrapped string + pub fn new(name: T) -> Self { + Self(name) + } + } + + impl, Rhs: AsRef> PartialEq for $name { + fn eq(&self, other: &Rhs) -> bool { + self.as_ref() == other.as_ref() + } + } + }; +} + +str_newtype!( + /// Feature name newtype + /// + /// Based on [cargo-util-schema's string newtype] but with two crucial differences: + /// + /// - This newtype does not verify the wrapped string. + /// - This newtype allows comparison with arbitrary types that implement `AsRef`. + /// + /// [cargo-util-schema's string newtype]: https://github.com/epage/cargo/blob/d8975d2901e132c02b3f6b1d107f2f50b275a058/crates/cargo-util-schemas/src/manifest/mod.rs#L1355-L1413 + FeatureName +); + +str_newtype!( + /// Package name newtype + /// + /// Based on [cargo-util-schema's string newtype] but with two crucial differences: + /// + /// - This newtype does not verify the wrapped string. + /// - This newtype allows comparison with arbitrary types that implement `AsRef`. + /// + /// [cargo-util-schema's string newtype]: https://github.com/epage/cargo/blob/d8975d2901e132c02b3f6b1d107f2f50b275a058/crates/cargo-util-schemas/src/manifest/mod.rs#L1355-L1413 + PackageName +); + +/// An "opaque" identifier for a package. +/// +/// It is possible to inspect the `repr` field, if the need arises, but its +/// precise format is an implementation detail and is subject to change. +/// +/// `Metadata` can be indexed by `PackageId`. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[serde(transparent)] +pub struct PackageId { + /// The underlying string representation of id. + pub repr: String, +} + +impl fmt::Display for PackageId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +/// Helpers for default metadata fields +fn is_null(value: &serde_json::Value) -> bool { + matches!(value, serde_json::Value::Null) +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Starting point for metadata returned by `cargo metadata` +pub struct Metadata { + /// A list of all crates referenced by this crate (and the crate itself) + pub packages: Vec, + /// A list of all workspace members + pub workspace_members: Vec, + /// The list of default workspace members + /// + /// This is not available if running with a version of Cargo older than 1.71. + /// + /// You can check whether it is available or missing using respectively + /// [`WorkspaceDefaultMembers::is_available`] and [`WorkspaceDefaultMembers::is_missing`]. + #[serde(default, skip_serializing_if = "WorkspaceDefaultMembers::is_missing")] + pub workspace_default_members: WorkspaceDefaultMembers, + /// Dependencies graph + pub resolve: Option, + /// Workspace root + pub workspace_root: Utf8PathBuf, + /// Target directory + pub target_directory: Utf8PathBuf, + /// Build directory + // TODO: This should become non optional once the MSRV is at or above `1.91.0` + pub build_directory: Option, + /// The workspace-level metadata object. Null if non-existent. + #[serde(rename = "metadata", default, skip_serializing_if = "is_null")] + pub workspace_metadata: serde_json::Value, + /// The metadata format version + version: usize, +} + +impl Metadata { + /// Get the workspace's root package of this metadata instance. + pub fn root_package(&self) -> Option<&Package> { + match &self.resolve { + Some(resolve) => { + // if dependencies are resolved, use Cargo's answer + let root = resolve.root.as_ref()?; + self.packages.iter().find(|pkg| &pkg.id == root) + } + None => { + // if dependencies aren't resolved, check for a root package manually + let root_manifest_path = self.workspace_root.join("Cargo.toml"); + self.packages + .iter() + .find(|pkg| pkg.manifest_path == root_manifest_path) + } + } + } + + /// Get the workspace packages. + pub fn workspace_packages(&self) -> Vec<&Package> { + self.packages + .iter() + .filter(|&p| self.workspace_members.contains(&p.id)) + .collect() + } + + /// Get the workspace default packages. + /// + /// # Panics + /// + /// This will panic if running with a version of Cargo older than 1.71. + pub fn workspace_default_packages(&self) -> Vec<&Package> { + self.packages + .iter() + .filter(|&p| self.workspace_default_members.contains(&p.id)) + .collect() + } +} + +impl<'a> std::ops::Index<&'a PackageId> for Metadata { + type Output = Package; + + fn index(&self, idx: &'a PackageId) -> &Self::Output { + self.packages + .iter() + .find(|p| p.id == *idx) + .unwrap_or_else(|| panic!("no package with this id: {idx:?}")) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash, Default)] +#[serde(transparent)] +/// A list of default workspace members. +/// +/// See [`Metadata::workspace_default_members`]. +/// +/// It is only available if running a version of Cargo of 1.71 or newer. +/// +/// # Panics +/// +/// Dereferencing when running an older version of Cargo will panic. +pub struct WorkspaceDefaultMembers(Option>); + +impl WorkspaceDefaultMembers { + /// Return `true` if the list of workspace default members is supported by + /// the called cargo-metadata version and `false` otherwise. + /// + /// In particular useful when parsing the output of `cargo-metadata` for + /// versions of Cargo < 1.71, as dereferencing [`WorkspaceDefaultMembers`] + /// for these versions will panic. + /// + /// Opposite of [`WorkspaceDefaultMembers::is_missing`]. + pub fn is_available(&self) -> bool { + self.0.is_some() + } + + /// Return `false` if the list of workspace default members is supported by + /// the called cargo-metadata version and `true` otherwise. + /// + /// In particular useful when parsing the output of `cargo-metadata` for + /// versions of Cargo < 1.71, as dereferencing [`WorkspaceDefaultMembers`] + /// for these versions will panic. + /// + /// Opposite of [`WorkspaceDefaultMembers::is_available`]. + pub fn is_missing(&self) -> bool { + self.0.is_none() + } +} + +impl core::ops::Deref for WorkspaceDefaultMembers { + type Target = [PackageId]; + + fn deref(&self) -> &Self::Target { + self.0 + .as_ref() + .expect("WorkspaceDefaultMembers should only be dereferenced on Cargo versions >= 1.71") + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency graph +pub struct Resolve { + /// Nodes in a dependencies graph + pub nodes: Vec, + + /// The crate for which the metadata was read. + pub root: Option, +} + +impl<'a> std::ops::Index<&'a PackageId> for Resolve { + type Output = Node; + + fn index(&self, idx: &'a PackageId) -> &Self::Output { + self.nodes + .iter() + .find(|p| p.id == *idx) + .unwrap_or_else(|| panic!("no Node with this id: {idx:?}")) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A node in a dependencies graph +pub struct Node { + /// An opaque identifier for a package + pub id: PackageId, + /// Dependencies in a structured format. + /// + /// `deps` handles renamed dependencies whereas `dependencies` does not. + #[serde(default)] + pub deps: Vec, + + /// List of opaque identifiers for this node's dependencies. + /// It doesn't support renamed dependencies. See `deps`. + pub dependencies: Vec, + + /// Features enabled on the crate + #[serde(default)] + pub features: Vec, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency in a node +pub struct NodeDep { + /// The name of the dependency's library target. + /// If the crate was renamed, it is the new name. + /// + /// If -Zbindeps is enabled local references may result in an empty + /// string. + /// + /// After -Zbindeps gets stabilized, cargo has indicated this field + /// will become deprecated. + pub name: String, + /// Package ID (opaque unique identifier) + pub pkg: PackageId, + /// The kinds of dependencies. + /// + /// This field was added in Rust 1.41. + #[serde(default)] + pub dep_kinds: Vec, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Information about a dependency kind. +pub struct DepKindInfo { + /// The kind of dependency. + #[serde(deserialize_with = "dependency::parse_dependency_kind")] + pub kind: DependencyKind, + /// The target platform for the dependency. + /// + /// This is `None` if it is not a target dependency. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// By default all platform dependencies are included in the resolve + /// graph. Use Cargo's `--filter-platform` flag if you only want to + /// include dependencies for a specific platform. + /// + /// [`Display`]: std::fmt::Display + pub target: Option, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// One or more crates described by a single `Cargo.toml` +/// +/// Each [`target`][Package::targets] of a `Package` will be built as a crate. +/// For more information, see . +pub struct Package { + /// The [`name` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field) as given in the `Cargo.toml` + // (We say "given in" instead of "specified in" since the `name` key cannot be inherited from the workspace.) + pub name: PackageName, + /// The [`version` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field) as specified in the `Cargo.toml` + pub version: Version, + /// The [`authors` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-authors-field) as specified in the `Cargo.toml` + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub authors: Vec, + /// An opaque identifier for a package + pub id: PackageId, + /// The source of the package, e.g. + /// crates.io or `None` for local projects. + // Note that this is NOT the same as cargo_util_schemas::RegistryName + #[cfg_attr(feature = "builder", builder(default))] + pub source: Option, + /// The [`description` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-description-field) as specified in the `Cargo.toml` + #[cfg_attr(feature = "builder", builder(default))] + pub description: Option, + /// List of dependencies of this particular package + #[cfg_attr(feature = "builder", builder(default))] + pub dependencies: Vec, + /// The [`license` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields) as specified in the `Cargo.toml` + #[cfg_attr(feature = "builder", builder(default))] + pub license: Option, + /// The [`license-file` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields) as specified in the `Cargo.toml`. + /// If the package is using a nonstandard license, this key may be specified instead of + /// `license`, and must point to a file relative to the manifest. + #[cfg_attr(feature = "builder", builder(default))] + pub license_file: Option, + /// Targets provided by the crate (lib, bin, example, test, ...) + #[cfg_attr(feature = "builder", builder(default))] + pub targets: Vec, + /// Features provided by the crate, mapped to the features required by that feature. + #[cfg_attr(feature = "builder", builder(default))] + pub features: BTreeMap>, + /// Path containing the `Cargo.toml` + pub manifest_path: Utf8PathBuf, + /// The [`categories` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-categories-field) as specified in the `Cargo.toml` + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub categories: Vec, + /// The [`keywords` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-keywords-field) as specified in the `Cargo.toml` + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub keywords: Vec, + /// The [`readme` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-readme-field) as specified in the `Cargo.toml` + #[cfg_attr(feature = "builder", builder(default))] + pub readme: Option, + /// The [`repository` URL](https://doc.rust-lang.org/cargo/reference/manifest.html#the-repository-field) as specified in the `Cargo.toml` + // can't use `url::Url` because that requires a more recent stable compiler + #[cfg_attr(feature = "builder", builder(default))] + pub repository: Option, + /// The [`homepage` URL](https://doc.rust-lang.org/cargo/reference/manifest.html#the-homepage-field) as specified in the `Cargo.toml`. + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + #[cfg_attr(feature = "builder", builder(default))] + pub homepage: Option, + /// The [`documentation` URL](https://doc.rust-lang.org/cargo/reference/manifest.html#the-documentation-field) as specified in the `Cargo.toml`. + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + #[cfg_attr(feature = "builder", builder(default))] + pub documentation: Option, + /// The default Rust edition for the package (either what's specified in the [`edition` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-edition-field) + /// or defaulting to [`Edition::E2015`]). + /// + /// Beware that individual targets may specify their own edition in + /// [`Target::edition`]. + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub edition: Edition, + /// Contents of the free form [`package.metadata` section](https://doc.rust-lang.org/cargo/reference/manifest.html#the-metadata-table). + /// + /// This contents can be serialized to a struct using serde: + /// + /// ```rust + /// use serde::Deserialize; + /// use serde_json::json; + /// + /// #[derive(Debug, Deserialize)] + /// struct SomePackageMetadata { + /// some_value: i32, + /// } + /// + /// let value = json!({ + /// "some_value": 42, + /// }); + /// + /// let package_metadata: SomePackageMetadata = serde_json::from_value(value).unwrap(); + /// assert_eq!(package_metadata.some_value, 42); + /// + /// ``` + #[serde(default, skip_serializing_if = "is_null")] + #[cfg_attr(feature = "builder", builder(default))] + pub metadata: serde_json::Value, + /// The name of a native library the package is linking to. + #[cfg_attr(feature = "builder", builder(default))] + pub links: Option, + /// List of registries to which this package may be published (derived from the [`publish` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field)). + /// + /// Publishing is unrestricted if `None`, and forbidden if the `Vec` is empty. + /// + /// This is always `None` if running with a version of Cargo older than 1.39. + #[cfg_attr(feature = "builder", builder(default))] + pub publish: Option>, + /// The [`default-run` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-default-run-field) as given in the `Cargo.toml` + // (We say "given in" instead of "specified in" since the `default-run` key cannot be inherited from the workspace.) + /// The default binary to run by `cargo run`. + /// + /// This is always `None` if running with a version of Cargo older than 1.55. + #[cfg_attr(feature = "builder", builder(default))] + pub default_run: Option, + /// The [`rust-version` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field) as specified in the `Cargo.toml`. + /// The minimum supported Rust version of this package. + /// + /// This is always `None` if running with a version of Cargo older than 1.58. + #[serde(default)] + #[serde(deserialize_with = "deserialize_rust_version")] + #[cfg_attr(feature = "builder", builder(default))] + pub rust_version: Option, +} + +#[cfg(feature = "builder")] +impl PackageBuilder { + /// Construct a new `PackageBuilder` with all required fields. + pub fn new( + name: impl Into, + version: impl Into, + id: impl Into, + path: impl Into, + ) -> Self { + Self::default() + .name(name) + .version(version) + .id(id) + .manifest_path(path) + } +} + +impl Package { + /// Full path to the license file if one is present in the manifest + pub fn license_file(&self) -> Option { + self.license_file.as_ref().map(|file| { + self.manifest_path + .parent() + .unwrap_or(&self.manifest_path) + .join(file) + }) + } + + /// Full path to the readme file if one is present in the manifest + pub fn readme(&self) -> Option { + self.readme.as_ref().map(|file| { + self.manifest_path + .parent() + .unwrap_or(&self.manifest_path) + .join(file) + }) + } +} + +/// The source of a package such as crates.io. +/// +/// It is possible to inspect the `repr` field, if the need arises, but its +/// precise format is an implementation detail and is subject to change. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[serde(transparent)] +pub struct Source { + /// The underlying string representation of a source. + pub repr: String, +} + +impl Source { + /// Returns true if the source is crates.io. + pub fn is_crates_io(&self) -> bool { + self.repr == "registry+https://github.com/rust-lang/crates.io-index" + } +} + +impl fmt::Display for Source { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +#[non_exhaustive] +/// A single target (lib, bin, example, ...) provided by a crate +pub struct Target { + /// Name as given in the `Cargo.toml` or generated from the file name + pub name: String, + /// Kind of target. + /// + /// The possible values are `example`, `test`, `bench`, `custom-build` and + /// [Cargo crate types](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field): + /// `bin`, `lib`, `rlib`, `dylib`, `cdylib`, `staticlib`, `proc-macro`. + /// + /// Other possible values may be added in the future. + pub kind: Vec, + /// Similar to `kind`, but only reports the + /// [Cargo crate types](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field): + /// `bin`, `lib`, `rlib`, `dylib`, `cdylib`, `staticlib`, `proc-macro`. + /// Everything that's not a proc macro or a library of some kind is reported as "bin". + /// + /// Other possible values may be added in the future. + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub crate_types: Vec, + + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + #[serde(rename = "required-features")] + /// This target is built only if these features are enabled. + /// It doesn't apply to `lib` targets. + pub required_features: Vec, + /// Path to the main source file of the target + pub src_path: Utf8PathBuf, + /// Rust edition for this target + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub edition: Edition, + /// Whether or not this target has doc tests enabled, and the target is + /// compatible with doc testing. + /// + /// This is always `true` if running with a version of Cargo older than 1.37. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doctest: bool, + /// Whether or not this target is tested by default by `cargo test`. + /// + /// This is always `true` if running with a version of Cargo older than 1.47. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub test: bool, + /// Whether or not this target is documented by `cargo doc`. + /// + /// This is always `true` if running with a version of Cargo older than 1.50. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doc: bool, +} + +macro_rules! methods_target_is_kind { + ($($name:ident => $kind:expr),*) => { + $( + /// Return true if this target is of kind `$kind`. + pub fn $name(&self) -> bool { + self.is_kind($kind) + } + )* + } +} + +impl Target { + /// Return true if this target is of the given kind. + pub fn is_kind(&self, name: TargetKind) -> bool { + self.kind.iter().any(|kind| kind == &name) + } + + // Generate `is_*` methods for each `TargetKind` + methods_target_is_kind! { + is_lib => TargetKind::Lib, + is_bin => TargetKind::Bin, + is_example => TargetKind::Example, + is_test => TargetKind::Test, + is_bench => TargetKind::Bench, + is_custom_build => TargetKind::CustomBuild, + is_proc_macro => TargetKind::ProcMacro, + is_cdylib => TargetKind::CDyLib, + is_dylib => TargetKind::DyLib, + is_rlib => TargetKind::RLib, + is_staticlib => TargetKind::StaticLib + } +} + +/// Kind of target. +/// +/// The possible values are `example`, `test`, `bench`, `custom-build` and +/// [Cargo crate types](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field): +/// `bin`, `lib`, `rlib`, `dylib`, `cdylib`, `staticlib`, `proc-macro`. +/// +/// Other possible values may be added in the future. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[non_exhaustive] +pub enum TargetKind { + /// `cargo bench` target + #[serde(rename = "bench")] + Bench, + /// Binary executable target + #[serde(rename = "bin")] + Bin, + /// Custom build target + #[serde(rename = "custom-build")] + CustomBuild, + /// Dynamic system library target + #[serde(rename = "cdylib")] + CDyLib, + /// Dynamic Rust library target + #[serde(rename = "dylib")] + DyLib, + /// Example target + #[serde(rename = "example")] + Example, + /// Rust library + #[serde(rename = "lib")] + Lib, + /// Procedural Macro + #[serde(rename = "proc-macro")] + ProcMacro, + /// Rust library for use as an intermediate artifact + #[serde(rename = "rlib")] + RLib, + /// Static system library + #[serde(rename = "staticlib")] + StaticLib, + /// Test target + #[serde(rename = "test")] + Test, + /// Unknown type + #[serde(untagged)] + Unknown(String), +} + +impl From<&str> for TargetKind { + fn from(value: &str) -> Self { + match value { + "example" => TargetKind::Example, + "test" => TargetKind::Test, + "bench" => TargetKind::Bench, + "custom-build" => TargetKind::CustomBuild, + "bin" => TargetKind::Bin, + "lib" => TargetKind::Lib, + "rlib" => TargetKind::RLib, + "dylib" => TargetKind::DyLib, + "cdylib" => TargetKind::CDyLib, + "staticlib" => TargetKind::StaticLib, + "proc-macro" => TargetKind::ProcMacro, + x => TargetKind::Unknown(x.to_string()), + } + } +} + +impl FromStr for TargetKind { + type Err = std::convert::Infallible; + + fn from_str(s: &str) -> std::result::Result { + Ok(TargetKind::from(s)) + } +} + +impl fmt::Display for TargetKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Bench => "bench".fmt(f), + Self::Bin => "bin".fmt(f), + Self::CustomBuild => "custom-build".fmt(f), + Self::CDyLib => "cdylib".fmt(f), + Self::DyLib => "dylib".fmt(f), + Self::Example => "example".fmt(f), + Self::Lib => "lib".fmt(f), + Self::ProcMacro => "proc-macro".fmt(f), + Self::RLib => "rlib".fmt(f), + Self::StaticLib => "staticlib".fmt(f), + Self::Test => "test".fmt(f), + Self::Unknown(x) => x.fmt(f), + } + } +} + +/// Similar to `kind`, but only reports the +/// [Cargo crate types](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field): +/// +/// `bin`, `lib`, `rlib`, `dylib`, `cdylib`, `staticlib`, `proc-macro`. +/// Everything that's not a proc macro or a library of some kind is reported as "bin". +/// +/// Other possible values may be added in the future. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[non_exhaustive] +pub enum CrateType { + /// Binary executable target + #[serde(rename = "bin")] + Bin, + /// Dynamic system library target + #[serde(rename = "cdylib")] + CDyLib, + /// Dynamic Rust library target + #[serde(rename = "dylib")] + DyLib, + /// Rust library + #[serde(rename = "lib")] + Lib, + /// Procedural Macro + #[serde(rename = "proc-macro")] + ProcMacro, + /// Rust library for use as an intermediate artifact + #[serde(rename = "rlib")] + RLib, + /// Static system library + #[serde(rename = "staticlib")] + StaticLib, + /// Unkown type + #[serde(untagged)] + Unknown(String), +} + +impl From<&str> for CrateType { + fn from(value: &str) -> Self { + match value { + "bin" => CrateType::Bin, + "lib" => CrateType::Lib, + "rlib" => CrateType::RLib, + "dylib" => CrateType::DyLib, + "cdylib" => CrateType::CDyLib, + "staticlib" => CrateType::StaticLib, + "proc-macro" => CrateType::ProcMacro, + x => CrateType::Unknown(x.to_string()), + } + } +} + +impl FromStr for CrateType { + type Err = std::convert::Infallible; + + fn from_str(s: &str) -> std::result::Result { + Ok(CrateType::from(s)) + } +} + +impl fmt::Display for CrateType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Bin => "bin".fmt(f), + Self::CDyLib => "cdylib".fmt(f), + Self::DyLib => "dylib".fmt(f), + Self::Lib => "lib".fmt(f), + Self::ProcMacro => "proc-macro".fmt(f), + Self::RLib => "rlib".fmt(f), + Self::StaticLib => "staticlib".fmt(f), + Self::Unknown(x) => x.fmt(f), + } + } +} + +/// The Rust edition +/// +/// As of writing this comment rust editions 2027 and 2030 are not actually a thing yet but are parsed nonetheless for future proofing. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[non_exhaustive] +#[derive(Default)] +pub enum Edition { + /// Edition 2015 + #[serde(rename = "2015")] + #[default] + E2015, + /// Edition 2018 + #[serde(rename = "2018")] + E2018, + /// Edition 2021 + #[serde(rename = "2021")] + E2021, + /// Edition 2024 + #[serde(rename = "2024")] + E2024, + #[doc(hidden)] + #[serde(rename = "2027")] + _E2027, + #[doc(hidden)] + #[serde(rename = "2030")] + _E2030, +} + +impl Edition { + /// Return the string representation of the edition + pub fn as_str(&self) -> &'static str { + use Edition::*; + match self { + E2015 => "2015", + E2018 => "2018", + E2021 => "2021", + E2024 => "2024", + _E2027 => "2027", + _E2030 => "2030", + } + } +} + +impl fmt::Display for Edition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +fn default_true() -> bool { + true +} + +/// Cargo features flags +#[derive(Debug, Clone)] +pub enum CargoOpt { + /// Run cargo with `--features-all` + AllFeatures, + /// Run cargo with `--no-default-features` + NoDefaultFeatures, + /// Run cargo with `--features ` + SomeFeatures(Vec), +} + +/// A builder for configuring `cargo metadata` invocation. +#[derive(Debug, Clone, Default)] +pub struct MetadataCommand { + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + cargo_path: Option, + /// Path to `Cargo.toml` + manifest_path: Option, + /// Current directory of the `cargo metadata` process. + current_dir: Option, + /// Output information only about workspace members and don't fetch dependencies. + no_deps: bool, + /// Collections of `CargoOpt::SomeFeatures(..)` + features: Vec, + /// Latched `CargoOpt::AllFeatures` + all_features: bool, + /// Latched `CargoOpt::NoDefaultFeatures` + no_default_features: bool, + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + other_options: Vec, + /// Arbitrary environment variables to set or remove (depending on + /// [`Option`] value) when running `cargo`. These will be merged into the + /// calling environment, overriding any which clash. + env: BTreeMap>, + /// Show stderr + verbose: bool, +} + +impl MetadataCommand { + /// Creates a default `cargo metadata` command, which will look for + /// `Cargo.toml` in the ancestors of the current directory. + pub fn new() -> MetadataCommand { + MetadataCommand::default() + } + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + pub fn cargo_path(&mut self, path: impl Into) -> &mut MetadataCommand { + self.cargo_path = Some(path.into()); + self + } + /// Path to `Cargo.toml` + pub fn manifest_path(&mut self, path: impl Into) -> &mut MetadataCommand { + self.manifest_path = Some(path.into()); + self + } + /// Current directory of the `cargo metadata` process. + pub fn current_dir(&mut self, path: impl Into) -> &mut MetadataCommand { + self.current_dir = Some(path.into()); + self + } + /// Output information only about workspace members and don't fetch dependencies. + pub fn no_deps(&mut self) -> &mut MetadataCommand { + self.no_deps = true; + self + } + /// Which features to include. + /// + /// Call this multiple times to specify advanced feature configurations: + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::SomeFeatures(vec!["feat1".into(), "feat2".into()])) + /// .features(CargoOpt::SomeFeatures(vec!["feat3".into()])) + /// // ... + /// # ; + /// ``` + /// + /// # Panics + /// + /// `cargo metadata` rejects multiple `--no-default-features` flags. Similarly, the `features()` + /// method panics when specifying multiple `CargoOpt::NoDefaultFeatures`: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::NoDefaultFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + /// + /// The method also panics for multiple `CargoOpt::AllFeatures` arguments: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::AllFeatures) + /// .features(CargoOpt::AllFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + pub fn features(&mut self, features: CargoOpt) -> &mut MetadataCommand { + match features { + CargoOpt::SomeFeatures(features) => self.features.extend(features), + CargoOpt::NoDefaultFeatures => { + assert!( + !self.no_default_features, + "Do not supply CargoOpt::NoDefaultFeatures more than once!" + ); + self.no_default_features = true; + } + CargoOpt::AllFeatures => { + assert!( + !self.all_features, + "Do not supply CargoOpt::AllFeatures more than once!" + ); + self.all_features = true; + } + } + self + } + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + pub fn other_options(&mut self, options: impl Into>) -> &mut MetadataCommand { + self.other_options = options.into(); + self + } + + /// Arbitrary environment variables to set when running `cargo`. These will be merged into + /// the calling environment, overriding any which clash. + /// + /// Some examples of when you may want to use this: + /// 1. Setting cargo config values without needing a .cargo/config.toml file, e.g. to set + /// `CARGO_NET_GIT_FETCH_WITH_CLI=true` + /// 2. To specify a custom path to RUSTC if your rust toolchain components aren't laid out in + /// the way cargo expects by default. + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .env("CARGO_NET_GIT_FETCH_WITH_CLI", "true") + /// .env("RUSTC", "/path/to/rustc") + /// // ... + /// # ; + /// ``` + pub fn env, V: Into>( + &mut self, + key: K, + val: V, + ) -> &mut MetadataCommand { + self.env.insert(key.into(), Some(val.into())); + self + } + + /// Arbitrary environment variables to remove when running `cargo`. These will be merged into + /// the calling environment, overriding any which clash. + /// + /// Some examples of when you may want to use this: + /// - Removing inherited environment variables in build scripts that can cause an error + /// when calling `cargo metadata` (for example, when cross-compiling). + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .env_remove("CARGO_ENCODED_RUSTFLAGS") + /// // ... + /// # ; + /// ``` + pub fn env_remove>(&mut self, key: K) -> &mut MetadataCommand { + self.env.insert(key.into(), None); + self + } + + /// Set whether to show stderr + pub fn verbose(&mut self, verbose: bool) -> &mut MetadataCommand { + self.verbose = verbose; + self + } + + /// Builds a command for `cargo metadata`. This is the first + /// part of the work of `exec`. + pub fn cargo_command(&self) -> Command { + let cargo = self + .cargo_path + .clone() + .or_else(|| env::var("CARGO").map(PathBuf::from).ok()) + .unwrap_or_else(|| PathBuf::from("cargo")); + let mut cmd = Command::new(cargo); + cmd.args(["metadata", "--format-version", "1"]); + + if self.no_deps { + cmd.arg("--no-deps"); + } + + if let Some(path) = self.current_dir.as_ref() { + cmd.current_dir(path); + } + + if !self.features.is_empty() { + cmd.arg("--features").arg(self.features.join(",")); + } + if self.all_features { + cmd.arg("--all-features"); + } + if self.no_default_features { + cmd.arg("--no-default-features"); + } + + if let Some(manifest_path) = &self.manifest_path { + cmd.arg("--manifest-path").arg(manifest_path.as_os_str()); + } + cmd.args(&self.other_options); + + for (key, val) in &self.env { + match val { + Some(val) => cmd.env(key, val), + None => cmd.env_remove(key), + }; + } + + cmd + } + + /// Parses `cargo metadata` output. `data` must have been + /// produced by a command built with `cargo_command`. + pub fn parse>(data: T) -> Result { + let meta = serde_json::from_str(data.as_ref())?; + Ok(meta) + } + + /// Runs configured `cargo metadata` and returns parsed `Metadata`. + pub fn exec(&self) -> Result { + let mut command = self.cargo_command(); + if self.verbose { + command.stderr(Stdio::inherit()); + } + let output = command.output()?; + if !output.status.success() { + return Err(Error::CargoMetadata { + stderr: String::from_utf8(output.stderr)?, + }); + } + let stdout = from_utf8(&output.stdout)? + .lines() + .find(|line| line.starts_with('{')) + .ok_or(Error::NoJson)?; + Self::parse(stdout) + } +} + +/// As per the Cargo Book the [`rust-version` field](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field) must: +/// +/// > be a bare version number with two or three components; +/// > it cannot include semver operators or pre-release identifiers. +/// +/// [`semver::Version`] however requires three components. This function takes +/// care of appending `.0` if the provided version number only has two components +/// and ensuring that it does not contain a pre-release version or build metadata. +fn deserialize_rust_version<'de, D>( + deserializer: D, +) -> std::result::Result, D::Error> +where + D: Deserializer<'de>, +{ + let mut buf = match Option::::deserialize(deserializer)? { + None => return Ok(None), + Some(buf) => buf, + }; + + for char in buf.chars() { + if char == '-' { + return Err(serde::de::Error::custom( + "pre-release identifiers are not supported in rust-version", + )); + } else if char == '+' { + return Err(serde::de::Error::custom( + "build metadata is not supported in rust-version", + )); + } + } + + if buf.matches('.').count() == 1 { + // e.g. 1.0 -> 1.0.0 + buf.push_str(".0"); + } + + Ok(Some( + Version::parse(&buf).map_err(serde::de::Error::custom)?, + )) +} + +#[cfg(test)] +mod test { + use semver::Version; + + #[derive(Debug, serde::Deserialize)] + struct BareVersion( + #[serde(deserialize_with = "super::deserialize_rust_version")] Option, + ); + + fn bare_version(str: &str) -> Version { + serde_json::from_str::(&format!(r#""{}""#, str)) + .unwrap() + .0 + .unwrap() + } + + fn bare_version_err(str: &str) -> String { + serde_json::from_str::(&format!(r#""{}""#, str)) + .unwrap_err() + .to_string() + } + + #[test] + fn test_deserialize_rust_version() { + assert_eq!(bare_version("1.2"), Version::new(1, 2, 0)); + assert_eq!(bare_version("1.2.0"), Version::new(1, 2, 0)); + assert_eq!( + bare_version_err("1.2.0-alpha"), + "pre-release identifiers are not supported in rust-version" + ); + assert_eq!( + bare_version_err("1.2.0+123"), + "build metadata is not supported in rust-version" + ); + } + + #[test] + fn package_name_eq() { + let my_package_name = super::PackageName::new("my_package"); + assert_eq!(my_package_name, "my_package"); + } +} diff --git a/anneal/v2/vendor/cargo_metadata/src/libtest.rs b/anneal/v2/vendor/cargo_metadata/src/libtest.rs new file mode 100644 index 0000000000..4de86e7d24 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/libtest.rs @@ -0,0 +1,165 @@ +//! Parses output of [libtest](https://github.com/rust-lang/rust/blob/master/library/test/src/formatters/json.rs). +//! +//! Since this module parses output in an unstable format, all structs in this module may change at any time, and are exempt from semver guarantees. +use serde::{Deserialize, Serialize}; + +/// Suite related event +#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[serde(tag = "event")] +#[serde(rename_all = "lowercase")] +/// Suite event +pub enum SuiteEvent { + /// emitted on the start of a test run, and the start of the doctests + Started { + /// number of tests in this suite + test_count: usize, + }, + /// the suite has finished + Ok { + /// the number of tests that passed + passed: usize, + /// the number of tests that failed + failed: usize, + /// number of tests that were ignored + ignored: usize, + /// number of benchmarks run + measured: usize, + /// i think this is based on what you specify in the cargo test argument + filtered_out: usize, + /// how long the suite took to run + exec_time: f32, + }, + /// the suite has at least one failing test + Failed { + /// the number of tests that passed + passed: usize, + /// the number of tests that failed + failed: usize, + /// number of tests that were ignored + ignored: usize, + /// i think its something to do with benchmarks? + measured: usize, + /// i think this is based on what you specify in the cargo test argument + filtered_out: usize, + /// how long the suite took to run + exec_time: f32, + }, +} + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[serde(tag = "event")] +#[serde(rename_all = "lowercase")] +/// Test event +pub enum TestEvent { + /// a new test starts + Started { + /// the name of this test + name: String, + }, + /// the test has finished + Ok { + /// which one + name: String, + /// in how long + exec_time: f32, + /// what did it say? + stdout: Option, + }, + /// the test has failed + Failed { + /// which one + name: String, + /// in how long + exec_time: f32, + /// why? + stdout: Option, + /// it timed out? + reason: Option, + /// what message + message: Option, + }, + /// the test has been ignored + Ignored { + /// which one + name: String, + }, + /// the test has timed out + Timeout { + /// which one + name: String, + }, +} + +impl TestEvent { + /// Get the name of this test + pub fn name(&self) -> &str { + let (Self::Started { name } + | Self::Ok { name, .. } + | Self::Ignored { name } + | Self::Failed { name, .. } + | Self::Timeout { name }) = self; + name + } + + /// Get the stdout of this test, if available. + pub fn stdout(&self) -> Option<&str> { + match self { + Self::Ok { stdout, .. } | Self::Failed { stdout, .. } => stdout.as_deref(), + _ => None, + } + } +} + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +/// Represents the output of `cargo test -- -Zunstable-options --report-time --show-output --format json`. +/// +/// requires --report-time +/// +/// # Stability +/// +/// As this struct is for interfacing with the unstable libtest json output, this struct may change at any time, without semver guarantees. +#[serde(tag = "type")] +#[serde(rename_all = "lowercase")] +pub enum TestMessage { + /// suite related message + Suite(SuiteEvent), + /// test related message + Test(TestEvent), + /// bench related message + Bench { + /// name of benchmark + name: String, + /// distribution + median: f32, + /// deviation + deviation: f32, + /// thruput in MiB per second + mib_per_second: Option, + }, +} + +#[test] +fn deser() { + macro_rules! run { + ($($input:literal parses to $output:expr),+) => { + $(assert_eq!(dbg!(serde_json::from_str::($input)).unwrap(), $output);)+ + }; + } + run![ + r#"{ "type": "suite", "event": "started", "test_count": 2 }"# parses to TestMessage::Suite(SuiteEvent::Started { test_count: 2 }), + r#"{ "type": "test", "event": "started", "name": "fail" }"# parses to TestMessage::Test(TestEvent::Started { name: "fail".into() }), + r#"{ "type": "test", "name": "fail", "event": "ok", "exec_time": 0.000003428, "stdout": "hello world" }"# parses to TestMessage::Test(TestEvent::Ok { name: "fail".into(), exec_time: 0.000003428, stdout: Some("hello world".into()) }), + r#"{ "type": "test", "event": "started", "name": "nope" }"# parses to TestMessage::Test(TestEvent::Started { name: "nope".into() }), + r#"{ "type": "test", "name": "nope", "event": "ignored" }"# parses to TestMessage::Test(TestEvent::Ignored { name: "nope".into() }), + r#"{ "type": "suite", "event": "ok", "passed": 1, "failed": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": 0.000684028 }"# parses to TestMessage::Suite(SuiteEvent::Ok { passed: 1, failed: 0, ignored: 1, measured: 0, filtered_out: 0, exec_time: 0.000684028 }) + ]; + + run![ + r#"{ "type": "suite", "event": "started", "test_count": 2 }"# parses to TestMessage::Suite(SuiteEvent::Started { test_count: 2 }), + r#"{ "type": "test", "event": "started", "name": "fail" }"# parses to TestMessage::Test(TestEvent::Started { name: "fail".into() }), + r#"{ "type": "test", "event": "started", "name": "benc" }"# parses to TestMessage::Test(TestEvent::Started { name: "benc".into() }), + r#"{ "type": "bench", "name": "benc", "median": 0, "deviation": 0 }"# parses to TestMessage::Bench { name: "benc".into(), median: 0., deviation: 0., mib_per_second: None }, + r#"{ "type": "test", "name": "fail", "event": "failed", "exec_time": 0.000081092, "stdout": "thread 'fail' panicked" }"# parses to TestMessage::Test(TestEvent::Failed { name: "fail".into(), exec_time: 0.000081092, stdout: Some("thread 'fail' panicked".into()), reason: None, message: None} ), + r#"{ "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 1, "filtered_out": 0, "exec_time": 0.000731068 }"# parses to TestMessage::Suite(SuiteEvent::Failed { passed: 0, failed: 1, ignored: 0, measured: 1, filtered_out: 0, exec_time: 0.000731068 }) + ]; +} diff --git a/anneal/v2/vendor/cargo_metadata/src/messages.rs b/anneal/v2/vendor/cargo_metadata/src/messages.rs new file mode 100644 index 0000000000..10d82090ed --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/src/messages.rs @@ -0,0 +1,297 @@ +use super::{Diagnostic, PackageId, Target}; +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{de, ser, Deserialize, Serialize}; +use std::fmt::{self, Write}; +use std::io::{self, BufRead, Read}; + +/// Profile settings used to determine which compiler flags to use for a +/// target. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct ArtifactProfile { + /// Optimization level. Possible values are 0-3, s or z. + pub opt_level: String, + /// The kind of debug information. + #[serde(default)] + pub debuginfo: ArtifactDebuginfo, + /// State of the `cfg(debug_assertions)` directive, enabling macros like + /// `debug_assert!` + pub debug_assertions: bool, + /// State of the overflow checks. + pub overflow_checks: bool, + /// Whether this profile is a test + pub test: bool, +} + +/// The kind of debug information included in the artifact. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +#[non_exhaustive] +pub enum ArtifactDebuginfo { + /// No debug information. + #[default] + None, + /// Line directives only. + LineDirectivesOnly, + /// Line tables only. + LineTablesOnly, + /// Debug information without type or variable-level information. + Limited, + /// Full debug information. + Full, + /// An unknown integer level. + /// + /// This may be produced by a version of rustc in the future that has + /// additional levels represented by an integer that are not known by this + /// version of `cargo_metadata`. + UnknownInt(i64), + /// An unknown string level. + /// + /// This may be produced by a version of rustc in the future that has + /// additional levels represented by a string that are not known by this + /// version of `cargo_metadata`. + UnknownString(String), +} + +impl ser::Serialize for ArtifactDebuginfo { + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + match self { + Self::None => 0.serialize(serializer), + Self::LineDirectivesOnly => "line-directives-only".serialize(serializer), + Self::LineTablesOnly => "line-tables-only".serialize(serializer), + Self::Limited => 1.serialize(serializer), + Self::Full => 2.serialize(serializer), + Self::UnknownInt(n) => n.serialize(serializer), + Self::UnknownString(s) => s.serialize(serializer), + } + } +} + +impl<'de> de::Deserialize<'de> for ArtifactDebuginfo { + fn deserialize(d: D) -> Result + where + D: de::Deserializer<'de>, + { + struct Visitor; + + impl de::Visitor<'_> for Visitor { + type Value = ArtifactDebuginfo; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("an integer or string") + } + + fn visit_i64(self, value: i64) -> Result + where + E: de::Error, + { + let debuginfo = match value { + 0 => ArtifactDebuginfo::None, + 1 => ArtifactDebuginfo::Limited, + 2 => ArtifactDebuginfo::Full, + n => ArtifactDebuginfo::UnknownInt(n), + }; + Ok(debuginfo) + } + + fn visit_u64(self, value: u64) -> Result + where + E: de::Error, + { + self.visit_i64(value as i64) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + let debuginfo = match value { + "none" => ArtifactDebuginfo::None, + "limited" => ArtifactDebuginfo::Limited, + "full" => ArtifactDebuginfo::Full, + "line-directives-only" => ArtifactDebuginfo::LineDirectivesOnly, + "line-tables-only" => ArtifactDebuginfo::LineTablesOnly, + s => ArtifactDebuginfo::UnknownString(s.to_string()), + }; + Ok(debuginfo) + } + + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(ArtifactDebuginfo::None) + } + } + + d.deserialize_any(Visitor) + } +} + +impl fmt::Display for ArtifactDebuginfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ArtifactDebuginfo::None => f.write_char('0'), + ArtifactDebuginfo::Limited => f.write_char('1'), + ArtifactDebuginfo::Full => f.write_char('2'), + ArtifactDebuginfo::LineDirectivesOnly => f.write_str("line-directives-only"), + ArtifactDebuginfo::LineTablesOnly => f.write_str("line-tables-only"), + ArtifactDebuginfo::UnknownInt(n) => write!(f, "{n}"), + ArtifactDebuginfo::UnknownString(s) => f.write_str(s), + } + } +} + +/// A compiler-generated file. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Artifact { + /// The package this artifact belongs to + pub package_id: PackageId, + /// Path to the `Cargo.toml` file + #[serde(default)] + pub manifest_path: Utf8PathBuf, + /// The target this artifact was compiled for + pub target: Target, + /// The profile this artifact was compiled with + pub profile: ArtifactProfile, + /// The enabled features for this artifact + pub features: Vec, + /// The full paths to the generated artifacts + /// (e.g. binary file and separate debug info) + pub filenames: Vec, + /// Path to the executable file + pub executable: Option, + /// If true, then the files were already generated + pub fresh: bool, +} + +/// Message left by the compiler +// TODO: Better name. This one comes from machine_message.rs +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct CompilerMessage { + /// The package this message belongs to + pub package_id: PackageId, + /// The target this message is aimed at + pub target: Target, + /// The message the compiler sent. + pub message: Diagnostic, +} + +/// Output of a build script execution. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildScript { + /// The package this build script execution belongs to + pub package_id: PackageId, + /// The libs to link + pub linked_libs: Vec, + /// The paths to search when resolving libs + pub linked_paths: Vec, + /// Various `--cfg` flags to pass to the compiler + pub cfgs: Vec, + /// The environment variables to add to the compilation + pub env: Vec<(String, String)>, + /// The `OUT_DIR` environment variable where this script places its output + /// + /// Added in Rust 1.41. + #[serde(default)] + pub out_dir: Utf8PathBuf, +} + +/// Final result of a build. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildFinished { + /// Whether or not the build finished successfully. + pub success: bool, +} + +/// A cargo message +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(tag = "reason", rename_all = "kebab-case")] +pub enum Message { + /// The compiler generated an artifact + CompilerArtifact(Artifact), + /// The compiler wants to display a message + CompilerMessage(CompilerMessage), + /// A build script successfully executed. + BuildScriptExecuted(BuildScript), + /// The build has finished. + /// + /// This is emitted at the end of the build as the last message. + /// Added in Rust 1.44. + BuildFinished(BuildFinished), + /// A line of text which isn't a cargo or compiler message. + /// Line separator is not included + #[serde(skip)] + TextLine(String), +} + +impl Message { + /// Creates an iterator of Message from a Read outputting a stream of JSON + /// messages. For usage information, look at the top-level documentation. + pub fn parse_stream(input: R) -> MessageIter { + MessageIter { input } + } +} + +impl fmt::Display for CompilerMessage { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.message) + } +} + +/// An iterator of Messages. +pub struct MessageIter { + input: R, +} + +impl Iterator for MessageIter { + type Item = io::Result; + fn next(&mut self) -> Option { + let mut line = String::new(); + self.input + .read_line(&mut line) + .map(|n| { + if n == 0 { + None + } else { + if line.ends_with('\n') { + line.truncate(line.len() - 1); + } + let mut deserializer = serde_json::Deserializer::from_str(&line); + deserializer.disable_recursion_limit(); + Some(Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(line))) + } + }) + .transpose() + } +} + +/// An iterator of Message. +type MessageIterator = + serde_json::StreamDeserializer<'static, serde_json::de::IoRead, Message>; + +/// Creates an iterator of Message from a Read outputting a stream of JSON +/// messages. For usage information, look at the top-level documentation. +#[deprecated(note = "Use Message::parse_stream instead")] +pub fn parse_messages(input: R) -> MessageIterator { + serde_json::Deserializer::from_reader(input).into_iter::() +} diff --git a/anneal/v2/vendor/cargo_metadata/tests/selftest.rs b/anneal/v2/vendor/cargo_metadata/tests/selftest.rs new file mode 100644 index 0000000000..35bc4180e2 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/tests/selftest.rs @@ -0,0 +1,214 @@ +use std::env::current_dir; +use std::path::PathBuf; + +use semver::Version; + +use cargo_metadata::{CargoOpt, Error, MetadataCommand}; +use serde::Deserialize; + +#[derive(Debug, PartialEq, Eq, Deserialize)] +struct TestPackageMetadata { + some_field: bool, + other_field: String, +} + +#[test] +fn metadata() { + let metadata = MetadataCommand::new().no_deps().exec().unwrap(); + + let this = &metadata.packages[0]; + assert_eq!(this.name.as_str(), "cargo_metadata"); + assert_eq!(this.targets.len(), 3); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib".into()); + assert_eq!(lib.crate_types[0], "lib".into()); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test".into()); + assert_eq!(selftest.crate_types[0], "bin".into()); + + let package_metadata = &metadata.packages[0] + .metadata + .as_object() + .expect("package.metadata must be a table."); + // The second field is docs.rs metadata, ignore it + assert_eq!(package_metadata.len(), 2); + + let value = package_metadata.get("cargo_metadata_test").unwrap(); + let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone()).unwrap(); + assert_eq!( + test_package_metadata, + TestPackageMetadata { + some_field: true, + other_field: "foo".into(), + } + ); +} + +#[test] +fn builder_interface() { + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(String::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(PathBuf::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .no_deps() + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .current_dir(current_dir().unwrap()) + .exec() + .unwrap(); +} + +#[test] +fn error1() { + let manifest_path = current_dir().unwrap().join("foo"); + let error = "error: the manifest-path must be a path to a Cargo.toml file"; + let error_with_path = format!("{error}: `{}`", manifest_path.display()); + match MetadataCommand::new().manifest_path("foo").exec() { + Err(Error::CargoMetadata { stderr }) => { + assert!([error, &error_with_path].contains(&stderr.trim())) + } + _ => unreachable!(), + } +} + +#[test] +fn error2() { + match MetadataCommand::new() + .manifest_path("foo/Cargo.toml") + .exec() + { + Err(Error::CargoMetadata { stderr }) => assert_eq!( + stderr.trim(), + "error: manifest path `foo/Cargo.toml` does not exist" + ), + _ => unreachable!(), + } +} + +#[test] +fn cargo_path() { + match MetadataCommand::new() + .cargo_path("this does not exist") + .exec() + { + Err(Error::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::NotFound), + _ => unreachable!(), + } +} + +#[test] +fn metadata_deps() { + std::env::set_var("CARGO_PROFILE", "3"); + let metadata = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let this_id = metadata + .workspace_members + .first() + .expect("Did not find ourselves"); + let this = &metadata[this_id]; + + assert_eq!(this.name.as_str(), "cargo_metadata"); + + let workspace_packages = metadata.workspace_packages(); + assert_eq!(workspace_packages.len(), 1); + assert_eq!(&workspace_packages[0].id, this_id); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib".into()); + assert_eq!(lib.crate_types[0], "lib".into()); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test".into()); + assert_eq!(selftest.crate_types[0], "bin".into()); + + let dependencies = &this.dependencies; + + let serde = dependencies + .iter() + .find(|dep| dep.name == "serde") + .expect("Did not find serde dependency"); + + assert_eq!(serde.kind, cargo_metadata::DependencyKind::Normal); + assert!(!serde.req.matches(&Version::parse("1.0.0").unwrap())); + assert!(serde.req.matches(&Version::parse("1.99.99").unwrap())); + assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap())); +} + +#[test] +fn workspace_default_packages() { + let metadata = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let workspace_packages = metadata.workspace_packages(); + // this will only trigger on cargo versions that expose + // workspace_default_members (that is, cargo >= 1.71) + if metadata.workspace_default_members.is_available() { + let default_packages = metadata.workspace_default_packages(); + assert_eq!(default_packages, workspace_packages); + } +} + +fn cargo_version() -> semver::Version { + let output = std::process::Command::new("cargo") + .arg("-V") + .output() + .expect("Failed to exec cargo."); + let out = std::str::from_utf8(&output.stdout) + .expect("invalid utf8") + .trim(); + let split: Vec<&str> = out.split_whitespace().collect(); + assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out); + let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed"); + // Don't care about metadata, it is awkward to compare. + ver.pre = semver::Prerelease::EMPTY; + ver.build = semver::BuildMetadata::EMPTY; + ver +} + +#[test] +fn build_dir() { + let metadata = MetadataCommand::new().no_deps().exec().unwrap(); + let ver = cargo_version(); + let minimum = semver::Version::parse("1.91.0").unwrap(); + if ver >= minimum { + assert!(&metadata.build_directory.is_some()); + assert!(&metadata + .build_directory + .unwrap() + .ends_with("cargo_metadata/target")); + } else { + assert!(&metadata.build_directory.is_none()); + } +} diff --git a/anneal/v2/vendor/cargo_metadata/tests/test_samples.rs b/anneal/v2/vendor/cargo_metadata/tests/test_samples.rs new file mode 100644 index 0000000000..95a8ab88a0 --- /dev/null +++ b/anneal/v2/vendor/cargo_metadata/tests/test_samples.rs @@ -0,0 +1,961 @@ +extern crate cargo_metadata; +extern crate semver; +#[macro_use] +extern crate serde_json; + +use camino::Utf8PathBuf; +use cargo_metadata::{ + ArtifactDebuginfo, CargoOpt, DependencyKind, Edition, FeatureName, Message, Metadata, + MetadataCommand, Source, +}; + +/// Output from oldest version ever supported (1.24). +/// +/// This intentionally has as many null fields as possible. +/// 1.8 is when metadata was introduced. +/// Older versions not supported because the following are required: +/// - `workspace_members` added in 1.13 +/// - `target_directory` added in 1.19 +/// - `workspace_root` added in 1.24 +const JSON_OLD_MINIMAL: &str = r#" +{ + "packages": [ + { + "name": "foo", + "version": "0.1.0", + "id": "foo 0.1.0 (path+file:///foo)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "somedep", + "source": null, + "req": "^1.0", + "kind": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null + } + ], + "targets": [ + { + "kind": [ + "bin" + ], + "crate_types": [ + "bin" + ], + "name": "foo", + "src_path": "/foo/src/main.rs" + } + ], + "features": {}, + "manifest_path": "/foo/Cargo.toml" + } + ], + "workspace_members": [ + "foo 0.1.0 (path+file:///foo)" + ], + "resolve": null, + "target_directory": "/foo/target", + "version": 1, + "workspace_root": "/foo" +} +"#; + +#[test] +fn old_minimal() { + let meta: Metadata = serde_json::from_str(JSON_OLD_MINIMAL).unwrap(); + assert_eq!(meta.packages.len(), 1); + let pkg = &meta.packages[0]; + assert_eq!(pkg.name.as_str(), "foo"); + assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(pkg.authors.len(), 0); + assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)"); + assert_eq!(pkg.description, None); + assert_eq!(pkg.license, None); + assert_eq!(pkg.license_file, None); + assert_eq!(pkg.default_run, None); + assert_eq!(pkg.rust_version, None); + assert_eq!(pkg.dependencies.len(), 1); + let dep = &pkg.dependencies[0]; + assert_eq!(dep.name, "somedep"); + assert_eq!(dep.source, None); + assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap()); + assert_eq!(dep.kind, DependencyKind::Normal); + assert!(!dep.optional); + assert!(dep.uses_default_features); + assert_eq!(dep.features.len(), 0); + assert!(dep.target.is_none()); + assert_eq!(dep.rename, None); + assert_eq!(dep.registry, None); + assert_eq!(pkg.targets.len(), 1); + let target = &pkg.targets[0]; + assert_eq!(target.name, "foo"); + assert_eq!(target.kind, vec!["bin".into()]); + assert_eq!(target.crate_types, vec!["bin".into()]); + assert_eq!(target.required_features.len(), 0); + assert_eq!(target.src_path, "/foo/src/main.rs"); + assert_eq!(target.edition, Edition::E2015); + assert!(target.doctest); + assert!(target.test); + assert!(target.doc); + assert_eq!(pkg.features.len(), 0); + assert_eq!(pkg.manifest_path, "/foo/Cargo.toml"); + assert_eq!(pkg.categories.len(), 0); + assert_eq!(pkg.keywords.len(), 0); + assert_eq!(pkg.readme, None); + assert_eq!(pkg.repository, None); + assert_eq!(pkg.homepage, None); + assert_eq!(pkg.documentation, None); + assert_eq!(pkg.edition, Edition::E2015); + assert_eq!(pkg.metadata, serde_json::Value::Null); + assert_eq!(pkg.links, None); + assert_eq!(pkg.publish, None); + assert_eq!(meta.workspace_members.len(), 1); + assert_eq!( + meta.workspace_members[0].to_string(), + "foo 0.1.0 (path+file:///foo)" + ); + assert!(meta.resolve.is_none()); + assert_eq!(meta.workspace_root, "/foo"); + assert_eq!(meta.workspace_metadata, serde_json::Value::Null); + assert_eq!(meta.target_directory, "/foo/target"); + + assert!(!meta.workspace_default_members.is_available()); + assert!(meta.workspace_default_members.is_missing()); + + let serialized = serde_json::to_value(meta).unwrap(); + assert!(!serialized + .as_object() + .unwrap() + .contains_key("workspace_default_members")); +} + +macro_rules! sorted { + ($e:expr) => {{ + let mut v = $e.clone(); + v.sort(); + v + }}; +} + +macro_rules! features { + ($($feat:expr),* $(,)?) => { + ::std::vec![ + $(FeatureName::new(String::from($feat))),* + ] + }; +} + +fn cargo_version() -> semver::Version { + let output = std::process::Command::new("cargo") + .arg("-V") + .output() + .expect("Failed to exec cargo."); + let out = std::str::from_utf8(&output.stdout) + .expect("invalid utf8") + .trim(); + let split: Vec<&str> = out.split_whitespace().collect(); + assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out); + let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed"); + // Don't care about metadata, it is awkward to compare. + ver.pre = semver::Prerelease::EMPTY; + ver.build = semver::BuildMetadata::EMPTY; + ver +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct WorkspaceMetadata { + testobject: TestObject, +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct TestObject { + myvalue: String, +} + +#[test] +fn all_the_fields() { + // All the fields currently generated as of 1.60. This tries to exercise as + // much as possible. + let ver = cargo_version(); + let minimum = semver::Version::parse("1.56.0").unwrap(); + if ver < minimum { + // edition added in 1.30 + // rename added in 1.31 + // links added in 1.33 + // doctest added in 1.37 + // publish added in 1.39 + // dep_kinds added in 1.41 + // test added in 1.47 + // homepage added in 1.49 + // documentation added in 1.49 + // doc added in 1.50 + // path added in 1.51 + // default_run added in 1.55 + // rust_version added in 1.58 + // workspace_default_members added in 1.71 + eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver); + return; + } + let meta = MetadataCommand::new() + .manifest_path("tests/all/Cargo.toml") + .exec() + .unwrap(); + assert_eq!(meta.workspace_root.file_name().unwrap(), "all"); + assert_eq!( + serde_json::from_value::(meta.workspace_metadata.clone()).unwrap(), + WorkspaceMetadata { + testobject: TestObject { + myvalue: "abc".to_string() + } + } + ); + assert_eq!(meta.workspace_members.len(), 1); + assert!(meta.workspace_members[0].to_string().contains("all")); + if ver >= semver::Version::parse("1.71.0").unwrap() { + assert_eq!(&*meta.workspace_default_members, &meta.workspace_members); + } + + assert_eq!(meta.packages.len(), 9); + let all = meta + .packages + .iter() + .find(|p| p.name.as_str() == "all") + .unwrap(); + assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(all.authors, vec!["Jane Doe "]); + assert!(all.id.to_string().contains("all")); + assert_eq!(all.description, Some("Package description.".to_string())); + assert_eq!(all.license, Some("MIT/Apache-2.0".to_string())); + assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE"))); + assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE")); + assert_eq!(all.publish, Some(vec![])); + assert_eq!(all.links, Some("foo".to_string())); + assert_eq!(all.default_run, Some("otherbin".to_string())); + if ver >= semver::Version::parse("1.58.0").unwrap() { + assert_eq!( + all.rust_version, + Some(semver::Version::parse("1.56.0").unwrap()) + ); + } + + assert_eq!(all.dependencies.len(), 8); + let bitflags = all + .dependencies + .iter() + .find(|d| d.name == "bitflags") + .unwrap(); + assert_eq!( + bitflags.source, + Some(Source { + repr: "registry+https://github.com/rust-lang/crates.io-index".to_string() + }) + ); + assert!(bitflags.optional); + assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap()); + + let path_dep = all + .dependencies + .iter() + .find(|d| d.name == "path-dep") + .unwrap(); + assert_eq!(path_dep.source, None); + assert_eq!(path_dep.kind, DependencyKind::Normal); + assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap()); + assert_eq!( + path_dep.path.as_ref().map(|p| p.ends_with("path-dep")), + Some(true), + ); + + all.dependencies + .iter() + .find(|d| d.name == "namedep") + .unwrap(); + + let featdep = all + .dependencies + .iter() + .find(|d| d.name == "featdep") + .unwrap(); + assert_eq!(featdep.features, vec!["i128"]); + assert!(!featdep.uses_default_features); + + let renamed = all + .dependencies + .iter() + .find(|d| d.name == "oldname") + .unwrap(); + assert_eq!(renamed.rename, Some("newname".to_string())); + + let devdep = all + .dependencies + .iter() + .find(|d| d.name == "devdep") + .unwrap(); + assert_eq!(devdep.kind, DependencyKind::Development); + + let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap(); + assert_eq!(bdep.kind, DependencyKind::Build); + + let windep = all + .dependencies + .iter() + .find(|d| d.name == "windep") + .unwrap(); + assert_eq!( + windep.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); + + macro_rules! get_file_name { + ($v:expr) => { + all.targets + .iter() + .find(|t| t.src_path.file_name().unwrap() == $v) + .unwrap() + }; + } + assert_eq!(all.targets.len(), 9); + let lib = get_file_name!("lib.rs"); + assert_eq!(lib.name, "all"); + assert_eq!( + sorted!(lib.kind), + vec!["cdylib".into(), "rlib".into(), "staticlib".into()] + ); + assert_eq!( + sorted!(lib.crate_types), + vec!["cdylib".into(), "rlib".into(), "staticlib".into()] + ); + assert_eq!(lib.required_features.len(), 0); + assert_eq!(lib.edition, Edition::E2018); + assert!(lib.doctest); + assert!(lib.test); + assert!(lib.doc); + + let main = get_file_name!("main.rs"); + assert_eq!(main.crate_types, vec!["bin".into()]); + assert_eq!(main.kind, vec!["bin".into()]); + assert!(!main.doctest); + assert!(main.test); + assert!(main.doc); + + let otherbin = get_file_name!("otherbin.rs"); + assert_eq!(otherbin.edition, Edition::E2015); + assert!(!otherbin.doc); + + let reqfeat = get_file_name!("reqfeat.rs"); + assert_eq!(reqfeat.required_features, vec!["feat2"]); + + let reqfeat_slash = get_file_name!("reqfeat_slash.rs"); + assert_eq!(reqfeat_slash.required_features, vec!["featdep/i128"]); + + let ex1 = get_file_name!("ex1.rs"); + assert_eq!(ex1.kind, vec!["example".into()]); + assert!(!ex1.test); + + let t1 = get_file_name!("t1.rs"); + assert_eq!(t1.kind, vec!["test".into()]); + + let b1 = get_file_name!("b1.rs"); + assert_eq!(b1.kind, vec!["bench".into()]); + + let build = get_file_name!("build.rs"); + assert_eq!(build.kind, vec!["custom-build".into()]); + + if ver >= semver::Version::parse("1.60.0").unwrap() { + // 1.60 now reports optional dependencies within the features table + assert_eq!(all.features.len(), 4); + assert_eq!(all.features["bitflags"], vec!["dep:bitflags"]); + } else { + assert_eq!(all.features.len(), 3); + } + assert_eq!(all.features["feat1"].len(), 0); + assert_eq!(all.features["feat2"].len(), 0); + assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]); + + assert!(all.manifest_path.ends_with("all/Cargo.toml")); + assert_eq!(all.categories, vec!["command-line-utilities"]); + assert_eq!(all.keywords, vec!["cli"]); + assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md"))); + assert!(all.readme().unwrap().ends_with("tests/all/README.md")); + assert_eq!( + all.repository, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.homepage, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.documentation, + Some("https://docs.rs/cargo_metadata/".to_string()) + ); + assert_eq!(all.edition, Edition::E2018); + assert_eq!( + all.metadata, + json!({ + "docs": { + "rs": { + "all-features": true, + "default-target": "x86_64-unknown-linux-gnu", + "rustc-args": ["--example-rustc-arg"] + } + } + }) + ); + + let resolve = meta.resolve.as_ref().unwrap(); + assert!(resolve.root.as_ref().unwrap().to_string().contains("all")); + + assert_eq!(resolve.nodes.len(), 9); + let path_dep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().contains("path-dep")) + .unwrap(); + assert_eq!(path_dep.deps.len(), 0); + assert_eq!(path_dep.dependencies.len(), 0); + assert_eq!(path_dep.features.len(), 0); + + let bitflags = resolve + .nodes + .iter() + .find(|n| n.id.to_string().contains("bitflags")) + .unwrap(); + assert_eq!(bitflags.features, features!["default"]); + + let featdep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().contains("featdep")) + .unwrap(); + assert_eq!(featdep.features, features!["i128"]); + + let all = resolve + .nodes + .iter() + .find(|n| n.id.to_string().contains("all")) + .unwrap(); + assert_eq!(all.dependencies.len(), 8); + assert_eq!(all.deps.len(), 8); + let newname = all.deps.iter().find(|d| &*d.name == "newname").unwrap(); + assert!(newname.pkg.to_string().contains("oldname")); + // Note the underscore here. + let path_dep = all.deps.iter().find(|d| &*d.name == "path_dep").unwrap(); + assert!(path_dep.pkg.to_string().contains("path-dep")); + assert_eq!(path_dep.dep_kinds.len(), 1); + let kind = &path_dep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert!(kind.target.is_none()); + + let namedep = all + .deps + .iter() + .find(|d| &*d.name == "different_name") + .unwrap(); + assert!(namedep.pkg.to_string().contains("namedep")); + assert_eq!( + sorted!(all.features), + features!["bitflags", "default", "feat1"] + ); + + let bdep = all.deps.iter().find(|d| &*d.name == "bdep").unwrap(); + assert_eq!(bdep.dep_kinds.len(), 1); + let kind = &bdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Build); + assert!(kind.target.is_none()); + + let devdep = all.deps.iter().find(|d| &*d.name == "devdep").unwrap(); + assert_eq!(devdep.dep_kinds.len(), 1); + let kind = &devdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Development); + assert!(kind.target.is_none()); + + let windep = all.deps.iter().find(|d| &*d.name == "windep").unwrap(); + assert_eq!(windep.dep_kinds.len(), 1); + let kind = &windep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert_eq!( + kind.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); + + let serialized = serde_json::to_value(meta).unwrap(); + if ver >= semver::Version::parse("1.71.0").unwrap() { + assert!(serialized.as_object().unwrap()["workspace_default_members"] + .as_array() + .is_some()); + } else { + assert!(!serialized + .as_object() + .unwrap() + .contains_key("workspace_default_members")); + } +} + +#[test] +fn alt_registry() { + // This is difficult to test (would need to set up a custom index). + // Just manually check the JSON is handled. + let json = r#" +{ + "packages": [ + { + "name": "alt", + "version": "0.1.0", + "id": "alt 0.1.0 (path+file:///alt)", + "source": null, + "dependencies": [ + { + "name": "alt2", + "source": "registry+https://example.com", + "req": "^0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": "https://example.com" + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "alt", + "src_path": "/alt/src/lib.rs", + "edition": "2018" + } + ], + "features": {}, + "manifest_path": "/alt/Cargo.toml", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2018", + "links": null + } + ], + "workspace_members": [ + "alt 0.1.0 (path+file:///alt)" + ], + "resolve": null, + "target_directory": "/alt/target", + "version": 1, + "workspace_root": "/alt" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + let alt = &meta.packages[0]; + let deps = &alt.dependencies; + assert_eq!(deps.len(), 1); + let dep = &deps[0]; + assert_eq!(dep.registry, Some("https://example.com".to_string())); +} + +#[test] +fn current_dir() { + let meta = MetadataCommand::new() + .current_dir("tests/all/namedep") + .exec() + .unwrap(); + let namedep = meta + .packages + .iter() + .find(|p| p.name.as_str() == "namedep") + .unwrap(); + assert!(namedep.name.starts_with("namedep")); +} + +#[test] +fn parse_stream_is_robust() { + // Proc macros can print stuff to stdout, which naturally breaks JSON messages. + // Let's check that we don't die horribly in this case, and report an error. + let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false} +Evil proc macro was here! +{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false} +"##; + let mut n_messages = 0; + let mut text = String::new(); + for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) { + let message = message.unwrap(); + match message { + cargo_metadata::Message::TextLine(line) => text = line, + _ => n_messages += 1, + } + } + assert_eq!(n_messages, 2); + assert_eq!(text, "Evil proc macro was here!"); +} + +#[test] +fn advanced_feature_configuration() { + fn build_features &mut MetadataCommand>( + func: F, + ) -> Vec { + let mut meta = MetadataCommand::new(); + let meta = meta.manifest_path("tests/all/Cargo.toml"); + + let meta = func(meta); + let meta = meta.exec().unwrap(); + + let resolve = meta.resolve.as_ref().unwrap(); + + let all = resolve + .nodes + .iter() + .find(|n| !n.features.is_empty()) + .unwrap(); + + all.features + .clone() + .into_iter() + .map(FeatureName::into_inner) + .collect() + } + + // Default behavior; tested above + let default_features = build_features(|meta| meta); + assert_eq!( + sorted!(default_features), + vec!["bitflags", "default", "feat1"] + ); + + // Manually specify the same default features + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec![ + "feat1".into(), + "bitflags".into(), + ])) + }); + assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]); + + // Multiple SomeFeatures is same as one longer SomeFeatures + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec!["feat1".into()])) + .features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + }); + assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]); + + // No features + All features == All features + let all_features = build_features(|meta| { + meta.features(CargoOpt::AllFeatures) + .features(CargoOpt::NoDefaultFeatures) + }); + assert_eq!( + sorted!(all_features), + vec!["bitflags", "default", "feat1", "feat2"] + ); + + // The '--all-features' flag supersedes other feature flags + let all_flag_variants = build_features(|meta| { + meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + .features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::AllFeatures) + }); + assert_eq!(sorted!(all_flag_variants), sorted!(all_features)); +} + +#[test] +fn depkind_to_string() { + assert_eq!(DependencyKind::Normal.to_string(), "normal"); + assert_eq!(DependencyKind::Development.to_string(), "dev"); + assert_eq!(DependencyKind::Build.to_string(), "build"); + assert_eq!(DependencyKind::Unknown.to_string(), "Unknown"); +} + +#[test] +fn basic_workspace_root_package_exists() { + // First try with dependencies + let meta = MetadataCommand::new() + .manifest_path("tests/basic_workspace/Cargo.toml") + .exec() + .unwrap(); + assert_eq!(meta.root_package().unwrap().name.as_str(), "ex_bin"); + // Now with no_deps, it should still work exactly the same + let meta = MetadataCommand::new() + .manifest_path("tests/basic_workspace/Cargo.toml") + .no_deps() + .exec() + .unwrap(); + assert_eq!( + meta.root_package() + .expect("workspace root still exists when no_deps used") + .name + .as_str(), + "ex_bin" + ); +} + +#[test] +fn debuginfo_variants() { + // Checks behavior for the different debuginfo variants. + let variants = [ + ("0", ArtifactDebuginfo::None), + ("1", ArtifactDebuginfo::Limited), + ("2", ArtifactDebuginfo::Full), + ( + "\"line-directives-only\"", + ArtifactDebuginfo::LineDirectivesOnly, + ), + ("\"line-tables-only\"", ArtifactDebuginfo::LineTablesOnly), + ("3", ArtifactDebuginfo::UnknownInt(3)), + ( + "\"abc\"", + ArtifactDebuginfo::UnknownString("abc".to_string()), + ), + ("null", ArtifactDebuginfo::None), + ]; + for (value, expected) in variants { + let s = r#"{"reason":"compiler-artifact","package_id":"cargo_metadata 0.16.0 (path+file:////cargo_metadata)","manifest_path":"/cargo_metadata/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cargo_metadata","src_path":"/cargo_metadata/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":DEBUGINFO,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/cargo_metadata/target/debug/deps/libcargo_metadata-27f582f7187b9a2c.rmeta"],"executable":null,"fresh":false}"#; + let message: Message = serde_json::from_str(&s.replace("DEBUGINFO", value)).unwrap(); + match message { + Message::CompilerArtifact(artifact) => { + assert_eq!(artifact.profile.debuginfo, expected); + let de_s = serde_json::to_string(&artifact.profile.debuginfo).unwrap(); + // Note: Roundtrip does not retain null value. + if value == "null" { + assert_eq!(artifact.profile.debuginfo.to_string(), "0"); + assert_eq!(de_s, "0"); + } else { + assert_eq!( + artifact.profile.debuginfo.to_string(), + value.trim_matches('"') + ); + assert_eq!(de_s, value); + } + } + _ => panic!("unexpected {:?}", message), + } + } +} + +#[test] +#[should_panic = "WorkspaceDefaultMembers should only be dereferenced on Cargo versions >= 1.71"] +fn missing_workspace_default_members() { + let meta: Metadata = serde_json::from_str(JSON_OLD_MINIMAL).unwrap(); + let _ = &*meta.workspace_default_members; +} + +#[test] +fn workspace_default_members_is_available() { + // generated with cargo +1.71.0 metadata --format-version 1 + let json = r#" +{ + "packages": [ + { + "name": "basic", + "version": "0.1.0", + "id": "basic 0.1.0 (path+file:///example)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "basic", + "src_path": "/example/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "/example/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "basic 0.1.0 (path+file:///example)" + ], + "workspace_default_members": [ + "basic 0.1.0 (path+file:///example)" + ], + "resolve": { + "nodes": [ + { + "id": "basic 0.1.0 (path+file:///example)", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": "basic 0.1.0 (path+file:///example)" + }, + "target_directory": "/example/target", + "version": 1, + "workspace_root": "/example", + "metadata": null +} +"#; + + let meta: Metadata = serde_json::from_str(json).unwrap(); + + assert!(meta.workspace_default_members.is_available()); + assert!(!meta.workspace_default_members.is_missing()); +} + +#[test] +fn workspace_default_members_is_missing() { + // generated with cargo +1.70.0 metadata --format-version 1 + let json = r#" +{ + "packages": [ + { + "name": "basic", + "version": "0.1.0", + "id": "basic 0.1.0 (path+file:///example)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "basic", + "src_path": "/example/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "/example/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "basic 0.1.0 (path+file:///example)" + ], + "resolve": { + "nodes": [ + { + "id": "basic 0.1.0 (path+file:///example)", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": "basic 0.1.0 (path+file:///example)" + }, + "target_directory": "/example/target", + "version": 1, + "workspace_root": "/example", + "metadata": null +} +"#; + + let meta: Metadata = serde_json::from_str(json).unwrap(); + + assert!(!meta.workspace_default_members.is_available()); + assert!(meta.workspace_default_members.is_missing()); +} + +#[test] +fn test_unknown_target_kind_and_crate_type() { + // Both kind and crate_type set to a type not yet known + let json = r#" +{ + "packages": [ + { + "name": "alt", + "version": "0.1.0", + "id": "alt 0.1.0 (path+file:///alt)", + "source": null, + "dependencies": [], + "targets": [ + { + "kind": [ + "future-kind" + ], + "crate_types": [ + "future-type" + ], + "name": "alt", + "src_path": "/alt/src/lib.rs", + "edition": "2018" + } + ], + "features": {}, + "manifest_path": "/alt/Cargo.toml", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2018", + "links": null + } + ], + "workspace_members": [ + "alt 0.1.0 (path+file:///alt)" + ], + "resolve": null, + "target_directory": "/alt/target", + "version": 1, + "workspace_root": "/alt" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + assert_eq!(meta.packages[0].targets.len(), 1); + let target = &meta.packages[0].targets[0]; + assert_eq!(target.kind[0], "future-kind".into()); + assert_eq!(target.crate_types[0], "future-type".into()); +} diff --git a/anneal/v2/vendor/clap-cargo/.cargo-checksum.json b/anneal/v2/vendor/clap-cargo/.cargo-checksum.json new file mode 100644 index 0000000000..20724e0235 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"db98ab249a64afbf4d2867d6f7c20aed3e0c4d5b4810474e8b93766806b3b5bd","Cargo.lock":"a5d54430c2d732e2e506aba7b6b517f860d0f2c81b8f4cc6ff47156854741e9f","Cargo.toml":"6a15ca9f4a6ad8ffe1c55e3502faf4bec29cd79a30cb05c7cf545b6b6e2b11f5","Cargo.toml.orig":"90dc8722ebd7079835fa2c5c50ed916c7eeb2314dbf8b700af8ac6381bdadab6","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"c5563e833b2434ad77b62dc78380c43c7b469fbcfb24cb2e519557fb6ab59710","examples/flags.rs":"c88d5ce1714976c19e8fb7a8a22abf166f06fcefdec4e77e0dfc12be8516cf6c","src/features.rs":"ea5ce44032267e4c584fa04e66ab439faad46043e4609dd70cf12ad45be6fe1d","src/lib.rs":"4badb514940c1506c6fa90597629372d05f81a433cf5cd0dd112afe5f7b1cfc8","src/manifest.rs":"523c4cdfa365a31bbf938364c1ac182cc8324655aee399d6a5d7bb411e226bc2","src/style.rs":"d037e05dd5ebf97024bfd8f3f0fd3aef92b2ed0ceb27bf6767e8d16a128cf4c8","src/workspace.rs":"c0e278e9d1f3b819cd2d2a4f1a5c2d3d90ee523e45c3bb50c9d89198f5d6d1d0"},"package":"936551935c8258754bb8216aec040957d261f977303754b9bf1a213518388006"} \ No newline at end of file diff --git a/anneal/v2/vendor/clap-cargo/.cargo_vcs_info.json b/anneal/v2/vendor/clap-cargo/.cargo_vcs_info.json new file mode 100644 index 0000000000..81bd0782f9 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "3c1a072f9e1bce7b933c69af6132398e6d6805ae" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/clap-cargo/Cargo.lock b/anneal/v2/vendor/clap-cargo/Cargo.lock new file mode 100644 index 0000000000..a4f5a81228 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/Cargo.lock @@ -0,0 +1,378 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122ec45a44b270afd1402f351b782c676b173e3c3fb28d86ff7ebfb4d86a4ee4" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981a6f317983eec002839b90fae7411a85621410ae591a9cab2ecf5cb5744873" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "clap" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap-cargo" +version = "0.18.3" +dependencies = [ + "anstyle", + "cargo_metadata", + "clap", + "serde", + "serde_json", +] + +[[package]] +name = "clap_builder" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/anneal/v2/vendor/clap-cargo/Cargo.toml b/anneal/v2/vendor/clap-cargo/Cargo.toml new file mode 100644 index 0000000000..d147237ddb --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/Cargo.toml @@ -0,0 +1,203 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.86" +name = "clap-cargo" +version = "0.18.3" +build = false +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "Cargo.lock", + "LICENSE*", + "README.md", + "examples/**/*", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Re-usable CLI flags for `cargo` plugins" +readme = "README.md" +keywords = ["cargo"] +categories = ["development-tools::cargo-plugins"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/crate-ci/clap-cargo" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "Unreleased" +replace = "{{version}}" +min = 1 + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = '\.\.\.HEAD' +replace = "...{{tag_name}}" +exactly = 1 + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "ReleaseDate" +replace = "{{date}}" +min = 1 + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "" +replace = """ + +## [Unreleased] - ReleaseDate +""" +exactly = 1 + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "" +replace = """ + +[Unreleased]: https://github.com/crate-ci/clap-cargo/compare/{{tag_name}}...HEAD""" +exactly = 1 + +[features] +cargo_metadata = [ + "dep:cargo_metadata", + "dep:serde", + "dep:serde_json", +] +clap = ["dep:clap"] +default = ["clap"] +testing_colors = [] + +[lib] +name = "clap_cargo" +path = "src/lib.rs" + +[[example]] +name = "flags" +path = "examples/flags.rs" +required-features = ["clap"] + +[dependencies.anstyle] +version = "1.0.13" + +[dependencies.cargo_metadata] +version = "0.23" +optional = true + +[dependencies.clap] +version = "4.5.48" +features = [ + "std", + "derive", +] +optional = true +default-features = false + +[dev-dependencies.clap] +version = "4.5.48" + +[target."cfg(any())".dependencies.serde] +version = "1.0.210" +optional = true + +[target."cfg(any())".dependencies.serde_json] +version = "1.0.133" +optional = true + +[lints.clippy] +bool_assert_comparison = "allow" +branches_sharing_code = "allow" +checked_conversions = "warn" +collapsible_else_if = "allow" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_same_then_else = "allow" +implicit_clone = "warn" +imprecise_flops = "warn" +inconsistent_struct_constructor = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" +invalid_upcast_comparisons = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_and_return = "allow" +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "allow" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +result_large_err = "allow" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +str_to_string = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +uninlined_format_args = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" + +[lints.rust] +unnameable_types = "warn" +unreachable_pub = "warn" +unsafe_op_in_unsafe_fn = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +[lints.rust.rust_2018_idioms] +level = "warn" +priority = -1 + +[profile.dev] +panic = "abort" + +[profile.release] +lto = true +codegen-units = 1 +panic = "abort" diff --git a/anneal/v2/vendor/clap-cargo/Cargo.toml.orig b/anneal/v2/vendor/clap-cargo/Cargo.toml.orig new file mode 100644 index 0000000000..f10789c92b --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/Cargo.toml.orig @@ -0,0 +1,146 @@ +[workspace] +resolver = "2" + +[workspace.package] +repository = "https://github.com/crate-ci/clap-cargo" +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.86" # MSRV +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "Cargo.lock", + "LICENSE*", + "README.md", + "examples/**/*" +] + +[workspace.lints.rust] +rust_2018_idioms = { level = "warn", priority = -1 } +unnameable_types = "warn" +unreachable_pub = "warn" +unsafe_op_in_unsafe_fn = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +[workspace.lints.clippy] +bool_assert_comparison = "allow" +branches_sharing_code = "allow" +checked_conversions = "warn" +collapsible_else_if = "allow" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_same_then_else = "allow" +implicit_clone = "warn" +imprecise_flops = "warn" +inconsistent_struct_constructor = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" +invalid_upcast_comparisons = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_and_return = "allow" # sometimes good to name what you are returning +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "allow" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +result_large_err = "allow" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +str_to_string = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +uninlined_format_args = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" +codegen-units = 1 +lto = true +# debug = "line-tables-only" # requires Cargo 1.71 + +[package] +name = "clap-cargo" +version = "0.18.3" +description = "Re-usable CLI flags for `cargo` plugins" +categories = ["development-tools::cargo-plugins"] +keywords = ["cargo"] +repository.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +include.workspace = true + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--generate-link-to-definition"] + +[package.metadata.release] +pre-release-replacements = [ + {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, + {file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1}, + {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, + {file="CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, + {file="CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/crate-ci/clap-cargo/compare/{{tag_name}}...HEAD", exactly=1}, +] + +[features] +default = ["clap"] +clap = ["dep:clap"] +cargo_metadata = ["dep:cargo_metadata", "dep:serde", "dep:serde_json"] +testing_colors = [] + +[dependencies] +anstyle = "1.0.13" +cargo_metadata = { version = "0.23", optional = true } +clap = { version = "4.5.48", default-features = false, features = ["std", "derive"], optional = true } + +[dev-dependencies] +clap = "4.5.48" + +[target.'cfg(any())'.dependencies] +serde = { version = "1.0.210", optional = true } # HACK: bad minimal dep in cargo_metadata +serde_json = { version = "1.0.133", optional = true } # HACK: bad minimal dep in cargo_metadata + +[[example]] +name = "flags" +required-features = ["clap"] + +[lints] +workspace = true diff --git a/anneal/v2/vendor/clap-cargo/LICENSE-APACHE b/anneal/v2/vendor/clap-cargo/LICENSE-APACHE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/anneal/v2/vendor/clap-cargo/LICENSE-MIT b/anneal/v2/vendor/clap-cargo/LICENSE-MIT new file mode 100644 index 0000000000..a2d01088b6 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) Individual contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/anneal/v2/vendor/clap-cargo/README.md b/anneal/v2/vendor/clap-cargo/README.md new file mode 100644 index 0000000000..aca42088d6 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/README.md @@ -0,0 +1,54 @@ +# clap-cargo + +> Re-usable CLI flags for `cargo` plugins + +[![codecov](https://codecov.io/gh/crate-ci/clap-cargo/branch/master/graph/badge.svg)](https://codecov.io/gh/crate-ci/clap-cargo) +[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation] +![License](https://img.shields.io/crates/l/clap-cargo.svg) +[![Crates Status](https://img.shields.io/crates/v/clap-cargo.svg)][Crates.io] + +## Examples + +```rust +// ... +#[derive(Debug, clap::Parser)] +#[command(styles = clap_cargo::style::CLAP_STYLING)] +struct Cli { + #[command(flatten)] + manifest: clap_cargo::Manifest, + #[command(flatten)] + workspace: clap_cargo::Workspace, + #[command(flatten)] + features: clap_cargo::Features, +} +``` + +## Relevant crates + +Other crates that might be useful for cargo plugins: +* [escargot][escargot] for wrapping `cargo-build`, `carg-run`, `cargo-test`, etc. +* [cargo_metadata][cargo_metadata] for getting crate information. +* [clap-verbosity][clap-verbosity] for adding logging to your CLI. + +[escargot]: https://crates.io/crates/escargot +[cargo_metadata]: https://crates.io/crates/cargo_metadata +[clap-verbosity]: https://crates.io/crates/clap-verbosity-flag + +## License + +Licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or ) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual-licensed as above, without any additional terms or +conditions. + +[Crates.io]: https://crates.io/crates/clap-cargo +[Documentation]: https://docs.rs/clap-cargo diff --git a/anneal/v2/vendor/clap-cargo/examples/flags.rs b/anneal/v2/vendor/clap-cargo/examples/flags.rs new file mode 100644 index 0000000000..0bda1a84b7 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/examples/flags.rs @@ -0,0 +1,16 @@ +use clap::Parser; + +#[derive(Debug, Parser)] +struct Cli { + #[clap(flatten)] + manifest: clap_cargo::Manifest, + #[clap(flatten)] + workspace: clap_cargo::Workspace, + #[clap(flatten)] + features: clap_cargo::Features, +} + +fn main() { + let args = Cli::parse(); + println!("args = {args:#?}"); +} diff --git a/anneal/v2/vendor/clap-cargo/src/features.rs b/anneal/v2/vendor/clap-cargo/src/features.rs new file mode 100644 index 0000000000..3e438979ba --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/src/features.rs @@ -0,0 +1,170 @@ +//! Cargo Feature Flags. + +/// Cargo Feature Flags. +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[cfg_attr(feature = "clap", command(about = None, long_about = None))] +#[non_exhaustive] +pub struct Features { + #[cfg_attr(feature = "clap", arg(long))] + /// Activate all available features + pub all_features: bool, + #[cfg_attr(feature = "clap", arg(long))] + /// Do not activate the `default` feature + pub no_default_features: bool, + #[cfg_attr(feature = "clap", arg(short = 'F', long, value_delimiter = ' '))] + /// Space-separated list of features to activate + pub features: Vec, +} + +#[cfg(feature = "cargo_metadata")] +impl Features { + /// Forward these flags to the `cargo_metadata` crate. + /// + /// Note: Requires the features `cargo_metadata`. + pub fn forward_metadata<'m>( + &self, + meta: &'m mut cargo_metadata::MetadataCommand, + ) -> &'m mut cargo_metadata::MetadataCommand { + if self.all_features { + meta.features(cargo_metadata::CargoOpt::AllFeatures); + } + if self.no_default_features { + meta.features(cargo_metadata::CargoOpt::NoDefaultFeatures); + } + if !self.features.is_empty() { + meta.features(cargo_metadata::CargoOpt::SomeFeatures( + self.features.clone(), + )); + } + meta + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + features: Features, + } + + use clap::CommandFactory; + Cli::command().debug_assert(); + } + + #[test] + #[cfg(feature = "clap")] + fn parse_multiple_occurrences() { + use clap::Parser; + + #[derive(PartialEq, Eq, Debug, Parser)] + struct Args { + positional: Option, + #[command(flatten)] + features: Features, + } + + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec![] + } + }, + Args::parse_from(["test"]) + ); + assert_eq!( + Args { + positional: Some("foo".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec![] + } + }, + Args::parse_from(["test", "foo"]) + ); + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo"]) + ); + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo bar"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo bar", "baz"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo", "--features", "bar", "baz"]) + ); + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn features_all() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + + let features = Features { + all_features: true, + ..Default::default() + }; + features.forward_metadata(&mut metadata); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn features_none() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + + let features = Features { + no_default_features: true, + ..Default::default() + }; + features.forward_metadata(&mut metadata); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } +} diff --git a/anneal/v2/vendor/clap-cargo/src/lib.rs b/anneal/v2/vendor/clap-cargo/src/lib.rs new file mode 100644 index 0000000000..c42a938b72 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/src/lib.rs @@ -0,0 +1,60 @@ +//! **clap-cargo**: Re-usable CLI flags for `cargo` plugins +//! +//! ## Examples +//! +//! ```rust,no_run +//! # #[cfg(feature = "clap")] { +//! # #[cfg(feature = "cargo_metadata")] { +//! use clap::Parser; +//! +//! // ... +//! #[derive(Debug, Parser)] +//! #[command(styles = clap_cargo::style::CLAP_STYLING)] +//! struct Cli { +//! #[command(flatten)] +//! manifest: clap_cargo::Manifest, +//! #[command(flatten)] +//! workspace: clap_cargo::Workspace, +//! #[command(flatten)] +//! features: clap_cargo::Features, +//! } +//! +//! let cli = // ... +//! # Cli::parse_from(["app"]); +//! let mut metadata = cli.manifest.metadata(); +//! cli.features.forward_metadata(&mut metadata); +//! let metadata = metadata.exec().unwrap(); +//! let (selected, excluded) = cli.workspace.partition_packages(&metadata); +//! # } +//! # } +//! ``` +//! +//! ## Relevant crates +//! +//! Other crates that might be useful for cargo plugins: +//! * [escargot][escargot] for wrapping `cargo-build`, `carg-run`, `cargo-test`, etc. +//! * [cargo_metadata][cargo_metadata] for getting crate information. +//! * [clap-verbosity][clap-verbosity] for adding logging to your CLI. +//! +//! [escargot]: https://crates.io/crates/escargot +//! [cargo_metadata]: https://crates.io/crates/cargo_metadata +//! [clap-verbosity]: https://crates.io/crates/clap-verbosity-flag + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn(clippy::print_stderr)] +#![warn(clippy::print_stdout)] + +#[doc = include_str!("../README.md")] +#[cfg(doctest)] +#[cfg(feature = "clap")] +pub struct ReadmeDoctests; + +mod features; +mod manifest; +mod workspace; + +pub mod style; + +pub use features::*; +pub use manifest::*; +pub use workspace::*; diff --git a/anneal/v2/vendor/clap-cargo/src/manifest.rs b/anneal/v2/vendor/clap-cargo/src/manifest.rs new file mode 100644 index 0000000000..97f139b481 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/src/manifest.rs @@ -0,0 +1,69 @@ +//! Cargo flag for selecting the relevant crate. + +use std::path; + +/// Cargo flag for selecting the relevant crate. +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[cfg_attr(feature = "clap", command(about = None, long_about = None))] +#[non_exhaustive] +pub struct Manifest { + #[cfg_attr(feature = "clap", arg(long, name = "PATH"))] + /// Path to Cargo.toml + pub manifest_path: Option, +} + +#[cfg(feature = "cargo_metadata")] +impl Manifest { + /// Create a `cargo_metadata::MetadataCommand` + /// + /// Note: Requires the features `cargo_metadata`. + pub fn metadata(&self) -> cargo_metadata::MetadataCommand { + let mut c = cargo_metadata::MetadataCommand::new(); + if let Some(ref manifest_path) = self.manifest_path { + c.manifest_path(manifest_path); + } + c + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + manifest: Manifest, + } + + use clap::CommandFactory; + Cli::command().debug_assert(); + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn metadata_with_path() { + let manifest = Manifest { + manifest_path: Some(path::PathBuf::from("tests/fixtures/simple/Cargo.toml")), + }; + let metadata = manifest.metadata(); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn metadata_without_path() { + let cwd = path::PathBuf::from("tests/fixtures/simple"); + let manifest = Manifest { + manifest_path: None, + }; + let mut metadata = manifest.metadata(); + metadata.current_dir(cwd).exec().unwrap(); + // TODO verify we forwarded correctly. + } +} diff --git a/anneal/v2/vendor/clap-cargo/src/style.rs b/anneal/v2/vendor/clap-cargo/src/style.rs new file mode 100644 index 0000000000..debc448ff7 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/src/style.rs @@ -0,0 +1,101 @@ +#![allow(missing_docs)] +#![allow(unused_qualifications)] // for copy/paste sake +#![allow(unreachable_pub)] // for copy/paste sake + +use anstyle::AnsiColor; +use anstyle::Effects; +use anstyle::Style; + +pub const NOP: Style = Style::new(); +pub const HEADER: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD); +pub const USAGE: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD); +pub const LITERAL: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD); +pub const PLACEHOLDER: Style = AnsiColor::Cyan.on_default(); +pub const ERROR: Style = annotate_snippets::renderer::DEFAULT_ERROR_STYLE; +pub const WARN: Style = annotate_snippets::renderer::DEFAULT_WARNING_STYLE; +pub const NOTE: Style = annotate_snippets::renderer::DEFAULT_NOTE_STYLE; +pub const GOOD: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD); +pub const VALID: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD); +pub const INVALID: Style = annotate_snippets::renderer::DEFAULT_WARNING_STYLE; +pub const TRANSIENT: Style = annotate_snippets::renderer::DEFAULT_HELP_STYLE; +pub const CONTEXT: Style = annotate_snippets::renderer::DEFAULT_CONTEXT_STYLE; + +pub const UPDATE_ADDED: Style = NOTE; +pub const UPDATE_REMOVED: Style = ERROR; +pub const UPDATE_UPGRADED: Style = GOOD; +pub const UPDATE_DOWNGRADED: Style = WARN; +pub const UPDATE_UNCHANGED: Style = anstyle::Style::new().bold(); + +pub const DEP_NORMAL: Style = anstyle::Style::new().effects(anstyle::Effects::DIMMED); +pub const DEP_BUILD: Style = anstyle::AnsiColor::Blue + .on_default() + .effects(anstyle::Effects::BOLD); +pub const DEP_DEV: Style = anstyle::AnsiColor::Cyan + .on_default() + .effects(anstyle::Effects::BOLD); +pub const DEP_FEATURE: Style = anstyle::AnsiColor::Magenta + .on_default() + .effects(anstyle::Effects::DIMMED); + +/// For use with +/// [`clap::Command::styles`](https://docs.rs/clap/latest/clap/struct.Command.html#method.styles) +#[cfg(feature = "clap")] +pub const CLAP_STYLING: clap::builder::styling::Styles = clap::builder::styling::Styles::styled() + .header(HEADER) + .usage(USAGE) + .literal(LITERAL) + .placeholder(PLACEHOLDER) + .error(ERROR) + .valid(VALID) + .invalid(INVALID); + +// Copied from https://github.com/rust-lang/annotate-snippets-rs/blob/5a632cdfadb5902bf063722f80b37fcb50da0416/src/renderer/mod.rs +mod annotate_snippets { + pub mod renderer { + #![allow(dead_code)] // for copy/paste sake + #![allow(rustdoc::broken_intra_doc_links)] // for copy/paste sake + use anstyle::{AnsiColor, Effects, Style}; + + const USE_WINDOWS_COLORS: bool = cfg!(windows) && !cfg!(feature = "testing_colors"); + const BRIGHT_BLUE: Style = if USE_WINDOWS_COLORS { + AnsiColor::BrightCyan.on_default() + } else { + AnsiColor::BrightBlue.on_default() + }; + /// [`Renderer::error`] applied by [`Renderer::styled`] + pub const DEFAULT_ERROR_STYLE: Style = + AnsiColor::BrightRed.on_default().effects(Effects::BOLD); + /// [`Renderer::warning`] applied by [`Renderer::styled`] + pub const DEFAULT_WARNING_STYLE: Style = if USE_WINDOWS_COLORS { + AnsiColor::BrightYellow.on_default() + } else { + AnsiColor::Yellow.on_default() + } + .effects(Effects::BOLD); + /// [`Renderer::info`] applied by [`Renderer::styled`] + pub const DEFAULT_INFO_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); + /// [`Renderer::note`] applied by [`Renderer::styled`] + pub const DEFAULT_NOTE_STYLE: Style = + AnsiColor::BrightGreen.on_default().effects(Effects::BOLD); + /// [`Renderer::help`] applied by [`Renderer::styled`] + pub const DEFAULT_HELP_STYLE: Style = + AnsiColor::BrightCyan.on_default().effects(Effects::BOLD); + /// [`Renderer::line_num`] applied by [`Renderer::styled`] + pub const DEFAULT_LINE_NUM_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); + /// [`Renderer::emphasis`] applied by [`Renderer::styled`] + pub const DEFAULT_EMPHASIS_STYLE: Style = if USE_WINDOWS_COLORS { + AnsiColor::BrightWhite.on_default() + } else { + Style::new() + } + .effects(Effects::BOLD); + /// [`Renderer::none`] applied by [`Renderer::styled`] + pub const DEFAULT_NONE_STYLE: Style = Style::new(); + /// [`Renderer::context`] applied by [`Renderer::styled`] + pub const DEFAULT_CONTEXT_STYLE: Style = BRIGHT_BLUE.effects(Effects::BOLD); + /// [`Renderer::addition`] applied by [`Renderer::styled`] + pub const DEFAULT_ADDITION_STYLE: Style = AnsiColor::BrightGreen.on_default(); + /// [`Renderer::removal`] applied by [`Renderer::styled`] + pub const DEFAULT_REMOVAL_STYLE: Style = AnsiColor::BrightRed.on_default(); + } +} diff --git a/anneal/v2/vendor/clap-cargo/src/workspace.rs b/anneal/v2/vendor/clap-cargo/src/workspace.rs new file mode 100644 index 0000000000..a987bb6bb0 --- /dev/null +++ b/anneal/v2/vendor/clap-cargo/src/workspace.rs @@ -0,0 +1,394 @@ +//! Cargo flags for selecting crates in a workspace. + +/// Cargo flags for selecting crates in a workspace. +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[cfg_attr(feature = "clap", command(about = None, long_about = None))] +#[non_exhaustive] +pub struct Workspace { + #[cfg_attr(feature = "clap", arg(short, long, value_name = "SPEC"))] + /// Package to process (see `cargo help pkgid`) + pub package: Vec, + #[cfg_attr(feature = "clap", arg(long))] + /// Process all packages in the workspace + pub workspace: bool, + #[cfg_attr(feature = "clap", arg(long, hide = true))] + /// Process all packages in the workspace + pub all: bool, + #[cfg_attr(feature = "clap", arg(long, value_name = "SPEC"))] + /// Exclude packages from being processed + pub exclude: Vec, +} + +#[cfg(feature = "cargo_metadata")] +impl Workspace { + /// Partition workspace members into those selected and those excluded. + /// + /// Notes: + /// - Requires the features `cargo_metadata`. + /// - Requires not calling `MetadataCommand::no_deps` + pub fn partition_packages<'m>( + &self, + meta: &'m cargo_metadata::Metadata, + ) -> ( + Vec<&'m cargo_metadata::Package>, + Vec<&'m cargo_metadata::Package>, + ) { + let selection = + Packages::from_flags(self.workspace || self.all, &self.exclude, &self.package); + let workspace_members: std::collections::HashSet<_> = + meta.workspace_members.iter().collect(); + let workspace_default_members: std::collections::HashSet<_> = + meta.workspace_default_members.iter().collect(); + let base_ids: std::collections::HashSet<_> = match selection { + Packages::Default => workspace_default_members, + Packages::All => workspace_members, + Packages::OptOut(_) => workspace_members, // Deviating from cargo by only checking workspace members + Packages::Packages(patterns) => { + meta.packages + .iter() + // Deviating from cargo by not supporting patterns + // Deviating from cargo by only checking workspace members + .filter(|p| workspace_members.contains(&p.id) && patterns.contains(&p.name)) + .map(|p| &p.id) + .collect() + } + }; + + meta.packages + .iter() + // Deviating from cargo by not supporting patterns + .partition(|p| base_ids.contains(&p.id) && !self.exclude.contains(&p.name)) + } +} + +// See cargo's src/cargo/ops/cargo_compile.rs +#[derive(Clone, PartialEq, Eq, Debug)] +#[cfg(feature = "cargo_metadata")] +#[allow(clippy::enum_variant_names)] +enum Packages<'p> { + Default, + All, + OptOut(&'p [String]), + Packages(&'p [String]), +} + +#[cfg(feature = "cargo_metadata")] +impl<'p> Packages<'p> { + fn from_flags(all: bool, exclude: &'p [String], package: &'p [String]) -> Self { + match (all, exclude.len(), package.len()) { + (false, 0, 0) => Packages::Default, + (false, 0, _) => Packages::Packages(package), + (false, _, 0) => Packages::OptOut(exclude), // Deviating from cargo because we don't do error handling + (false, _, _) => Packages::Packages(package), // Deviating from cargo because we don't do error handling + (true, 0, _) => Packages::All, + (true, _, _) => Packages::OptOut(exclude), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + workspace: Workspace, + } + + use clap::CommandFactory; + Cli::command().debug_assert(); + } + + #[test] + #[cfg(feature = "clap")] + fn parse_multiple_occurrences() { + use clap::Parser; + + #[derive(PartialEq, Eq, Debug, Parser)] + struct Args { + positional: Option, + #[command(flatten)] + workspace: Workspace, + } + + assert_eq!( + Args { + positional: None, + workspace: Workspace { + package: vec![], + workspace: false, + all: false, + exclude: vec![], + } + }, + Args::parse_from(["test"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + workspace: Workspace { + package: vec!["foo".to_owned(), "bar".to_owned()], + workspace: false, + all: false, + exclude: vec![], + } + }, + Args::parse_from(["test", "--package", "foo", "--package", "bar", "baz"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + workspace: Workspace { + package: vec![], + workspace: false, + all: false, + exclude: vec!["foo".to_owned(), "bar".to_owned()], + } + }, + Args::parse_from(["test", "--exclude", "foo", "--exclude", "bar", "baz"]) + ); + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_default { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_all { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_package { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["simple".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + } +} diff --git a/anneal/v2/vendor/console/.cargo-checksum.json b/anneal/v2/vendor/console/.cargo-checksum.json new file mode 100644 index 0000000000..e142f8ce87 --- /dev/null +++ b/anneal/v2/vendor/console/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"cef3fac107da39e56796b166289bb9ae0697b91b3e97f9d63455ab486fdf16b1","CHANGELOG.md":"38259591ad24ff6f6d37edd7ea27cfb53a38b8920ad62cd48a20ff79386ccf02","Cargo.lock":"4227a1f5357faab5280823563b03d9e5a188a4213f2976045616ad6d0fb3539f","Cargo.toml":"6af0aef48fe57dfc4424127dd0e3581b65b2995998b91d1dd61040169a74271d","Cargo.toml.orig":"256091515b44899f450dda1c5221851d1d53037341f4be17d13e1a5f091f4e64","LICENSE":"2022c11b24fc1e50fa06a5959e40198a3464f560729ad3d00139abb8a328362d","README.md":"1e63da96ef7031371c4eeddabed863a657f15e03543c5c4186c918e254c3f64c","src/ansi.rs":"a5250b0e3afe75935b0d9f2334c3b32c4de203cfb101b8b58ea41ac1327dba0a","src/common_term.rs":"3c55f5c811713543517b06da945440d84543a2ddbadc33fedf41b2bdfbf28d7b","src/kb.rs":"41d9022d2b0afed2663c3c4023b97fe1915edc29ba961ee09697dd4bf2e9e1af","src/lib.rs":"fbda5641166c16bc353e55dd6d27da3ebf3c0bcf6ed2d2cb70cc93c0412e64ed","src/term.rs":"24bfddbdaea4201b6ee7039645a782412eb68de0ad04282489560639aef2f10d","src/unix_term.rs":"9393f12b646e3130cc76edf3a8f9aca442f87f933a5df93eb68a851ce40a7966","src/utils.rs":"d2bb80a3e9921578b4f06557ffae2ca663284f5bf0e704dca175715b50bc398b","src/wasm_term.rs":"b4c32538077c8616829739d1ab7c2fd3f220f556d83fccda477397fedbecb7dd","src/windows_term/colors.rs":"9f3c8bc7ae4b83fcff9dd947ba87b11539414e804f2b9cd6ea251ca29ed89193","src/windows_term/mod.rs":"29c408b2140a96b7f66efde69384bfb623039e3a52ee209e1a6b3dc04c0096b2"},"package":"d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87"} \ No newline at end of file diff --git a/anneal/v2/vendor/console/.cargo_vcs_info.json b/anneal/v2/vendor/console/.cargo_vcs_info.json new file mode 100644 index 0000000000..5e4dbd2e54 --- /dev/null +++ b/anneal/v2/vendor/console/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "70ea3d0a6ecf1ca2f3891827631ca6e9b8e2b10a" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/console/CHANGELOG.md b/anneal/v2/vendor/console/CHANGELOG.md new file mode 100644 index 0000000000..7fa33486b3 --- /dev/null +++ b/anneal/v2/vendor/console/CHANGELOG.md @@ -0,0 +1,120 @@ +# Changelog + +Newer changelog entries can be found [on +GitHub](https://github.com/console-rs/console/releases). + +## 0.15.8 + +### Enhancements + +* Added `wasm32-unknown-emscripten` target. (#179) +* `read_line_initial_text` now retains the initial prefix. (#190) +* Reading raw input now traps Ctrl+C. (#189) + +### Bugfixes + +* Properly use configured output of `Term` to get terminal size (#186) +* Aligned `read_line` and `read_line_initial_text`'s behavior. (#181) +* Fixed soundness issue in `msys_tty_on`. (#183) + +## 0.15.7 + +### Enhancements + +* Set an appropriate lower version of libc for macos changes. +* Improved behavior of `read_single_key` so it does not disturb other + threads quite as much. (#165) +* More reliably reset raw mode in terminal. (#171) + +## 0.15.6 + +### Enhancements + +* Switch to `select()` on macOS for polling on TTYs to work around + a macOS bug. (#169) +* Added blink fast and strikethrough attributes. (#159) + +## 0.15.5 + +### Enhancements + +* Removed `regex` dependency. (#153) +* Clarified that `clicolors-control` is no longer used. +* Handle non-tty terminals in `read_char`. (#124) + +## 0.15.4 + +### Enhancements + +* Fix for regression where console size was misreported on windows. (#151) + +## 0.15.3 + +### Enhancements + +* Dropped `terminal_size` dependency. + +## 0.15.2 + +### Enhancements + +* Dropped `once_cell` dependency to support MSRV again. + +## 0.15.1 + +### Enhancements + +* ANSI support no longer depends on `regex` crate. +* Crate now supports `minver`. + +## 0.15.0 + +### Enhancements + +* Added more key recognitions +* Exposed `pad_str_with` to public API +* Added `ReadWritePair` +* Support `color256` in `Style::from_dotted_str` + +### BREAKING + +* Added `ReadWritePair` to `TermTarget` to allow arbitrary read write pairs behave as a term +* Removed `Copy` and `PartialEq` from `TermTarget` + +## 0.14.1 + +### Enhancements + +* Added `NO_COLOR` support +* Added some more key recognitions +* Undeprecate `Term::is_term` + +## 0.14.0 + +### Enhancements + +* Added emoji support for newer Windows terminals. + +### BREAKING + +* Made the windows terminal emulation a non default feature (`windows-console-colors`) + +## 0.13.0 + +### Enhancements + +* Added `user_attended_stderr` for checking if stderr is a terminal +* Removed `termios` dependency + +### Bug Fixes + +* Better handling of key recognition on unix +* `Term::terminal_size()` on stderr terms correctly returns stderr term info + +### Deprecated + +* Deprecate `Term::is_term()` in favor of `Term::features().is_attended()` + +### BREAKING + +* Remove `Term::want_emoji()` in favor of `Term::features().wants_emoji()` diff --git a/anneal/v2/vendor/console/Cargo.lock b/anneal/v2/vendor/console/Cargo.lock new file mode 100644 index 0000000000..39a1aef742 --- /dev/null +++ b/anneal/v2/vendor/console/Cargo.lock @@ -0,0 +1,303 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "console" +version = "0.16.3" +dependencies = [ + "encode_unicode", + "libc", + "proptest", + "regex", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[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 = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +dependencies = [ + "bit-set", + "bitflags", + "byteorder", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.6.29", + "unarray", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[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 = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/anneal/v2/vendor/console/Cargo.toml b/anneal/v2/vendor/console/Cargo.toml new file mode 100644 index 0000000000..03c5feea82 --- /dev/null +++ b/anneal/v2/vendor/console/Cargo.toml @@ -0,0 +1,92 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.71" +name = "console" +version = "0.16.3" +build = false +include = [ + "CHANGELOG.md", + "Cargo.toml", + "LICENSE", + "README.md", + "src/**/*.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A terminal and console abstraction for Rust" +homepage = "https://github.com/console-rs/console" +documentation = "https://docs.rs/console" +readme = "README.md" +keywords = [ + "cli", + "terminal", + "colors", + "console", + "ansi", +] +license = "MIT" +repository = "https://github.com/console-rs/console" + +[features] +alloc = [] +ansi-parsing = [] +default = [ + "unicode-width", + "ansi-parsing", + "std", +] +std = [ + "dep:libc", + "alloc", +] +windows-console-colors = ["ansi-parsing"] + +[lib] +name = "console" +path = "src/lib.rs" + +[dependencies.libc] +version = "0.2.99" +optional = true + +[dependencies.unicode-width] +version = "0.2" +optional = true + +[dev-dependencies.proptest] +version = "1.0.0" +features = [ + "std", + "bit-set", + "break-dead-code", +] +default-features = false + +[dev-dependencies.regex] +version = "1.4.2" + +[target."cfg(windows)".dependencies.encode_unicode] +version = "1" + +[target."cfg(windows)".dependencies.windows-sys] +version = "0.61" +features = [ + "Win32_Foundation", + "Win32_System_Console", + "Win32_Storage_FileSystem", + "Win32_UI_Input_KeyboardAndMouse", +] diff --git a/anneal/v2/vendor/console/Cargo.toml.orig b/anneal/v2/vendor/console/Cargo.toml.orig new file mode 100644 index 0000000000..5e9df1f5c2 --- /dev/null +++ b/anneal/v2/vendor/console/Cargo.toml.orig @@ -0,0 +1,72 @@ +[package] +name = "console" +description = "A terminal and console abstraction for Rust" +version = "0.16.3" +keywords = ["cli", "terminal", "colors", "console", "ansi"] +license = "MIT" +edition = "2021" +homepage = "https://github.com/console-rs/console" +repository = "https://github.com/console-rs/console" +documentation = "https://docs.rs/console" +readme = "README.md" +rust-version = "1.71" +include = ["CHANGELOG.md", "Cargo.toml", "LICENSE", "README.md", "src/**/*.rs"] + +[features] +default = ["unicode-width", "ansi-parsing", "std"] +std = ["dep:libc", "alloc"] +alloc = [] +windows-console-colors = ["ansi-parsing"] +ansi-parsing = [] + +[dependencies] +libc = { version = "0.2.99", optional = true } +unicode-width = { version = "0.2", optional = true } + +[target.'cfg(windows)'.dependencies] +encode_unicode = "1" + +[target.'cfg(windows)'.dependencies.windows-sys] +version = "0.61" +features = [ + "Win32_Foundation", + "Win32_System_Console", + "Win32_Storage_FileSystem", + "Win32_UI_Input_KeyboardAndMouse", +] + +[dev-dependencies] +# Pick a setup for proptest that works with wasi +proptest = { version = "1.0.0", default-features = false, features = [ + "std", + "bit-set", + "break-dead-code", +] } +regex = "1.4.2" + +[[example]] +name = "colors" +required-features = ["std"] + +[[example]] +name = "colors256" +required-features = ["std"] + +[[example]] +name = "cursor_at" +required-features = ["std"] + +[[example]] +name = "keyboard" +required-features = ["std"] + +[[example]] +name = "term" +required-features = ["std"] + +## These are currently disabled. If you want to play around with the benchmarks +## uncommit this. +#criterion = "0.3.5" +#[[bench]] +#name = "ansi_parser" +#harness = false diff --git a/anneal/v2/vendor/console/LICENSE b/anneal/v2/vendor/console/LICENSE new file mode 100644 index 0000000000..dc9a85c1ee --- /dev/null +++ b/anneal/v2/vendor/console/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 Armin Ronacher + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/anneal/v2/vendor/console/README.md b/anneal/v2/vendor/console/README.md new file mode 100644 index 0000000000..7afe0887e5 --- /dev/null +++ b/anneal/v2/vendor/console/README.md @@ -0,0 +1,76 @@ +# `console` + +[![Build Status](https://github.com/console-rs/console/actions/workflows/ci.yml/badge.svg)](https://github.com/console-rs/console/actions?query=workflow%3ACI) +[![crates.io](https://img.shields.io/crates/d/console.svg)](https://crates.io/crates/console) +[![License](https://img.shields.io/github/license/console-rs/console)](https://github.com/console-rs/console/blob/main/LICENSE) +[![Documentation](https://docs.rs/console/badge.svg)](https://docs.rs/console) + +**console** is a library for Rust that provides access to various terminal +features so you can build nicer looking command line interfaces. It +comes with various tools and utilities for working with Terminals and +formatting text. + +Best paired with other libraries in the family: + +* [dialoguer](https://docs.rs/dialoguer) +* [indicatif](https://docs.rs/indicatif) + +## Terminal Access + +The terminal is abstracted through the `console::Term` type. It can +either directly provide access to the connected terminal or by buffering +up commands. A buffered terminal will however not be completely buffered +on windows where cursor movements are currently directly passed through. + +Example usage: + +```rust +use std::thread; +use std::time::Duration; + +use console::Term; + +let term = Term::stdout(); +term.write_line("Hello World!")?; +thread::sleep(Duration::from_millis(2000)); +term.clear_line()?; +``` + +## Colors and Styles + +`console` automatically detects when to use colors based on the tty flag, following the +[clicolors standard](https://bixense.com/clicolors/) for color enabling/disabling. It also +provides higher level wrappers for styling text and other things that can be +displayed with the `style` function and utility types. + +Example usage: + +```rust +use console::style; + +println!("This is {} neat", style("quite").cyan()); +``` + +You can also store styles and apply them to text later: + +```rust +use console::Style; + +let cyan = Style::new().cyan(); +println!("This is {} neat", cyan.apply_to("quite")); +``` + +## Working with ANSI Codes + +The crate provides the function `strip_ansi_codes` to remove ANSI codes +from a string as well as `measure_text_width` to calculate the width of a +string as it would be displayed by the terminal. Both of those together +are useful for more complex formatting. + +## Unicode Width Support + +By default this crate depends on the `unicode-width` crate to calculate +the width of terminal characters. If you do not need this you can disable +the `unicode-width` feature which will cut down on dependencies. + +License: MIT diff --git a/anneal/v2/vendor/console/src/ansi.rs b/anneal/v2/vendor/console/src/ansi.rs new file mode 100644 index 0000000000..e3a39aad39 --- /dev/null +++ b/anneal/v2/vendor/console/src/ansi.rs @@ -0,0 +1,471 @@ +#[cfg(feature = "alloc")] +use alloc::{borrow::Cow, string::String}; +use core::{ + fmt::Display, + iter::{FusedIterator, Peekable}, + str::CharIndices, +}; + +#[derive(Debug, Clone, Copy, Default)] +enum State { + #[default] + Start, + S1, + S2, + S3, + S4, + S5, + S6, + S7, + S8, + S9, + S10, + S11, + Trap, +} + +impl State { + fn is_final(&self) -> bool { + #[allow(clippy::match_like_matches_macro)] + match self { + Self::S3 | Self::S5 | Self::S6 | Self::S7 | Self::S8 | Self::S9 | Self::S11 => true, + _ => false, + } + } + + fn is_trapped(&self) -> bool { + #[allow(clippy::match_like_matches_macro)] + match self { + Self::Trap => true, + _ => false, + } + } + + fn transition(&mut self, c: char) { + *self = match c { + '\u{1b}' | '\u{9b}' => match self { + Self::Start => Self::S1, + _ => Self::Trap, + }, + '(' | ')' => match self { + Self::S1 => Self::S2, + Self::S2 | Self::S4 => Self::S4, + _ => Self::Trap, + }, + ';' => match self { + Self::S1 | Self::S2 | Self::S4 => Self::S4, + Self::S5 | Self::S6 | Self::S7 | Self::S8 | Self::S10 => Self::S10, + _ => Self::Trap, + }, + + '[' | '#' | '?' => match self { + Self::S1 | Self::S2 | Self::S4 => Self::S4, + _ => Self::Trap, + }, + '0'..='2' => match self { + Self::S1 | Self::S4 => Self::S5, + Self::S2 => Self::S3, + Self::S5 => Self::S6, + Self::S6 => Self::S7, + Self::S7 => Self::S8, + Self::S8 => Self::S9, + Self::S10 => Self::S5, + _ => Self::Trap, + }, + '3'..='9' => match self { + Self::S1 | Self::S4 => Self::S5, + Self::S2 => Self::S5, + Self::S5 => Self::S6, + Self::S6 => Self::S7, + Self::S7 => Self::S8, + Self::S8 => Self::S9, + Self::S10 => Self::S5, + _ => Self::Trap, + }, + 'A'..='P' | 'R' | 'Z' | 'c' | 'f'..='n' | 'q' | 'r' | 'y' | '=' | '>' | '<' => { + match self { + Self::S1 + | Self::S2 + | Self::S4 + | Self::S5 + | Self::S6 + | Self::S7 + | Self::S8 + | Self::S10 => Self::S11, + _ => Self::Trap, + } + } + _ => Self::Trap, + }; + } +} + +#[derive(Debug)] +struct Matches<'a> { + s: &'a str, + it: Peekable>, +} + +impl<'a> Matches<'a> { + fn new(s: &'a str) -> Self { + let it = s.char_indices().peekable(); + Self { s, it } + } +} + +#[derive(Debug)] +struct Match<'a> { + text: &'a str, + start: usize, + end: usize, +} + +impl<'a> Match<'a> { + #[inline] + pub(crate) fn as_str(&self) -> &'a str { + &self.text[self.start..self.end] + } +} + +impl<'a> Iterator for Matches<'a> { + type Item = Match<'a>; + + fn next(&mut self) -> Option { + find_ansi_code_exclusive(&mut self.it).map(|(start, end)| Match { + text: self.s, + start, + end, + }) + } +} + +impl FusedIterator for Matches<'_> {} + +fn find_ansi_code_exclusive(it: &mut Peekable) -> Option<(usize, usize)> { + 'outer: loop { + if let (start, '\u{1b}') | (start, '\u{9b}') = it.peek()? { + let start = *start; + let mut state = State::default(); + let mut maybe_end = None; + + loop { + let item = it.peek(); + + if let Some((idx, c)) = item { + state.transition(*c); + + if state.is_final() { + maybe_end = Some(*idx); + } + } + + // The match is greedy so run till we hit the trap state no matter what. A valid + // match is just one that was final at some point + if state.is_trapped() || item.is_none() { + match maybe_end { + Some(end) => { + // All possible final characters are a single byte so it's safe to make + // the end exclusive by just adding one + return Some((start, end + 1)); + } + // The character we are peeking right now might be the start of a match so + // we want to continue the loop without popping off that char + None => continue 'outer, + } + } + + it.next(); + } + } + + it.next(); + } +} + +/// Helper function to strip ansi codes. +#[cfg(feature = "alloc")] +pub fn strip_ansi_codes(s: &str) -> Cow<'_, str> { + let mut char_it = s.char_indices().peekable(); + match find_ansi_code_exclusive(&mut char_it) { + Some(_) => { + let stripped: String = AnsiCodeIterator::new(s) + .filter_map(|(text, is_ansi)| if is_ansi { None } else { Some(text) }) + .collect(); + Cow::Owned(stripped) + } + None => Cow::Borrowed(s), + } +} + +/// A wrapper struct that implements [`core::fmt::Display`], only displaying non-ansi parts. +pub struct WithoutAnsi<'a> { + str: &'a str, +} + +impl<'a> WithoutAnsi<'a> { + pub fn new(str: &'a str) -> Self { + Self { str } + } +} + +impl Display for WithoutAnsi<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + for (str, is_ansi) in AnsiCodeIterator::new(self.str) { + if !is_ansi { + f.write_str(str)?; + } + } + Ok(()) + } +} + +/// An iterator over ansi codes in a string. +/// +/// This type can be used to scan over ansi codes in a string. +/// It yields tuples in the form `(s, is_ansi)` where `s` is a slice of +/// the original string and `is_ansi` indicates if the slice contains +/// ansi codes or string values. +pub struct AnsiCodeIterator<'a> { + s: &'a str, + pending_item: Option<(&'a str, bool)>, + last_idx: usize, + cur_idx: usize, + iter: Matches<'a>, +} + +impl<'a> AnsiCodeIterator<'a> { + /// Creates a new ansi code iterator. + pub fn new(s: &'a str) -> AnsiCodeIterator<'a> { + AnsiCodeIterator { + s, + pending_item: None, + last_idx: 0, + cur_idx: 0, + iter: Matches::new(s), + } + } + + /// Returns the string slice up to the current match. + pub fn current_slice(&self) -> &str { + &self.s[..self.cur_idx] + } + + /// Returns the string slice from the current match to the end. + pub fn rest_slice(&self) -> &str { + &self.s[self.cur_idx..] + } +} + +impl<'a> Iterator for AnsiCodeIterator<'a> { + type Item = (&'a str, bool); + + fn next(&mut self) -> Option<(&'a str, bool)> { + if let Some(pending_item) = self.pending_item.take() { + self.cur_idx += pending_item.0.len(); + Some(pending_item) + } else if let Some(m) = self.iter.next() { + let s = &self.s[self.last_idx..m.start]; + self.last_idx = m.end; + if s.is_empty() { + self.cur_idx = m.end; + Some((m.as_str(), true)) + } else { + self.cur_idx = m.start; + self.pending_item = Some((m.as_str(), true)); + Some((s, false)) + } + } else if self.last_idx < self.s.len() { + let rv = &self.s[self.last_idx..]; + self.cur_idx = self.s.len(); + self.last_idx = self.s.len(); + Some((rv, false)) + } else { + None + } + } +} + +impl FusedIterator for AnsiCodeIterator<'_> {} + +#[cfg(test)] +mod tests { + use super::*; + + use core::fmt::Write; + use proptest::prelude::*; + use regex::Regex; + use std::sync::OnceLock; + + // The manual dfa `State` is a handwritten translation from the previously used regex. That + // regex is kept here and used to ensure that the new matches are the same as the old + fn strip_ansi_re() -> &'static Regex { + static RE: OnceLock = OnceLock::new(); + + RE.get_or_init(|| Regex::new( + r"[\x1b\x9b]([()][012AB]|[\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><])", + ).unwrap()) + } + + impl<'a> PartialEq> for regex::Match<'_> { + fn eq(&self, other: &Match<'a>) -> bool { + self.start() == other.start && self.end() == other.end + } + } + + proptest! { + #[test] + fn dfa_matches_old_regex(s in r"([\x1b\x9b]?.*){0,5}") { + let old_matches: Vec<_> = strip_ansi_re().find_iter(&s).collect(); + let new_matches: Vec<_> = Matches::new(&s).collect(); + assert_eq!(old_matches, new_matches); + } + } + + #[test] + fn dfa_matches_regex_on_small_strings() { + // To make sure the test runs in a reasonable time this is a slimmed down list of + // characters to reduce the groups that are only used with each other along with one + // arbitrarily chosen character not used in the regex (' ') + const POSSIBLE_BYTES: &[u8] = &[b' ', 0x1b, 0x9b, b'(', b'0', b'[', b';', b'3', b'C']; + + fn check_all_strings_of_len(len: usize) { + _check_all_strings_of_len(len, &mut Vec::with_capacity(len)); + } + + fn _check_all_strings_of_len(len: usize, chunk: &mut Vec) { + if len == 0 { + if let Ok(s) = core::str::from_utf8(chunk) { + let old_matches: Vec<_> = strip_ansi_re().find_iter(s).collect(); + let new_matches: Vec<_> = Matches::new(s).collect(); + assert_eq!(old_matches, new_matches); + } + + return; + } + + for b in POSSIBLE_BYTES { + chunk.push(*b); + _check_all_strings_of_len(len - 1, chunk); + chunk.pop(); + } + } + + for str_len in 0..=6 { + check_all_strings_of_len(str_len); + } + } + + #[test] + fn complex_data() { + let s = std::fs::read_to_string( + std::path::Path::new("tests") + .join("data") + .join("sample_zellij_session.log"), + ) + .unwrap(); + + let old_matches: Vec<_> = strip_ansi_re().find_iter(&s).collect(); + let new_matches: Vec<_> = Matches::new(&s).collect(); + assert_eq!(old_matches, new_matches); + } + + #[test] + fn state_machine() { + let ansi_code = "\x1b)B"; + let mut state = State::default(); + assert!(!state.is_final()); + + for c in ansi_code.chars() { + state.transition(c); + } + assert!(state.is_final()); + + state.transition('A'); + assert!(state.is_trapped()); + } + + #[test] + fn back_to_back_entry_char() { + let s = "\x1b\x1bf"; + let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); + assert_eq!(&["\x1bf"], matches.as_slice()); + } + + #[test] + fn early_paren_can_use_many_chars() { + let s = "\x1b(C"; + let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); + assert_eq!(&[s], matches.as_slice()); + } + + #[test] + fn long_run_of_digits() { + let s = "\u{1b}00000"; + let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); + assert_eq!(&[s], matches.as_slice()); + } + + #[test] + fn test_without_ansi() { + let str_with_ansi = "\x1b[1;97;41mError\x1b[0m"; + let without_ansi = WithoutAnsi::new(str_with_ansi); + for _ in 0..2 { + let mut output = String::default(); + write!(output, "{without_ansi}").unwrap(); + assert_eq!(output, "Error"); + } + } + + #[test] + fn test_ansi_iter_re_vt100() { + let s = "\x1b(0lpq\x1b)Benglish"; + let mut iter = AnsiCodeIterator::new(s); + assert_eq!(iter.next(), Some(("\x1b(0", true))); + assert_eq!(iter.next(), Some(("lpq", false))); + assert_eq!(iter.next(), Some(("\x1b)B", true))); + assert_eq!(iter.next(), Some(("english", false))); + } + + #[test] + fn test_ansi_iter_re() { + use crate::style; + let s = format!("Hello {}!", style("World").red().force_styling(true)); + let mut iter = AnsiCodeIterator::new(&s); + assert_eq!(iter.next(), Some(("Hello ", false))); + assert_eq!(iter.current_slice(), "Hello "); + assert_eq!(iter.rest_slice(), "\x1b[31mWorld\x1b[0m!"); + assert_eq!(iter.next(), Some(("\x1b[31m", true))); + assert_eq!(iter.current_slice(), "Hello \x1b[31m"); + assert_eq!(iter.rest_slice(), "World\x1b[0m!"); + assert_eq!(iter.next(), Some(("World", false))); + assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld"); + assert_eq!(iter.rest_slice(), "\x1b[0m!"); + assert_eq!(iter.next(), Some(("\x1b[0m", true))); + assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld\x1b[0m"); + assert_eq!(iter.rest_slice(), "!"); + assert_eq!(iter.next(), Some(("!", false))); + assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld\x1b[0m!"); + assert_eq!(iter.rest_slice(), ""); + assert_eq!(iter.next(), None); + } + + #[test] + fn test_ansi_iter_re_on_multi() { + use crate::style; + let s = format!("{}", style("a").red().bold().force_styling(true)); + let mut iter = AnsiCodeIterator::new(&s); + assert_eq!(iter.next(), Some(("\x1b[31m", true))); + assert_eq!(iter.current_slice(), "\x1b[31m"); + assert_eq!(iter.rest_slice(), "\x1b[1ma\x1b[0m"); + assert_eq!(iter.next(), Some(("\x1b[1m", true))); + assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1m"); + assert_eq!(iter.rest_slice(), "a\x1b[0m"); + assert_eq!(iter.next(), Some(("a", false))); + assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1ma"); + assert_eq!(iter.rest_slice(), "\x1b[0m"); + assert_eq!(iter.next(), Some(("\x1b[0m", true))); + assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1ma\x1b[0m"); + assert_eq!(iter.rest_slice(), ""); + assert_eq!(iter.next(), None); + } +} diff --git a/anneal/v2/vendor/console/src/common_term.rs b/anneal/v2/vendor/console/src/common_term.rs new file mode 100644 index 0000000000..825899c7fc --- /dev/null +++ b/anneal/v2/vendor/console/src/common_term.rs @@ -0,0 +1,72 @@ +use std::io; + +use crate::term::Term; + +pub(crate) fn move_cursor_down(out: &Term, n: usize) -> io::Result<()> { + if n > 0 { + out.write_str(&format!("\x1b[{n}B")) + } else { + Ok(()) + } +} + +pub(crate) fn move_cursor_up(out: &Term, n: usize) -> io::Result<()> { + if n > 0 { + out.write_str(&format!("\x1b[{n}A")) + } else { + Ok(()) + } +} +pub(crate) fn move_cursor_left(out: &Term, n: usize) -> io::Result<()> { + if n > 0 { + out.write_str(&format!("\x1b[{n}D")) + } else { + Ok(()) + } +} + +pub(crate) fn move_cursor_right(out: &Term, n: usize) -> io::Result<()> { + if n > 0 { + out.write_str(&format!("\x1b[{n}C")) + } else { + Ok(()) + } +} + +#[inline] +pub(crate) fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> { + out.write_str(&format!("\x1B[{};{}H", y + 1, x + 1)) +} + +pub(crate) fn clear_chars(out: &Term, n: usize) -> io::Result<()> { + if n > 0 { + out.write_str(&format!("\x1b[{n}D\x1b[0K")) + } else { + Ok(()) + } +} + +#[inline] +pub(crate) fn clear_line(out: &Term) -> io::Result<()> { + out.write_str("\r\x1b[2K") +} + +#[inline] +pub(crate) fn clear_screen(out: &Term) -> io::Result<()> { + out.write_str("\r\x1b[2J\r\x1b[H") +} + +#[inline] +pub(crate) fn clear_to_end_of_screen(out: &Term) -> io::Result<()> { + out.write_str("\r\x1b[0J") +} + +#[inline] +pub(crate) fn show_cursor(out: &Term) -> io::Result<()> { + out.write_str("\x1b[?25h") +} + +#[inline] +pub(crate) fn hide_cursor(out: &Term) -> io::Result<()> { + out.write_str("\x1b[?25l") +} diff --git a/anneal/v2/vendor/console/src/kb.rs b/anneal/v2/vendor/console/src/kb.rs new file mode 100644 index 0000000000..101d77e7c4 --- /dev/null +++ b/anneal/v2/vendor/console/src/kb.rs @@ -0,0 +1,32 @@ +use alloc::vec::Vec; + +/// Key mapping +/// +/// This is an incomplete mapping of keys that are supported for reading +/// from the keyboard. +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum Key { + Unknown, + /// Unrecognized sequence containing Esc and a list of chars + UnknownEscSeq(Vec), + ArrowLeft, + ArrowRight, + ArrowUp, + ArrowDown, + Enter, + Escape, + Backspace, + Home, + End, + Tab, + BackTab, + Alt, + Del, + Shift, + Insert, + PageUp, + PageDown, + Char(char), + CtrlC, +} diff --git a/anneal/v2/vendor/console/src/lib.rs b/anneal/v2/vendor/console/src/lib.rs new file mode 100644 index 0000000000..9cd0b050f6 --- /dev/null +++ b/anneal/v2/vendor/console/src/lib.rs @@ -0,0 +1,123 @@ +//! console is a library for Rust that provides access to various terminal +//! features so you can build nicer looking command line interfaces. It +//! comes with various tools and utilities for working with Terminals and +//! formatting text. +//! +//! Best paired with other libraries in the family: +//! +//! * [dialoguer](https://docs.rs/dialoguer) +//! * [indicatif](https://docs.rs/indicatif) +//! +//! # Terminal Access +//! +//! The terminal is abstracted through the `console::Term` type. It can +//! either directly provide access to the connected terminal or by buffering +//! up commands. A buffered terminal will however not be completely buffered +//! on windows where cursor movements are currently directly passed through. +//! +//! Example usage: +//! +//! ``` +//! # fn test() -> Result<(), Box> { +//! use std::thread; +//! use std::time::Duration; +//! +//! use console::Term; +//! +//! let term = Term::stdout(); +//! term.write_line("Hello World!")?; +//! thread::sleep(Duration::from_millis(2000)); +//! term.clear_line()?; +//! # Ok(()) } test().unwrap(); +//! ``` +//! +//! # Colors and Styles +//! +//! `console` automatically detects when to use colors based on the tty flag. It also +//! provides higher level wrappers for styling text and other things that can be +//! displayed with the `style` function and utility types. +//! +//! Example usage: +//! +//! ``` +//! use console::style; +//! +//! println!("This is {} neat", style("quite").cyan()); +//! ``` +//! +//! You can also store styles and apply them to text later: +//! +//! ``` +//! use console::Style; +//! +//! let cyan = Style::new().cyan(); +//! println!("This is {} neat", cyan.apply_to("quite")); +//! ``` +//! +//! # Working with ANSI Codes +//! +//! The crate provides the function `strip_ansi_codes` to remove ANSI codes +//! from a string as well as `measure_text_width` to calculate the width of a +//! string as it would be displayed by the terminal. Both of those together +//! are useful for more complex formatting. +//! +//! # Unicode Width Support +//! +//! By default this crate depends on the `unicode-width` crate to calculate +//! the width of terminal characters. If you do not need this you can disable +//! the `unicode-width` feature which will cut down on dependencies. +//! +//! # Features +//! +//! By default all features are enabled. The following features exist: +//! +//! * `unicode-width`: adds support for unicode width calculations +//! * `ansi-parsing`: adds support for parsing ansi codes (this adds support +//! for stripping and taking ansi escape codes into account for length +//! calculations). + +#![warn( + unreachable_pub, + clippy::std_instead_of_core, + clippy::std_instead_of_alloc +)] +#![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "alloc")] +pub use crate::kb::Key; +#[cfg(feature = "std")] +pub use crate::term::{ + user_attended, user_attended_stderr, Term, TermFamily, TermFeatures, TermTarget, +}; +#[cfg(feature = "std")] +pub use crate::utils::{ + colors_enabled, colors_enabled_stderr, measure_text_width, pad_str, pad_str_with, + set_colors_enabled, set_colors_enabled_stderr, set_true_colors_enabled, + set_true_colors_enabled_stderr, style, true_colors_enabled, true_colors_enabled_stderr, + truncate_str, Alignment, Attribute, Color, Emoji, Style, StyledObject, +}; + +#[cfg(all(feature = "ansi-parsing", feature = "alloc"))] +pub use crate::ansi::strip_ansi_codes; +#[cfg(feature = "ansi-parsing")] +pub use crate::ansi::{AnsiCodeIterator, WithoutAnsi}; + +#[cfg(feature = "std")] +mod common_term; +#[cfg(feature = "alloc")] +mod kb; +#[cfg(feature = "std")] +mod term; +#[cfg(all(unix, not(target_arch = "wasm32"), feature = "std"))] +mod unix_term; +#[cfg(feature = "std")] +mod utils; +#[cfg(all(feature = "std", target_arch = "wasm32"))] +mod wasm_term; +#[cfg(all(feature = "std", windows))] +mod windows_term; + +#[cfg(feature = "ansi-parsing")] +mod ansi; diff --git a/anneal/v2/vendor/console/src/term.rs b/anneal/v2/vendor/console/src/term.rs new file mode 100644 index 0000000000..7965b4612b --- /dev/null +++ b/anneal/v2/vendor/console/src/term.rs @@ -0,0 +1,672 @@ +use alloc::sync::Arc; +use core::fmt::{Debug, Display}; +use std::io::{self, Read, Write}; +#[cfg(any(unix, all(target_os = "wasi", target_env = "p1")))] +use std::os::fd::{AsRawFd, RawFd}; +#[cfg(windows)] +use std::os::windows::io::{AsRawHandle, RawHandle}; +use std::sync::{Mutex, RwLock}; + +use crate::{kb::Key, utils::Style}; + +#[cfg(unix)] +trait TermWrite: Write + Debug + AsRawFd + Send {} +#[cfg(unix)] +impl TermWrite for T {} + +#[cfg(unix)] +trait TermRead: Read + Debug + AsRawFd + Send {} +#[cfg(unix)] +impl TermRead for T {} + +#[cfg(unix)] +#[derive(Debug, Clone)] +pub struct ReadWritePair { + #[allow(unused)] + read: Arc>, + write: Arc>, + style: Style, +} + +/// Where the term is writing. +#[derive(Debug, Clone)] +pub enum TermTarget { + Stdout, + Stderr, + #[cfg(unix)] + ReadWritePair(ReadWritePair), +} + +#[derive(Debug)] +struct TermInner { + target: TermTarget, + buffer: Option>>, + prompt: RwLock, + prompt_guard: Mutex<()>, +} + +/// The family of the terminal. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum TermFamily { + /// Redirected to a file or file like thing. + File, + /// A standard unix terminal. + UnixTerm, + /// A cmd.exe like windows console. + WindowsConsole, + /// A dummy terminal (for instance on wasm) + Dummy, +} + +/// Gives access to the terminal features. +#[derive(Debug, Clone)] +pub struct TermFeatures<'a>(&'a Term); + +impl TermFeatures<'_> { + /// Check if this is a real user attended terminal (`isatty`) + #[inline] + pub fn is_attended(&self) -> bool { + is_a_terminal(self.0) + } + + /// Check if colors are supported by this terminal. + /// + /// This does not check if colors are enabled. Currently all terminals + /// are considered to support colors + #[inline] + pub fn colors_supported(&self) -> bool { + is_a_color_terminal(self.0) + } + + /// Check if true colors are supported by this terminal. + pub fn true_colors_supported(&self) -> bool { + is_a_true_color_terminal(self.0) + } + + /// Check if this terminal is an msys terminal. + /// + /// This is sometimes useful to disable features that are known to not + /// work on msys terminals or require special handling. + #[inline] + pub fn is_msys_tty(&self) -> bool { + #[cfg(windows)] + { + msys_tty_on(self.0) + } + #[cfg(not(windows))] + { + false + } + } + + /// Check if this terminal wants emojis. + #[inline] + pub fn wants_emoji(&self) -> bool { + self.is_attended() && wants_emoji() + } + + /// Return the family of the terminal. + #[inline] + pub fn family(&self) -> TermFamily { + if !self.is_attended() { + return TermFamily::File; + } + #[cfg(windows)] + { + TermFamily::WindowsConsole + } + #[cfg(all(unix, not(target_arch = "wasm32")))] + { + TermFamily::UnixTerm + } + #[cfg(target_arch = "wasm32")] + { + TermFamily::Dummy + } + } +} + +/// Abstraction around a terminal. +/// +/// A terminal can be cloned. If a buffer is used it's shared across all +/// clones which means it largely acts as a handle. +#[derive(Clone, Debug)] +pub struct Term { + inner: Arc, + pub(crate) is_msys_tty: bool, + pub(crate) is_tty: bool, +} + +impl Term { + fn with_inner(inner: TermInner) -> Term { + let mut term = Term { + inner: Arc::new(inner), + is_msys_tty: false, + is_tty: false, + }; + + term.is_msys_tty = term.features().is_msys_tty(); + term.is_tty = term.features().is_attended(); + term + } + + /// Return a new unbuffered terminal. + #[inline] + pub fn stdout() -> Term { + Term::with_inner(TermInner { + target: TermTarget::Stdout, + buffer: None, + prompt: RwLock::new(String::new()), + prompt_guard: Mutex::new(()), + }) + } + + /// Return a new unbuffered terminal to stderr. + #[inline] + pub fn stderr() -> Term { + Term::with_inner(TermInner { + target: TermTarget::Stderr, + buffer: None, + prompt: RwLock::new(String::new()), + prompt_guard: Mutex::new(()), + }) + } + + /// Return a new buffered terminal. + pub fn buffered_stdout() -> Term { + Term::with_inner(TermInner { + target: TermTarget::Stdout, + buffer: Some(Mutex::new(vec![])), + prompt: RwLock::new(String::new()), + prompt_guard: Mutex::new(()), + }) + } + + /// Return a new buffered terminal to stderr. + pub fn buffered_stderr() -> Term { + Term::with_inner(TermInner { + target: TermTarget::Stderr, + buffer: Some(Mutex::new(vec![])), + prompt: RwLock::new(String::new()), + prompt_guard: Mutex::new(()), + }) + } + + /// Return a terminal for the given Read/Write pair styled like stderr. + #[cfg(unix)] + pub fn read_write_pair(read: R, write: W) -> Term + where + R: Read + Debug + AsRawFd + Send + 'static, + W: Write + Debug + AsRawFd + Send + 'static, + { + Self::read_write_pair_with_style(read, write, Style::new().for_stderr()) + } + + /// Return a terminal for the given Read/Write pair. + #[cfg(unix)] + pub fn read_write_pair_with_style(read: R, write: W, style: Style) -> Term + where + R: Read + Debug + AsRawFd + Send + 'static, + W: Write + Debug + AsRawFd + Send + 'static, + { + Term::with_inner(TermInner { + target: TermTarget::ReadWritePair(ReadWritePair { + read: Arc::new(Mutex::new(read)), + write: Arc::new(Mutex::new(write)), + style, + }), + buffer: None, + prompt: RwLock::new(String::new()), + prompt_guard: Mutex::new(()), + }) + } + + /// Return the style for this terminal. + #[inline] + pub fn style(&self) -> Style { + match self.inner.target { + TermTarget::Stderr => Style::new().for_stderr(), + TermTarget::Stdout => Style::new().for_stdout(), + #[cfg(unix)] + TermTarget::ReadWritePair(ReadWritePair { ref style, .. }) => style.clone(), + } + } + + /// Return the target of this terminal. + #[inline] + pub fn target(&self) -> TermTarget { + self.inner.target.clone() + } + + #[doc(hidden)] + pub fn write_str(&self, s: &str) -> io::Result<()> { + match self.inner.buffer { + Some(ref buffer) => buffer.lock().unwrap().write_all(s.as_bytes()), + None => self.write_through(s.as_bytes()), + } + } + + /// Write a string to the terminal and add a newline. + pub fn write_line(&self, s: &str) -> io::Result<()> { + let prompt = self.inner.prompt.read().unwrap(); + if !prompt.is_empty() { + self.clear_line()?; + } + match self.inner.buffer { + Some(ref mutex) => { + let mut buffer = mutex.lock().unwrap(); + buffer.extend_from_slice(s.as_bytes()); + buffer.push(b'\n'); + buffer.extend_from_slice(prompt.as_bytes()); + Ok(()) + } + None => self.write_through(format!("{}\n{}", s, prompt.as_str()).as_bytes()), + } + } + + /// Read a single character from the terminal. + /// + /// This does not echo the character and blocks until a single character + /// or complete key chord is entered. If the terminal is not user attended + /// the return value will be an error. + pub fn read_char(&self) -> io::Result { + if !self.is_tty { + return Err(io::Error::new( + io::ErrorKind::NotConnected, + "Not a terminal", + )); + } + loop { + match self.read_key()? { + Key::Char(c) => { + return Ok(c); + } + Key::Enter => { + return Ok('\n'); + } + _ => {} + } + } + } + + /// Read a single key from the terminal. + /// + /// This does not echo anything. If the terminal is not user attended + /// the return value will always be the unknown key. + pub fn read_key(&self) -> io::Result { + if !self.is_tty { + Ok(Key::Unknown) + } else { + read_single_key(false) + } + } + + pub fn read_key_raw(&self) -> io::Result { + if !self.is_tty { + Ok(Key::Unknown) + } else { + read_single_key(true) + } + } + + /// Read one line of input. + /// + /// This does not include the trailing newline. If the terminal is not + /// user attended the return value will always be an empty string. + pub fn read_line(&self) -> io::Result { + self.read_line_initial_text("") + } + + /// Read one line of input with initial text. + /// + /// This method blocks until no other thread is waiting for this read_line + /// before reading a line from the terminal. + /// This does not include the trailing newline. If the terminal is not + /// user attended the return value will always be an empty string. + pub fn read_line_initial_text(&self, initial: &str) -> io::Result { + if !self.is_tty { + return Ok("".into()); + } + *self.inner.prompt.write().unwrap() = initial.to_string(); + // use a guard in order to prevent races with other calls to read_line_initial_text + let _guard = self.inner.prompt_guard.lock().unwrap(); + + self.write_str(initial)?; + + fn read_line_internal(slf: &Term, initial: &str) -> io::Result { + let prefix_len = initial.len(); + + let mut chars: Vec = initial.chars().collect(); + + loop { + match slf.read_key()? { + Key::Backspace => { + if prefix_len < chars.len() { + if let Some(ch) = chars.pop() { + slf.clear_chars(crate::utils::char_width(ch))?; + } + } + slf.flush()?; + } + Key::Char(chr) => { + chars.push(chr); + let mut bytes_char = [0; 4]; + chr.encode_utf8(&mut bytes_char); + slf.write_str(chr.encode_utf8(&mut bytes_char))?; + slf.flush()?; + } + Key::Enter => { + slf.write_through(format!("\n{initial}").as_bytes())?; + break; + } + _ => (), + } + } + Ok(chars.iter().skip(prefix_len).collect::()) + } + let ret = read_line_internal(self, initial); + + *self.inner.prompt.write().unwrap() = String::new(); + ret + } + + /// Read a line of input securely. + /// + /// This is similar to `read_line` but will not echo the output. This + /// also switches the terminal into a different mode where not all + /// characters might be accepted. + pub fn read_secure_line(&self) -> io::Result { + if !self.is_tty { + return Ok("".into()); + } + match read_secure() { + Ok(rv) => { + self.write_line("")?; + Ok(rv) + } + Err(err) => Err(err), + } + } + + /// Flush internal buffers. + /// + /// This forces the contents of the internal buffer to be written to + /// the terminal. This is unnecessary for unbuffered terminals which + /// will automatically flush. + pub fn flush(&self) -> io::Result<()> { + if let Some(ref buffer) = self.inner.buffer { + let mut buffer = buffer.lock().unwrap(); + if !buffer.is_empty() { + self.write_through(&buffer[..])?; + buffer.clear(); + } + } + Ok(()) + } + + /// Check if the terminal is indeed a terminal. + #[inline] + pub fn is_term(&self) -> bool { + self.is_tty + } + + /// Check for common terminal features. + #[inline] + pub fn features(&self) -> TermFeatures<'_> { + TermFeatures(self) + } + + /// Return the terminal size in rows and columns or gets sensible defaults. + #[inline] + pub fn size(&self) -> (u16, u16) { + self.size_checked().unwrap_or((24, DEFAULT_WIDTH)) + } + + /// Return the terminal size in rows and columns. + /// + /// If the size cannot be reliably determined `None` is returned. + #[inline] + pub fn size_checked(&self) -> Option<(u16, u16)> { + terminal_size(self) + } + + /// Move the cursor to row `x` and column `y`. Values are 0-based. + #[inline] + pub fn move_cursor_to(&self, x: usize, y: usize) -> io::Result<()> { + move_cursor_to(self, x, y) + } + + /// Move the cursor up by `n` lines, if possible. + /// + /// If there are less than `n` lines above the current cursor position, + /// the cursor is moved to the top line of the terminal (i.e., as far up as possible). + #[inline] + pub fn move_cursor_up(&self, n: usize) -> io::Result<()> { + move_cursor_up(self, n) + } + + /// Move the cursor down by `n` lines, if possible. + /// + /// If there are less than `n` lines below the current cursor position, + /// the cursor is moved to the bottom line of the terminal (i.e., as far down as possible). + #[inline] + pub fn move_cursor_down(&self, n: usize) -> io::Result<()> { + move_cursor_down(self, n) + } + + /// Move the cursor `n` characters to the left, if possible. + /// + /// If there are fewer than `n` characters to the left of the current cursor position, + /// the cursor is moved to the beginning of the line (i.e., as far to the left as possible). + #[inline] + pub fn move_cursor_left(&self, n: usize) -> io::Result<()> { + move_cursor_left(self, n) + } + + /// Move the cursor `n` characters to the right. + /// + /// If there are fewer than `n` characters to the right of the current cursor position, + /// the cursor is moved to the end of the current line (i.e., as far to the right as possible). + #[inline] + pub fn move_cursor_right(&self, n: usize) -> io::Result<()> { + move_cursor_right(self, n) + } + + /// Clear the current line. + /// + /// Position the cursor at the beginning of the current line. + #[inline] + pub fn clear_line(&self) -> io::Result<()> { + clear_line(self) + } + + /// Clear the last `n` lines before the current line. + /// + /// Position the cursor at the beginning of the first line that was cleared. + pub fn clear_last_lines(&self, n: usize) -> io::Result<()> { + self.move_cursor_up(n)?; + for _ in 0..n { + self.clear_line()?; + self.move_cursor_down(1)?; + } + self.move_cursor_up(n)?; + Ok(()) + } + + /// Clear the entire screen. + /// + /// Move the cursor to the upper left corner of the screen. + #[inline] + pub fn clear_screen(&self) -> io::Result<()> { + clear_screen(self) + } + + /// Clear everything from the current cursor position to the end of the screen. + /// The cursor stays in its position. + #[inline] + pub fn clear_to_end_of_screen(&self) -> io::Result<()> { + clear_to_end_of_screen(self) + } + + /// Clear the last `n` characters of the current line. + #[inline] + pub fn clear_chars(&self, n: usize) -> io::Result<()> { + clear_chars(self, n) + } + + /// Set the terminal title. + pub fn set_title(&self, title: T) { + if !self.is_tty { + return; + } + set_title(title); + } + + /// Make the cursor visible again. + #[inline] + pub fn show_cursor(&self) -> io::Result<()> { + show_cursor(self) + } + + /// Hide the cursor. + #[inline] + pub fn hide_cursor(&self) -> io::Result<()> { + hide_cursor(self) + } + + // helpers + + #[cfg(all(windows, feature = "windows-console-colors"))] + fn write_through(&self, bytes: &[u8]) -> io::Result<()> { + if self.is_msys_tty || !self.is_tty { + self.write_through_common(bytes) + } else { + match self.inner.target { + TermTarget::Stdout => console_colors(self, Console::stdout()?, bytes), + TermTarget::Stderr => console_colors(self, Console::stderr()?, bytes), + } + } + } + + #[cfg(not(all(windows, feature = "windows-console-colors")))] + fn write_through(&self, bytes: &[u8]) -> io::Result<()> { + self.write_through_common(bytes) + } + + pub(crate) fn write_through_common(&self, bytes: &[u8]) -> io::Result<()> { + match self.inner.target { + TermTarget::Stdout => { + io::stdout().write_all(bytes)?; + io::stdout().flush()?; + } + TermTarget::Stderr => { + io::stderr().write_all(bytes)?; + io::stderr().flush()?; + } + #[cfg(unix)] + TermTarget::ReadWritePair(ReadWritePair { ref write, .. }) => { + let mut write = write.lock().unwrap(); + write.write_all(bytes)?; + write.flush()?; + } + } + Ok(()) + } +} + +/// A fast way to check if the application has a user attended for stdout. +/// +/// This means that stdout is connected to a terminal instead of a +/// file or redirected by other means. This is a shortcut for +/// checking the `is_attended` feature on the stdout terminal. +#[inline] +pub fn user_attended() -> bool { + Term::stdout().features().is_attended() +} + +/// A fast way to check if the application has a user attended for stderr. +/// +/// This means that stderr is connected to a terminal instead of a +/// file or redirected by other means. This is a shortcut for +/// checking the `is_attended` feature on the stderr terminal. +#[inline] +pub fn user_attended_stderr() -> bool { + Term::stderr().features().is_attended() +} + +#[cfg(any(unix, all(target_os = "wasi", target_env = "p1")))] +impl AsRawFd for Term { + fn as_raw_fd(&self) -> RawFd { + match self.inner.target { + TermTarget::Stdout => libc::STDOUT_FILENO, + TermTarget::Stderr => libc::STDERR_FILENO, + #[cfg(unix)] + TermTarget::ReadWritePair(ReadWritePair { ref write, .. }) => { + write.lock().unwrap().as_raw_fd() + } + } + } +} + +#[cfg(windows)] +impl AsRawHandle for Term { + fn as_raw_handle(&self) -> RawHandle { + use windows_sys::Win32::System::Console::{ + GetStdHandle, STD_ERROR_HANDLE, STD_OUTPUT_HANDLE, + }; + + unsafe { + GetStdHandle(match self.inner.target { + TermTarget::Stdout => STD_OUTPUT_HANDLE, + TermTarget::Stderr => STD_ERROR_HANDLE, + }) as RawHandle + } + } +} + +impl Write for Term { + fn write(&mut self, buf: &[u8]) -> io::Result { + match self.inner.buffer { + Some(ref buffer) => buffer.lock().unwrap().write_all(buf), + None => self.write_through(buf), + }?; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Term::flush(self) + } +} + +impl Write for &Term { + fn write(&mut self, buf: &[u8]) -> io::Result { + match self.inner.buffer { + Some(ref buffer) => buffer.lock().unwrap().write_all(buf), + None => self.write_through(buf), + }?; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Term::flush(self) + } +} + +impl Read for Term { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::stdin().read(buf) + } +} + +impl Read for &Term { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::stdin().read(buf) + } +} + +#[cfg(all(unix, not(target_arch = "wasm32")))] +pub(crate) use crate::unix_term::*; +#[cfg(target_arch = "wasm32")] +pub(crate) use crate::wasm_term::*; +#[cfg(windows)] +pub(crate) use crate::windows_term::*; diff --git a/anneal/v2/vendor/console/src/unix_term.rs b/anneal/v2/vendor/console/src/unix_term.rs new file mode 100644 index 0000000000..ec445d4b8f --- /dev/null +++ b/anneal/v2/vendor/console/src/unix_term.rs @@ -0,0 +1,424 @@ +#[cfg(target_os = "macos")] +use core::ptr; +use core::{fmt::Display, mem, str}; +use std::env; +use std::fs; +use std::io::{self, BufRead, BufReader}; +use std::os::fd::{AsRawFd, RawFd}; + +#[cfg(not(target_os = "macos"))] +use std::sync::OnceLock; + +use crate::kb::Key; +use crate::term::Term; + +pub(crate) use crate::common_term::*; + +pub(crate) const DEFAULT_WIDTH: u16 = 80; + +#[inline] +pub(crate) fn is_a_terminal(out: &impl AsRawFd) -> bool { + unsafe { libc::isatty(out.as_raw_fd()) != 0 } +} + +pub(crate) fn is_a_color_terminal(out: &Term) -> bool { + if !is_a_terminal(out) { + return false; + } + + if env::var("NO_COLOR").is_ok() { + return false; + } + + match env::var("TERM") { + Ok(term) => term != "dumb", + Err(_) => false, + } +} + +pub(crate) fn is_a_true_color_terminal(out: &Term) -> bool { + if !is_a_color_terminal(out) { + return false; + } + env::var("COLORTERM").is_ok_and(|term| term == "truecolor" || term == "24bit") +} + +fn c_result libc::c_int>(f: F) -> io::Result<()> { + let res = f(); + if res != 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +pub(crate) fn terminal_size(out: &Term) -> Option<(u16, u16)> { + if !is_a_terminal(out) { + return None; + } + let winsize = unsafe { + let mut winsize: libc::winsize = mem::zeroed(); + + // FIXME: ".into()" used as a temporary fix for a libc bug + // https://github.com/rust-lang/libc/pull/704 + #[allow(clippy::useless_conversion)] + libc::ioctl(out.as_raw_fd(), libc::TIOCGWINSZ.into(), &mut winsize); + winsize + }; + if winsize.ws_row > 0 && winsize.ws_col > 0 { + Some((winsize.ws_row, winsize.ws_col)) + } else { + None + } +} + +enum Input { + Stdin(io::Stdin), + File(T), +} + +impl Input> { + fn buffered() -> io::Result { + Ok(match Input::unbuffered()? { + Input::Stdin(s) => Input::Stdin(s), + Input::File(f) => Input::File(BufReader::new(f)), + }) + } +} + +impl Input { + fn unbuffered() -> io::Result { + let stdin = io::stdin(); + if is_a_terminal(&stdin) { + Ok(Input::Stdin(stdin)) + } else { + let f = fs::OpenOptions::new() + .read(true) + .write(true) + .open("/dev/tty")?; + Ok(Input::File(f)) + } + } +} + +// NB: this is not a full BufRead implementation because io::Stdin does not implement BufRead. +impl Input { + fn read_line(&mut self, buf: &mut String) -> io::Result { + match self { + Self::Stdin(s) => s.read_line(buf), + Self::File(f) => f.read_line(buf), + } + } +} + +impl AsRawFd for Input { + fn as_raw_fd(&self) -> RawFd { + match self { + Self::Stdin(s) => s.as_raw_fd(), + Self::File(f) => f.as_raw_fd(), + } + } +} + +impl AsRawFd for Input> { + fn as_raw_fd(&self) -> RawFd { + match self { + Self::Stdin(s) => s.as_raw_fd(), + Self::File(f) => f.get_ref().as_raw_fd(), + } + } +} + +pub(crate) fn read_secure() -> io::Result { + let mut input = Input::buffered()?; + + let mut termios = mem::MaybeUninit::uninit(); + c_result(|| unsafe { libc::tcgetattr(input.as_raw_fd(), termios.as_mut_ptr()) })?; + let mut termios = unsafe { termios.assume_init() }; + let original = termios; + termios.c_lflag &= !libc::ECHO; + c_result(|| unsafe { libc::tcsetattr(input.as_raw_fd(), libc::TCSAFLUSH, &termios) })?; + let mut rv = String::new(); + + let read_rv = input.read_line(&mut rv); + + c_result(|| unsafe { libc::tcsetattr(input.as_raw_fd(), libc::TCSAFLUSH, &original) })?; + + read_rv.map(|_| { + let len = rv.trim_end_matches(&['\r', '\n'][..]).len(); + rv.truncate(len); + rv + }) +} + +fn poll_fd(fd: RawFd, timeout: i32) -> io::Result { + let mut pollfd = libc::pollfd { + fd, + events: libc::POLLIN, + revents: 0, + }; + let ret = unsafe { libc::poll(&mut pollfd as *mut _, 1, timeout) }; + if ret < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(pollfd.revents & libc::POLLIN != 0) + } +} + +#[cfg(target_os = "macos")] +fn select_fd(fd: RawFd, timeout: i32) -> io::Result { + unsafe { + let mut read_fd_set: libc::fd_set = mem::zeroed(); + + let mut timeout_val; + let timeout = if timeout < 0 { + ptr::null_mut() + } else { + timeout_val = libc::timeval { + tv_sec: (timeout / 1000) as _, + tv_usec: (timeout * 1000) as _, + }; + &mut timeout_val + }; + + libc::FD_ZERO(&mut read_fd_set); + libc::FD_SET(fd, &mut read_fd_set); + let ret = libc::select( + fd + 1, + &mut read_fd_set, + ptr::null_mut(), + ptr::null_mut(), + timeout, + ); + if ret < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(libc::FD_ISSET(fd, &read_fd_set)) + } + } +} + +fn select_or_poll_term_fd(fd: RawFd, timeout: i32) -> io::Result { + // There is a bug on macos that ttys cannot be polled, only select() + // works. However given how problematic select is in general, we + // normally want to use poll there too. + #[cfg(target_os = "macos")] + { + if unsafe { libc::isatty(fd) == 1 } { + return select_fd(fd, timeout); + } + } + poll_fd(fd, timeout) +} + +fn read_single_char(fd: RawFd) -> io::Result> { + // timeout of zero means that it will not block + let is_ready = select_or_poll_term_fd(fd, 0)?; + + if is_ready { + // if there is something to be read, take 1 byte from it + let mut buf: [u8; 1] = [0]; + + read_bytes(fd, &mut buf, 1)?; + Ok(Some(buf[0] as char)) + } else { + //there is nothing to be read + Ok(None) + } +} + +// Similar to libc::read. Read count bytes into slice buf from descriptor fd. +// If successful, return the number of bytes read. +// Will return an error if nothing was read, i.e when called at end of file. +fn read_bytes(fd: RawFd, buf: &mut [u8], count: u8) -> io::Result { + let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, count as usize) }; + if read < 0 { + Err(io::Error::last_os_error()) + } else if read == 0 { + Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "Reached end of file", + )) + } else if buf[0] == b'\x03' { + Err(io::Error::new( + io::ErrorKind::Interrupted, + "read interrupted", + )) + } else { + Ok(read as u8) + } +} + +fn read_single_key_impl(fd: RawFd) -> Result { + loop { + match read_single_char(fd)? { + Some('\x1b') => { + // Escape was read, keep reading in case we find a familiar key + break if let Some(c1) = read_single_char(fd)? { + if c1 == '[' { + if let Some(c2) = read_single_char(fd)? { + match c2 { + 'A' => Ok(Key::ArrowUp), + 'B' => Ok(Key::ArrowDown), + 'C' => Ok(Key::ArrowRight), + 'D' => Ok(Key::ArrowLeft), + 'H' => Ok(Key::Home), + 'F' => Ok(Key::End), + 'Z' => Ok(Key::BackTab), + _ => { + let c3 = read_single_char(fd)?; + if let Some(c3) = c3 { + if c3 == '~' { + match c2 { + '1' => Ok(Key::Home), // tmux + '2' => Ok(Key::Insert), + '3' => Ok(Key::Del), + '4' => Ok(Key::End), // tmux + '5' => Ok(Key::PageUp), + '6' => Ok(Key::PageDown), + '7' => Ok(Key::Home), // xrvt + '8' => Ok(Key::End), // xrvt + _ => Ok(Key::UnknownEscSeq(vec![c1, c2, c3])), + } + } else { + Ok(Key::UnknownEscSeq(vec![c1, c2, c3])) + } + } else { + // \x1b[ and 1 more char + Ok(Key::UnknownEscSeq(vec![c1, c2])) + } + } + } + } else { + // \x1b[ and no more input + Ok(Key::UnknownEscSeq(vec![c1])) + } + } else { + // char after escape is not [ + Ok(Key::UnknownEscSeq(vec![c1])) + } + } else { + //nothing after escape + Ok(Key::Escape) + }; + } + Some(c) => { + let byte = c as u8; + let mut buf: [u8; 4] = [byte, 0, 0, 0]; + + break if byte & 224u8 == 192u8 { + // a two byte unicode character + read_bytes(fd, &mut buf[1..], 1)?; + Ok(key_from_utf8(&buf[..2])) + } else if byte & 240u8 == 224u8 { + // a three byte unicode character + read_bytes(fd, &mut buf[1..], 2)?; + Ok(key_from_utf8(&buf[..3])) + } else if byte & 248u8 == 240u8 { + // a four byte unicode character + read_bytes(fd, &mut buf[1..], 3)?; + Ok(key_from_utf8(&buf[..4])) + } else { + Ok(match c { + '\n' | '\r' => Key::Enter, + '\x7f' => Key::Backspace, + '\t' => Key::Tab, + '\x01' => Key::Home, // Control-A (home) + '\x05' => Key::End, // Control-E (end) + '\x08' => Key::Backspace, // Control-H (8) (Identical to '\b') + _ => Key::Char(c), + }) + }; + } + None => { + // there is no subsequent byte ready to be read, block and wait for input + // negative timeout means that it will block indefinitely + match select_or_poll_term_fd(fd, -1) { + Ok(_) => continue, + Err(_) => break Err(io::Error::last_os_error()), + } + } + } + } +} + +pub(crate) fn read_single_key(ctrlc_key: bool) -> io::Result { + let input = Input::unbuffered()?; + + let mut termios = core::mem::MaybeUninit::uninit(); + c_result(|| unsafe { libc::tcgetattr(input.as_raw_fd(), termios.as_mut_ptr()) })?; + let mut termios = unsafe { termios.assume_init() }; + let original = termios; + make_raw(&mut termios); + termios.c_oflag = original.c_oflag; + c_result(|| unsafe { libc::tcsetattr(input.as_raw_fd(), libc::TCSADRAIN, &termios) })?; + let rv = read_single_key_impl(input.as_raw_fd()); + c_result(|| unsafe { libc::tcsetattr(input.as_raw_fd(), libc::TCSADRAIN, &original) })?; + + // if the user hit ^C we want to signal SIGINT to ourselves. + if let Err(ref err) = rv { + if err.kind() == io::ErrorKind::Interrupted { + if !ctrlc_key { + unsafe { + libc::raise(libc::SIGINT); + } + } else { + return Ok(Key::CtrlC); + } + } + } + + rv +} + +fn key_from_utf8(buf: &[u8]) -> Key { + if let Ok(s) = str::from_utf8(buf) { + if let Some(c) = s.chars().next() { + return Key::Char(c); + } + } + Key::Unknown +} + +#[cfg(target_os = "macos")] +pub(crate) fn wants_emoji() -> bool { + true +} + +#[cfg(not(target_os = "macos"))] +pub(crate) fn wants_emoji() -> bool { + static IS_LANG_UTF8: OnceLock = OnceLock::new(); + + *IS_LANG_UTF8.get_or_init(|| match std::env::var("LANG") { + Ok(lang) => lang.to_uppercase().ends_with("UTF-8"), + _ => false, + }) +} + +pub(crate) fn set_title(title: T) { + print!("\x1b]0;{title}\x07"); +} + +#[cfg(target_os = "nto")] +fn make_raw(termios: &mut libc::termios) { + // This is the manual implementation for QNX, which does not have cfmakeraw. + termios.c_iflag &= !(libc::IGNBRK + | libc::BRKINT + | libc::PARMRK + | libc::ISTRIP + | libc::INLCR + | libc::IGNCR + | libc::ICRNL + | libc::IXON); + termios.c_oflag &= !libc::OPOST; + termios.c_lflag &= !(libc::ECHO | libc::ECHONL | libc::ICANON | libc::ISIG | libc::IEXTEN); + termios.c_cflag &= !(libc::CSIZE | libc::PARENB); + termios.c_cflag |= libc::CS8; +} + +// This version will be compiled for all targets that are NOT QNX. +#[cfg(not(target_os = "nto"))] +fn make_raw(termios: &mut libc::termios) { + // For other systems (Linux, macOS, BSD, etc.), use the standard libc call. + unsafe { libc::cfmakeraw(termios) }; +} diff --git a/anneal/v2/vendor/console/src/utils.rs b/anneal/v2/vendor/console/src/utils.rs new file mode 100644 index 0000000000..db182a9939 --- /dev/null +++ b/anneal/v2/vendor/console/src/utils.rs @@ -0,0 +1,1197 @@ +use alloc::borrow::Cow; +use core::{ + fmt::{self, Debug, Formatter}, + sync::atomic::{AtomicBool, Ordering}, +}; +use std::env; + +use std::sync::OnceLock; + +use crate::term::{wants_emoji, Term}; + +#[cfg(feature = "ansi-parsing")] +use crate::ansi::AnsiCodeIterator; + +fn default_colors_enabled(out: &Term) -> bool { + (out.features().colors_supported() + && &env::var("CLICOLOR").unwrap_or_else(|_| "1".into()) != "0") + || &env::var("CLICOLOR_FORCE").unwrap_or_else(|_| "0".into()) != "0" +} + +fn default_true_colors_enabled(out: &Term) -> bool { + out.features().true_colors_supported() +} + +fn stdout_colors() -> &'static AtomicBool { + static ENABLED: OnceLock = OnceLock::new(); + ENABLED.get_or_init(|| AtomicBool::new(default_colors_enabled(&Term::stdout()))) +} +fn stdout_true_colors() -> &'static AtomicBool { + static ENABLED: OnceLock = OnceLock::new(); + ENABLED.get_or_init(|| AtomicBool::new(default_true_colors_enabled(&Term::stdout()))) +} +fn stderr_colors() -> &'static AtomicBool { + static ENABLED: OnceLock = OnceLock::new(); + ENABLED.get_or_init(|| AtomicBool::new(default_colors_enabled(&Term::stderr()))) +} +fn stderr_true_colors() -> &'static AtomicBool { + static ENABLED: OnceLock = OnceLock::new(); + ENABLED.get_or_init(|| AtomicBool::new(default_true_colors_enabled(&Term::stderr()))) +} + +/// Returns `true` if colors should be enabled for stdout. +/// +/// This honors the [clicolors spec](http://bixense.com/clicolors/). +/// +/// * `CLICOLOR != 0`: ANSI colors are supported and should be used when the program isn't piped. +/// * `CLICOLOR == 0`: Don't output ANSI color escape codes. +/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what. +#[inline] +pub fn colors_enabled() -> bool { + stdout_colors().load(Ordering::Relaxed) +} + +/// Returns `true` if true colors should be enabled for stdout. +#[inline] +pub fn true_colors_enabled() -> bool { + stdout_true_colors().load(Ordering::Relaxed) +} + +/// Forces colorization on or off for stdout. +/// +/// This overrides the default for the current process and changes the return value of the +/// `colors_enabled` function. +#[inline] +pub fn set_colors_enabled(val: bool) { + stdout_colors().store(val, Ordering::Relaxed) +} + +/// Forces true colorization on or off for stdout. +/// +/// This overrides the default for the current process and changes the return value of the +/// `true_colors_enabled` function. +#[inline] +pub fn set_true_colors_enabled(val: bool) { + stdout_true_colors().store(val, Ordering::Relaxed) +} + +/// Returns `true` if colors should be enabled for stderr. +/// +/// This honors the [clicolors spec](http://bixense.com/clicolors/). +/// +/// * `CLICOLOR != 0`: ANSI colors are supported and should be used when the program isn't piped. +/// * `CLICOLOR == 0`: Don't output ANSI color escape codes. +/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what. +#[inline] +pub fn colors_enabled_stderr() -> bool { + stderr_colors().load(Ordering::Relaxed) +} + +/// Returns `true` if true colors should be enabled for stderr. +#[inline] +pub fn true_colors_enabled_stderr() -> bool { + stderr_true_colors().load(Ordering::Relaxed) +} + +/// Forces colorization on or off for stderr. +/// +/// This overrides the default for the current process and changes the return value of the +/// `colors_enabled_stderr` function. +#[inline] +pub fn set_colors_enabled_stderr(val: bool) { + stderr_colors().store(val, Ordering::Relaxed) +} + +/// Forces true colorization on or off for stderr. +/// +/// This overrides the default for the current process and changes the return value of the +/// `true_colors_enabled_stderr` function. +#[inline] +pub fn set_true_colors_enabled_stderr(val: bool) { + stderr_true_colors().store(val, Ordering::Relaxed) +} + +/// Measure the width of a string in terminal characters. +pub fn measure_text_width(s: &str) -> usize { + #[cfg(feature = "ansi-parsing")] + { + AnsiCodeIterator::new(s) + .filter_map(|(s, is_ansi)| match is_ansi { + false => Some(str_width(s)), + true => None, + }) + .sum() + } + #[cfg(not(feature = "ansi-parsing"))] + { + str_width(s) + } +} + +/// A terminal color. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Color { + Black, + Red, + Green, + Yellow, + Blue, + Magenta, + Cyan, + White, + Color256(u8), + TrueColor(u8, u8, u8), +} + +impl Color { + #[inline] + fn ansi_num(self) -> usize { + match self { + Color::Black => 0, + Color::Red => 1, + Color::Green => 2, + Color::Yellow => 3, + Color::Blue => 4, + Color::Magenta => 5, + Color::Cyan => 6, + Color::White => 7, + Color::Color256(x) => x as usize, + Color::TrueColor(_, _, _) => panic!("RGB colors must be handled separately"), + } + } + + #[inline] + fn is_color256(self) -> bool { + #[allow(clippy::match_like_matches_macro)] + match self { + Color::Color256(_) => true, + _ => false, + } + } +} + +/// A terminal style attribute. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] +#[repr(u16)] +pub enum Attribute { + // This mapping is important, it exactly matches ansi_num = (x as u16 + 1) + // See `ATTRIBUTES_LOOKUP` as well + Bold = 0, + Dim = 1, + Italic = 2, + Underlined = 3, + Blink = 4, + BlinkFast = 5, + Reverse = 6, + Hidden = 7, + StrikeThrough = 8, +} + +impl Attribute { + const MAP: [Attribute; 9] = [ + Attribute::Bold, + Attribute::Dim, + Attribute::Italic, + Attribute::Underlined, + Attribute::Blink, + Attribute::BlinkFast, + Attribute::Reverse, + Attribute::Hidden, + Attribute::StrikeThrough, + ]; +} + +#[derive(Clone, Copy, PartialEq, Eq)] +struct Attributes(u16); + +impl Attributes { + #[inline] + const fn new() -> Self { + Self(0) + } + + #[inline] + #[must_use] + const fn insert(mut self, attr: Attribute) -> Self { + let bit = attr as u16; + self.0 |= 1 << bit; + self + } + + #[inline] + const fn bits(self) -> BitsIter { + BitsIter(self.0) + } + + #[inline] + fn attrs(self) -> impl Iterator { + self.bits().map(|bit| Attribute::MAP[bit as usize]) + } + + #[inline] + fn is_empty(self) -> bool { + self.0 == 0 + } +} + +impl fmt::Display for Attributes { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for ansi in self.bits().map(|bit| bit + 1) { + write!(f, "\x1b[{ansi}m")?; + } + Ok(()) + } +} + +struct BitsIter(u16); + +impl Iterator for BitsIter { + type Item = u16; + + fn next(&mut self) -> Option { + if self.0 == 0 { + return None; + } + let bit = self.0.trailing_zeros(); + self.0 ^= (1 << bit) as u16; + Some(bit as u16) + } +} + +impl Debug for Attributes { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_set().entries(self.attrs()).finish() + } +} + +/// Defines the alignment for padding operations. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Alignment { + Left, + Center, + Right, +} + +/// A stored style that can be applied. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Style { + fg: Option, + bg: Option, + fg_bright: bool, + bg_bright: bool, + attrs: Attributes, + force: Option, + for_stderr: bool, +} + +impl Default for Style { + fn default() -> Self { + Self::new() + } +} + +impl Style { + /// Returns an empty default style. + pub const fn new() -> Self { + Self { + fg: None, + bg: None, + fg_bright: false, + bg_bright: false, + attrs: Attributes::new(), + force: None, + for_stderr: false, + } + } + + /// Creates a style from a dotted string. + /// + /// Effectively the string is split at each dot and then the + /// terms in between are applied. For instance `red.on_blue` will + /// create a string that is red on blue background. `9.on_12` is + /// the same, but using 256 color numbers. Unknown terms are + /// ignored. + pub fn from_dotted_str(s: &str) -> Self { + let mut rv = Self::new(); + for part in s.split('.') { + rv = match part { + "black" => rv.black(), + "red" => rv.red(), + "green" => rv.green(), + "yellow" => rv.yellow(), + "blue" => rv.blue(), + "magenta" => rv.magenta(), + "cyan" => rv.cyan(), + "white" => rv.white(), + "bright" => rv.bright(), + "on_black" => rv.on_black(), + "on_red" => rv.on_red(), + "on_green" => rv.on_green(), + "on_yellow" => rv.on_yellow(), + "on_blue" => rv.on_blue(), + "on_magenta" => rv.on_magenta(), + "on_cyan" => rv.on_cyan(), + "on_white" => rv.on_white(), + "on_bright" => rv.on_bright(), + "bold" => rv.bold(), + "dim" => rv.dim(), + "underlined" => rv.underlined(), + "blink" => rv.blink(), + "blink_fast" => rv.blink_fast(), + "reverse" => rv.reverse(), + "hidden" => rv.hidden(), + "strikethrough" => rv.strikethrough(), + on_true_color if on_true_color.starts_with("on_#") && on_true_color.len() == 10 => { + if let (Ok(r), Ok(g), Ok(b)) = ( + u8::from_str_radix(&on_true_color[4..6], 16), + u8::from_str_radix(&on_true_color[6..8], 16), + u8::from_str_radix(&on_true_color[8..10], 16), + ) { + rv.on_true_color(r, g, b) + } else { + continue; + } + } + true_color if true_color.starts_with('#') && true_color.len() == 7 => { + if let (Ok(r), Ok(g), Ok(b)) = ( + u8::from_str_radix(&true_color[1..3], 16), + u8::from_str_radix(&true_color[3..5], 16), + u8::from_str_radix(&true_color[5..7], 16), + ) { + rv.true_color(r, g, b) + } else { + continue; + } + } + on_c if on_c.starts_with("on_") => { + if let Ok(n) = on_c[3..].parse::() { + rv.on_color256(n) + } else { + continue; + } + } + c => { + if let Ok(n) = c.parse::() { + rv.color256(n) + } else { + continue; + } + } + }; + } + rv + } + + /// Apply the style to something that can be displayed. + pub fn apply_to(&self, val: D) -> StyledObject { + StyledObject { + style: self.clone(), + val, + } + } + + /// Forces styling on or off. + /// + /// This overrides the automatic detection. + #[inline] + pub const fn force_styling(mut self, value: bool) -> Self { + self.force = Some(value); + self + } + + /// Specifies that style is applying to something being written on stderr. + #[inline] + pub const fn for_stderr(mut self) -> Self { + self.for_stderr = true; + self + } + + /// Specifies that style is applying to something being written on stdout. + /// + /// This is the default behaviour. + #[inline] + pub const fn for_stdout(mut self) -> Self { + self.for_stderr = false; + self + } + + /// Sets a foreground color. + #[inline] + pub const fn fg(mut self, color: Color) -> Self { + self.fg = Some(color); + self + } + + /// Sets a background color. + #[inline] + pub const fn bg(mut self, color: Color) -> Self { + self.bg = Some(color); + self + } + + /// Adds a attr. + #[inline] + pub const fn attr(mut self, attr: Attribute) -> Self { + self.attrs = self.attrs.insert(attr); + self + } + + #[inline] + pub const fn black(self) -> Self { + self.fg(Color::Black) + } + #[inline] + pub const fn red(self) -> Self { + self.fg(Color::Red) + } + #[inline] + pub const fn green(self) -> Self { + self.fg(Color::Green) + } + #[inline] + pub const fn yellow(self) -> Self { + self.fg(Color::Yellow) + } + #[inline] + pub const fn blue(self) -> Self { + self.fg(Color::Blue) + } + #[inline] + pub const fn magenta(self) -> Self { + self.fg(Color::Magenta) + } + #[inline] + pub const fn cyan(self) -> Self { + self.fg(Color::Cyan) + } + #[inline] + pub const fn white(self) -> Self { + self.fg(Color::White) + } + #[inline] + pub const fn color256(self, color: u8) -> Self { + self.fg(Color::Color256(color)) + } + #[inline] + pub const fn true_color(self, r: u8, g: u8, b: u8) -> Self { + self.fg(Color::TrueColor(r, g, b)) + } + + #[inline] + pub const fn bright(mut self) -> Self { + self.fg_bright = true; + self + } + + #[inline] + pub const fn on_black(self) -> Self { + self.bg(Color::Black) + } + #[inline] + pub const fn on_red(self) -> Self { + self.bg(Color::Red) + } + #[inline] + pub const fn on_green(self) -> Self { + self.bg(Color::Green) + } + #[inline] + pub const fn on_yellow(self) -> Self { + self.bg(Color::Yellow) + } + #[inline] + pub const fn on_blue(self) -> Self { + self.bg(Color::Blue) + } + #[inline] + pub const fn on_magenta(self) -> Self { + self.bg(Color::Magenta) + } + #[inline] + pub const fn on_cyan(self) -> Self { + self.bg(Color::Cyan) + } + #[inline] + pub const fn on_white(self) -> Self { + self.bg(Color::White) + } + #[inline] + pub const fn on_color256(self, color: u8) -> Self { + self.bg(Color::Color256(color)) + } + #[inline] + pub const fn on_true_color(self, r: u8, g: u8, b: u8) -> Self { + self.bg(Color::TrueColor(r, g, b)) + } + + #[inline] + pub const fn on_bright(mut self) -> Self { + self.bg_bright = true; + self + } + + #[inline] + pub const fn bold(self) -> Self { + self.attr(Attribute::Bold) + } + #[inline] + pub const fn dim(self) -> Self { + self.attr(Attribute::Dim) + } + #[inline] + pub const fn italic(self) -> Self { + self.attr(Attribute::Italic) + } + #[inline] + pub const fn underlined(self) -> Self { + self.attr(Attribute::Underlined) + } + #[inline] + pub const fn blink(self) -> Self { + self.attr(Attribute::Blink) + } + #[inline] + pub const fn blink_fast(self) -> Self { + self.attr(Attribute::BlinkFast) + } + #[inline] + pub const fn reverse(self) -> Self { + self.attr(Attribute::Reverse) + } + #[inline] + pub const fn hidden(self) -> Self { + self.attr(Attribute::Hidden) + } + #[inline] + pub const fn strikethrough(self) -> Self { + self.attr(Attribute::StrikeThrough) + } +} + +/// Wraps an object for formatting for styling. +/// +/// Example: +/// +/// ```rust,no_run +/// # use console::style; +/// format!("Hello {}", style("World").cyan()); +/// ``` +/// +/// This is a shortcut for making a new style and applying it +/// to a value: +/// +/// ```rust,no_run +/// # use console::Style; +/// format!("Hello {}", Style::new().cyan().apply_to("World")); +/// ``` +pub fn style(val: D) -> StyledObject { + Style::new().apply_to(val) +} + +/// A formatting wrapper that can be styled for a terminal. +#[derive(Clone)] +pub struct StyledObject { + style: Style, + val: D, +} + +impl StyledObject { + /// Forces styling on or off. + /// + /// This overrides the automatic detection. + #[inline] + pub fn force_styling(mut self, value: bool) -> StyledObject { + self.style = self.style.force_styling(value); + self + } + + /// Specifies that style is applying to something being written on stderr + #[inline] + pub fn for_stderr(mut self) -> StyledObject { + self.style = self.style.for_stderr(); + self + } + + /// Specifies that style is applying to something being written on stdout + /// + /// This is the default + #[inline] + pub const fn for_stdout(mut self) -> StyledObject { + self.style = self.style.for_stdout(); + self + } + + /// Sets a foreground color. + #[inline] + pub const fn fg(mut self, color: Color) -> StyledObject { + self.style = self.style.fg(color); + self + } + + /// Sets a background color. + #[inline] + pub const fn bg(mut self, color: Color) -> StyledObject { + self.style = self.style.bg(color); + self + } + + /// Adds a attr. + #[inline] + pub const fn attr(mut self, attr: Attribute) -> StyledObject { + self.style = self.style.attr(attr); + self + } + + #[inline] + pub const fn black(self) -> StyledObject { + self.fg(Color::Black) + } + #[inline] + pub const fn red(self) -> StyledObject { + self.fg(Color::Red) + } + #[inline] + pub const fn green(self) -> StyledObject { + self.fg(Color::Green) + } + #[inline] + pub const fn yellow(self) -> StyledObject { + self.fg(Color::Yellow) + } + #[inline] + pub const fn blue(self) -> StyledObject { + self.fg(Color::Blue) + } + #[inline] + pub const fn magenta(self) -> StyledObject { + self.fg(Color::Magenta) + } + #[inline] + pub const fn cyan(self) -> StyledObject { + self.fg(Color::Cyan) + } + #[inline] + pub const fn white(self) -> StyledObject { + self.fg(Color::White) + } + #[inline] + pub const fn color256(self, color: u8) -> StyledObject { + self.fg(Color::Color256(color)) + } + #[inline] + pub const fn true_color(self, r: u8, g: u8, b: u8) -> StyledObject { + self.fg(Color::TrueColor(r, g, b)) + } + + #[inline] + pub const fn bright(mut self) -> StyledObject { + self.style = self.style.bright(); + self + } + + #[inline] + pub const fn on_black(self) -> StyledObject { + self.bg(Color::Black) + } + #[inline] + pub const fn on_red(self) -> StyledObject { + self.bg(Color::Red) + } + #[inline] + pub const fn on_green(self) -> StyledObject { + self.bg(Color::Green) + } + #[inline] + pub const fn on_yellow(self) -> StyledObject { + self.bg(Color::Yellow) + } + #[inline] + pub const fn on_blue(self) -> StyledObject { + self.bg(Color::Blue) + } + #[inline] + pub const fn on_magenta(self) -> StyledObject { + self.bg(Color::Magenta) + } + #[inline] + pub const fn on_cyan(self) -> StyledObject { + self.bg(Color::Cyan) + } + #[inline] + pub const fn on_white(self) -> StyledObject { + self.bg(Color::White) + } + #[inline] + pub const fn on_color256(self, color: u8) -> StyledObject { + self.bg(Color::Color256(color)) + } + #[inline] + pub const fn on_true_color(self, r: u8, g: u8, b: u8) -> StyledObject { + self.bg(Color::TrueColor(r, g, b)) + } + + #[inline] + pub const fn on_bright(mut self) -> StyledObject { + self.style = self.style.on_bright(); + self + } + + #[inline] + pub const fn bold(self) -> StyledObject { + self.attr(Attribute::Bold) + } + #[inline] + pub const fn dim(self) -> StyledObject { + self.attr(Attribute::Dim) + } + #[inline] + pub const fn italic(self) -> StyledObject { + self.attr(Attribute::Italic) + } + #[inline] + pub const fn underlined(self) -> StyledObject { + self.attr(Attribute::Underlined) + } + #[inline] + pub const fn blink(self) -> StyledObject { + self.attr(Attribute::Blink) + } + #[inline] + pub const fn blink_fast(self) -> StyledObject { + self.attr(Attribute::BlinkFast) + } + #[inline] + pub const fn reverse(self) -> StyledObject { + self.attr(Attribute::Reverse) + } + #[inline] + pub const fn hidden(self) -> StyledObject { + self.attr(Attribute::Hidden) + } + #[inline] + pub const fn strikethrough(self) -> StyledObject { + self.attr(Attribute::StrikeThrough) + } +} + +macro_rules! impl_fmt { + ($name:ident) => { + impl fmt::$name for StyledObject { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut reset = false; + if self + .style + .force + .unwrap_or_else(|| match self.style.for_stderr { + true => colors_enabled_stderr(), + false => colors_enabled(), + }) + { + if let Some(fg) = self.style.fg { + if let Color::TrueColor(r, g, b) = fg { + write!(f, "\x1b[38;2;{};{};{}m", r, g, b)?; + } else if fg.is_color256() { + write!(f, "\x1b[38;5;{}m", fg.ansi_num())?; + } else if self.style.fg_bright { + write!(f, "\x1b[38;5;{}m", fg.ansi_num() + 8)?; + } else { + write!(f, "\x1b[{}m", fg.ansi_num() + 30)?; + } + reset = true; + } + if let Some(bg) = self.style.bg { + if let Color::TrueColor(r, g, b) = bg { + write!(f, "\x1b[48;2;{};{};{}m", r, g, b)?; + } else if bg.is_color256() { + write!(f, "\x1b[48;5;{}m", bg.ansi_num())?; + } else if self.style.bg_bright { + write!(f, "\x1b[48;5;{}m", bg.ansi_num() + 8)?; + } else { + write!(f, "\x1b[{}m", bg.ansi_num() + 40)?; + } + reset = true; + } + if !self.style.attrs.is_empty() { + write!(f, "{}", self.style.attrs)?; + reset = true; + } + } + fmt::$name::fmt(&self.val, f)?; + if reset { + write!(f, "\x1b[0m")?; + } + Ok(()) + } + } + }; +} + +impl_fmt!(Binary); +impl_fmt!(Debug); +impl_fmt!(Display); +impl_fmt!(LowerExp); +impl_fmt!(LowerHex); +impl_fmt!(Octal); +impl_fmt!(Pointer); +impl_fmt!(UpperExp); +impl_fmt!(UpperHex); + +/// "Intelligent" emoji formatter. +/// +/// This struct intelligently wraps an emoji so that it is rendered +/// only on systems that want emojis and renders a fallback on others. +/// +/// Example: +/// +/// ```rust +/// use console::Emoji; +/// println!("[3/4] {}Downloading ...", Emoji("🚚 ", "")); +/// println!("[4/4] {} Done!", Emoji("✨", ":-)")); +/// ``` +#[derive(Copy, Clone)] +pub struct Emoji<'a, 'b>(pub &'a str, pub &'b str); + +impl<'a, 'b> Emoji<'a, 'b> { + pub fn new(emoji: &'a str, fallback: &'b str) -> Emoji<'a, 'b> { + Emoji(emoji, fallback) + } +} + +impl fmt::Display for Emoji<'_, '_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if wants_emoji() { + write!(f, "{}", self.0) + } else { + write!(f, "{}", self.1) + } + } +} + +fn str_width(s: &str) -> usize { + #[cfg(feature = "unicode-width")] + { + use unicode_width::UnicodeWidthStr; + s.width() + } + #[cfg(not(feature = "unicode-width"))] + { + s.chars().count() + } +} + +#[cfg(feature = "ansi-parsing")] +pub(crate) fn char_width(c: char) -> usize { + #[cfg(feature = "unicode-width")] + { + use unicode_width::UnicodeWidthChar; + c.width().unwrap_or(0) + } + #[cfg(not(feature = "unicode-width"))] + { + let _c = c; + 1 + } +} + +#[cfg(not(feature = "ansi-parsing"))] +pub(crate) fn char_width(_c: char) -> usize { + 1 +} + +/// Truncates a string to a certain number of characters. +/// +/// This ensures that escape codes are not screwed up in the process. +/// If the maximum length is hit the string will be truncated but +/// escapes code will still be honored. If truncation takes place +/// the tail string will be appended. +pub fn truncate_str<'a>(s: &'a str, width: usize, tail: &str) -> Cow<'a, str> { + if measure_text_width(s) <= width { + return Cow::Borrowed(s); + } + + #[cfg(feature = "ansi-parsing")] + { + use core::cmp::Ordering; + let mut iter = AnsiCodeIterator::new(s); + let mut length = 0; + let mut rv = None; + + while let Some(item) = iter.next() { + match item { + (s, false) => { + if rv.is_none() { + if str_width(s) + length > width.saturating_sub(str_width(tail)) { + let ts = iter.current_slice(); + + let mut s_byte = 0; + let mut s_width = 0; + let rest_width = + width.saturating_sub(str_width(tail)).saturating_sub(length); + for c in s.chars() { + s_byte += c.len_utf8(); + s_width += char_width(c); + match s_width.cmp(&rest_width) { + Ordering::Equal => break, + Ordering::Greater => { + s_byte -= c.len_utf8(); + break; + } + Ordering::Less => continue, + } + } + + let idx = ts.len() - s.len() + s_byte; + let mut buf = ts[..idx].to_string(); + buf.push_str(tail); + rv = Some(buf); + } + length += str_width(s); + } + } + (s, true) => { + if let Some(ref mut rv) = rv { + rv.push_str(s); + } + } + } + } + + if let Some(buf) = rv { + Cow::Owned(buf) + } else { + Cow::Borrowed(s) + } + } + + #[cfg(not(feature = "ansi-parsing"))] + { + Cow::Owned(format!( + "{}{}", + &s[..width.saturating_sub(tail.len())], + tail + )) + } +} + +/// Pads a string to fill a certain number of characters. +/// +/// This will honor ansi codes correctly and allows you to align a string +/// on the left, right or centered. Additionally truncation can be enabled +/// by setting `truncate` to a string that should be used as a truncation +/// marker. +pub fn pad_str<'a>( + s: &'a str, + width: usize, + align: Alignment, + truncate: Option<&str>, +) -> Cow<'a, str> { + pad_str_with(s, width, align, truncate, ' ') +} +/// Pads a string with specific padding to fill a certain number of characters. +/// +/// This will honor ansi codes correctly and allows you to align a string +/// on the left, right or centered. Additionally truncation can be enabled +/// by setting `truncate` to a string that should be used as a truncation +/// marker. +pub fn pad_str_with<'a>( + s: &'a str, + width: usize, + align: Alignment, + truncate: Option<&str>, + pad: char, +) -> Cow<'a, str> { + let cols = measure_text_width(s); + + if cols >= width { + return match truncate { + None => Cow::Borrowed(s), + Some(tail) => truncate_str(s, width, tail), + }; + } + + let diff = width - cols; + + let (left_pad, right_pad) = match align { + Alignment::Left => (0, diff), + Alignment::Right => (diff, 0), + Alignment::Center => (diff / 2, diff - diff / 2), + }; + + let mut rv = String::new(); + for _ in 0..left_pad { + rv.push(pad); + } + rv.push_str(s); + for _ in 0..right_pad { + rv.push(pad); + } + Cow::Owned(rv) +} + +#[test] +fn test_text_width() { + let s = style("foo") + .red() + .on_black() + .bold() + .force_styling(true) + .to_string(); + + assert_eq!( + measure_text_width(&s), + if cfg!(feature = "ansi-parsing") { + 3 + } else { + 21 + } + ); + + let s = style("🐶 <3").red().force_styling(true).to_string(); + + assert_eq!( + measure_text_width(&s), + match ( + cfg!(feature = "ansi-parsing"), + cfg!(feature = "unicode-width") + ) { + (true, true) => 5, // "🐶 <3" + (true, false) => 4, // "🐶 <3", no unicode-aware width + (false, true) => 14, // full string + (false, false) => 13, // full string, no unicode-aware width + } + ); +} + +#[test] +#[cfg(all(feature = "unicode-width", feature = "ansi-parsing"))] +fn test_truncate_str() { + let s = format!("foo {}", style("bar").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 5, ""), + &format!("foo {}", style("b").red().force_styling(true)) + ); + let s = format!("foo {}", style("bar").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 5, "!"), + &format!("foo {}", style("!").red().force_styling(true)) + ); + let s = format!("foo {} baz", style("bar").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 10, "..."), + &format!("foo {}...", style("bar").red().force_styling(true)) + ); + let s = format!("foo {}", style("バー").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 5, ""), + &format!("foo {}", style("").red().force_styling(true)) + ); + let s = format!("foo {}", style("バー").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 6, ""), + &format!("foo {}", style("バ").red().force_styling(true)) + ); + let s = format!("foo {}", style("バー").red().force_styling(true)); + assert_eq!( + &truncate_str(&s, 2, "!!!"), + &format!("!!!{}", style("").red().force_styling(true)) + ); +} + +#[test] +fn test_truncate_str_no_ansi() { + assert_eq!(&truncate_str("foo bar", 7, "!"), "foo bar"); + assert_eq!(&truncate_str("foo bar", 5, ""), "foo b"); + assert_eq!(&truncate_str("foo bar", 5, "!"), "foo !"); + assert_eq!(&truncate_str("foo bar baz", 10, "..."), "foo bar..."); + assert_eq!(&truncate_str("foo bar", 0, ""), ""); + assert_eq!(&truncate_str("foo bar", 0, "!"), "!"); + assert_eq!(&truncate_str("foo bar", 2, "!!!"), "!!!"); + assert_eq!(&truncate_str("ab", 2, "!!!"), "ab"); +} + +#[test] +fn test_pad_str() { + assert_eq!(pad_str("foo", 7, Alignment::Center, None), " foo "); + assert_eq!(pad_str("foo", 7, Alignment::Left, None), "foo "); + assert_eq!(pad_str("foo", 7, Alignment::Right, None), " foo"); + assert_eq!(pad_str("foo", 3, Alignment::Left, None), "foo"); + assert_eq!(pad_str("foobar", 3, Alignment::Left, None), "foobar"); + assert_eq!(pad_str("foobar", 3, Alignment::Left, Some("")), "foo"); + assert_eq!( + pad_str("foobarbaz", 6, Alignment::Left, Some("...")), + "foo..." + ); +} + +#[test] +fn test_pad_str_with() { + assert_eq!( + pad_str_with("foo", 7, Alignment::Center, None, '#'), + "##foo##" + ); + assert_eq!( + pad_str_with("foo", 7, Alignment::Left, None, '#'), + "foo####" + ); + assert_eq!( + pad_str_with("foo", 7, Alignment::Right, None, '#'), + "####foo" + ); + assert_eq!(pad_str_with("foo", 3, Alignment::Left, None, '#'), "foo"); + assert_eq!( + pad_str_with("foobar", 3, Alignment::Left, None, '#'), + "foobar" + ); + assert_eq!( + pad_str_with("foobar", 3, Alignment::Left, Some(""), '#'), + "foo" + ); + assert_eq!( + pad_str_with("foobarbaz", 6, Alignment::Left, Some("..."), '#'), + "foo..." + ); +} + +#[test] +fn test_attributes_single() { + for attr in Attribute::MAP { + let attrs = Attributes::new().insert(attr); + assert_eq!(attrs.bits().collect::>(), [attr as u16]); + assert_eq!(attrs.attrs().collect::>(), [attr]); + assert_eq!(format!("{attrs:?}"), format!("{{{:?}}}", attr)); + } +} + +#[test] +fn test_attributes_many() { + let tests: [&[Attribute]; 3] = [ + &[ + Attribute::Bold, + Attribute::Underlined, + Attribute::BlinkFast, + Attribute::Hidden, + ], + &[ + Attribute::Dim, + Attribute::Italic, + Attribute::Blink, + Attribute::Reverse, + Attribute::StrikeThrough, + ], + &Attribute::MAP, + ]; + for test_attrs in tests { + let mut attrs = Attributes::new(); + for attr in test_attrs { + attrs = attrs.insert(*attr); + } + assert_eq!( + attrs.bits().collect::>(), + test_attrs + .iter() + .map(|attr| *attr as u16) + .collect::>() + ); + assert_eq!(&attrs.attrs().collect::>(), test_attrs); + } +} diff --git a/anneal/v2/vendor/console/src/wasm_term.rs b/anneal/v2/vendor/console/src/wasm_term.rs new file mode 100644 index 0000000000..bd1b89dc56 --- /dev/null +++ b/anneal/v2/vendor/console/src/wasm_term.rs @@ -0,0 +1,60 @@ +use std::fmt::Display; +use std::io; + +use crate::kb::Key; +use crate::term::Term; + +pub(crate) use crate::common_term::*; + +pub(crate) const DEFAULT_WIDTH: u16 = 80; + +#[inline] +pub(crate) fn is_a_terminal(_out: &Term) -> bool { + #[cfg(all(target_os = "wasi", target_env = "p1"))] + { + use std::os::fd::AsRawFd; + unsafe { libc::isatty(_out.as_raw_fd()) != 0 } + } + #[cfg(not(all(target_os = "wasi", target_env = "p1")))] + { + false + } +} + +#[inline] +pub(crate) fn is_a_color_terminal(_out: &Term) -> bool { + // We currently never report color terminals. For discussion see + // the issue in the WASI repo: https://github.com/WebAssembly/WASI/issues/162 + false +} + +#[inline] +pub(crate) fn is_a_true_color_terminal(_out: &Term) -> bool { + false +} + +#[inline] +pub(crate) fn terminal_size(_out: &Term) -> Option<(u16, u16)> { + None +} + +pub(crate) fn read_secure() -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "unsupported operation", + )) +} + +pub(crate) fn read_single_key(_ctrlc_key: bool) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "unsupported operation", + )) +} + +#[inline] +pub(crate) fn wants_emoji() -> bool { + false +} + +pub(crate) fn set_title(_title: T) {} diff --git a/anneal/v2/vendor/console/src/windows_term/colors.rs b/anneal/v2/vendor/console/src/windows_term/colors.rs new file mode 100644 index 0000000000..46e4e02d94 --- /dev/null +++ b/anneal/v2/vendor/console/src/windows_term/colors.rs @@ -0,0 +1,450 @@ +use crate::ansi::AnsiCodeIterator; +use core::mem; +use core::str::{from_utf8, Bytes}; +use std::io; +use std::os::windows::io::AsRawHandle; + +use windows_sys::Win32::Foundation::HANDLE; +use windows_sys::Win32::System::Console::{ + GetConsoleScreenBufferInfo, SetConsoleTextAttribute, CONSOLE_SCREEN_BUFFER_INFO, + FOREGROUND_BLUE as FG_BLUE, FOREGROUND_GREEN as FG_GREEN, FOREGROUND_INTENSITY as FG_INTENSITY, + FOREGROUND_RED as FG_RED, +}; + +use crate::Term; + +#[allow(clippy::upper_case_acronyms)] +type WORD = u16; + +const FG_CYAN: WORD = FG_BLUE | FG_GREEN; +const FG_MAGENTA: WORD = FG_BLUE | FG_RED; +const FG_YELLOW: WORD = FG_GREEN | FG_RED; +const FG_WHITE: WORD = FG_BLUE | FG_GREEN | FG_RED; + +/// Query the given handle for information about the console's screen buffer. +/// +/// The given handle should represent a console. Otherwise, an error is +/// returned. +/// +/// This corresponds to calling [`GetConsoleScreenBufferInfo`]. +/// +/// [`GetConsoleScreenBufferInfo`]: https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo +pub(crate) fn screen_buffer_info(h: HANDLE) -> io::Result { + unsafe { + let mut info: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); + let rc = GetConsoleScreenBufferInfo(h, &mut info); + if rc == 0 { + return Err(io::Error::last_os_error()); + } + Ok(ScreenBufferInfo(info)) + } +} + +/// Set the text attributes of the console represented by the given handle. +/// +/// This corresponds to calling [`SetConsoleTextAttribute`]. +/// +/// [`SetConsoleTextAttribute`]: https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute +pub(crate) fn set_text_attributes(h: HANDLE, attributes: u16) -> io::Result<()> { + if unsafe { SetConsoleTextAttribute(h, attributes) } == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +/// Represents console screen buffer information such as size, cursor position +/// and styling attributes. +/// +/// This wraps a [`CONSOLE_SCREEN_BUFFER_INFO`]. +/// +/// [`CONSOLE_SCREEN_BUFFER_INFO`]: https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str +#[derive(Clone)] +pub(crate) struct ScreenBufferInfo(CONSOLE_SCREEN_BUFFER_INFO); + +impl ScreenBufferInfo { + /// Returns the character attributes associated with this console. + /// + /// This corresponds to `wAttributes`. + /// + /// See [`char info`] for more details. + /// + /// [`char info`]: https://docs.microsoft.com/en-us/windows/console/char-info-str + pub(crate) fn attributes(&self) -> u16 { + self.0.wAttributes + } +} + +/// A Windows console. +/// +/// This represents a very limited set of functionality available to a Windows +/// console. In particular, it can only change text attributes such as color +/// and intensity. This may grow over time. If you need more routines, please +/// file an issue and/or PR. +/// +/// There is no way to "write" to this console. Simply write to +/// stdout or stderr instead, while interleaving instructions to the console +/// to change text attributes. +/// +/// A common pitfall when using a console is to forget to flush writes to +/// stdout before setting new text attributes. +#[derive(Debug)] +pub(crate) struct Console { + kind: HandleKind, + start_attr: TextAttributes, + cur_attr: TextAttributes, +} + +#[derive(Clone, Copy, Debug)] +enum HandleKind { + Stdout, + Stderr, +} + +impl HandleKind { + fn handle(&self) -> HANDLE { + match *self { + HandleKind::Stdout => io::stdout().as_raw_handle() as HANDLE, + HandleKind::Stderr => io::stderr().as_raw_handle() as HANDLE, + } + } +} + +impl Console { + /// Get a console for a standard I/O stream. + fn create_for_stream(kind: HandleKind) -> io::Result { + let h = kind.handle(); + let info = screen_buffer_info(h)?; + let attr = TextAttributes::from_word(info.attributes()); + Ok(Console { + kind, + start_attr: attr, + cur_attr: attr, + }) + } + + /// Create a new Console to stdout. + /// + /// If there was a problem creating the console, then an error is returned. + pub(crate) fn stdout() -> io::Result { + Self::create_for_stream(HandleKind::Stdout) + } + + /// Create a new Console to stderr. + /// + /// If there was a problem creating the console, then an error is returned. + pub(crate) fn stderr() -> io::Result { + Self::create_for_stream(HandleKind::Stderr) + } + + /// Applies the current text attributes. + fn set(&mut self) -> io::Result<()> { + set_text_attributes(self.kind.handle(), self.cur_attr.to_word()) + } + + /// Apply the given intensity and color attributes to the console + /// foreground. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub(crate) fn fg(&mut self, intense: Intense, color: Color) -> io::Result<()> { + self.cur_attr.fg_color = color; + self.cur_attr.fg_intense = intense; + self.set() + } + + /// Apply the given intensity and color attributes to the console + /// background. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub(crate) fn bg(&mut self, intense: Intense, color: Color) -> io::Result<()> { + self.cur_attr.bg_color = color; + self.cur_attr.bg_intense = intense; + self.set() + } + + /// Reset the console text attributes to their original settings. + /// + /// The original settings correspond to the text attributes on the console + /// when this `Console` value was created. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub(crate) fn reset(&mut self) -> io::Result<()> { + self.cur_attr = self.start_attr; + self.set() + } +} + +/// A representation of text attributes for the Windows console. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct TextAttributes { + fg_color: Color, + fg_intense: Intense, + bg_color: Color, + bg_intense: Intense, +} + +impl TextAttributes { + fn to_word(self) -> WORD { + let mut w = 0; + w |= self.fg_color.to_fg(); + w |= self.fg_intense.to_fg(); + w |= self.bg_color.to_bg(); + w |= self.bg_intense.to_bg(); + w + } + + fn from_word(word: WORD) -> TextAttributes { + TextAttributes { + fg_color: Color::from_fg(word), + fg_intense: Intense::from_fg(word), + bg_color: Color::from_bg(word), + bg_intense: Intense::from_bg(word), + } + } +} + +/// Whether to use intense colors or not. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(crate) enum Intense { + Yes, + No, +} + +impl Intense { + fn to_bg(self) -> WORD { + self.to_fg() << 4 + } + + fn from_bg(word: WORD) -> Intense { + Intense::from_fg(word >> 4) + } + + fn to_fg(self) -> WORD { + match self { + Intense::No => 0, + Intense::Yes => FG_INTENSITY, + } + } + + fn from_fg(word: WORD) -> Intense { + if word & FG_INTENSITY > 0 { + Intense::Yes + } else { + Intense::No + } + } +} + +/// The set of available colors for use with a Windows console. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(crate) enum Color { + Black, + Blue, + Green, + Red, + Cyan, + Magenta, + Yellow, + White, +} + +impl Color { + fn to_bg(self) -> WORD { + self.to_fg() << 4 + } + + fn from_bg(word: WORD) -> Color { + Color::from_fg(word >> 4) + } + + fn to_fg(self) -> WORD { + match self { + Color::Black => 0, + Color::Blue => FG_BLUE, + Color::Green => FG_GREEN, + Color::Red => FG_RED, + Color::Cyan => FG_CYAN, + Color::Magenta => FG_MAGENTA, + Color::Yellow => FG_YELLOW, + Color::White => FG_WHITE, + } + } + + fn from_fg(word: WORD) -> Color { + match word & 0b111 { + FG_BLUE => Color::Blue, + FG_GREEN => Color::Green, + FG_RED => Color::Red, + FG_CYAN => Color::Cyan, + FG_MAGENTA => Color::Magenta, + FG_YELLOW => Color::Yellow, + FG_WHITE => Color::White, + _ => Color::Black, + } + } +} + +pub(crate) fn console_colors(out: &Term, mut con: Console, bytes: &[u8]) -> io::Result<()> { + let s = from_utf8(bytes).expect("data to be printed is not an ansi string"); + let mut iter = AnsiCodeIterator::new(s); + + while !iter.rest_slice().is_empty() { + if let Some((part, is_esc)) = iter.next() { + if !is_esc { + out.write_through_common(part.as_bytes())?; + } else if part == "\x1b[0m" { + con.reset()?; + } else if let Some((intense, color, fg_bg)) = driver(parse_color, part) { + match fg_bg { + FgBg::Foreground => con.fg(intense, color), + FgBg::Background => con.bg(intense, color), + }?; + } else if driver(parse_attr, part).is_none() { + out.write_through_common(part.as_bytes())?; + } + } + } + + Ok(()) +} + +#[derive(Debug, PartialEq, Eq)] +enum FgBg { + Foreground, + Background, +} + +impl FgBg { + fn new(byte: u8) -> Option { + match byte { + b'3' => Some(Self::Foreground), + b'4' => Some(Self::Background), + _ => None, + } + } +} + +fn driver(parse: fn(Bytes<'_>) -> Option, part: &str) -> Option { + let mut bytes = part.bytes(); + + loop { + while bytes.next()? != b'\x1b' {} + + if let ret @ Some(_) = (parse)(bytes.clone()) { + return ret; + } + } +} + +// `driver(parse_color, s)` parses the equivalent of the regex +// \x1b\[(3|4)8;5;(8|9|1[0-5])m +// for intense or +// \x1b\[(3|4)([0-7])m +// for normal +fn parse_color(mut bytes: Bytes<'_>) -> Option<(Intense, Color, FgBg)> { + parse_prefix(&mut bytes)?; + + let fg_bg = FgBg::new(bytes.next()?)?; + let (intense, color) = match bytes.next()? { + b @ b'0'..=b'7' => (Intense::No, normal_color_ansi_from_byte(b)?), + b'8' => { + if &[bytes.next()?, bytes.next()?, bytes.next()?] != b";5;" { + return None; + } + (Intense::Yes, parse_intense_color_ansi(&mut bytes)?) + } + _ => return None, + }; + + parse_suffix(&mut bytes)?; + Some((intense, color, fg_bg)) +} + +// `driver(parse_attr, s)` parses the equivalent of the regex +// \x1b\[([1-8])m +fn parse_attr(mut bytes: Bytes<'_>) -> Option { + parse_prefix(&mut bytes)?; + let attr = match bytes.next()? { + attr @ b'1'..=b'8' => attr, + _ => return None, + }; + parse_suffix(&mut bytes)?; + Some(attr) +} + +fn parse_prefix(bytes: &mut Bytes<'_>) -> Option<()> { + if bytes.next()? == b'[' { + Some(()) + } else { + None + } +} + +fn parse_intense_color_ansi(bytes: &mut Bytes<'_>) -> Option { + let color = match bytes.next()? { + b'8' => Color::Black, + b'9' => Color::Red, + b'1' => match bytes.next()? { + b'0' => Color::Green, + b'1' => Color::Yellow, + b'2' => Color::Blue, + b'3' => Color::Magenta, + b'4' => Color::Cyan, + b'5' => Color::White, + _ => return None, + }, + _ => return None, + }; + Some(color) +} + +fn normal_color_ansi_from_byte(b: u8) -> Option { + let color = match b { + b'0' => Color::Black, + b'1' => Color::Red, + b'2' => Color::Green, + b'3' => Color::Yellow, + b'4' => Color::Blue, + b'5' => Color::Magenta, + b'6' => Color::Cyan, + b'7' => Color::White, + _ => return None, + }; + Some(color) +} + +fn parse_suffix(bytes: &mut Bytes<'_>) -> Option<()> { + if bytes.next()? == b'm' { + Some(()) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn color_parsing() { + let intense_color = "leading bytes \x1b[38;5;10m trailing bytes"; + let parsed = driver(parse_color, intense_color).unwrap(); + assert_eq!(parsed, (Intense::Yes, Color::Green, FgBg::Foreground)); + + let normal_color = "leading bytes \x1b[40m trailing bytes"; + let parsed = driver(parse_color, normal_color).unwrap(); + assert_eq!(parsed, (Intense::No, Color::Black, FgBg::Background)); + } + + #[test] + fn attr_parsing() { + let attr = "leading bytes \x1b[1m trailing bytes"; + let parsed = driver(parse_attr, attr).unwrap(); + assert_eq!(parsed, b'1'); + } +} diff --git a/anneal/v2/vendor/console/src/windows_term/mod.rs b/anneal/v2/vendor/console/src/windows_term/mod.rs new file mode 100644 index 0000000000..eddbe0dad0 --- /dev/null +++ b/anneal/v2/vendor/console/src/windows_term/mod.rs @@ -0,0 +1,639 @@ +use core::fmt::Display; +use core::iter::once; +use core::mem::{self, MaybeUninit}; +use core::{char, cmp}; +use std::env; +use std::ffi::OsStr; +use std::io; +use std::os::raw::c_void; +use std::os::windows::ffi::OsStrExt; +use std::os::windows::io::AsRawHandle; + +use encode_unicode::error::Utf16TupleError; +use encode_unicode::CharExt; +use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE, MAX_PATH}; +use windows_sys::Win32::Storage::FileSystem::{FileNameInfo, GetFileInformationByHandleEx}; +use windows_sys::Win32::System::Console::CONSOLE_MODE; +use windows_sys::Win32::System::Console::{ + FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetConsoleCursorInfo, GetConsoleMode, + GetConsoleScreenBufferInfo, GetNumberOfConsoleInputEvents, GetStdHandle, ReadConsoleInputW, + SetConsoleCursorInfo, SetConsoleCursorPosition, SetConsoleMode, SetConsoleTitleW, + CONSOLE_CURSOR_INFO, CONSOLE_SCREEN_BUFFER_INFO, COORD, ENABLE_PROCESSED_INPUT, + ENABLE_VIRTUAL_TERMINAL_PROCESSING, INPUT_RECORD, INPUT_RECORD_0, KEY_EVENT, KEY_EVENT_RECORD, + STD_ERROR_HANDLE, STD_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, +}; +use windows_sys::Win32::UI::Input::KeyboardAndMouse::VIRTUAL_KEY; + +use crate::common_term; +use crate::kb::Key; +use crate::term::{Term, TermTarget}; + +#[cfg(feature = "windows-console-colors")] +mod colors; + +#[cfg(feature = "windows-console-colors")] +pub(crate) use self::colors::*; + +pub(crate) const DEFAULT_WIDTH: u16 = 79; + +pub(crate) fn as_handle(term: &Term) -> HANDLE { + // convert between windows_sys::Win32::Foundation::HANDLE and std::os::windows::raw::HANDLE + term.as_raw_handle() as HANDLE +} + +pub(crate) fn is_a_terminal(out: &Term) -> bool { + let (fd, others) = match out.target() { + TermTarget::Stdout => (STD_OUTPUT_HANDLE, [STD_INPUT_HANDLE, STD_ERROR_HANDLE]), + TermTarget::Stderr => (STD_ERROR_HANDLE, [STD_INPUT_HANDLE, STD_OUTPUT_HANDLE]), + }; + + if unsafe { console_on_any(&[fd]) } { + // False positives aren't possible. If we got a console then + // we definitely have a tty on stdin. + return true; + } + + // At this point, we *could* have a false negative. We can determine that + // this is true negative if we can detect the presence of a console on + // any of the other streams. If another stream has a console, then we know + // we're in a Windows console and can therefore trust the negative. + if unsafe { console_on_any(&others) } { + return false; + } + + msys_tty_on(out) +} + +pub(crate) fn is_a_color_terminal(out: &Term) -> bool { + if !is_a_terminal(out) { + return false; + } + if env::var("NO_COLOR").is_ok() { + return false; + } + if msys_tty_on(out) { + return match env::var("TERM") { + Ok(term) => term != "dumb", + Err(_) => true, + }; + } + enable_ansi_on(out) +} + +pub(crate) fn is_a_true_color_terminal(out: &Term) -> bool { + if !is_a_color_terminal(out) { + return false; + } + // Powershell does not respect the COLORTERM var despite supporting true colors + // but other shells may respect it + if msys_tty_on(out) { + return match env::var("COLORTERM") { + Ok(term) => term == "truecolor" || term == "24bit", + Err(_) => true, + }; + } + false +} + +/// Enables or disables the `mode` flag on the given `HANDLE` and yields the previous mode. +fn set_console_mode(handle: HANDLE, mode: CONSOLE_MODE, enable: bool) -> Option { + unsafe { + let mut dw_mode = 0; + if GetConsoleMode(handle, &mut dw_mode) == 0 { + return None; + } + + let new_dw_mode = match enable { + true => dw_mode | mode, + false => dw_mode & !mode, + }; + + if SetConsoleMode(handle, new_dw_mode) == 0 { + return None; + } + + Some(dw_mode) + } +} + +struct ConsoleModeGuard { + handle: HANDLE, + restore_mode: CONSOLE_MODE, +} + +impl ConsoleModeGuard { + fn set(handle: HANDLE, mode: CONSOLE_MODE, enable: bool) -> Option { + Some(ConsoleModeGuard { + handle, + restore_mode: set_console_mode(handle, mode, enable)?, + }) + } +} + +impl Drop for ConsoleModeGuard { + fn drop(&mut self) { + unsafe { + SetConsoleMode(self.handle, self.restore_mode); + } + } +} + +fn enable_ansi_on(out: &Term) -> bool { + set_console_mode( + out.as_raw_handle(), + ENABLE_VIRTUAL_TERMINAL_PROCESSING, + true, + ) + .is_some() +} + +unsafe fn console_on_any(fds: &[STD_HANDLE]) -> bool { + for &fd in fds { + let mut out = 0; + let handle = GetStdHandle(fd); + if GetConsoleMode(handle, &mut out) != 0 { + return true; + } + } + false +} + +pub(crate) fn terminal_size(out: &Term) -> Option<(u16, u16)> { + use windows_sys::Win32::System::Console::SMALL_RECT; + + // convert between windows_sys::Win32::Foundation::HANDLE and std::os::windows::raw::HANDLE + let handle = out.as_raw_handle(); + let hand = handle as windows_sys::Win32::Foundation::HANDLE; + + if hand == INVALID_HANDLE_VALUE { + return None; + } + + let zc = COORD { X: 0, Y: 0 }; + let mut csbi = CONSOLE_SCREEN_BUFFER_INFO { + dwSize: zc, + dwCursorPosition: zc, + wAttributes: 0, + srWindow: SMALL_RECT { + Left: 0, + Top: 0, + Right: 0, + Bottom: 0, + }, + dwMaximumWindowSize: zc, + }; + if unsafe { GetConsoleScreenBufferInfo(hand, &mut csbi) } == 0 { + return None; + } + + let rows = (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) as u16; + let columns = (csbi.srWindow.Right - csbi.srWindow.Left + 1) as u16; + + Some((rows, columns)) +} + +pub(crate) fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::move_cursor_to(out, x, y); + } + if let Some((hand, _)) = get_console_screen_buffer_info(as_handle(out)) { + unsafe { + SetConsoleCursorPosition( + hand, + COORD { + X: x as i16, + Y: y as i16, + }, + ); + } + } + Ok(()) +} + +pub(crate) fn move_cursor_up(out: &Term, n: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::move_cursor_up(out, n); + } + + if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + move_cursor_to(out, 0, csbi.dwCursorPosition.Y as usize - n)?; + } + Ok(()) +} + +pub(crate) fn move_cursor_down(out: &Term, n: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::move_cursor_down(out, n); + } + + if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + move_cursor_to(out, 0, csbi.dwCursorPosition.Y as usize + n)?; + } + Ok(()) +} + +pub(crate) fn move_cursor_left(out: &Term, n: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::move_cursor_left(out, n); + } + + if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + move_cursor_to( + out, + csbi.dwCursorPosition.X as usize - n, + csbi.dwCursorPosition.Y as usize, + )?; + } + Ok(()) +} + +pub(crate) fn move_cursor_right(out: &Term, n: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::move_cursor_right(out, n); + } + + if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + move_cursor_to( + out, + csbi.dwCursorPosition.X as usize + n, + csbi.dwCursorPosition.Y as usize, + )?; + } + Ok(()) +} + +pub(crate) fn clear_line(out: &Term) -> io::Result<()> { + if out.is_msys_tty { + return common_term::clear_line(out); + } + if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + unsafe { + let width = csbi.srWindow.Right - csbi.srWindow.Left; + let pos = COORD { + X: 0, + Y: csbi.dwCursorPosition.Y, + }; + let mut written = 0; + FillConsoleOutputCharacterA(hand, b' ' as i8, width as u32, pos, &mut written); + FillConsoleOutputAttribute(hand, csbi.wAttributes, width as u32, pos, &mut written); + SetConsoleCursorPosition(hand, pos); + } + } + Ok(()) +} + +pub(crate) fn clear_chars(out: &Term, n: usize) -> io::Result<()> { + if out.is_msys_tty { + return common_term::clear_chars(out, n); + } + if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + unsafe { + let width = cmp::min(csbi.dwCursorPosition.X, n as i16); + let pos = COORD { + X: csbi.dwCursorPosition.X - width, + Y: csbi.dwCursorPosition.Y, + }; + let mut written = 0; + FillConsoleOutputCharacterA(hand, b' ' as i8, width as u32, pos, &mut written); + FillConsoleOutputAttribute(hand, csbi.wAttributes, width as u32, pos, &mut written); + SetConsoleCursorPosition(hand, pos); + } + } + Ok(()) +} + +pub(crate) fn clear_screen(out: &Term) -> io::Result<()> { + if out.is_msys_tty { + return common_term::clear_screen(out); + } + if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + unsafe { + let cells = csbi.dwSize.X as u32 * csbi.dwSize.Y as u32; // as u32, or else this causes stack overflows. + let pos = COORD { X: 0, Y: 0 }; + let mut written = 0; + FillConsoleOutputCharacterA(hand, b' ' as i8, cells, pos, &mut written); // cells as u32 no longer needed. + FillConsoleOutputAttribute(hand, csbi.wAttributes, cells, pos, &mut written); + SetConsoleCursorPosition(hand, pos); + } + } + Ok(()) +} + +pub(crate) fn clear_to_end_of_screen(out: &Term) -> io::Result<()> { + if out.is_msys_tty { + return common_term::clear_to_end_of_screen(out); + } + if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { + unsafe { + let bottom = csbi.srWindow.Right as u32 * csbi.srWindow.Bottom as u32; + let cells = bottom - (csbi.dwCursorPosition.X as u32 * csbi.dwCursorPosition.Y as u32); // as u32, or else this causes stack overflows. + let pos = COORD { + X: 0, + Y: csbi.dwCursorPosition.Y, + }; + let mut written = 0; + FillConsoleOutputCharacterA(hand, b' ' as i8, cells, pos, &mut written); // cells as u32 no longer needed. + FillConsoleOutputAttribute(hand, csbi.wAttributes, cells, pos, &mut written); + SetConsoleCursorPosition(hand, pos); + } + } + Ok(()) +} + +pub(crate) fn show_cursor(out: &Term) -> io::Result<()> { + if out.is_msys_tty { + return common_term::show_cursor(out); + } + if let Some((hand, mut cci)) = get_console_cursor_info(as_handle(out)) { + unsafe { + cci.bVisible = 1; + SetConsoleCursorInfo(hand, &cci); + } + } + Ok(()) +} + +pub(crate) fn hide_cursor(out: &Term) -> io::Result<()> { + if out.is_msys_tty { + return common_term::hide_cursor(out); + } + if let Some((hand, mut cci)) = get_console_cursor_info(as_handle(out)) { + unsafe { + cci.bVisible = 0; + SetConsoleCursorInfo(hand, &cci); + } + } + Ok(()) +} + +fn get_console_screen_buffer_info(hand: HANDLE) -> Option<(HANDLE, CONSOLE_SCREEN_BUFFER_INFO)> { + let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() }; + match unsafe { GetConsoleScreenBufferInfo(hand, &mut csbi) } { + 0 => None, + _ => Some((hand, csbi)), + } +} + +fn get_console_cursor_info(hand: HANDLE) -> Option<(HANDLE, CONSOLE_CURSOR_INFO)> { + let mut cci: CONSOLE_CURSOR_INFO = unsafe { mem::zeroed() }; + match unsafe { GetConsoleCursorInfo(hand, &mut cci) } { + 0 => None, + _ => Some((hand, cci)), + } +} + +pub(crate) fn key_from_key_code(code: VIRTUAL_KEY) -> Key { + use windows_sys::Win32::UI::Input::KeyboardAndMouse; + + match code { + KeyboardAndMouse::VK_LEFT => Key::ArrowLeft, + KeyboardAndMouse::VK_RIGHT => Key::ArrowRight, + KeyboardAndMouse::VK_UP => Key::ArrowUp, + KeyboardAndMouse::VK_DOWN => Key::ArrowDown, + KeyboardAndMouse::VK_RETURN => Key::Enter, + KeyboardAndMouse::VK_ESCAPE => Key::Escape, + KeyboardAndMouse::VK_BACK => Key::Backspace, + KeyboardAndMouse::VK_TAB => Key::Tab, + KeyboardAndMouse::VK_HOME => Key::Home, + KeyboardAndMouse::VK_END => Key::End, + KeyboardAndMouse::VK_DELETE => Key::Del, + KeyboardAndMouse::VK_SHIFT => Key::Shift, + KeyboardAndMouse::VK_MENU => Key::Alt, + _ => Key::Unknown, + } +} + +pub(crate) fn read_secure() -> io::Result { + let mut rv = String::new(); + loop { + match read_single_key(false)? { + Key::Enter => { + break; + } + Key::Char('\x08') => { + if !rv.is_empty() { + let new_len = rv.len() - 1; + rv.truncate(new_len); + } + } + Key::Char(c) => { + rv.push(c); + } + _ => {} + } + } + Ok(rv) +} + +pub(crate) fn read_single_key(ctrlc_key: bool) -> io::Result { + let key_event = { + let _guard = ctrlc_key.then(|| { + ConsoleModeGuard::set( + unsafe { GetStdHandle(STD_INPUT_HANDLE) }, + ENABLE_PROCESSED_INPUT, + false, + ) + }); + read_key_event()? + }; + + let unicode_char = unsafe { key_event.uChar.UnicodeChar }; + if unicode_char == 0 { + Ok(key_from_key_code(key_event.wVirtualKeyCode)) + } else { + // This is a unicode character, in utf-16. Try to decode it by itself. + match char::from_utf16_tuple((unicode_char, None)) { + Ok(c) => { + // Maintain backward compatibility. The previous implementation (_getwch()) would return + // a special keycode for `Enter`, while ReadConsoleInputW() prefers to use '\r'. + if c == '\r' { + Ok(Key::Enter) + } else if c == '\t' { + Ok(Key::Tab) + } else if c == '\x08' { + Ok(Key::Backspace) + } else if c == '\x1B' { + Ok(Key::Escape) + } else if c == '\x03' && ctrlc_key { + Ok(Key::CtrlC) + } else { + Ok(Key::Char(c)) + } + } + // This is part of a surrogate pair. Try to read the second half. + Err(Utf16TupleError::MissingSecond) => { + // Confirm that there is a next character to read. + if get_key_event_count()? == 0 { + let message = format!( + "Read invalid utf16 {}: {}", + unicode_char, + Utf16TupleError::MissingSecond + ); + return Err(io::Error::new(io::ErrorKind::InvalidData, message)); + } + + // Read the next character. + let next_event = read_key_event()?; + let next_surrogate = unsafe { next_event.uChar.UnicodeChar }; + + // Attempt to decode it. + match char::from_utf16_tuple((unicode_char, Some(next_surrogate))) { + Ok(c) => Ok(Key::Char(c)), + + // Return an InvalidData error. This is the recommended value for UTF-related I/O errors. + // (This error is given when reading a non-UTF8 file into a String, for example.) + Err(e) => { + let message = format!( + "Read invalid surrogate pair ({unicode_char}, {next_surrogate}): {e}", + ); + Err(io::Error::new(io::ErrorKind::InvalidData, message)) + } + } + } + + // Return an InvalidData error. This is the recommended value for UTF-related I/O errors. + // (This error is given when reading a non-UTF8 file into a String, for example.) + Err(e) => { + let message = format!("Read invalid utf16 {unicode_char}: {e}"); + Err(io::Error::new(io::ErrorKind::InvalidData, message)) + } + } + } +} + +fn get_stdin_handle() -> io::Result { + let handle = unsafe { GetStdHandle(STD_INPUT_HANDLE) }; + if handle == INVALID_HANDLE_VALUE { + Err(io::Error::last_os_error()) + } else { + Ok(handle) + } +} + +/// Get the number of pending events in the ReadConsoleInput queue. Note that while +/// these aren't necessarily key events, the only way that multiple events can be +/// put into the queue simultaneously is if a unicode character spanning multiple u16's +/// is read. +/// +/// Therefore, this is accurate as long as at least one KEY_EVENT has already been read. +fn get_key_event_count() -> io::Result { + let handle = get_stdin_handle()?; + let mut event_count: u32 = unsafe { mem::zeroed() }; + + let success = unsafe { GetNumberOfConsoleInputEvents(handle, &mut event_count) }; + if success == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(event_count) + } +} + +fn read_key_event() -> io::Result { + let handle = get_stdin_handle()?; + let mut buffer: INPUT_RECORD = unsafe { mem::zeroed() }; + + let mut events_read: u32 = unsafe { mem::zeroed() }; + + let mut key_event: KEY_EVENT_RECORD; + loop { + let success = unsafe { ReadConsoleInputW(handle, &mut buffer, 1, &mut events_read) }; + if success == 0 { + return Err(io::Error::last_os_error()); + } + if events_read == 0 { + return Err(io::Error::new( + io::ErrorKind::Other, + "ReadConsoleInput returned no events, instead of waiting for an event", + )); + } + + if events_read == 1 && buffer.EventType != KEY_EVENT as u16 { + // This isn't a key event; ignore it. + continue; + } + + key_event = unsafe { mem::transmute::(buffer.Event) }; + + if key_event.bKeyDown == 0 { + // This is a key being released; ignore it. + continue; + } + + return Ok(key_event); + } +} + +pub(crate) fn wants_emoji() -> bool { + // If WT_SESSION is set, we can assume we're running in the new + // Windows Terminal. The correct way to detect this is not available + // yet. See https://github.com/microsoft/terminal/issues/1040 + env::var("WT_SESSION").is_ok() +} + +/// Returns true if there is an MSYS tty on the given handle. +pub(crate) fn msys_tty_on(term: &Term) -> bool { + let handle = term.as_raw_handle(); + unsafe { + // Check whether the Windows 10 native pty is enabled + { + let mut out = MaybeUninit::uninit(); + let res = GetConsoleMode(handle as HANDLE, out.as_mut_ptr()); + if res != 0 // If res is true then out was initialized. + && (out.assume_init() & ENABLE_VIRTUAL_TERMINAL_PROCESSING) + == ENABLE_VIRTUAL_TERMINAL_PROCESSING + { + return true; + } + } + + /// Mirrors windows_sys::Win32::Storage::FileSystem::FILE_NAME_INFO, giving + /// it a fixed length that we can stack allocate + #[repr(C)] + #[allow(non_snake_case)] + struct FILE_NAME_INFO { + FileNameLength: u32, + FileName: [u16; MAX_PATH as usize], + } + + let mut name_info = FILE_NAME_INFO { + FileNameLength: 0, + FileName: [0; MAX_PATH as usize], + }; + let res = GetFileInformationByHandleEx( + handle as HANDLE, + FileNameInfo, + &mut name_info as *mut _ as *mut c_void, + mem::size_of::() as u32, + ); + if res == 0 { + return false; + } + + // Use `get` because `FileNameLength` can be out of range. + let s = match name_info + .FileName + .get(..name_info.FileNameLength as usize / 2) + { + Some(s) => s, + None => return false, + }; + let name = String::from_utf16_lossy(s); + // This checks whether 'pty' exists in the file name, which indicates that + // a pseudo-terminal is attached. To mitigate against false positives + // (e.g., an actual file name that contains 'pty'), we also require that + // either the strings 'msys-' or 'cygwin-' are in the file name as well.) + let is_msys = name.contains("msys-") || name.contains("cygwin-"); + let is_pty = name.contains("-pty"); + is_msys && is_pty + } +} + +pub(crate) fn set_title(title: T) { + let buffer: Vec = OsStr::new(&format!("{title}")) + .encode_wide() + .chain(once(0)) + .collect(); + unsafe { + SetConsoleTitleW(buffer.as_ptr()); + } +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/.cargo-checksum.json b/anneal/v2/vendor/cpufeatures-0.2.17/.cargo-checksum.json new file mode 100644 index 0000000000..d879b96085 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"019c8f463e3ce1db689f6d0f695126264aeb0c4c5fc5000efb3db7cd2170f48c","CHANGELOG.md":"17727a361379fce31e61fc8c0a982082d7df871f3cf9d058d452ce4576d36af4","Cargo.lock":"79e190795c040e8716fbdec683a76aaae9709ea9f276bf6ec2061fa170d00256","Cargo.toml":"25160ea4dfa195721d352d42827b882a41f18f4c55fff58e5c3878ecae84ca44","Cargo.toml.orig":"5aee1d3bb7edabc7c62ef0b6f1c9a96fd5cf67eaab8224a5e2079735b7ff2c8f","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"ae9baa7beea910273c2f384c2a6b721fb7bd02bda3436074a1072e4ee689f985","README.md":"eb7ccf38bd407faaff4897884dce2179323b6b5c9455ea5e2e32d213c5b52f83","src/aarch64.rs":"e85b099f40f51f99f82ff9ffae97078ec7991da5bca4eb61e29abf15c44a8d01","src/lib.rs":"3d633614ff24afdba603e4f2d3e36bdb7b190fff9e7f0d2b385c1f9d5d8144d1","src/loongarch64.rs":"431cf8c3cdcc55cb46275da5c778033e3bd60e03d04910e7756f5ce3a89c3a32","src/miri.rs":"acf1a7e7ae31a1de07941084c6b589a2d4c6ea5f87012c811592c865d04c02cb","src/x86.rs":"b23201081392c38084f15200b071b16f5467aadba98616cce878be16b836f03f","tests/aarch64.rs":"f6f0f55d821dbcac61e54cec8d35bf944cd09f90f3422eee2b6d55a1e9899635","tests/loongarch64.rs":"1b95140c68f673721699dcb40176540818641785f7863a99214bcad2014aa181","tests/x86.rs":"fcf476ca6ebd0845ab547cea4fe40c2ba2a2324c024264d9a86f666586f3a480"},"package":"59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"} \ No newline at end of file diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/.cargo_vcs_info.json b/anneal/v2/vendor/cpufeatures-0.2.17/.cargo_vcs_info.json new file mode 100644 index 0000000000..ac21e033a9 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9d92d5e95ab4c07c5d8bfd024bf2a17e96d20feb" + }, + "path_in_vcs": "cpufeatures" +} \ No newline at end of file diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/CHANGELOG.md b/anneal/v2/vendor/cpufeatures-0.2.17/CHANGELOG.md new file mode 100644 index 0000000000..991cb07281 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/CHANGELOG.md @@ -0,0 +1,168 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.2.17 (2025-01-24) +### Fixed +- Don't link `std` when linking `libc` ([#1142]) + +[#1142]: https://github.com/RustCrypto/utils/pull/1142 + +## 0.2.16 (2024-11-22) +### Fixed +- `cfg` for freestanding x86 targets ([#1137]) + +[#1137]: https://github.com/RustCrypto/utils/pull/1137 + +## 0.2.15 (2024-11-11) +### Fixed +- Relax XSAVE checks ([#1130]) + +[#1130]: https://github.com/RustCrypto/utils/pull/1130 + +## 0.2.14 (2024-09-05) +### Added +- Support for detecting Data Independent Timing (DIT) on AArch64 ([#1100], [#1101]) + +[#1100]: https://github.com/RustCrypto/utils/pull/1100 +[#1101]: https://github.com/RustCrypto/utils/pull/1101 + +## 0.2.13 (2024-08-12) +### Changed +- Use `#[cold]` for initialization code ([#1096]) + +[#1096]: https://github.com/RustCrypto/utils/pull/1096 + +## 0.2.12 (2024-01-04) +### Added +- Support for x86-64 AVX-512 target features: `gfni`, `vaes`, `vpclmulqdq`, `avx512bitalg`, `avx512vpopcntdq` ([#1035]) + +[#1035]: https://github.com/RustCrypto/utils/pull/1035 + +## 0.2.11 (2023-10-26) +### Added +- Support for AArch64's `sm4` target feature ([#972]) + +[#972]: https://github.com/RustCrypto/utils/pull/972 + +## 0.2.10 (2023-10-20) +### Added +- LoongArch64 target support ([#955]) + +[#955]: https://github.com/RustCrypto/utils/pull/955 + +## 0.2.9 (2023-07-05) +### Added +- Support for `avx512vbmi` and `avx512vbmi2` target features ([#926]) + +[#926]: https://github.com/RustCrypto/utils/pull/926 + +## 0.2.8 (2023-06-15) +### Fixed +- Check OS register support on x86 targets ([#919]) + +[#919]: https://github.com/RustCrypto/utils/issues/919 + +## 0.2.7 (2023-04-20) +### Added +- Support freestanding/UEFI `x86` targets ([#821]) + +[#821]: https://github.com/RustCrypto/utils/issues/821 + +## 0.2.6 (2023-03-24) +### Added +- Support dynamic feature detection on iOS and derivative platforms ([#848]) +- Support for detecting AVX-512 target features ([#862]) + +[#848]: https://github.com/RustCrypto/utils/issues/848 +[#862]: https://github.com/RustCrypto/utils/pull/862 + +## 0.2.5 (2022-09-04) +### Fixed +- Add workaround for [CPUID bug] in `std` ([#800]) + +[CPUID bug]: https://github.com/rust-lang/rust/issues/101346 +[#800]: https://github.com/RustCrypto/utils/pull/800 + +## 0.2.4 (2022-08-22) [YANKED] +- Re-release v0.2.3 without any changes to fix [#795] ([#796]) + +[#795]: https://github.com/RustCrypto/utils/issues/795 +[#796]: https://github.com/RustCrypto/utils/pull/796 + +## 0.2.3 (2022-08-18) [YANKED] +### Changed +- Update `libc` version to v0.2.95 ([#789]) +- Disable all target features under MIRI ([#779]) +- Check AVX availability when detecting AVX2 and FMA ([#792]) + +[#779]: https://github.com/RustCrypto/utils/pull/779 +[#789]: https://github.com/RustCrypto/utils/pull/789 +[#792]: https://github.com/RustCrypto/utils/pull/792 + +## 0.2.2 (2022-03-18) [YANKED] +### Added +- Support for Android on `aarch64` ([#752]) + +### Removed +- Vestigial code around `crypto` target feature ([#600]) + +[#600]: https://github.com/RustCrypto/utils/pull/600 +[#752]: https://github.com/RustCrypto/utils/pull/752 + +## 0.2.1 (2021-08-26) [YANKED] +### Changed +- Revert [#583] "Use from_bytes_with_nul for string check" ([#597]) + +[#583]: https://github.com/RustCrypto/utils/pull/583 +[#597]: https://github.com/RustCrypto/utils/pull/597 + +## 0.2.0 (2021-08-26) [YANKED] +### Removed +- AArch64 `crypto` target feature ([#594]) + +[#594]: https://github.com/RustCrypto/utils/pull/594 + +## 0.1.5 (2021-06-21) +### Added +- iOS support ([#435], [#501]) + +### Changed +- Map `aarch64` HWCAPs to target features; add `crypto` ([#456]) + +[#435]: https://github.com/RustCrypto/utils/pull/435 +[#456]: https://github.com/RustCrypto/utils/pull/456 +[#501]: https://github.com/RustCrypto/utils/pull/501 + +## 0.1.4 (2021-05-14) +### Added +- Support compiling on non-Linux/macOS aarch64 targets ([#408]) + +[#408]: https://github.com/RustCrypto/utils/pull/408 + +## 0.1.3 (2021-05-13) +### Removed +- `neon` on `aarch64` targets: already enabled by default ([#406]) + +[#406]: https://github.com/RustCrypto/utils/pull/406 + +## 0.1.2 (2021-05-13) [YANKED] +### Added +- `neon` feature detection on `aarch64` targets ([#403]) + +### Fixed +- Support for `musl`-based targets ([#403]) + +[#403]: https://github.com/RustCrypto/utils/pull/403 + +## 0.1.1 (2021-05-06) +### Added +- `aarch64` support for Linux and macOS/M4 targets ([#393]) + +[#393]: https://github.com/RustCrypto/utils/pull/393 + +## 0.1.0 (2021-04-29) +- Initial release diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.lock b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.lock new file mode 100644 index 0000000000..b1bbb75f76 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cpufeatures" +version = "0.2.17" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml new file mode 100644 index 0000000000..0b79182c56 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml @@ -0,0 +1,71 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cpufeatures" +version = "0.2.17" +authors = ["RustCrypto Developers"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, +with no_std support and support for mobile targets including Android and iOS +""" +documentation = "https://docs.rs/cpufeatures" +readme = "README.md" +keywords = [ + "cpuid", + "target-feature", +] +categories = [ + "hardware-support", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RustCrypto/utils" +resolver = "2" + +[lib] +name = "cpufeatures" +path = "src/lib.rs" + +[[test]] +name = "aarch64" +path = "tests/aarch64.rs" + +[[test]] +name = "loongarch64" +path = "tests/loongarch64.rs" + +[[test]] +name = "x86" +path = "tests/x86.rs" + +[target.aarch64-linux-android.dependencies.libc] +version = "0.2.155" +default-features = false + +[target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies.libc] +version = "0.2.155" +default-features = false + +[target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies.libc] +version = "0.2.155" +default-features = false + +[target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies.libc] +version = "0.2.155" +default-features = false diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml.orig b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml.orig new file mode 100644 index 0000000000..307faea489 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/Cargo.toml.orig @@ -0,0 +1,27 @@ +[package] +name = "cpufeatures" +version = "0.2.17" +description = """ +Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, +with no_std support and support for mobile targets including Android and iOS +""" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/cpufeatures" +repository = "https://github.com/RustCrypto/utils" +keywords = ["cpuid", "target-feature"] +categories = ["hardware-support", "no-std"] +edition = "2018" +readme = "README.md" + +[target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] +libc = { version = "0.2.155", default-features = false } + +[target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] +libc = { version = "0.2.155", default-features = false } + +[target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies] +libc = { version = "0.2.155", default-features = false } + +[target.aarch64-linux-android.dependencies] +libc = { version = "0.2.155", default-features = false } diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-APACHE b/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-APACHE new file mode 100644 index 0000000000..78173fa2e7 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-MIT b/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-MIT new file mode 100644 index 0000000000..0cd648f76b --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2020-2025 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/README.md b/anneal/v2/vendor/cpufeatures-0.2.17/README.md new file mode 100644 index 0000000000..c99ff8d7fe --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/README.md @@ -0,0 +1,126 @@ +# [RustCrypto]: CPU Feature Detection + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] + +Lightweight and efficient runtime CPU feature detection for `aarch64`, `loongarch64`, and +`x86`/`x86_64` targets. + +Supports `no_std` as well as mobile targets including iOS and Android, +providing an alternative to the `std`-dependent `is_x86_feature_detected!` +macro. + +[Documentation][docs-link] + +# Supported target architectures + +*NOTE: target features with an asterisk are unstable (nightly-only) and subject +to change to match upstream name changes in the Rust standard library. + +## `aarch64` + +Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature detection) + +Target features: + +- `aes`* +- `sha2`* +- `sha3`* + +## `loongarch64` + +Linux only (LoongArch64 does not support OS-independent feature detection) + +Target features: + +- `lam`* +- `ual`* +- `fpu`* +- `lsx`* +- `lasx`* +- `crc32`* +- `complex`* +- `crypto`* +- `lvz`* +- `lbt.x86`* +- `lbt.arm`* +- `lbt.mips`* +- `ptw`* + +## `x86`/`x86_64` + +OS independent and `no_std`-friendly + +Target features: + +- `adx` +- `aes` +- `avx` +- `avx2` +- `avx512bw`* +- `avx512cd`* +- `avx512dq`* +- `avx512er`* +- `avx512f`* +- `avx512ifma`* +- `avx512pf`* +- `avx512vl`* +- `avx512vbmi`* +- `avx512vbmi2`* +- `bmi1` +- `bmi2` +- `fma`, +- `mmx` +- `pclmulqdq` +- `popcnt` +- `rdrand` +- `rdseed` +- `sgx` +- `sha` +- `sse` +- `sse2` +- `sse3` +- `sse4.1` +- `sse4.2` +- `ssse3` + +If you would like detection support for a target feature which is not on +this list, please [open a GitHub issue]. + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/cpufeatures.svg?logo=rust +[crate-link]: https://crates.io/crates/cpufeatures +[docs-image]: https://docs.rs/cpufeatures/badge.svg +[docs-link]: https://docs.rs/cpufeatures/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.40+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils +[build-image]: https://github.com/RustCrypto/utils/actions/workflows/cpufeatures.yml/badge.svg +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/cpufeatures.yml + +[//]: # (general links) + +[RustCrypto]: https://github.com/rustcrypto +[RustCrypto/utils#378]: https://github.com/RustCrypto/utils/issues/378 +[open a GitHub issue]: https://github.com/RustCrypto/utils/issues/new?title=cpufeatures:%20requesting%20support%20for%20CHANGEME%20target%20feature diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/src/aarch64.rs b/anneal/v2/vendor/cpufeatures-0.2.17/src/aarch64.rs new file mode 100644 index 0000000000..36c253bd78 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/src/aarch64.rs @@ -0,0 +1,167 @@ +//! ARM64 CPU feature detection support. +//! +//! Unfortunately ARM instructions to detect CPU features cannot be called from +//! unprivileged userspace code, so this implementation relies on OS-specific +//! APIs for feature detection. + +// Evaluate the given `$body` expression any of the supplied target features +// are not enabled. Otherwise returns true. +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => { + { + #[cfg(not(all($(target_feature=$tf,)*)))] + $body + + #[cfg(all($(target_feature=$tf,)*))] + true + } + }; +} + +// Linux runtime detection of target CPU features using `getauxval`. +#[cfg(any(target_os = "linux", target_os = "android"))] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => {{ + let hwcaps = $crate::aarch64::getauxval_hwcap(); + $($crate::check!(hwcaps, $tf) & )+ true + }}; +} + +/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. +#[cfg(any(target_os = "linux", target_os = "android"))] +pub fn getauxval_hwcap() -> u64 { + unsafe { libc::getauxval(libc::AT_HWCAP) } +} + +// Apple platform's runtime detection of target CPU features using `sysctlbyname`. +#[cfg(target_vendor = "apple")] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => {{ + $($crate::check!($tf) & )+ true + }}; +} + +// Linux `expand_check_macro` +#[cfg(any(target_os = "linux", target_os = "android"))] +macro_rules! __expand_check_macro { + ($(($name:tt, $hwcap:ident)),* $(,)?) => { + #[macro_export] + #[doc(hidden)] + macro_rules! check { + $( + ($hwcaps:expr, $name) => { + (($hwcaps & $crate::aarch64::hwcaps::$hwcap) != 0) + }; + )* + } + }; +} + +// Linux `expand_check_macro` +#[cfg(any(target_os = "linux", target_os = "android"))] +__expand_check_macro! { + ("aes", AES), // Enable AES support. + ("dit", DIT), // Enable DIT support. + ("sha2", SHA2), // Enable SHA1 and SHA256 support. + ("sha3", SHA3), // Enable SHA512 and SHA3 support. + ("sm4", SM4), // Enable SM3 and SM4 support. +} + +/// Linux hardware capabilities mapped to target features. +/// +/// Note that LLVM target features are coarser grained than what Linux supports +/// and imply more capabilities under each feature. This module attempts to +/// provide that mapping accordingly. +/// +/// See this issue for more info: +#[cfg(any(target_os = "linux", target_os = "android"))] +pub mod hwcaps { + use libc::c_ulong; + + pub const AES: c_ulong = libc::HWCAP_AES | libc::HWCAP_PMULL; + pub const DIT: c_ulong = libc::HWCAP_DIT; + pub const SHA2: c_ulong = libc::HWCAP_SHA2; + pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512; + pub const SM4: c_ulong = libc::HWCAP_SM3 | libc::HWCAP_SM4; +} + +// Apple OS (macOS, iOS, watchOS, and tvOS) `check!` macro. +// +// NOTE: several of these instructions (e.g. `aes`, `sha2`) can be assumed to +// be present on all Apple ARM64 hardware. +// +// Newer CPU instructions now have nodes within sysctl's `hw.optional` +// namespace, however the ones that do not can safely be assumed to be +// present on all Apple ARM64 devices, now and for the foreseeable future. +// +// See discussion on this issue for more information: +// +#[cfg(target_vendor = "apple")] +#[macro_export] +#[doc(hidden)] +macro_rules! check { + ("aes") => { + true + }; + ("dit") => { + // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Enable-DIT-for-constant-time-cryptographic-operations + unsafe { + $crate::aarch64::sysctlbyname(b"hw.optional.arm.FEAT_DIT\0") + } + }; + ("sha2") => { + true + }; + ("sha3") => { + unsafe { + // `sha3` target feature implies SHA-512 as well + $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha512\0") + && $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha3\0") + } + }; + ("sm4") => { + false + }; +} + +/// Apple helper function for calling `sysctlbyname`. +#[cfg(target_vendor = "apple")] +pub unsafe fn sysctlbyname(name: &[u8]) -> bool { + assert_eq!( + name.last().cloned(), + Some(0), + "name is not NUL terminated: {:?}", + name + ); + + let mut value: u32 = 0; + let mut size = core::mem::size_of::(); + + let rc = libc::sysctlbyname( + name.as_ptr() as *const i8, + &mut value as *mut _ as *mut libc::c_void, + &mut size, + core::ptr::null_mut(), + 0, + ); + + assert_eq!(size, 4, "unexpected sysctlbyname(3) result size"); + assert_eq!(rc, 0, "sysctlbyname returned error code: {}", rc); + value != 0 +} + +// On other targets, runtime CPU feature detection is unavailable +#[cfg(not(any(target_vendor = "apple", target_os = "linux", target_os = "android",)))] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => { + false + }; +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/src/lib.rs b/anneal/v2/vendor/cpufeatures-0.2.17/src/lib.rs new file mode 100644 index 0000000000..bc4afd9ad2 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/src/lib.rs @@ -0,0 +1,220 @@ +//! This crate provides macros for runtime CPU feature detection. It's intended +//! as a stopgap until Rust [RFC 2725] adding first-class target feature detection +//! macros to `libcore` is implemented. +//! +//! # Supported target architectures +//! +//! *NOTE: target features with an asterisk are unstable (nightly-only) and +//! subject to change to match upstream name changes in the Rust standard +//! library. +//! +//! ## `aarch64` +//! +//! Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature detection) +//! +//! Target features: +//! +//! - `aes`* +//! - `sha2`* +//! - `sha3`* +//! +//! Linux only +//! +//! - `sm4`* +//! +//! ## `loongarch64` +//! +//! Linux only (LoongArch64 does not support OS-independent feature detection) +//! +//! Target features: +//! +//! - `lam`* +//! - `ual`* +//! - `fpu`* +//! - `lsx`* +//! - `lasx`* +//! - `crc32`* +//! - `complex`* +//! - `crypto`* +//! - `lvz`* +//! - `lbt.x86`* +//! - `lbt.arm`* +//! - `lbt.mips`* +//! - `ptw`* +//! +//! ## `x86`/`x86_64` +//! +//! OS independent and `no_std`-friendly +//! +//! Target features: +//! +//! - `adx` +//! - `aes` +//! - `avx` +//! - `avx2` +//! - `avx512bw`* +//! - `avx512cd`* +//! - `avx512dq`* +//! - `avx512er`* +//! - `avx512f`* +//! - `avx512ifma`* +//! - `avx512pf`* +//! - `avx512vl`* +//! - `bmi1` +//! - `bmi2` +//! - `fma`, +//! - `mmx` +//! - `pclmulqdq` +//! - `popcnt` +//! - `rdrand` +//! - `rdseed` +//! - `sgx` +//! - `sha` +//! - `sse` +//! - `sse2` +//! - `sse3` +//! - `sse4.1` +//! - `sse4.2` +//! - `ssse3` +//! +//! If you would like detection support for a target feature which is not on +//! this list, please [open a GitHub issue][gh]. +//! +//! # Example +//! ``` +//! # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +//! # { +//! // This macro creates `cpuid_aes_sha` module +//! cpufeatures::new!(cpuid_aes_sha, "aes", "sha"); +//! +//! // `token` is a Zero Sized Type (ZST) value, which guarantees +//! // that underlying static storage got properly initialized, +//! // which allows to omit initialization branch +//! let token: cpuid_aes_sha::InitToken = cpuid_aes_sha::init(); +//! +//! if token.get() { +//! println!("CPU supports both SHA and AES extensions"); +//! } else { +//! println!("SHA and AES extensions are not supported"); +//! } +//! +//! // If stored value needed only once you can get stored value +//! // omitting the token +//! let val = cpuid_aes_sha::get(); +//! assert_eq!(val, token.get()); +//! +//! // Additionally you can get both token and value +//! let (token, val) = cpuid_aes_sha::init_get(); +//! assert_eq!(val, token.get()); +//! # } +//! ``` +//! +//! Note that if all tested target features are enabled via compiler options +//! (e.g. by using `RUSTFLAGS`), the `get` method will always return `true` +//! and `init` will not use CPUID instruction. Such behavior allows +//! compiler to completely eliminate fallback code. +//! +//! After first call macro caches result and returns it in subsequent +//! calls, thus runtime overhead for them is minimal. +//! +//! [RFC 2725]: https://github.com/rust-lang/rfcs/pull/2725 +//! [gh]: https://github.com/RustCrypto/utils/issues/new?title=cpufeatures:%20requesting%20support%20for%20CHANGEME%20target%20feature + +#![no_std] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] + +#[cfg(not(miri))] +#[cfg(target_arch = "aarch64")] +#[doc(hidden)] +pub mod aarch64; + +#[cfg(not(miri))] +#[cfg(target_arch = "loongarch64")] +#[doc(hidden)] +pub mod loongarch64; + +#[cfg(not(miri))] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86; + +#[cfg(miri)] +mod miri; + +#[cfg(not(any( + target_arch = "aarch64", + target_arch = "loongarch64", + target_arch = "x86", + target_arch = "x86_64" +)))] +compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets."); + +/// Create module with CPU feature detection code. +#[macro_export] +macro_rules! new { + ($mod_name:ident, $($tf:tt),+ $(,)?) => { + mod $mod_name { + use core::sync::atomic::{AtomicU8, Ordering::Relaxed}; + + const UNINIT: u8 = u8::max_value(); + static STORAGE: AtomicU8 = AtomicU8::new(UNINIT); + + /// Initialization token + #[derive(Copy, Clone, Debug)] + pub struct InitToken(()); + + impl InitToken { + /// Get initialized value + #[inline(always)] + pub fn get(&self) -> bool { + $crate::__unless_target_features! { + $($tf),+ => { + STORAGE.load(Relaxed) == 1 + } + } + } + } + + /// Get stored value and initialization token, + /// initializing underlying storage if needed. + #[inline] + pub fn init_get() -> (InitToken, bool) { + let res = $crate::__unless_target_features! { + $($tf),+ => { + #[cold] + fn init_inner() -> bool { + let res = $crate::__detect_target_features!($($tf),+); + STORAGE.store(res as u8, Relaxed); + res + } + + // Relaxed ordering is fine, as we only have a single atomic variable. + let val = STORAGE.load(Relaxed); + + if val == UNINIT { + init_inner() + } else { + val == 1 + } + } + }; + + (InitToken(()), res) + } + + /// Initialize underlying storage if needed and get initialization token. + #[inline] + pub fn init() -> InitToken { + init_get().0 + } + + /// Initialize underlying storage if needed and get stored value. + #[inline] + pub fn get() -> bool { + init_get().1 + } + } + }; +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/src/loongarch64.rs b/anneal/v2/vendor/cpufeatures-0.2.17/src/loongarch64.rs new file mode 100644 index 0000000000..077cc7c648 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/src/loongarch64.rs @@ -0,0 +1,106 @@ +//! LoongArch64 CPU feature detection support. +//! +//! This implementation relies on OS-specific APIs for feature detection. + +// Evaluate the given `$body` expression any of the supplied target features +// are not enabled. Otherwise returns true. +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => { + { + #[cfg(not(all($(target_feature=$tf,)*)))] + $body + + #[cfg(all($(target_feature=$tf,)*))] + true + } + }; +} + +// Linux runtime detection of target CPU features using `getauxval`. +#[cfg(target_os = "linux")] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => {{ + let hwcaps = $crate::loongarch64::getauxval_hwcap(); + $($crate::check!(hwcaps, $tf) & )+ true + }}; +} + +/// Linux helper function for calling `getauxval` to get `AT_HWCAP`. +#[cfg(target_os = "linux")] +pub fn getauxval_hwcap() -> u64 { + unsafe { libc::getauxval(libc::AT_HWCAP) } +} + +// Linux `expand_check_macro` +#[cfg(target_os = "linux")] +macro_rules! __expand_check_macro { + ($(($name:tt, $hwcap:ident)),* $(,)?) => { + #[macro_export] + #[doc(hidden)] + macro_rules! check { + $( + ($hwcaps:expr, $name) => { + (($hwcaps & $crate::loongarch64::hwcaps::$hwcap) != 0) + }; + )* + } + }; +} + +// Linux `expand_check_macro` +#[cfg(target_os = "linux")] +__expand_check_macro! { + ("cpucfg", CPUCFG), // Enable CPUCFG support. + ("lam", LAM), // Enable LAM support. + ("ual", UAL), // Enable UAL support. + ("fpu", FPU), // Enable FPU support. + ("lsx", LSX), // Enable LSX support. + ("lasx", LASX), // Enable LASX support. + ("crc32", CRC32), // Enable CRC32 support. + ("complex", COMPLEX), // Enable COMPLEX support. + ("crypto", CRYPTO), // Enable CRYPTO support. + ("lvz", LVZ), // Enable LVZ support. + ("lbt.x86", LBT_X86), // Enable LBT_X86 support. + ("lbt.arm", LBT_ARM), // Enable LBT_ARM support. + ("lbt.mips", LBT_MIPS), // Enable LBT_MIPS support. + ("ptw", PTW), // Enable PTW support. +} + +/// Linux hardware capabilities mapped to target features. +/// +/// Note that LLVM target features are coarser grained than what Linux supports +/// and imply more capabilities under each feature. This module attempts to +/// provide that mapping accordingly. +#[cfg(target_os = "linux")] +pub mod hwcaps { + use libc::c_ulong; + + pub const CPUCFG: c_ulong = libc::HWCAP_LOONGARCH_CPUCFG; + pub const LAM: c_ulong = libc::HWCAP_LOONGARCH_LAM; + pub const UAL: c_ulong = libc::HWCAP_LOONGARCH_UAL; + pub const FPU: c_ulong = libc::HWCAP_LOONGARCH_FPU; + pub const LSX: c_ulong = libc::HWCAP_LOONGARCH_LSX; + pub const LASX: c_ulong = libc::HWCAP_LOONGARCH_LASX; + pub const CRC32: c_ulong = libc::HWCAP_LOONGARCH_CRC32; + pub const COMPLEX: c_ulong = libc::HWCAP_LOONGARCH_COMPLEX; + pub const CRYPTO: c_ulong = libc::HWCAP_LOONGARCH_CRYPTO; + pub const LVZ: c_ulong = libc::HWCAP_LOONGARCH_LVZ; + pub const LBT_X86: c_ulong = libc::HWCAP_LOONGARCH_LBT_X86; + pub const LBT_ARM: c_ulong = libc::HWCAP_LOONGARCH_LBT_ARM; + pub const LBT_MIPS: c_ulong = libc::HWCAP_LOONGARCH_LBT_MIPS; + pub const PTW: c_ulong = libc::HWCAP_LOONGARCH_PTW; +} + +// On other targets, runtime CPU feature detection is unavailable +#[cfg(not(target_os = "linux"))] +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => { + false + }; +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/src/miri.rs b/anneal/v2/vendor/cpufeatures-0.2.17/src/miri.rs new file mode 100644 index 0000000000..8dff21c13e --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/src/miri.rs @@ -0,0 +1,20 @@ +//! Minimal miri support. +//! +//! Miri is an interpreter, and though it tries to emulate the target CPU +//! it does not support any target features. + +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => { + false + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => { + false + }; +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/src/x86.rs b/anneal/v2/vendor/cpufeatures-0.2.17/src/x86.rs new file mode 100644 index 0000000000..031dcae70e --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/src/x86.rs @@ -0,0 +1,152 @@ +//! x86/x86-64 CPU feature detection support. +//! +//! Portable, `no_std`-friendly implementation that relies on the x86 `CPUID` +//! instruction for feature detection. + +/// Evaluate the given `$body` expression any of the supplied target features +/// are not enabled. Otherwise returns true. +/// +/// The `$body` expression is not evaluated on SGX targets, and returns false +/// on these targets unless *all* supplied target features are enabled. +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => {{ + #[cfg(not(all($(target_feature=$tf,)*)))] + { + #[cfg(not(any(target_env = "sgx", target_os = "none", target_os = "uefi")))] + $body + + // CPUID is not available on SGX. Freestanding and UEFI targets + // do not support SIMD features with default compilation flags. + #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] + false + } + + #[cfg(all($(target_feature=$tf,)*))] + true + }}; +} + +/// Use CPUID to detect the presence of all supplied target features. +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => {{ + #[cfg(target_arch = "x86")] + use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult}; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult}; + + // These wrappers are workarounds around + // https://github.com/rust-lang/rust/issues/101346 + // + // DO NOT remove it until MSRV is bumped to a version + // with the issue fix (at least 1.64). + #[inline(never)] + unsafe fn cpuid(leaf: u32) -> CpuidResult { + __cpuid(leaf) + } + + #[inline(never)] + unsafe fn cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { + __cpuid_count(leaf, sub_leaf) + } + + let cr = unsafe { + [cpuid(1), cpuid_count(7, 0)] + }; + + $($crate::check!(cr, $tf) & )+ true + }}; +} + +/// Check that OS supports required SIMD registers +#[macro_export] +#[doc(hidden)] +macro_rules! __xgetbv { + ($cr:expr, $mask:expr) => {{ + #[cfg(target_arch = "x86")] + use core::arch::x86 as arch; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64 as arch; + + // Check bits 26 and 27 + let xmask = 0b11 << 26; + let xsave = $cr[0].ecx & xmask == xmask; + if xsave { + let xcr0 = unsafe { arch::_xgetbv(arch::_XCR_XFEATURE_ENABLED_MASK) }; + (xcr0 & $mask) == $mask + } else { + false + } + }}; +} + +macro_rules! __expand_check_macro { + ($(($name:tt, $reg_cap:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => { + #[macro_export] + #[doc(hidden)] + macro_rules! check { + $( + ($cr:expr, $name) => {{ + // Register bits are listed here: + // https://wiki.osdev.org/CPU_Registers_x86#Extended_Control_Registers + let reg_cap = match $reg_cap { + // Bit 1 + "xmm" => $crate::__xgetbv!($cr, 0b10), + // Bits 1 and 2 + "ymm" => $crate::__xgetbv!($cr, 0b110), + // Bits 1, 2, 5, 6, and 7 + "zmm" => $crate::__xgetbv!($cr, 0b1110_0110), + _ => true, + }; + reg_cap + $( + & ($cr[$i].$reg & (1 << $offset) != 0) + )* + }}; + )* + } + }; +} + +__expand_check_macro! { + ("sse3", "", 0, ecx, 0), + ("pclmulqdq", "", 0, ecx, 1), + ("ssse3", "", 0, ecx, 9), + ("fma", "ymm", 0, ecx, 12, 0, ecx, 28), + ("sse4.1", "", 0, ecx, 19), + ("sse4.2", "", 0, ecx, 20), + ("popcnt", "", 0, ecx, 23), + ("aes", "", 0, ecx, 25), + ("avx", "xmm", 0, ecx, 28), + ("rdrand", "", 0, ecx, 30), + + ("mmx", "", 0, edx, 23), + ("sse", "", 0, edx, 25), + ("sse2", "", 0, edx, 26), + + ("sgx", "", 1, ebx, 2), + ("bmi1", "", 1, ebx, 3), + ("bmi2", "", 1, ebx, 8), + ("avx2", "ymm", 1, ebx, 5, 0, ecx, 28), + ("avx512f", "zmm", 1, ebx, 16), + ("avx512dq", "zmm", 1, ebx, 17), + ("rdseed", "", 1, ebx, 18), + ("adx", "", 1, ebx, 19), + ("avx512ifma", "zmm", 1, ebx, 21), + ("avx512pf", "zmm", 1, ebx, 26), + ("avx512er", "zmm", 1, ebx, 27), + ("avx512cd", "zmm", 1, ebx, 28), + ("sha", "", 1, ebx, 29), + ("avx512bw", "zmm", 1, ebx, 30), + ("avx512vl", "zmm", 1, ebx, 31), + ("avx512vbmi", "zmm", 1, ecx, 1), + ("avx512vbmi2", "zmm", 1, ecx, 6), + ("gfni", "zmm", 1, ecx, 8), + ("vaes", "zmm", 1, ecx, 9), + ("vpclmulqdq", "zmm", 1, ecx, 10), + ("avx512bitalg", "zmm", 1, ecx, 12), + ("avx512vpopcntdq", "zmm", 1, ecx, 14), +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/tests/aarch64.rs b/anneal/v2/vendor/cpufeatures-0.2.17/tests/aarch64.rs new file mode 100644 index 0000000000..41a6123314 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/tests/aarch64.rs @@ -0,0 +1,17 @@ +//! ARM64 tests + +#![cfg(target_arch = "aarch64")] + +cpufeatures::new!(armcaps, "aes", "sha2", "sha3", "sm4"); + +#[test] +fn init() { + let token: armcaps::InitToken = armcaps::init(); + assert_eq!(token.get(), armcaps::get()); +} + +#[test] +fn init_get() { + let (token, val) = armcaps::init_get(); + assert_eq!(val, token.get()); +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/tests/loongarch64.rs b/anneal/v2/vendor/cpufeatures-0.2.17/tests/loongarch64.rs new file mode 100644 index 0000000000..fbcbe9d3b4 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/tests/loongarch64.rs @@ -0,0 +1,20 @@ +//! LoongArch64 tests + +#![cfg(target_arch = "loongarch64")] + +cpufeatures::new!( + lacaps, "cpucfg", "lam", "ual", "fpu", "lsx", "lasx", "crc32", "complex", "crypto", "lvz", + "lbt.x86", "lbt.arm", "lbt.mips", "ptw" +); + +#[test] +fn init() { + let token: lacaps::InitToken = lacaps::init(); + assert_eq!(token.get(), lacaps::get()); +} + +#[test] +fn init_get() { + let (token, val) = lacaps::init_get(); + assert_eq!(val, token.get()); +} diff --git a/anneal/v2/vendor/cpufeatures-0.2.17/tests/x86.rs b/anneal/v2/vendor/cpufeatures-0.2.17/tests/x86.rs new file mode 100644 index 0000000000..0d81242389 --- /dev/null +++ b/anneal/v2/vendor/cpufeatures-0.2.17/tests/x86.rs @@ -0,0 +1,17 @@ +//! x86/x86_64 tests + +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] + +cpufeatures::new!(cpuid, "aes", "sha"); + +#[test] +fn init() { + let token: cpuid::InitToken = cpuid::init(); + assert_eq!(token.get(), cpuid::get()); +} + +#[test] +fn init_get() { + let (token, val) = cpuid::init_get(); + assert_eq!(val, token.get()); +} diff --git a/anneal/v2/vendor/crossbeam-deque/.cargo-checksum.json b/anneal/v2/vendor/crossbeam-deque/.cargo-checksum.json new file mode 100644 index 0000000000..219fd0230e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"d9ccc496cf1bd0f02d77bac0221c8ff040efca5156f835d0adf491d8ebdb89ca","CHANGELOG.md":"0291dc92112ba4d6fe899162cded7f2b7150ed2d06d23e08e5d02a0b53a469f8","Cargo.toml":"93550ef824cb400b7a92af6b2ebe9ef24aa5a37567d80be5e4ba149bdc651be1","Cargo.toml.orig":"2b164c815b5ae4e596a6dc8b5f7b99b9eed7681d8b3372267638ac0d73ddcbc5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"86445da156ad68ea1d1f2dc49a3cef942ccc377ff56316aefe89732ded763aba","src/deque.rs":"f3c0f92946eb0f71a42a5de2549cf2da137f0a07f31b79def69451fd85c15776","src/lib.rs":"3427a4468253e91e09b264e1f8fd6fc67cfda54be5aecbd38f1b0cb7e0d928de","tests/fifo.rs":"3d98e0d4ca7cfddf10708b71642cf1ff05543d067ad837e48401d63cc31c0a18","tests/injector.rs":"859a0e6fd306e844e8fd660104a994aa894a165f20fa326f4b807e660eaf7878","tests/lifo.rs":"57abdb3fc5920a422f785ba308b658bdc5400947532eeffb799f2395a2061549","tests/steal.rs":"cdf588cc13eeb275ef1231eb18e3245faca7a2d054fa6527bfdba2a34bc8f7bf"},"package":"9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-deque/.cargo_vcs_info.json b/anneal/v2/vendor/crossbeam-deque/.cargo_vcs_info.json new file mode 100644 index 0000000000..0c63ec5c82 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ccd83ac4108a2a1b41e9c6e79c87267167d18dfa" + }, + "path_in_vcs": "crossbeam-deque" +} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-deque/CHANGELOG.md b/anneal/v2/vendor/crossbeam-deque/CHANGELOG.md new file mode 100644 index 0000000000..5bc6e9f47a --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/CHANGELOG.md @@ -0,0 +1,141 @@ +# Version 0.8.6 + +- Fix stack overflow when pushing large value to `Injector`. (#1146, #1147, #1159) + +# Version 0.8.5 + +- Remove dependency on `cfg-if`. (#1072) + +# Version 0.8.4 + +- Bump the minimum supported Rust version to 1.61. (#1037) + +# Version 0.8.3 + +- Add `Stealer::{steal_batch_with_limit, steal_batch_with_limit_and_pop}` methods. (#903) +- Add `Injector::{steal_batch_with_limit, steal_batch_with_limit_and_pop}` methods. (#903) + +# Version 0.8.2 + +- Bump the minimum supported Rust version to 1.38. (#877) + +# Version 0.8.1 + +- Fix deque steal race condition. (#726) +- Add `Stealer::len` method. (#708) + +# Version 0.8.0 + +**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details. + +- Bump the minimum supported Rust version to 1.36. +- Add `Worker::len()` and `Injector::len()` methods. +- Add `std` (enabled by default) feature for forward compatibility. + +# Version 0.7.4 + +- Fix deque steal race condition. + +# Version 0.7.3 + +**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details. + +- Stop stealing from the same deque. (#448) +- Fix unsoundness issues by adopting `MaybeUninit`. (#458) + +# Version 0.7.2 + +**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details. + +- Bump `crossbeam-epoch` to `0.8`. +- Bump `crossbeam-utils` to `0.7`. + +# Version 0.7.1 + +**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details. + +- Bump the minimum required version of `crossbeam-utils`. + +# Version 0.7.0 + +**Note:** This release has been yanked. See [GHSA-pqqp-xmhj-wgcw](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-pqqp-xmhj-wgcw) for details. + +- Make `Worker::pop()` faster in the FIFO case. +- Replace `fifo()` nad `lifo()` with `Worker::new_fifo()` and `Worker::new_lifo()`. +- Add more batched steal methods. +- Introduce `Injector`, a MPMC queue. +- Rename `Steal::Data` to `Steal::Success`. +- Add `Steal::or_else()` and implement `FromIterator` for `Steal`. +- Add `#[must_use]` to `Steal`. + +# Version 0.6.3 + +- Bump `crossbeam-epoch` to `0.7`. + +# Version 0.6.2 + +- Update `crosbeam-utils` to `0.6`. + +# Version 0.6.1 + +- Change a few `Relaxed` orderings to `Release` in order to fix false positives by tsan. + +# Version 0.6.0 + +- Add `Stealer::steal_many` for batched stealing. +- Change the return type of `pop` to `Pop` so that spinning can be handled manually. + +# Version 0.5.2 + +- Update `crossbeam-utils` to `0.5.0`. + +# Version 0.5.1 + +- Minor optimizations. + +# Version 0.5.0 + +- Add two deque constructors : `fifo()` and `lifo()`. +- Update `rand` to `0.5.3`. +- Rename `Deque` to `Worker`. +- Return `Option` from `Stealer::steal`. +- Remove methods `Deque::len` and `Stealer::len`. +- Remove method `Deque::stealer`. +- Remove method `Deque::steal`. + +# Version 0.4.1 + +- Update `crossbeam-epoch` to `0.5.0`. + +# Version 0.4.0 + +- Update `crossbeam-epoch` to `0.4.2`. +- Update `crossbeam-utils` to `0.4.0`. +- Require minimum Rust version 1.25. + +# Version 0.3.1 + +- Add `Deque::capacity`. +- Add `Deque::min_capacity`. +- Add `Deque::shrink_to_fit`. +- Update `crossbeam-epoch` to `0.3.0`. +- Support Rust 1.20. +- Shrink the buffer in `Deque::push` if necessary. + +# Version 0.3.0 + +- Update `crossbeam-epoch` to `0.4.0`. +- Drop support for Rust 1.13. + +# Version 0.2.0 + +- Update `crossbeam-epoch` to `0.3.0`. +- Support Rust 1.13. + +# Version 0.1.1 + +- Update `crossbeam-epoch` to `0.2.0`. + +# Version 0.1.0 + +- First implementation of the Chase-Lev deque. diff --git a/anneal/v2/vendor/crossbeam-deque/Cargo.toml b/anneal/v2/vendor/crossbeam-deque/Cargo.toml new file mode 100644 index 0000000000..79278183e0 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/Cargo.toml @@ -0,0 +1,92 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.61" +name = "crossbeam-deque" +version = "0.8.6" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Concurrent work-stealing deque" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque" +readme = "README.md" +keywords = [ + "chase-lev", + "lock-free", + "scheduler", + "scheduling", +] +categories = [ + "algorithms", + "concurrency", + "data-structures", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" + +[lib] +name = "crossbeam_deque" +path = "src/lib.rs" + +[[test]] +name = "fifo" +path = "tests/fifo.rs" + +[[test]] +name = "injector" +path = "tests/injector.rs" + +[[test]] +name = "lifo" +path = "tests/lifo.rs" + +[[test]] +name = "steal" +path = "tests/steal.rs" + +[dependencies.crossbeam-epoch] +version = "0.9.17" +default-features = false + +[dependencies.crossbeam-utils] +version = "0.8.18" +default-features = false + +[dev-dependencies.rand] +version = "0.8" + +[features] +default = ["std"] +std = [ + "crossbeam-epoch/std", + "crossbeam-utils/std", +] + +[lints.clippy.declare_interior_mutable_const] +level = "allow" +priority = 1 + +[lints.clippy.lint_groups_priority] +level = "allow" +priority = 1 + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(crossbeam_loom)", + "cfg(crossbeam_sanitize)", +] diff --git a/anneal/v2/vendor/crossbeam-deque/Cargo.toml.orig b/anneal/v2/vendor/crossbeam-deque/Cargo.toml.orig new file mode 100644 index 0000000000..3c6d446396 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/Cargo.toml.orig @@ -0,0 +1,34 @@ +[package] +name = "crossbeam-deque" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md (when increasing major or minor version) +# - Run './tools/publish.sh crossbeam-deque ' +version = "0.8.6" +edition = "2021" +rust-version = "1.61" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque" +description = "Concurrent work-stealing deque" +keywords = ["chase-lev", "lock-free", "scheduler", "scheduling"] +categories = ["algorithms", "concurrency", "data-structures"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +# +# NOTE: Disabling `std` feature is not supported yet. +std = ["crossbeam-epoch/std", "crossbeam-utils/std"] + +[dependencies] +crossbeam-epoch = { version = "0.9.17", path = "../crossbeam-epoch", default-features = false } +crossbeam-utils = { version = "0.8.18", path = "../crossbeam-utils", default-features = false } + +[dev-dependencies] +rand = "0.8" + +[lints] +workspace = true diff --git a/anneal/v2/vendor/crossbeam-deque/LICENSE-APACHE b/anneal/v2/vendor/crossbeam-deque/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/crossbeam-deque/LICENSE-MIT b/anneal/v2/vendor/crossbeam-deque/LICENSE-MIT new file mode 100644 index 0000000000..068d491fd5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/LICENSE-MIT @@ -0,0 +1,27 @@ +The MIT License (MIT) + +Copyright (c) 2019 The Crossbeam Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/crossbeam-deque/README.md b/anneal/v2/vendor/crossbeam-deque/README.md new file mode 100644 index 0000000000..4eae1447ec --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/README.md @@ -0,0 +1,46 @@ +# Crossbeam Deque + +[![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)]( +https://github.com/crossbeam-rs/crossbeam/actions) +[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)]( +https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque#license) +[![Cargo](https://img.shields.io/crates/v/crossbeam-deque.svg)]( +https://crates.io/crates/crossbeam-deque) +[![Documentation](https://docs.rs/crossbeam-deque/badge.svg)]( +https://docs.rs/crossbeam-deque) +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( +https://www.rust-lang.org) +[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) + +This crate provides work-stealing deques, which are primarily intended for +building task schedulers. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +crossbeam-deque = "0.8" +``` + +## Compatibility + +Crossbeam Deque supports stable Rust releases going back at least six months, +and every time the minimum supported Rust version is increased, a new minor +version is released. Currently, the minimum supported Rust version is 1.61. + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +#### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/crossbeam-deque/src/deque.rs b/anneal/v2/vendor/crossbeam-deque/src/deque.rs new file mode 100644 index 0000000000..84ba0b8c04 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/src/deque.rs @@ -0,0 +1,2216 @@ +use std::alloc::{alloc_zeroed, handle_alloc_error, Layout}; +use std::boxed::Box; +use std::cell::{Cell, UnsafeCell}; +use std::cmp; +use std::fmt; +use std::marker::PhantomData; +use std::mem::{self, MaybeUninit}; +use std::ptr; +use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering}; +use std::sync::Arc; + +use crossbeam_epoch::{self as epoch, Atomic, Owned}; +use crossbeam_utils::{Backoff, CachePadded}; + +// Minimum buffer capacity. +const MIN_CAP: usize = 64; +// Maximum number of tasks that can be stolen in `steal_batch()` and `steal_batch_and_pop()`. +const MAX_BATCH: usize = 32; +// If a buffer of at least this size is retired, thread-local garbage is flushed so that it gets +// deallocated as soon as possible. +const FLUSH_THRESHOLD_BYTES: usize = 1 << 10; + +/// A buffer that holds tasks in a worker queue. +/// +/// This is just a pointer to the buffer and its length - dropping an instance of this struct will +/// *not* deallocate the buffer. +struct Buffer { + /// Pointer to the allocated memory. + ptr: *mut T, + + /// Capacity of the buffer. Always a power of two. + cap: usize, +} + +unsafe impl Send for Buffer {} + +impl Buffer { + /// Allocates a new buffer with the specified capacity. + fn alloc(cap: usize) -> Buffer { + debug_assert_eq!(cap, cap.next_power_of_two()); + + let ptr = Box::into_raw( + (0..cap) + .map(|_| MaybeUninit::::uninit()) + .collect::>(), + ) + .cast::(); + + Buffer { ptr, cap } + } + + /// Deallocates the buffer. + unsafe fn dealloc(self) { + drop(Box::from_raw(ptr::slice_from_raw_parts_mut( + self.ptr.cast::>(), + self.cap, + ))); + } + + /// Returns a pointer to the task at the specified `index`. + unsafe fn at(&self, index: isize) -> *mut T { + // `self.cap` is always a power of two. + // We do all the loads at `MaybeUninit` because we might realize, after loading, that we + // don't actually have the right to access this memory. + self.ptr.offset(index & (self.cap - 1) as isize) + } + + /// Writes `task` into the specified `index`. + /// + /// This method might be concurrently called with another `read` at the same index, which is + /// technically speaking a data race and therefore UB. We should use an atomic store here, but + /// that would be more expensive and difficult to implement generically for all types `T`. + /// Hence, as a hack, we use a volatile write instead. + unsafe fn write(&self, index: isize, task: MaybeUninit) { + ptr::write_volatile(self.at(index).cast::>(), task) + } + + /// Reads a task from the specified `index`. + /// + /// This method might be concurrently called with another `write` at the same index, which is + /// technically speaking a data race and therefore UB. We should use an atomic load here, but + /// that would be more expensive and difficult to implement generically for all types `T`. + /// Hence, as a hack, we use a volatile load instead. + unsafe fn read(&self, index: isize) -> MaybeUninit { + ptr::read_volatile(self.at(index).cast::>()) + } +} + +impl Clone for Buffer { + fn clone(&self) -> Buffer { + *self + } +} + +impl Copy for Buffer {} + +/// Internal queue data shared between the worker and stealers. +/// +/// The implementation is based on the following work: +/// +/// 1. [Chase and Lev. Dynamic circular work-stealing deque. SPAA 2005.][chase-lev] +/// 2. [Le, Pop, Cohen, and Nardelli. Correct and efficient work-stealing for weak memory models. +/// PPoPP 2013.][weak-mem] +/// 3. [Norris and Demsky. CDSchecker: checking concurrent data structures written with C/C++ +/// atomics. OOPSLA 2013.][checker] +/// +/// [chase-lev]: https://dl.acm.org/citation.cfm?id=1073974 +/// [weak-mem]: https://dl.acm.org/citation.cfm?id=2442524 +/// [checker]: https://dl.acm.org/citation.cfm?id=2509514 +struct Inner { + /// The front index. + front: AtomicIsize, + + /// The back index. + back: AtomicIsize, + + /// The underlying buffer. + buffer: CachePadded>>, +} + +impl Drop for Inner { + fn drop(&mut self) { + // Load the back index, front index, and buffer. + let b = *self.back.get_mut(); + let f = *self.front.get_mut(); + + unsafe { + let buffer = self.buffer.load(Ordering::Relaxed, epoch::unprotected()); + + // Go through the buffer from front to back and drop all tasks in the queue. + let mut i = f; + while i != b { + buffer.deref().at(i).drop_in_place(); + i = i.wrapping_add(1); + } + + // Free the memory allocated by the buffer. + buffer.into_owned().into_box().dealloc(); + } + } +} + +/// Worker queue flavor: FIFO or LIFO. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Flavor { + /// The first-in first-out flavor. + Fifo, + + /// The last-in first-out flavor. + Lifo, +} + +/// A worker queue. +/// +/// This is a FIFO or LIFO queue that is owned by a single thread, but other threads may steal +/// tasks from it. Task schedulers typically create a single worker queue per thread. +/// +/// # Examples +/// +/// A FIFO worker: +/// +/// ``` +/// use crossbeam_deque::{Steal, Worker}; +/// +/// let w = Worker::new_fifo(); +/// let s = w.stealer(); +/// +/// w.push(1); +/// w.push(2); +/// w.push(3); +/// +/// assert_eq!(s.steal(), Steal::Success(1)); +/// assert_eq!(w.pop(), Some(2)); +/// assert_eq!(w.pop(), Some(3)); +/// ``` +/// +/// A LIFO worker: +/// +/// ``` +/// use crossbeam_deque::{Steal, Worker}; +/// +/// let w = Worker::new_lifo(); +/// let s = w.stealer(); +/// +/// w.push(1); +/// w.push(2); +/// w.push(3); +/// +/// assert_eq!(s.steal(), Steal::Success(1)); +/// assert_eq!(w.pop(), Some(3)); +/// assert_eq!(w.pop(), Some(2)); +/// ``` +pub struct Worker { + /// A reference to the inner representation of the queue. + inner: Arc>>, + + /// A copy of `inner.buffer` for quick access. + buffer: Cell>, + + /// The flavor of the queue. + flavor: Flavor, + + /// Indicates that the worker cannot be shared among threads. + _marker: PhantomData<*mut ()>, // !Send + !Sync +} + +unsafe impl Send for Worker {} + +impl Worker { + /// Creates a FIFO worker queue. + /// + /// Tasks are pushed and popped from opposite ends. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::::new_fifo(); + /// ``` + pub fn new_fifo() -> Worker { + let buffer = Buffer::alloc(MIN_CAP); + + let inner = Arc::new(CachePadded::new(Inner { + front: AtomicIsize::new(0), + back: AtomicIsize::new(0), + buffer: CachePadded::new(Atomic::new(buffer)), + })); + + Worker { + inner, + buffer: Cell::new(buffer), + flavor: Flavor::Fifo, + _marker: PhantomData, + } + } + + /// Creates a LIFO worker queue. + /// + /// Tasks are pushed and popped from the same end. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::::new_lifo(); + /// ``` + pub fn new_lifo() -> Worker { + let buffer = Buffer::alloc(MIN_CAP); + + let inner = Arc::new(CachePadded::new(Inner { + front: AtomicIsize::new(0), + back: AtomicIsize::new(0), + buffer: CachePadded::new(Atomic::new(buffer)), + })); + + Worker { + inner, + buffer: Cell::new(buffer), + flavor: Flavor::Lifo, + _marker: PhantomData, + } + } + + /// Creates a stealer for this queue. + /// + /// The returned stealer can be shared among threads and cloned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::::new_lifo(); + /// let s = w.stealer(); + /// ``` + pub fn stealer(&self) -> Stealer { + Stealer { + inner: self.inner.clone(), + flavor: self.flavor, + } + } + + /// Resizes the internal buffer to the new capacity of `new_cap`. + #[cold] + unsafe fn resize(&self, new_cap: usize) { + // Load the back index, front index, and buffer. + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::Relaxed); + let buffer = self.buffer.get(); + + // Allocate a new buffer and copy data from the old buffer to the new one. + let new = Buffer::alloc(new_cap); + let mut i = f; + while i != b { + ptr::copy_nonoverlapping(buffer.at(i), new.at(i), 1); + i = i.wrapping_add(1); + } + + let guard = &epoch::pin(); + + // Replace the old buffer with the new one. + self.buffer.replace(new); + let old = + self.inner + .buffer + .swap(Owned::new(new).into_shared(guard), Ordering::Release, guard); + + // Destroy the old buffer later. + guard.defer_unchecked(move || old.into_owned().into_box().dealloc()); + + // If the buffer is very large, then flush the thread-local garbage in order to deallocate + // it as soon as possible. + if mem::size_of::() * new_cap >= FLUSH_THRESHOLD_BYTES { + guard.flush(); + } + } + + /// Reserves enough capacity so that `reserve_cap` tasks can be pushed without growing the + /// buffer. + fn reserve(&self, reserve_cap: usize) { + if reserve_cap > 0 { + // Compute the current length. + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::SeqCst); + let len = b.wrapping_sub(f) as usize; + + // The current capacity. + let cap = self.buffer.get().cap; + + // Is there enough capacity to push `reserve_cap` tasks? + if cap - len < reserve_cap { + // Keep doubling the capacity as much as is needed. + let mut new_cap = cap * 2; + while new_cap - len < reserve_cap { + new_cap *= 2; + } + + // Resize the buffer. + unsafe { + self.resize(new_cap); + } + } + } + } + + /// Returns `true` if the queue is empty. + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_lifo(); + /// + /// assert!(w.is_empty()); + /// w.push(1); + /// assert!(!w.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::SeqCst); + b.wrapping_sub(f) <= 0 + } + + /// Returns the number of tasks in the deque. + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_lifo(); + /// + /// assert_eq!(w.len(), 0); + /// w.push(1); + /// assert_eq!(w.len(), 1); + /// w.push(1); + /// assert_eq!(w.len(), 2); + /// ``` + pub fn len(&self) -> usize { + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::SeqCst); + b.wrapping_sub(f).max(0) as usize + } + + /// Pushes a task into the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_lifo(); + /// w.push(1); + /// w.push(2); + /// ``` + pub fn push(&self, task: T) { + // Load the back index, front index, and buffer. + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::Acquire); + let mut buffer = self.buffer.get(); + + // Calculate the length of the queue. + let len = b.wrapping_sub(f); + + // Is the queue full? + if len >= buffer.cap as isize { + // Yes. Grow the underlying buffer. + unsafe { + self.resize(2 * buffer.cap); + } + buffer = self.buffer.get(); + } + + // Write `task` into the slot. + unsafe { + buffer.write(b, MaybeUninit::new(task)); + } + + atomic::fence(Ordering::Release); + + // Increment the back index. + // + // This ordering could be `Relaxed`, but then thread sanitizer would falsely report data + // races because it doesn't understand fences. + self.inner.back.store(b.wrapping_add(1), Ordering::Release); + } + + /// Pops a task from the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_fifo(); + /// w.push(1); + /// w.push(2); + /// + /// assert_eq!(w.pop(), Some(1)); + /// assert_eq!(w.pop(), Some(2)); + /// assert_eq!(w.pop(), None); + /// ``` + pub fn pop(&self) -> Option { + // Load the back and front index. + let b = self.inner.back.load(Ordering::Relaxed); + let f = self.inner.front.load(Ordering::Relaxed); + + // Calculate the length of the queue. + let len = b.wrapping_sub(f); + + // Is the queue empty? + if len <= 0 { + return None; + } + + match self.flavor { + // Pop from the front of the queue. + Flavor::Fifo => { + // Try incrementing the front index to pop the task. + let f = self.inner.front.fetch_add(1, Ordering::SeqCst); + let new_f = f.wrapping_add(1); + + if b.wrapping_sub(new_f) < 0 { + self.inner.front.store(f, Ordering::Relaxed); + return None; + } + + unsafe { + // Read the popped task. + let buffer = self.buffer.get(); + let task = buffer.read(f).assume_init(); + + // Shrink the buffer if `len - 1` is less than one fourth of the capacity. + if buffer.cap > MIN_CAP && len <= buffer.cap as isize / 4 { + self.resize(buffer.cap / 2); + } + + Some(task) + } + } + + // Pop from the back of the queue. + Flavor::Lifo => { + // Decrement the back index. + let b = b.wrapping_sub(1); + self.inner.back.store(b, Ordering::Relaxed); + + atomic::fence(Ordering::SeqCst); + + // Load the front index. + let f = self.inner.front.load(Ordering::Relaxed); + + // Compute the length after the back index was decremented. + let len = b.wrapping_sub(f); + + if len < 0 { + // The queue is empty. Restore the back index to the original task. + self.inner.back.store(b.wrapping_add(1), Ordering::Relaxed); + None + } else { + // Read the task to be popped. + let buffer = self.buffer.get(); + let mut task = unsafe { Some(buffer.read(b)) }; + + // Are we popping the last task from the queue? + if len == 0 { + // Try incrementing the front index. + if self + .inner + .front + .compare_exchange( + f, + f.wrapping_add(1), + Ordering::SeqCst, + Ordering::Relaxed, + ) + .is_err() + { + // Failed. We didn't pop anything. Reset to `None`. + task.take(); + } + + // Restore the back index to the original task. + self.inner.back.store(b.wrapping_add(1), Ordering::Relaxed); + } else { + // Shrink the buffer if `len` is less than one fourth of the capacity. + if buffer.cap > MIN_CAP && len < buffer.cap as isize / 4 { + unsafe { + self.resize(buffer.cap / 2); + } + } + } + + task.map(|t| unsafe { t.assume_init() }) + } + } + } + } +} + +impl fmt::Debug for Worker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Worker { .. }") + } +} + +/// A stealer handle of a worker queue. +/// +/// Stealers can be shared among threads. +/// +/// Task schedulers typically have a single worker queue per worker thread. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_deque::{Steal, Worker}; +/// +/// let w = Worker::new_lifo(); +/// w.push(1); +/// w.push(2); +/// +/// let s = w.stealer(); +/// assert_eq!(s.steal(), Steal::Success(1)); +/// assert_eq!(s.steal(), Steal::Success(2)); +/// assert_eq!(s.steal(), Steal::Empty); +/// ``` +pub struct Stealer { + /// A reference to the inner representation of the queue. + inner: Arc>>, + + /// The flavor of the queue. + flavor: Flavor, +} + +unsafe impl Send for Stealer {} +unsafe impl Sync for Stealer {} + +impl Stealer { + /// Returns `true` if the queue is empty. + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_lifo(); + /// let s = w.stealer(); + /// + /// assert!(s.is_empty()); + /// w.push(1); + /// assert!(!s.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + let f = self.inner.front.load(Ordering::Acquire); + atomic::fence(Ordering::SeqCst); + let b = self.inner.back.load(Ordering::Acquire); + b.wrapping_sub(f) <= 0 + } + + /// Returns the number of tasks in the deque. + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w = Worker::new_lifo(); + /// let s = w.stealer(); + /// + /// assert_eq!(s.len(), 0); + /// w.push(1); + /// assert_eq!(s.len(), 1); + /// w.push(2); + /// assert_eq!(s.len(), 2); + /// ``` + pub fn len(&self) -> usize { + let f = self.inner.front.load(Ordering::Acquire); + atomic::fence(Ordering::SeqCst); + let b = self.inner.back.load(Ordering::Acquire); + b.wrapping_sub(f).max(0) as usize + } + + /// Steals a task from the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Steal, Worker}; + /// + /// let w = Worker::new_lifo(); + /// w.push(1); + /// w.push(2); + /// + /// let s = w.stealer(); + /// assert_eq!(s.steal(), Steal::Success(1)); + /// assert_eq!(s.steal(), Steal::Success(2)); + /// ``` + pub fn steal(&self) -> Steal { + // Load the front index. + let f = self.inner.front.load(Ordering::Acquire); + + // A SeqCst fence is needed here. + // + // If the current thread is already pinned (reentrantly), we must manually issue the + // fence. Otherwise, the following pinning will issue the fence anyway, so we don't + // have to. + if epoch::is_pinned() { + atomic::fence(Ordering::SeqCst); + } + + let guard = &epoch::pin(); + + // Load the back index. + let b = self.inner.back.load(Ordering::Acquire); + + // Is the queue empty? + if b.wrapping_sub(f) <= 0 { + return Steal::Empty; + } + + // Load the buffer and read the task at the front. + let buffer = self.inner.buffer.load(Ordering::Acquire, guard); + let task = unsafe { buffer.deref().read(f) }; + + // Try incrementing the front index to steal the task. + // If the buffer has been swapped or the increment fails, we retry. + if self.inner.buffer.load(Ordering::Acquire, guard) != buffer + || self + .inner + .front + .compare_exchange(f, f.wrapping_add(1), Ordering::SeqCst, Ordering::Relaxed) + .is_err() + { + // We didn't steal this task, forget it. + return Steal::Retry; + } + + // Return the stolen task. + Steal::Success(unsafe { task.assume_init() }) + } + + /// Steals a batch of tasks and pushes them into another worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// let _ = s.steal_batch(&w2); + /// assert_eq!(w2.pop(), Some(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// ``` + pub fn steal_batch(&self, dest: &Worker) -> Steal<()> { + self.steal_batch_with_limit(dest, MAX_BATCH) + } + + /// Steals no more than `limit` of tasks and pushes them into another worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// w1.push(5); + /// w1.push(6); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// let _ = s.steal_batch_with_limit(&w2, 2); + /// assert_eq!(w2.pop(), Some(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// assert_eq!(w2.pop(), None); + /// + /// w1.push(7); + /// w1.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// let _ = s.steal_batch_with_limit(&w2, std::usize::MAX); + /// assert_eq!(w2.len(), 3); + /// ``` + pub fn steal_batch_with_limit(&self, dest: &Worker, limit: usize) -> Steal<()> { + assert!(limit > 0); + if Arc::ptr_eq(&self.inner, &dest.inner) { + if dest.is_empty() { + return Steal::Empty; + } else { + return Steal::Success(()); + } + } + + // Load the front index. + let mut f = self.inner.front.load(Ordering::Acquire); + + // A SeqCst fence is needed here. + // + // If the current thread is already pinned (reentrantly), we must manually issue the + // fence. Otherwise, the following pinning will issue the fence anyway, so we don't + // have to. + if epoch::is_pinned() { + atomic::fence(Ordering::SeqCst); + } + + let guard = &epoch::pin(); + + // Load the back index. + let b = self.inner.back.load(Ordering::Acquire); + + // Is the queue empty? + let len = b.wrapping_sub(f); + if len <= 0 { + return Steal::Empty; + } + + // Reserve capacity for the stolen batch. + let batch_size = cmp::min((len as usize + 1) / 2, limit); + dest.reserve(batch_size); + let mut batch_size = batch_size as isize; + + // Get the destination buffer and back index. + let dest_buffer = dest.buffer.get(); + let mut dest_b = dest.inner.back.load(Ordering::Relaxed); + + // Load the buffer. + let buffer = self.inner.buffer.load(Ordering::Acquire, guard); + + match self.flavor { + // Steal a batch of tasks from the front at once. + Flavor::Fifo => { + // Copy the batch from the source to the destination buffer. + match dest.flavor { + Flavor::Fifo => { + for i in 0..batch_size { + unsafe { + let task = buffer.deref().read(f.wrapping_add(i)); + dest_buffer.write(dest_b.wrapping_add(i), task); + } + } + } + Flavor::Lifo => { + for i in 0..batch_size { + unsafe { + let task = buffer.deref().read(f.wrapping_add(i)); + dest_buffer.write(dest_b.wrapping_add(batch_size - 1 - i), task); + } + } + } + } + + // Try incrementing the front index to steal the batch. + // If the buffer has been swapped or the increment fails, we retry. + if self.inner.buffer.load(Ordering::Acquire, guard) != buffer + || self + .inner + .front + .compare_exchange( + f, + f.wrapping_add(batch_size), + Ordering::SeqCst, + Ordering::Relaxed, + ) + .is_err() + { + return Steal::Retry; + } + + dest_b = dest_b.wrapping_add(batch_size); + } + + // Steal a batch of tasks from the front one by one. + Flavor::Lifo => { + // This loop may modify the batch_size, which triggers a clippy lint warning. + // Use a new variable to avoid the warning, and to make it clear we aren't + // modifying the loop exit condition during iteration. + let original_batch_size = batch_size; + + for i in 0..original_batch_size { + // If this is not the first steal, check whether the queue is empty. + if i > 0 { + // We've already got the current front index. Now execute the fence to + // synchronize with other threads. + atomic::fence(Ordering::SeqCst); + + // Load the back index. + let b = self.inner.back.load(Ordering::Acquire); + + // Is the queue empty? + if b.wrapping_sub(f) <= 0 { + batch_size = i; + break; + } + } + + // Read the task at the front. + let task = unsafe { buffer.deref().read(f) }; + + // Try incrementing the front index to steal the task. + // If the buffer has been swapped or the increment fails, we retry. + if self.inner.buffer.load(Ordering::Acquire, guard) != buffer + || self + .inner + .front + .compare_exchange( + f, + f.wrapping_add(1), + Ordering::SeqCst, + Ordering::Relaxed, + ) + .is_err() + { + // We didn't steal this task, forget it and break from the loop. + batch_size = i; + break; + } + + // Write the stolen task into the destination buffer. + unsafe { + dest_buffer.write(dest_b, task); + } + + // Move the source front index and the destination back index one step forward. + f = f.wrapping_add(1); + dest_b = dest_b.wrapping_add(1); + } + + // If we didn't steal anything, the operation needs to be retried. + if batch_size == 0 { + return Steal::Retry; + } + + // If stealing into a FIFO queue, stolen tasks need to be reversed. + if dest.flavor == Flavor::Fifo { + for i in 0..batch_size / 2 { + unsafe { + let i1 = dest_b.wrapping_sub(batch_size - i); + let i2 = dest_b.wrapping_sub(i + 1); + let t1 = dest_buffer.read(i1); + let t2 = dest_buffer.read(i2); + dest_buffer.write(i1, t2); + dest_buffer.write(i2, t1); + } + } + } + } + } + + atomic::fence(Ordering::Release); + + // Update the back index in the destination queue. + // + // This ordering could be `Relaxed`, but then thread sanitizer would falsely report data + // races because it doesn't understand fences. + dest.inner.back.store(dest_b, Ordering::Release); + + // Return with success. + Steal::Success(()) + } + + /// Steals a batch of tasks, pushes them into another worker, and pops a task from that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Steal, Worker}; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// assert_eq!(s.steal_batch_and_pop(&w2), Steal::Success(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// ``` + pub fn steal_batch_and_pop(&self, dest: &Worker) -> Steal { + self.steal_batch_with_limit_and_pop(dest, MAX_BATCH) + } + + /// Steals no more than `limit` of tasks, pushes them into another worker, and pops a task from + /// that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Steal, Worker}; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// w1.push(5); + /// w1.push(6); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, 2), Steal::Success(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// assert_eq!(w2.pop(), None); + /// + /// w1.push(7); + /// w1.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, std::usize::MAX), Steal::Success(3)); + /// assert_eq!(w2.pop(), Some(4)); + /// assert_eq!(w2.pop(), Some(5)); + /// assert_eq!(w2.pop(), None); + /// ``` + pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker, limit: usize) -> Steal { + assert!(limit > 0); + if Arc::ptr_eq(&self.inner, &dest.inner) { + match dest.pop() { + None => return Steal::Empty, + Some(task) => return Steal::Success(task), + } + } + + // Load the front index. + let mut f = self.inner.front.load(Ordering::Acquire); + + // A SeqCst fence is needed here. + // + // If the current thread is already pinned (reentrantly), we must manually issue the + // fence. Otherwise, the following pinning will issue the fence anyway, so we don't + // have to. + if epoch::is_pinned() { + atomic::fence(Ordering::SeqCst); + } + + let guard = &epoch::pin(); + + // Load the back index. + let b = self.inner.back.load(Ordering::Acquire); + + // Is the queue empty? + let len = b.wrapping_sub(f); + if len <= 0 { + return Steal::Empty; + } + + // Reserve capacity for the stolen batch. + let batch_size = cmp::min((len as usize - 1) / 2, limit - 1); + dest.reserve(batch_size); + let mut batch_size = batch_size as isize; + + // Get the destination buffer and back index. + let dest_buffer = dest.buffer.get(); + let mut dest_b = dest.inner.back.load(Ordering::Relaxed); + + // Load the buffer + let buffer = self.inner.buffer.load(Ordering::Acquire, guard); + + // Read the task at the front. + let mut task = unsafe { buffer.deref().read(f) }; + + match self.flavor { + // Steal a batch of tasks from the front at once. + Flavor::Fifo => { + // Copy the batch from the source to the destination buffer. + match dest.flavor { + Flavor::Fifo => { + for i in 0..batch_size { + unsafe { + let task = buffer.deref().read(f.wrapping_add(i + 1)); + dest_buffer.write(dest_b.wrapping_add(i), task); + } + } + } + Flavor::Lifo => { + for i in 0..batch_size { + unsafe { + let task = buffer.deref().read(f.wrapping_add(i + 1)); + dest_buffer.write(dest_b.wrapping_add(batch_size - 1 - i), task); + } + } + } + } + + // Try incrementing the front index to steal the task. + // If the buffer has been swapped or the increment fails, we retry. + if self.inner.buffer.load(Ordering::Acquire, guard) != buffer + || self + .inner + .front + .compare_exchange( + f, + f.wrapping_add(batch_size + 1), + Ordering::SeqCst, + Ordering::Relaxed, + ) + .is_err() + { + // We didn't steal this task, forget it. + return Steal::Retry; + } + + dest_b = dest_b.wrapping_add(batch_size); + } + + // Steal a batch of tasks from the front one by one. + Flavor::Lifo => { + // Try incrementing the front index to steal the task. + if self + .inner + .front + .compare_exchange(f, f.wrapping_add(1), Ordering::SeqCst, Ordering::Relaxed) + .is_err() + { + // We didn't steal this task, forget it. + return Steal::Retry; + } + + // Move the front index one step forward. + f = f.wrapping_add(1); + + // Repeat the same procedure for the batch steals. + // + // This loop may modify the batch_size, which triggers a clippy lint warning. + // Use a new variable to avoid the warning, and to make it clear we aren't + // modifying the loop exit condition during iteration. + let original_batch_size = batch_size; + for i in 0..original_batch_size { + // We've already got the current front index. Now execute the fence to + // synchronize with other threads. + atomic::fence(Ordering::SeqCst); + + // Load the back index. + let b = self.inner.back.load(Ordering::Acquire); + + // Is the queue empty? + if b.wrapping_sub(f) <= 0 { + batch_size = i; + break; + } + + // Read the task at the front. + let tmp = unsafe { buffer.deref().read(f) }; + + // Try incrementing the front index to steal the task. + // If the buffer has been swapped or the increment fails, we retry. + if self.inner.buffer.load(Ordering::Acquire, guard) != buffer + || self + .inner + .front + .compare_exchange( + f, + f.wrapping_add(1), + Ordering::SeqCst, + Ordering::Relaxed, + ) + .is_err() + { + // We didn't steal this task, forget it and break from the loop. + batch_size = i; + break; + } + + // Write the previously stolen task into the destination buffer. + unsafe { + dest_buffer.write(dest_b, mem::replace(&mut task, tmp)); + } + + // Move the source front index and the destination back index one step forward. + f = f.wrapping_add(1); + dest_b = dest_b.wrapping_add(1); + } + + // If stealing into a FIFO queue, stolen tasks need to be reversed. + if dest.flavor == Flavor::Fifo { + for i in 0..batch_size / 2 { + unsafe { + let i1 = dest_b.wrapping_sub(batch_size - i); + let i2 = dest_b.wrapping_sub(i + 1); + let t1 = dest_buffer.read(i1); + let t2 = dest_buffer.read(i2); + dest_buffer.write(i1, t2); + dest_buffer.write(i2, t1); + } + } + } + } + } + + atomic::fence(Ordering::Release); + + // Update the back index in the destination queue. + // + // This ordering could be `Relaxed`, but then thread sanitizer would falsely report data + // races because it doesn't understand fences. + dest.inner.back.store(dest_b, Ordering::Release); + + // Return with success. + Steal::Success(unsafe { task.assume_init() }) + } +} + +impl Clone for Stealer { + fn clone(&self) -> Stealer { + Stealer { + inner: self.inner.clone(), + flavor: self.flavor, + } + } +} + +impl fmt::Debug for Stealer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Stealer { .. }") + } +} + +// Bits indicating the state of a slot: +// * If a task has been written into the slot, `WRITE` is set. +// * If a task has been read from the slot, `READ` is set. +// * If the block is being destroyed, `DESTROY` is set. +const WRITE: usize = 1; +const READ: usize = 2; +const DESTROY: usize = 4; + +// Each block covers one "lap" of indices. +const LAP: usize = 64; +// The maximum number of values a block can hold. +const BLOCK_CAP: usize = LAP - 1; +// How many lower bits are reserved for metadata. +const SHIFT: usize = 1; +// Indicates that the block is not the last one. +const HAS_NEXT: usize = 1; + +/// A slot in a block. +struct Slot { + /// The task. + task: UnsafeCell>, + + /// The state of the slot. + state: AtomicUsize, +} + +impl Slot { + /// Waits until a task is written into the slot. + fn wait_write(&self) { + let backoff = Backoff::new(); + while self.state.load(Ordering::Acquire) & WRITE == 0 { + backoff.snooze(); + } + } +} + +/// A block in a linked list. +/// +/// Each block in the list can hold up to `BLOCK_CAP` values. +struct Block { + /// The next block in the linked list. + next: AtomicPtr>, + + /// Slots for values. + slots: [Slot; BLOCK_CAP], +} + +impl Block { + const LAYOUT: Layout = { + let layout = Layout::new::(); + assert!( + layout.size() != 0, + "Block should never be zero-sized, as it has an AtomicPtr field" + ); + layout + }; + + /// Creates an empty block. + fn new() -> Box { + // SAFETY: layout is not zero-sized + let ptr = unsafe { alloc_zeroed(Self::LAYOUT) }; + // Handle allocation failure + if ptr.is_null() { + handle_alloc_error(Self::LAYOUT) + } + // SAFETY: This is safe because: + // [1] `Block::next` (AtomicPtr) may be safely zero initialized. + // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. + // [3] `Slot::task` (UnsafeCell) may be safely zero initialized because it + // holds a MaybeUninit. + // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. + // TODO: unsafe { Box::new_zeroed().assume_init() } + unsafe { Box::from_raw(ptr.cast()) } + } + + /// Waits until the next pointer is set. + fn wait_next(&self) -> *mut Block { + let backoff = Backoff::new(); + loop { + let next = self.next.load(Ordering::Acquire); + if !next.is_null() { + return next; + } + backoff.snooze(); + } + } + + /// Sets the `DESTROY` bit in slots starting from `start` and destroys the block. + unsafe fn destroy(this: *mut Block, count: usize) { + // It is not necessary to set the `DESTROY` bit in the last slot because that slot has + // begun destruction of the block. + for i in (0..count).rev() { + let slot = (*this).slots.get_unchecked(i); + + // Mark the `DESTROY` bit if a thread is still using the slot. + if slot.state.load(Ordering::Acquire) & READ == 0 + && slot.state.fetch_or(DESTROY, Ordering::AcqRel) & READ == 0 + { + // If a thread is still using the slot, it will continue destruction of the block. + return; + } + } + + // No thread is using the block, now it is safe to destroy it. + drop(Box::from_raw(this)); + } +} + +/// A position in a queue. +struct Position { + /// The index in the queue. + index: AtomicUsize, + + /// The block in the linked list. + block: AtomicPtr>, +} + +/// An injector queue. +/// +/// This is a FIFO queue that can be shared among multiple threads. Task schedulers typically have +/// a single injector queue, which is the entry point for new tasks. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_deque::{Injector, Steal}; +/// +/// let q = Injector::new(); +/// q.push(1); +/// q.push(2); +/// +/// assert_eq!(q.steal(), Steal::Success(1)); +/// assert_eq!(q.steal(), Steal::Success(2)); +/// assert_eq!(q.steal(), Steal::Empty); +/// ``` +pub struct Injector { + /// The head of the queue. + head: CachePadded>, + + /// The tail of the queue. + tail: CachePadded>, + + /// Indicates that dropping a `Injector` may drop values of type `T`. + _marker: PhantomData, +} + +unsafe impl Send for Injector {} +unsafe impl Sync for Injector {} + +impl Default for Injector { + fn default() -> Self { + let block = Box::into_raw(Block::::new()); + Self { + head: CachePadded::new(Position { + block: AtomicPtr::new(block), + index: AtomicUsize::new(0), + }), + tail: CachePadded::new(Position { + block: AtomicPtr::new(block), + index: AtomicUsize::new(0), + }), + _marker: PhantomData, + } + } +} + +impl Injector { + /// Creates a new injector queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Injector; + /// + /// let q = Injector::::new(); + /// ``` + pub fn new() -> Injector { + Self::default() + } + + /// Pushes a task into the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Injector; + /// + /// let w = Injector::new(); + /// w.push(1); + /// w.push(2); + /// ``` + pub fn push(&self, task: T) { + let backoff = Backoff::new(); + let mut tail = self.tail.index.load(Ordering::Acquire); + let mut block = self.tail.block.load(Ordering::Acquire); + let mut next_block = None; + + loop { + // Calculate the offset of the index into the block. + let offset = (tail >> SHIFT) % LAP; + + // If we reached the end of the block, wait until the next one is installed. + if offset == BLOCK_CAP { + backoff.snooze(); + tail = self.tail.index.load(Ordering::Acquire); + block = self.tail.block.load(Ordering::Acquire); + continue; + } + + // If we're going to have to install the next block, allocate it in advance in order to + // make the wait for other threads as short as possible. + if offset + 1 == BLOCK_CAP && next_block.is_none() { + next_block = Some(Block::::new()); + } + + let new_tail = tail + (1 << SHIFT); + + // Try advancing the tail forward. + match self.tail.index.compare_exchange_weak( + tail, + new_tail, + Ordering::SeqCst, + Ordering::Acquire, + ) { + Ok(_) => unsafe { + // If we've reached the end of the block, install the next one. + if offset + 1 == BLOCK_CAP { + let next_block = Box::into_raw(next_block.unwrap()); + let next_index = new_tail.wrapping_add(1 << SHIFT); + + self.tail.block.store(next_block, Ordering::Release); + self.tail.index.store(next_index, Ordering::Release); + (*block).next.store(next_block, Ordering::Release); + } + + // Write the task into the slot. + let slot = (*block).slots.get_unchecked(offset); + slot.task.get().write(MaybeUninit::new(task)); + slot.state.fetch_or(WRITE, Ordering::Release); + + return; + }, + Err(t) => { + tail = t; + block = self.tail.block.load(Ordering::Acquire); + backoff.spin(); + } + } + } + } + + /// Steals a task from the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Steal}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// + /// assert_eq!(q.steal(), Steal::Success(1)); + /// assert_eq!(q.steal(), Steal::Success(2)); + /// assert_eq!(q.steal(), Steal::Empty); + /// ``` + pub fn steal(&self) -> Steal { + let mut head; + let mut block; + let mut offset; + + let backoff = Backoff::new(); + loop { + head = self.head.index.load(Ordering::Acquire); + block = self.head.block.load(Ordering::Acquire); + + // Calculate the offset of the index into the block. + offset = (head >> SHIFT) % LAP; + + // If we reached the end of the block, wait until the next one is installed. + if offset == BLOCK_CAP { + backoff.snooze(); + } else { + break; + } + } + + let mut new_head = head + (1 << SHIFT); + + if new_head & HAS_NEXT == 0 { + atomic::fence(Ordering::SeqCst); + let tail = self.tail.index.load(Ordering::Relaxed); + + // If the tail equals the head, that means the queue is empty. + if head >> SHIFT == tail >> SHIFT { + return Steal::Empty; + } + + // If head and tail are not in the same block, set `HAS_NEXT` in head. + if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP { + new_head |= HAS_NEXT; + } + } + + // Try moving the head index forward. + if self + .head + .index + .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire) + .is_err() + { + return Steal::Retry; + } + + unsafe { + // If we've reached the end of the block, move to the next one. + if offset + 1 == BLOCK_CAP { + let next = (*block).wait_next(); + let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT); + if !(*next).next.load(Ordering::Relaxed).is_null() { + next_index |= HAS_NEXT; + } + + self.head.block.store(next, Ordering::Release); + self.head.index.store(next_index, Ordering::Release); + } + + // Read the task. + let slot = (*block).slots.get_unchecked(offset); + slot.wait_write(); + let task = slot.task.get().read().assume_init(); + + // Destroy the block if we've reached the end, or if another thread wanted to destroy + // but couldn't because we were busy reading from the slot. + if (offset + 1 == BLOCK_CAP) + || (slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0) + { + Block::destroy(block, offset); + } + + Steal::Success(task) + } + } + + /// Steals a batch of tasks and pushes them into a worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// + /// let w = Worker::new_fifo(); + /// let _ = q.steal_batch(&w); + /// assert_eq!(w.pop(), Some(1)); + /// assert_eq!(w.pop(), Some(2)); + /// ``` + pub fn steal_batch(&self, dest: &Worker) -> Steal<()> { + self.steal_batch_with_limit(dest, MAX_BATCH) + } + + /// Steals no more than of tasks and pushes them into a worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// q.push(5); + /// q.push(6); + /// + /// let w = Worker::new_fifo(); + /// let _ = q.steal_batch_with_limit(&w, 2); + /// assert_eq!(w.pop(), Some(1)); + /// assert_eq!(w.pop(), Some(2)); + /// assert_eq!(w.pop(), None); + /// + /// q.push(7); + /// q.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// let _ = q.steal_batch_with_limit(&w, std::usize::MAX); + /// assert_eq!(w.len(), 3); + /// ``` + pub fn steal_batch_with_limit(&self, dest: &Worker, limit: usize) -> Steal<()> { + assert!(limit > 0); + let mut head; + let mut block; + let mut offset; + + let backoff = Backoff::new(); + loop { + head = self.head.index.load(Ordering::Acquire); + block = self.head.block.load(Ordering::Acquire); + + // Calculate the offset of the index into the block. + offset = (head >> SHIFT) % LAP; + + // If we reached the end of the block, wait until the next one is installed. + if offset == BLOCK_CAP { + backoff.snooze(); + } else { + break; + } + } + + let mut new_head = head; + let advance; + + if new_head & HAS_NEXT == 0 { + atomic::fence(Ordering::SeqCst); + let tail = self.tail.index.load(Ordering::Relaxed); + + // If the tail equals the head, that means the queue is empty. + if head >> SHIFT == tail >> SHIFT { + return Steal::Empty; + } + + // If head and tail are not in the same block, set `HAS_NEXT` in head. Also, calculate + // the right batch size to steal. + if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP { + new_head |= HAS_NEXT; + // We can steal all tasks till the end of the block. + advance = (BLOCK_CAP - offset).min(limit); + } else { + let len = (tail - head) >> SHIFT; + // Steal half of the available tasks. + advance = ((len + 1) / 2).min(limit); + } + } else { + // We can steal all tasks till the end of the block. + advance = (BLOCK_CAP - offset).min(limit); + } + + new_head += advance << SHIFT; + let new_offset = offset + advance; + + // Try moving the head index forward. + if self + .head + .index + .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire) + .is_err() + { + return Steal::Retry; + } + + // Reserve capacity for the stolen batch. + let batch_size = new_offset - offset; + dest.reserve(batch_size); + + // Get the destination buffer and back index. + let dest_buffer = dest.buffer.get(); + let dest_b = dest.inner.back.load(Ordering::Relaxed); + + unsafe { + // If we've reached the end of the block, move to the next one. + if new_offset == BLOCK_CAP { + let next = (*block).wait_next(); + let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT); + if !(*next).next.load(Ordering::Relaxed).is_null() { + next_index |= HAS_NEXT; + } + + self.head.block.store(next, Ordering::Release); + self.head.index.store(next_index, Ordering::Release); + } + + // Copy values from the injector into the destination queue. + match dest.flavor { + Flavor::Fifo => { + for i in 0..batch_size { + // Read the task. + let slot = (*block).slots.get_unchecked(offset + i); + slot.wait_write(); + let task = slot.task.get().read(); + + // Write it into the destination queue. + dest_buffer.write(dest_b.wrapping_add(i as isize), task); + } + } + + Flavor::Lifo => { + for i in 0..batch_size { + // Read the task. + let slot = (*block).slots.get_unchecked(offset + i); + slot.wait_write(); + let task = slot.task.get().read(); + + // Write it into the destination queue. + dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task); + } + } + } + + atomic::fence(Ordering::Release); + + // Update the back index in the destination queue. + // + // This ordering could be `Relaxed`, but then thread sanitizer would falsely report + // data races because it doesn't understand fences. + dest.inner + .back + .store(dest_b.wrapping_add(batch_size as isize), Ordering::Release); + + // Destroy the block if we've reached the end, or if another thread wanted to destroy + // but couldn't because we were busy reading from the slot. + if new_offset == BLOCK_CAP { + Block::destroy(block, offset); + } else { + for i in offset..new_offset { + let slot = (*block).slots.get_unchecked(i); + + if slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0 { + Block::destroy(block, offset); + break; + } + } + } + + Steal::Success(()) + } + } + + /// Steals a batch of tasks, pushes them into a worker, and pops a task from that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Steal, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// + /// let w = Worker::new_fifo(); + /// assert_eq!(q.steal_batch_and_pop(&w), Steal::Success(1)); + /// assert_eq!(w.pop(), Some(2)); + /// ``` + pub fn steal_batch_and_pop(&self, dest: &Worker) -> Steal { + // TODO: we use `MAX_BATCH + 1` as the hard limit for Injecter as the performance is slightly + // better, but we may change it in the future to be compatible with the same method in Stealer. + self.steal_batch_with_limit_and_pop(dest, MAX_BATCH + 1) + } + + /// Steals no more than `limit` of tasks, pushes them into a worker, and pops a task from that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Steal, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// q.push(5); + /// q.push(6); + /// + /// let w = Worker::new_fifo(); + /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, 2), Steal::Success(1)); + /// assert_eq!(w.pop(), Some(2)); + /// assert_eq!(w.pop(), None); + /// + /// q.push(7); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, std::usize::MAX), Steal::Success(3)); + /// assert_eq!(w.pop(), Some(4)); + /// assert_eq!(w.pop(), Some(5)); + /// assert_eq!(w.pop(), None); + /// ``` + pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker, limit: usize) -> Steal { + assert!(limit > 0); + let mut head; + let mut block; + let mut offset; + + let backoff = Backoff::new(); + loop { + head = self.head.index.load(Ordering::Acquire); + block = self.head.block.load(Ordering::Acquire); + + // Calculate the offset of the index into the block. + offset = (head >> SHIFT) % LAP; + + // If we reached the end of the block, wait until the next one is installed. + if offset == BLOCK_CAP { + backoff.snooze(); + } else { + break; + } + } + + let mut new_head = head; + let advance; + + if new_head & HAS_NEXT == 0 { + atomic::fence(Ordering::SeqCst); + let tail = self.tail.index.load(Ordering::Relaxed); + + // If the tail equals the head, that means the queue is empty. + if head >> SHIFT == tail >> SHIFT { + return Steal::Empty; + } + + // If head and tail are not in the same block, set `HAS_NEXT` in head. + if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP { + new_head |= HAS_NEXT; + // We can steal all tasks till the end of the block. + advance = (BLOCK_CAP - offset).min(limit); + } else { + let len = (tail - head) >> SHIFT; + // Steal half of the available tasks. + advance = ((len + 1) / 2).min(limit); + } + } else { + // We can steal all tasks till the end of the block. + advance = (BLOCK_CAP - offset).min(limit); + } + + new_head += advance << SHIFT; + let new_offset = offset + advance; + + // Try moving the head index forward. + if self + .head + .index + .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire) + .is_err() + { + return Steal::Retry; + } + + // Reserve capacity for the stolen batch. + let batch_size = new_offset - offset - 1; + dest.reserve(batch_size); + + // Get the destination buffer and back index. + let dest_buffer = dest.buffer.get(); + let dest_b = dest.inner.back.load(Ordering::Relaxed); + + unsafe { + // If we've reached the end of the block, move to the next one. + if new_offset == BLOCK_CAP { + let next = (*block).wait_next(); + let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT); + if !(*next).next.load(Ordering::Relaxed).is_null() { + next_index |= HAS_NEXT; + } + + self.head.block.store(next, Ordering::Release); + self.head.index.store(next_index, Ordering::Release); + } + + // Read the task. + let slot = (*block).slots.get_unchecked(offset); + slot.wait_write(); + let task = slot.task.get().read(); + + match dest.flavor { + Flavor::Fifo => { + // Copy values from the injector into the destination queue. + for i in 0..batch_size { + // Read the task. + let slot = (*block).slots.get_unchecked(offset + i + 1); + slot.wait_write(); + let task = slot.task.get().read(); + + // Write it into the destination queue. + dest_buffer.write(dest_b.wrapping_add(i as isize), task); + } + } + + Flavor::Lifo => { + // Copy values from the injector into the destination queue. + for i in 0..batch_size { + // Read the task. + let slot = (*block).slots.get_unchecked(offset + i + 1); + slot.wait_write(); + let task = slot.task.get().read(); + + // Write it into the destination queue. + dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task); + } + } + } + + atomic::fence(Ordering::Release); + + // Update the back index in the destination queue. + // + // This ordering could be `Relaxed`, but then thread sanitizer would falsely report + // data races because it doesn't understand fences. + dest.inner + .back + .store(dest_b.wrapping_add(batch_size as isize), Ordering::Release); + + // Destroy the block if we've reached the end, or if another thread wanted to destroy + // but couldn't because we were busy reading from the slot. + if new_offset == BLOCK_CAP { + Block::destroy(block, offset); + } else { + for i in offset..new_offset { + let slot = (*block).slots.get_unchecked(i); + + if slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0 { + Block::destroy(block, offset); + break; + } + } + } + + Steal::Success(task.assume_init()) + } + } + + /// Returns `true` if the queue is empty. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Injector; + /// + /// let q = Injector::new(); + /// + /// assert!(q.is_empty()); + /// q.push(1); + /// assert!(!q.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + let head = self.head.index.load(Ordering::SeqCst); + let tail = self.tail.index.load(Ordering::SeqCst); + head >> SHIFT == tail >> SHIFT + } + + /// Returns the number of tasks in the queue. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Injector; + /// + /// let q = Injector::new(); + /// + /// assert_eq!(q.len(), 0); + /// q.push(1); + /// assert_eq!(q.len(), 1); + /// q.push(1); + /// assert_eq!(q.len(), 2); + /// ``` + pub fn len(&self) -> usize { + loop { + // Load the tail index, then load the head index. + let mut tail = self.tail.index.load(Ordering::SeqCst); + let mut head = self.head.index.load(Ordering::SeqCst); + + // If the tail index didn't change, we've got consistent indices to work with. + if self.tail.index.load(Ordering::SeqCst) == tail { + // Erase the lower bits. + tail &= !((1 << SHIFT) - 1); + head &= !((1 << SHIFT) - 1); + + // Fix up indices if they fall onto block ends. + if (tail >> SHIFT) & (LAP - 1) == LAP - 1 { + tail = tail.wrapping_add(1 << SHIFT); + } + if (head >> SHIFT) & (LAP - 1) == LAP - 1 { + head = head.wrapping_add(1 << SHIFT); + } + + // Rotate indices so that head falls into the first block. + let lap = (head >> SHIFT) / LAP; + tail = tail.wrapping_sub((lap * LAP) << SHIFT); + head = head.wrapping_sub((lap * LAP) << SHIFT); + + // Remove the lower bits. + tail >>= SHIFT; + head >>= SHIFT; + + // Return the difference minus the number of blocks between tail and head. + return tail - head - tail / LAP; + } + } + } +} + +impl Drop for Injector { + fn drop(&mut self) { + let mut head = *self.head.index.get_mut(); + let mut tail = *self.tail.index.get_mut(); + let mut block = *self.head.block.get_mut(); + + // Erase the lower bits. + head &= !((1 << SHIFT) - 1); + tail &= !((1 << SHIFT) - 1); + + unsafe { + // Drop all values between `head` and `tail` and deallocate the heap-allocated blocks. + while head != tail { + let offset = (head >> SHIFT) % LAP; + + if offset < BLOCK_CAP { + // Drop the task in the slot. + let slot = (*block).slots.get_unchecked(offset); + (*slot.task.get()).assume_init_drop(); + } else { + // Deallocate the block and move to the next one. + let next = *(*block).next.get_mut(); + drop(Box::from_raw(block)); + block = next; + } + + head = head.wrapping_add(1 << SHIFT); + } + + // Deallocate the last remaining block. + drop(Box::from_raw(block)); + } + } +} + +impl fmt::Debug for Injector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Worker { .. }") + } +} + +/// Possible outcomes of a steal operation. +/// +/// # Examples +/// +/// There are lots of ways to chain results of steal operations together: +/// +/// ``` +/// use crossbeam_deque::Steal::{self, Empty, Retry, Success}; +/// +/// let collect = |v: Vec>| v.into_iter().collect::>(); +/// +/// assert_eq!(collect(vec![Empty, Empty, Empty]), Empty); +/// assert_eq!(collect(vec![Empty, Retry, Empty]), Retry); +/// assert_eq!(collect(vec![Retry, Success(1), Empty]), Success(1)); +/// +/// assert_eq!(collect(vec![Empty, Empty]).or_else(|| Retry), Retry); +/// assert_eq!(collect(vec![Retry, Empty]).or_else(|| Success(1)), Success(1)); +/// ``` +#[must_use] +#[derive(PartialEq, Eq, Copy, Clone)] +pub enum Steal { + /// The queue was empty at the time of stealing. + Empty, + + /// At least one task was successfully stolen. + Success(T), + + /// The steal operation needs to be retried. + Retry, +} + +impl Steal { + /// Returns `true` if the queue was empty at the time of stealing. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Steal::{Empty, Retry, Success}; + /// + /// assert!(!Success(7).is_empty()); + /// assert!(!Retry::.is_empty()); + /// + /// assert!(Empty::.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + match self { + Steal::Empty => true, + _ => false, + } + } + + /// Returns `true` if at least one task was stolen. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Steal::{Empty, Retry, Success}; + /// + /// assert!(!Empty::.is_success()); + /// assert!(!Retry::.is_success()); + /// + /// assert!(Success(7).is_success()); + /// ``` + pub fn is_success(&self) -> bool { + match self { + Steal::Success(_) => true, + _ => false, + } + } + + /// Returns `true` if the steal operation needs to be retried. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Steal::{Empty, Retry, Success}; + /// + /// assert!(!Empty::.is_retry()); + /// assert!(!Success(7).is_retry()); + /// + /// assert!(Retry::.is_retry()); + /// ``` + pub fn is_retry(&self) -> bool { + match self { + Steal::Retry => true, + _ => false, + } + } + + /// Returns the result of the operation, if successful. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Steal::{Empty, Retry, Success}; + /// + /// assert_eq!(Empty::.success(), None); + /// assert_eq!(Retry::.success(), None); + /// + /// assert_eq!(Success(7).success(), Some(7)); + /// ``` + pub fn success(self) -> Option { + match self { + Steal::Success(res) => Some(res), + _ => None, + } + } + + /// If no task was stolen, attempts another steal operation. + /// + /// Returns this steal result if it is `Success`. Otherwise, closure `f` is invoked and then: + /// + /// * If the second steal resulted in `Success`, it is returned. + /// * If both steals were unsuccessful but any resulted in `Retry`, then `Retry` is returned. + /// * If both resulted in `None`, then `None` is returned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Steal::{Empty, Retry, Success}; + /// + /// assert_eq!(Success(1).or_else(|| Success(2)), Success(1)); + /// assert_eq!(Retry.or_else(|| Success(2)), Success(2)); + /// + /// assert_eq!(Retry.or_else(|| Empty), Retry::); + /// assert_eq!(Empty.or_else(|| Retry), Retry::); + /// + /// assert_eq!(Empty.or_else(|| Empty), Empty::); + /// ``` + pub fn or_else(self, f: F) -> Steal + where + F: FnOnce() -> Steal, + { + match self { + Steal::Empty => f(), + Steal::Success(_) => self, + Steal::Retry => { + if let Steal::Success(res) = f() { + Steal::Success(res) + } else { + Steal::Retry + } + } + } + } +} + +impl fmt::Debug for Steal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Steal::Empty => f.pad("Empty"), + Steal::Success(_) => f.pad("Success(..)"), + Steal::Retry => f.pad("Retry"), + } + } +} + +impl FromIterator> for Steal { + /// Consumes items until a `Success` is found and returns it. + /// + /// If no `Success` was found, but there was at least one `Retry`, then returns `Retry`. + /// Otherwise, `Empty` is returned. + fn from_iter(iter: I) -> Steal + where + I: IntoIterator>, + { + let mut retry = false; + for s in iter { + match &s { + Steal::Empty => {} + Steal::Success(_) => return s, + Steal::Retry => retry = true, + } + } + + if retry { + Steal::Retry + } else { + Steal::Empty + } + } +} diff --git a/anneal/v2/vendor/crossbeam-deque/src/lib.rs b/anneal/v2/vendor/crossbeam-deque/src/lib.rs new file mode 100644 index 0000000000..0d856c8541 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/src/lib.rs @@ -0,0 +1,106 @@ +//! Concurrent work-stealing deques. +//! +//! These data structures are most commonly used in work-stealing schedulers. The typical setup +//! involves a number of threads, each having its own FIFO or LIFO queue (*worker*). There is also +//! one global FIFO queue (*injector*) and a list of references to *worker* queues that are able to +//! steal tasks (*stealers*). +//! +//! We spawn a new task onto the scheduler by pushing it into the *injector* queue. Each worker +//! thread waits in a loop until it finds the next task to run and then runs it. To find a task, it +//! first looks into its local *worker* queue, and then into the *injector* and *stealers*. +//! +//! # Queues +//! +//! [`Injector`] is a FIFO queue, where tasks are pushed and stolen from opposite ends. It is +//! shared among threads and is usually the entry point for new tasks. +//! +//! [`Worker`] has two constructors: +//! +//! * [`new_fifo()`] - Creates a FIFO queue, in which tasks are pushed and popped from opposite +//! ends. +//! * [`new_lifo()`] - Creates a LIFO queue, in which tasks are pushed and popped from the same +//! end. +//! +//! Each [`Worker`] is owned by a single thread and supports only push and pop operations. +//! +//! Method [`stealer()`] creates a [`Stealer`] that may be shared among threads and can only steal +//! tasks from its [`Worker`]. Tasks are stolen from the end opposite to where they get pushed. +//! +//! # Stealing +//! +//! Steal operations come in three flavors: +//! +//! 1. [`steal()`] - Steals one task. +//! 2. [`steal_batch()`] - Steals a batch of tasks and moves them into another worker. +//! 3. [`steal_batch_and_pop()`] - Steals a batch of tasks, moves them into another queue, and pops +//! one task from that worker. +//! +//! In contrast to push and pop operations, stealing can spuriously fail with [`Steal::Retry`], in +//! which case the steal operation needs to be retried. +//! +//! # Examples +//! +//! Suppose a thread in a work-stealing scheduler is idle and looking for the next task to run. To +//! find an available task, it might do the following: +//! +//! 1. Try popping one task from the local worker queue. +//! 2. Try stealing a batch of tasks from the global injector queue. +//! 3. Try stealing one task from another thread using the stealer list. +//! +//! An implementation of this work-stealing strategy: +//! +//! ``` +//! use crossbeam_deque::{Injector, Stealer, Worker}; +//! use std::iter; +//! +//! fn find_task( +//! local: &Worker, +//! global: &Injector, +//! stealers: &[Stealer], +//! ) -> Option { +//! // Pop a task from the local queue, if not empty. +//! local.pop().or_else(|| { +//! // Otherwise, we need to look for a task elsewhere. +//! iter::repeat_with(|| { +//! // Try stealing a batch of tasks from the global queue. +//! global.steal_batch_and_pop(local) +//! // Or try stealing a task from one of the other threads. +//! .or_else(|| stealers.iter().map(|s| s.steal()).collect()) +//! }) +//! // Loop while no task was stolen and any steal operation needs to be retried. +//! .find(|s| !s.is_retry()) +//! // Extract the stolen task, if there is one. +//! .and_then(|s| s.success()) +//! }) +//! } +//! ``` +//! +//! [`new_fifo()`]: Worker::new_fifo +//! [`new_lifo()`]: Worker::new_lifo +//! [`stealer()`]: Worker::stealer +//! [`steal()`]: Stealer::steal +//! [`steal_batch()`]: Stealer::steal_batch +//! [`steal_batch_and_pop()`]: Stealer::steal_batch_and_pop + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn( + missing_docs, + missing_debug_implementations, + rust_2018_idioms, + unreachable_pub +)] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "std")] +mod deque; +#[cfg(feature = "std")] +pub use crate::deque::{Injector, Steal, Stealer, Worker}; diff --git a/anneal/v2/vendor/crossbeam-deque/tests/fifo.rs b/anneal/v2/vendor/crossbeam-deque/tests/fifo.rs new file mode 100644 index 0000000000..f98737b58d --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/tests/fifo.rs @@ -0,0 +1,357 @@ +use std::sync::atomic::Ordering::SeqCst; +use std::sync::atomic::{AtomicBool, AtomicUsize}; +use std::sync::{Arc, Mutex}; + +use crossbeam_deque::Steal::{Empty, Success}; +use crossbeam_deque::Worker; +use crossbeam_utils::thread::scope; +use rand::Rng; + +#[test] +fn smoke() { + let w = Worker::new_fifo(); + let s = w.stealer(); + assert_eq!(w.pop(), None); + assert_eq!(s.steal(), Empty); + + w.push(1); + assert_eq!(w.pop(), Some(1)); + assert_eq!(w.pop(), None); + assert_eq!(s.steal(), Empty); + + w.push(2); + assert_eq!(s.steal(), Success(2)); + assert_eq!(s.steal(), Empty); + assert_eq!(w.pop(), None); + + w.push(3); + w.push(4); + w.push(5); + assert_eq!(s.steal(), Success(3)); + assert_eq!(s.steal(), Success(4)); + assert_eq!(s.steal(), Success(5)); + assert_eq!(s.steal(), Empty); + + w.push(6); + w.push(7); + w.push(8); + w.push(9); + assert_eq!(w.pop(), Some(6)); + assert_eq!(s.steal(), Success(7)); + assert_eq!(w.pop(), Some(8)); + assert_eq!(w.pop(), Some(9)); + assert_eq!(w.pop(), None); +} + +#[test] +fn is_empty() { + let w = Worker::new_fifo(); + let s = w.stealer(); + + assert!(w.is_empty()); + w.push(1); + assert!(!w.is_empty()); + w.push(2); + assert!(!w.is_empty()); + let _ = w.pop(); + assert!(!w.is_empty()); + let _ = w.pop(); + assert!(w.is_empty()); + + assert!(s.is_empty()); + w.push(1); + assert!(!s.is_empty()); + w.push(2); + assert!(!s.is_empty()); + let _ = s.steal(); + assert!(!s.is_empty()); + let _ = s.steal(); + assert!(s.is_empty()); +} + +#[test] +fn spsc() { + #[cfg(miri)] + const STEPS: usize = 500; + #[cfg(not(miri))] + const STEPS: usize = 50_000; + + let w = Worker::new_fifo(); + let s = w.stealer(); + + scope(|scope| { + scope.spawn(|_| { + for i in 0..STEPS { + loop { + if let Success(v) = s.steal() { + assert_eq!(i, v); + break; + } + } + } + + assert_eq!(s.steal(), Empty); + }); + + for i in 0..STEPS { + w.push(i); + } + }) + .unwrap(); +} + +#[test] +fn stampede() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let w = Worker::new_fifo(); + + for i in 0..COUNT { + w.push(Box::new(i + 1)); + } + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let remaining = remaining.clone(); + + scope.spawn(move |_| { + let mut last = 0; + while remaining.load(SeqCst) > 0 { + if let Success(x) = s.steal() { + assert!(last < *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + let mut last = 0; + while remaining.load(SeqCst) > 0 { + if let Some(x) = w.pop() { + assert!(last < *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); +} + +#[test] +fn stress() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let w = Worker::new_fifo(); + let done = Arc::new(AtomicBool::new(false)); + let hits = Arc::new(AtomicUsize::new(0)); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let done = done.clone(); + let hits = hits.clone(); + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + + while !done.load(SeqCst) { + if let Success(_) = s.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut expected = 0; + while expected < COUNT { + if rng.gen_range(0..3) == 0 { + while w.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } else { + w.push(expected); + expected += 1; + } + } + + while hits.load(SeqCst) < COUNT { + while w.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[cfg_attr(miri, ignore)] // Miri is too slow +#[test] +fn no_starvation() { + const THREADS: usize = 8; + const COUNT: usize = 50_000; + + let w = Worker::new_fifo(); + let done = Arc::new(AtomicBool::new(false)); + let mut all_hits = Vec::new(); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let done = done.clone(); + let hits = Arc::new(AtomicUsize::new(0)); + all_hits.push(hits.clone()); + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + + while !done.load(SeqCst) { + if let Success(_) = s.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut my_hits = 0; + loop { + for i in 0..rng.gen_range(0..COUNT) { + if rng.gen_range(0..3) == 0 && my_hits == 0 { + while w.pop().is_some() { + my_hits += 1; + } + } else { + w.push(i); + } + } + + if my_hits > 0 && all_hits.iter().all(|h| h.load(SeqCst) > 0) { + break; + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[test] +fn destructors() { + #[cfg(miri)] + const THREADS: usize = 2; + #[cfg(not(miri))] + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + #[cfg(miri)] + const STEPS: usize = 100; + #[cfg(not(miri))] + const STEPS: usize = 1000; + + struct Elem(usize, Arc>>); + + impl Drop for Elem { + fn drop(&mut self) { + self.1.lock().unwrap().push(self.0); + } + } + + let w = Worker::new_fifo(); + let dropped = Arc::new(Mutex::new(Vec::new())); + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + for i in 0..COUNT { + w.push(Elem(i, dropped.clone())); + } + + scope(|scope| { + for _ in 0..THREADS { + let remaining = remaining.clone(); + let s = w.stealer(); + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + let mut cnt = 0; + + while cnt < STEPS { + if let Success(_) = s.steal() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + while w2.pop().is_some() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + for _ in 0..STEPS { + if w.pop().is_some() { + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); + + let rem = remaining.load(SeqCst); + assert!(rem > 0); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), COUNT - rem); + v.clear(); + } + + drop(w); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), rem); + v.sort_unstable(); + for pair in v.windows(2) { + assert_eq!(pair[0] + 1, pair[1]); + } + } +} diff --git a/anneal/v2/vendor/crossbeam-deque/tests/injector.rs b/anneal/v2/vendor/crossbeam-deque/tests/injector.rs new file mode 100644 index 0000000000..5f6c3e98e1 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/tests/injector.rs @@ -0,0 +1,391 @@ +use std::sync::atomic::Ordering::SeqCst; +use std::sync::atomic::{AtomicBool, AtomicUsize}; +use std::sync::{Arc, Mutex}; + +use crossbeam_deque::Steal::{Empty, Success}; +use crossbeam_deque::{Injector, Worker}; +use crossbeam_utils::thread::scope; +use rand::Rng; + +#[test] +fn smoke() { + let q = Injector::new(); + assert_eq!(q.steal(), Empty); + + q.push(1); + q.push(2); + assert_eq!(q.steal(), Success(1)); + assert_eq!(q.steal(), Success(2)); + assert_eq!(q.steal(), Empty); + + q.push(3); + assert_eq!(q.steal(), Success(3)); + assert_eq!(q.steal(), Empty); +} + +#[test] +fn is_empty() { + let q = Injector::new(); + assert!(q.is_empty()); + + q.push(1); + assert!(!q.is_empty()); + q.push(2); + assert!(!q.is_empty()); + + let _ = q.steal(); + assert!(!q.is_empty()); + let _ = q.steal(); + assert!(q.is_empty()); + + q.push(3); + assert!(!q.is_empty()); + let _ = q.steal(); + assert!(q.is_empty()); +} + +#[test] +fn spsc() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + + let q = Injector::new(); + + scope(|scope| { + scope.spawn(|_| { + for i in 0..COUNT { + loop { + if let Success(v) = q.steal() { + assert_eq!(i, v); + break; + } + #[cfg(miri)] + std::hint::spin_loop(); + } + } + + assert_eq!(q.steal(), Empty); + }); + + for i in 0..COUNT { + q.push(i); + } + }) + .unwrap(); +} + +#[test] +fn mpmc() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 25_000; + const THREADS: usize = 4; + + let q = Injector::new(); + let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::>(); + + scope(|scope| { + for _ in 0..THREADS { + scope.spawn(|_| { + for i in 0..COUNT { + q.push(i); + } + }); + } + + for _ in 0..THREADS { + scope.spawn(|_| { + for _ in 0..COUNT { + loop { + if let Success(n) = q.steal() { + v[n].fetch_add(1, SeqCst); + break; + } + #[cfg(miri)] + std::hint::spin_loop(); + } + } + }); + } + }) + .unwrap(); + + for c in v { + assert_eq!(c.load(SeqCst), THREADS); + } +} + +#[test] +fn stampede() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let q = Injector::new(); + + for i in 0..COUNT { + q.push(Box::new(i + 1)); + } + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + scope(|scope| { + for _ in 0..THREADS { + let remaining = remaining.clone(); + let q = &q; + + scope.spawn(move |_| { + let mut last = 0; + while remaining.load(SeqCst) > 0 { + if let Success(x) = q.steal() { + assert!(last < *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + let mut last = 0; + while remaining.load(SeqCst) > 0 { + if let Success(x) = q.steal() { + assert!(last < *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); +} + +#[test] +fn stress() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let q = Injector::new(); + let done = Arc::new(AtomicBool::new(false)); + let hits = Arc::new(AtomicUsize::new(0)); + + scope(|scope| { + for _ in 0..THREADS { + let done = done.clone(); + let hits = hits.clone(); + let q = &q; + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + + while !done.load(SeqCst) { + if let Success(_) = q.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = q.steal_batch(&w2); + + if let Success(_) = q.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut expected = 0; + while expected < COUNT { + if rng.gen_range(0..3) == 0 { + while let Success(_) = q.steal() { + hits.fetch_add(1, SeqCst); + } + } else { + q.push(expected); + expected += 1; + } + } + + while hits.load(SeqCst) < COUNT { + while let Success(_) = q.steal() { + hits.fetch_add(1, SeqCst); + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[cfg_attr(miri, ignore)] // Miri is too slow +#[test] +fn no_starvation() { + const THREADS: usize = 8; + const COUNT: usize = 50_000; + + let q = Injector::new(); + let done = Arc::new(AtomicBool::new(false)); + let mut all_hits = Vec::new(); + + scope(|scope| { + for _ in 0..THREADS { + let done = done.clone(); + let hits = Arc::new(AtomicUsize::new(0)); + all_hits.push(hits.clone()); + let q = &q; + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + + while !done.load(SeqCst) { + if let Success(_) = q.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = q.steal_batch(&w2); + + if let Success(_) = q.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut my_hits = 0; + loop { + for i in 0..rng.gen_range(0..COUNT) { + if rng.gen_range(0..3) == 0 && my_hits == 0 { + while let Success(_) = q.steal() { + my_hits += 1; + } + } else { + q.push(i); + } + } + + if my_hits > 0 && all_hits.iter().all(|h| h.load(SeqCst) > 0) { + break; + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[test] +fn destructors() { + #[cfg(miri)] + const THREADS: usize = 2; + #[cfg(not(miri))] + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + #[cfg(miri)] + const STEPS: usize = 100; + #[cfg(not(miri))] + const STEPS: usize = 1000; + + struct Elem(usize, Arc>>); + + impl Drop for Elem { + fn drop(&mut self) { + self.1.lock().unwrap().push(self.0); + } + } + + let q = Injector::new(); + let dropped = Arc::new(Mutex::new(Vec::new())); + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + for i in 0..COUNT { + q.push(Elem(i, dropped.clone())); + } + + scope(|scope| { + for _ in 0..THREADS { + let remaining = remaining.clone(); + let q = &q; + + scope.spawn(move |_| { + let w2 = Worker::new_fifo(); + let mut cnt = 0; + + while cnt < STEPS { + if let Success(_) = q.steal() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + let _ = q.steal_batch(&w2); + + if let Success(_) = q.steal_batch_and_pop(&w2) { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + while w2.pop().is_some() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + for _ in 0..STEPS { + if let Success(_) = q.steal() { + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); + + let rem = remaining.load(SeqCst); + assert!(rem > 0); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), COUNT - rem); + v.clear(); + } + + drop(q); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), rem); + v.sort_unstable(); + for pair in v.windows(2) { + assert_eq!(pair[0] + 1, pair[1]); + } + } +} + +// If `Block` is created on the stack, the array of slots will multiply this `BigStruct` and +// probably overflow the thread stack. It's now directly created on the heap to avoid this. +#[test] +fn stack_overflow() { + const N: usize = 32_768; + struct BigStruct { + _data: [u8; N], + } + + let q = Injector::new(); + + q.push(BigStruct { _data: [0u8; N] }); + + while !matches!(q.steal(), Empty) {} +} diff --git a/anneal/v2/vendor/crossbeam-deque/tests/lifo.rs b/anneal/v2/vendor/crossbeam-deque/tests/lifo.rs new file mode 100644 index 0000000000..c1a65cd2ef --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/tests/lifo.rs @@ -0,0 +1,359 @@ +use std::sync::atomic::Ordering::SeqCst; +use std::sync::atomic::{AtomicBool, AtomicUsize}; +use std::sync::{Arc, Mutex}; + +use crossbeam_deque::Steal::{Empty, Success}; +use crossbeam_deque::Worker; +use crossbeam_utils::thread::scope; +use rand::Rng; + +#[test] +fn smoke() { + let w = Worker::new_lifo(); + let s = w.stealer(); + assert_eq!(w.pop(), None); + assert_eq!(s.steal(), Empty); + + w.push(1); + assert_eq!(w.pop(), Some(1)); + assert_eq!(w.pop(), None); + assert_eq!(s.steal(), Empty); + + w.push(2); + assert_eq!(s.steal(), Success(2)); + assert_eq!(s.steal(), Empty); + assert_eq!(w.pop(), None); + + w.push(3); + w.push(4); + w.push(5); + assert_eq!(s.steal(), Success(3)); + assert_eq!(s.steal(), Success(4)); + assert_eq!(s.steal(), Success(5)); + assert_eq!(s.steal(), Empty); + + w.push(6); + w.push(7); + w.push(8); + w.push(9); + assert_eq!(w.pop(), Some(9)); + assert_eq!(s.steal(), Success(6)); + assert_eq!(w.pop(), Some(8)); + assert_eq!(w.pop(), Some(7)); + assert_eq!(w.pop(), None); +} + +#[test] +fn is_empty() { + let w = Worker::new_lifo(); + let s = w.stealer(); + + assert!(w.is_empty()); + w.push(1); + assert!(!w.is_empty()); + w.push(2); + assert!(!w.is_empty()); + let _ = w.pop(); + assert!(!w.is_empty()); + let _ = w.pop(); + assert!(w.is_empty()); + + assert!(s.is_empty()); + w.push(1); + assert!(!s.is_empty()); + w.push(2); + assert!(!s.is_empty()); + let _ = s.steal(); + assert!(!s.is_empty()); + let _ = s.steal(); + assert!(s.is_empty()); +} + +#[test] +fn spsc() { + #[cfg(miri)] + const STEPS: usize = 500; + #[cfg(not(miri))] + const STEPS: usize = 50_000; + + let w = Worker::new_lifo(); + let s = w.stealer(); + + scope(|scope| { + scope.spawn(|_| { + for i in 0..STEPS { + loop { + if let Success(v) = s.steal() { + assert_eq!(i, v); + break; + } + #[cfg(miri)] + std::hint::spin_loop(); + } + } + + assert_eq!(s.steal(), Empty); + }); + + for i in 0..STEPS { + w.push(i); + } + }) + .unwrap(); +} + +#[test] +fn stampede() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let w = Worker::new_lifo(); + + for i in 0..COUNT { + w.push(Box::new(i + 1)); + } + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let remaining = remaining.clone(); + + scope.spawn(move |_| { + let mut last = 0; + while remaining.load(SeqCst) > 0 { + if let Success(x) = s.steal() { + assert!(last < *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + let mut last = COUNT + 1; + while remaining.load(SeqCst) > 0 { + if let Some(x) = w.pop() { + assert!(last > *x); + last = *x; + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); +} + +#[test] +fn stress() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + + let w = Worker::new_lifo(); + let done = Arc::new(AtomicBool::new(false)); + let hits = Arc::new(AtomicUsize::new(0)); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let done = done.clone(); + let hits = hits.clone(); + + scope.spawn(move |_| { + let w2 = Worker::new_lifo(); + + while !done.load(SeqCst) { + if let Success(_) = s.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut expected = 0; + while expected < COUNT { + if rng.gen_range(0..3) == 0 { + while w.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } else { + w.push(expected); + expected += 1; + } + } + + while hits.load(SeqCst) < COUNT { + while w.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[cfg_attr(miri, ignore)] // Miri is too slow +#[test] +fn no_starvation() { + const THREADS: usize = 8; + const COUNT: usize = 50_000; + + let w = Worker::new_lifo(); + let done = Arc::new(AtomicBool::new(false)); + let mut all_hits = Vec::new(); + + scope(|scope| { + for _ in 0..THREADS { + let s = w.stealer(); + let done = done.clone(); + let hits = Arc::new(AtomicUsize::new(0)); + all_hits.push(hits.clone()); + + scope.spawn(move |_| { + let w2 = Worker::new_lifo(); + + while !done.load(SeqCst) { + if let Success(_) = s.steal() { + hits.fetch_add(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + hits.fetch_add(1, SeqCst); + } + + while w2.pop().is_some() { + hits.fetch_add(1, SeqCst); + } + } + }); + } + + let mut rng = rand::thread_rng(); + let mut my_hits = 0; + loop { + for i in 0..rng.gen_range(0..COUNT) { + if rng.gen_range(0..3) == 0 && my_hits == 0 { + while w.pop().is_some() { + my_hits += 1; + } + } else { + w.push(i); + } + } + + if my_hits > 0 && all_hits.iter().all(|h| h.load(SeqCst) > 0) { + break; + } + } + done.store(true, SeqCst); + }) + .unwrap(); +} + +#[test] +fn destructors() { + #[cfg(miri)] + const THREADS: usize = 2; + #[cfg(not(miri))] + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 50_000; + #[cfg(miri)] + const STEPS: usize = 100; + #[cfg(not(miri))] + const STEPS: usize = 1000; + + struct Elem(usize, Arc>>); + + impl Drop for Elem { + fn drop(&mut self) { + self.1.lock().unwrap().push(self.0); + } + } + + let w = Worker::new_lifo(); + let dropped = Arc::new(Mutex::new(Vec::new())); + let remaining = Arc::new(AtomicUsize::new(COUNT)); + + for i in 0..COUNT { + w.push(Elem(i, dropped.clone())); + } + + scope(|scope| { + for _ in 0..THREADS { + let remaining = remaining.clone(); + let s = w.stealer(); + + scope.spawn(move |_| { + let w2 = Worker::new_lifo(); + let mut cnt = 0; + + while cnt < STEPS { + if let Success(_) = s.steal() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + let _ = s.steal_batch(&w2); + + if let Success(_) = s.steal_batch_and_pop(&w2) { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + + while w2.pop().is_some() { + cnt += 1; + remaining.fetch_sub(1, SeqCst); + } + } + }); + } + + for _ in 0..STEPS { + if w.pop().is_some() { + remaining.fetch_sub(1, SeqCst); + } + } + }) + .unwrap(); + + let rem = remaining.load(SeqCst); + assert!(rem > 0); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), COUNT - rem); + v.clear(); + } + + drop(w); + + { + let mut v = dropped.lock().unwrap(); + assert_eq!(v.len(), rem); + v.sort_unstable(); + for pair in v.windows(2) { + assert_eq!(pair[0] + 1, pair[1]); + } + } +} diff --git a/anneal/v2/vendor/crossbeam-deque/tests/steal.rs b/anneal/v2/vendor/crossbeam-deque/tests/steal.rs new file mode 100644 index 0000000000..af2499856c --- /dev/null +++ b/anneal/v2/vendor/crossbeam-deque/tests/steal.rs @@ -0,0 +1,212 @@ +use crossbeam_deque::Steal::Success; +use crossbeam_deque::{Injector, Worker}; + +#[test] +fn steal_fifo() { + let w = Worker::new_fifo(); + for i in 1..=3 { + w.push(i); + } + + let s = w.stealer(); + assert_eq!(s.steal(), Success(1)); + assert_eq!(s.steal(), Success(2)); + assert_eq!(s.steal(), Success(3)); +} + +#[test] +fn steal_lifo() { + let w = Worker::new_lifo(); + for i in 1..=3 { + w.push(i); + } + + let s = w.stealer(); + assert_eq!(s.steal(), Success(1)); + assert_eq!(s.steal(), Success(2)); + assert_eq!(s.steal(), Success(3)); +} + +#[test] +fn steal_injector() { + let q = Injector::new(); + for i in 1..=3 { + q.push(i); + } + + assert_eq!(q.steal(), Success(1)); + assert_eq!(q.steal(), Success(2)); + assert_eq!(q.steal(), Success(3)); +} + +#[test] +fn steal_batch_fifo_fifo() { + let w = Worker::new_fifo(); + for i in 1..=4 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_fifo(); + + assert_eq!(s.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(1)); + assert_eq!(w2.pop(), Some(2)); +} + +#[test] +fn steal_batch_lifo_lifo() { + let w = Worker::new_lifo(); + for i in 1..=4 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_lifo(); + + assert_eq!(s.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(1)); +} + +#[test] +fn steal_batch_fifo_lifo() { + let w = Worker::new_fifo(); + for i in 1..=4 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_lifo(); + + assert_eq!(s.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(1)); + assert_eq!(w2.pop(), Some(2)); +} + +#[test] +fn steal_batch_lifo_fifo() { + let w = Worker::new_lifo(); + for i in 1..=4 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_fifo(); + + assert_eq!(s.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(1)); +} + +#[test] +fn steal_batch_injector_fifo() { + let q = Injector::new(); + for i in 1..=4 { + q.push(i); + } + + let w2 = Worker::new_fifo(); + assert_eq!(q.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(1)); + assert_eq!(w2.pop(), Some(2)); +} + +#[test] +fn steal_batch_injector_lifo() { + let q = Injector::new(); + for i in 1..=4 { + q.push(i); + } + + let w2 = Worker::new_lifo(); + assert_eq!(q.steal_batch(&w2), Success(())); + assert_eq!(w2.pop(), Some(1)); + assert_eq!(w2.pop(), Some(2)); +} + +#[test] +fn steal_batch_and_pop_fifo_fifo() { + let w = Worker::new_fifo(); + for i in 1..=6 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_fifo(); + + assert_eq!(s.steal_batch_and_pop(&w2), Success(1)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(3)); +} + +#[test] +fn steal_batch_and_pop_lifo_lifo() { + let w = Worker::new_lifo(); + for i in 1..=6 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_lifo(); + + assert_eq!(s.steal_batch_and_pop(&w2), Success(3)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(1)); +} + +#[test] +fn steal_batch_and_pop_fifo_lifo() { + let w = Worker::new_fifo(); + for i in 1..=6 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_lifo(); + + assert_eq!(s.steal_batch_and_pop(&w2), Success(1)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(3)); +} + +#[test] +fn steal_batch_and_pop_lifo_fifo() { + let w = Worker::new_lifo(); + for i in 1..=6 { + w.push(i); + } + + let s = w.stealer(); + let w2 = Worker::new_fifo(); + + assert_eq!(s.steal_batch_and_pop(&w2), Success(3)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(1)); +} + +#[test] +fn steal_batch_and_pop_injector_fifo() { + let q = Injector::new(); + for i in 1..=6 { + q.push(i); + } + + let w2 = Worker::new_fifo(); + assert_eq!(q.steal_batch_and_pop(&w2), Success(1)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(3)); +} + +#[test] +fn steal_batch_and_pop_injector_lifo() { + let q = Injector::new(); + for i in 1..=6 { + q.push(i); + } + + let w2 = Worker::new_lifo(); + assert_eq!(q.steal_batch_and_pop(&w2), Success(1)); + assert_eq!(w2.pop(), Some(2)); + assert_eq!(w2.pop(), Some(3)); +} diff --git a/anneal/v2/vendor/crossbeam-epoch/.cargo-checksum.json b/anneal/v2/vendor/crossbeam-epoch/.cargo-checksum.json new file mode 100644 index 0000000000..7f83164d8d --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"49529baffd2fd52cbf26931156570b752c8fc679c09a5091ba11c48645c77754","CHANGELOG.md":"678c7c5b4e522345076d63e8f24f7ab4dc9f6b7428ca2f665e4017f7ef24a087","Cargo.lock":"fd85f51f6b4a2dabbb41d9f96775abd21d89221fa01c154afac970c539022f17","Cargo.toml":"cfbceb820c7a1519351826839decd3ff1b1ad54ef2c4dfc4d2c9f173e4726046","Cargo.toml.orig":"b3c80c139498aac55f4caabab81579a87169f6b92156312ebcaec61f5578af9d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"6ba897c52496a66705df72da33dea5f6e0ce5caa87c4ff073b0faf4e05516dad","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","src/atomic.rs":"48b8b02d1e0235b2d87342c13c09d778fba076f79addef32294bed5b8f67b21a","src/collector.rs":"df05c7573413a8f3ac933de7cf941d24bd0ca7341f5923dcad2f811a020c49eb","src/default.rs":"8196e9a2a7a43fdd668177585ba1d4deaec2d16a8a9532f819e4d9afd64ca73d","src/deferred.rs":"092c49e65d5f0ccad8c868b9bcaf431b580c98b7efed98c3797d82d0b9d0c471","src/epoch.rs":"e6813975198df667423c7e1911f7a0f5cb3a917e56080eecd6250d9cca7af950","src/guard.rs":"8db7a20503f55e9e29fc1cf33f99522ec0a5873683ab16638e0e55c917bfc30a","src/internal.rs":"74a15b34b235ab428ffa41cb3a01930e29e3f91e35a288f8f6e0c3c2f56e63f6","src/lib.rs":"3f81f1727c3f74114fbd2f9225a4899834fc254f1444f7c7355901c8fd755494","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/queue.rs":"d4ad500501c52a90b6624dc31196793be09bd19e9c298d5dd7b3ae37bee6b6a8","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-epoch/.cargo_vcs_info.json b/anneal/v2/vendor/crossbeam-epoch/.cargo_vcs_info.json new file mode 100644 index 0000000000..d24fe6d54a --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "9c3182abebb36bdc9446d75d4644190fef70fa01" + }, + "path_in_vcs": "crossbeam-epoch" +} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-epoch/CHANGELOG.md b/anneal/v2/vendor/crossbeam-epoch/CHANGELOG.md new file mode 100644 index 0000000000..d5ca3a0717 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/CHANGELOG.md @@ -0,0 +1,204 @@ +# Version 0.9.18 + +- Remove dependency on `cfg-if`. (#1072) +- Remove dependency on `autocfg`. (#1071) + +# Version 0.9.17 + +- Remove dependency on `memoffset`. (#1058) + +# Version 0.9.16 + +- Bump the minimum supported Rust version to 1.61. (#1037) +- Improve support for targets without atomic CAS. (#1037) +- Remove build script. (#1037) +- Remove dependency on `scopeguard`. (#1045) +- Update `loom` dependency to 0.7. + +# Version 0.9.15 + +- Update `memoffset` to 0.9. (#981) + +# Version 0.9.14 + +- Update `memoffset` to 0.8. (#955) + +# Version 0.9.13 + +- Fix build script bug introduced in 0.9.12. (#932) + +# Version 0.9.12 + +**Note:** This release has been yanked due to regression fixed in 0.9.13. + +- Update `memoffset` to 0.7. (#926) +- Improve support for custom targets. (#922) + +# Version 0.9.11 + +- Removes the dependency on the `once_cell` crate to restore the MSRV. (#913) +- Work around [rust-lang#98302](https://github.com/rust-lang/rust/issues/98302), which causes compile error on windows-gnu when LTO is enabled. (#913) + +# Version 0.9.10 + +- Bump the minimum supported Rust version to 1.38. (#877) +- Mitigate the risk of segmentation faults in buggy downstream implementations. (#879) +- Add `{Atomic, Shared}::try_into_owned` (#701) + +# Version 0.9.9 + +- Replace lazy_static with once_cell. (#817) + +# Version 0.9.8 + +- Make `Atomic::null()` const function at 1.61+. (#797) + +# Version 0.9.7 + +- Fix Miri error when `-Zmiri-check-number-validity` is enabled. (#779) + +# Version 0.9.6 + +- Add `Atomic::fetch_update`. (#706) + +# Version 0.9.5 + +- Fix UB in `Pointable` impl of `[MaybeUninit]`. (#694) +- Support targets that do not have atomic CAS on stable Rust. (#698) +- Fix breakage with nightly feature due to rust-lang/rust#84510. (#692) + +# Version 0.9.4 + +**Note**: This release has been yanked. See [#693](https://github.com/crossbeam-rs/crossbeam/issues/693) for details. + +- Fix UB in `<[MaybeUninit] as Pointable>::init` when global allocator failed allocation. (#690) +- Bump `loom` dependency to version 0.5. (#686) + +# Version 0.9.3 + +**Note**: This release has been yanked. See [#693](https://github.com/crossbeam-rs/crossbeam/issues/693) for details. + +- Make `loom` dependency optional. (#666) + +# Version 0.9.2 + +**Note**: This release has been yanked. See [#693](https://github.com/crossbeam-rs/crossbeam/issues/693) for details. + +- Add `Atomic::compare_exchange` and `Atomic::compare_exchange_weak`. (#628) +- Deprecate `Atomic::compare_and_set` and `Atomic::compare_and_set_weak`. Use `Atomic::compare_exchange` or `Atomic::compare_exchange_weak` instead. (#628) +- Make `const_fn` dependency optional. (#611) +- Add unstable support for `loom`. (#487) + +# Version 0.9.1 + +**Note**: This release has been yanked. See [#693](https://github.com/crossbeam-rs/crossbeam/issues/693) for details. + +- Bump `memoffset` dependency to version 0.6. (#592) + +# Version 0.9.0 + +**Note**: This release has been yanked. See [#693](https://github.com/crossbeam-rs/crossbeam/issues/693) for details. + +- Bump the minimum supported Rust version to 1.36. +- Support dynamically sized types. + +# Version 0.8.2 + +- Fix bug in release (yanking 0.8.1) + +# Version 0.8.1 + +- Bump `autocfg` dependency to version 1.0. (#460) +- Reduce stall in list iteration. (#376) +- Stop stealing from the same deque. (#448) +- Fix unsoundness issues by adopting `MaybeUninit`. (#458) +- Fix use-after-free in lock-free queue. (#466) + +# Version 0.8.0 + +- Bump the minimum required version to 1.28. +- Fix breakage with nightly feature due to rust-lang/rust#65214. +- Make `Atomic::null()` const function at 1.31+. +- Bump `crossbeam-utils` to `0.7`. + +# Version 0.7.2 + +- Add `Atomic::into_owned()`. +- Update `memoffset` dependency. + +# Version 0.7.1 + +- Add `Shared::deref_mut()`. +- Add a Treiber stack to examples. + +# Version 0.7.0 + +- Remove `Guard::clone()`. +- Bump dependencies. + +# Version 0.6.1 + +- Update `crossbeam-utils` to `0.6`. + +# Version 0.6.0 + +- `defer` now requires `F: Send + 'static`. +- Bump the minimum Rust version to 1.26. +- Pinning while TLS is tearing down does not fail anymore. +- Rename `Handle` to `LocalHandle`. +- Add `defer_unchecked` and `defer_destroy`. +- Remove `Clone` impl for `LocalHandle`. + +# Version 0.5.2 + +- Update `crossbeam-utils` to `0.5`. + +# Version 0.5.1 + +- Fix compatibility with the latest Rust nightly. + +# Version 0.5.0 + +- Update `crossbeam-utils` to `0.4`. +- Specify the minimum Rust version to `1.25.0`. + +# Version 0.4.3 + +- Downgrade `crossbeam-utils` to `0.3` because it was a breaking change. + +# Version 0.4.2 + +- Expose the `Pointer` trait. +- Warn missing docs and missing debug impls. +- Update `crossbeam-utils` to `0.4`. + +# Version 0.4.1 + +- Add `Debug` impls for `Collector`, `Handle`, and `Guard`. +- Add `load_consume` to `Atomic`. +- Rename `Collector::handle` to `Collector::register`. +- Remove the `Send` implementation for `Handle` (this was a bug). Only + `Collector`s can be shared among multiple threads, while `Handle`s and + `Guard`s must stay within the thread in which they were created. + +# Version 0.4.0 + +- Update dependencies. +- Remove support for Rust 1.13. + +# Version 0.3.0 + +- Add support for Rust 1.13. +- Improve documentation for CAS. + +# Version 0.2.0 + +- Add method `Owned::into_box`. +- Fix a use-after-free bug in `Local::finalize`. +- Fix an ordering bug in `Global::push_bag`. +- Fix a bug in calculating distance between epochs. +- Remove `impl Into> for Owned`. + +# Version 0.1.0 + +- First version of the new epoch-based GC. diff --git a/anneal/v2/vendor/crossbeam-epoch/Cargo.lock b/anneal/v2/vendor/crossbeam-epoch/Cargo.lock new file mode 100644 index 0000000000..3a2c62417b --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/Cargo.lock @@ -0,0 +1,457 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +dependencies = [ + "crossbeam-utils", + "loom", + "rand", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" +dependencies = [ + "cfg-if", + "loom", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "loom" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e045d70ddfbc984eacfa964ded019534e8f6cbf36f6410aee0ed5cefa5a9175" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[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" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/anneal/v2/vendor/crossbeam-epoch/Cargo.toml b/anneal/v2/vendor/crossbeam-epoch/Cargo.toml new file mode 100644 index 0000000000..0a8fc81cf5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/Cargo.toml @@ -0,0 +1,57 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.61" +name = "crossbeam-epoch" +version = "0.9.18" +description = "Epoch-based garbage collection" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch" +readme = "README.md" +keywords = [ + "lock-free", + "rcu", + "atomic", + "garbage", +] +categories = [ + "concurrency", + "memory-management", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" + +[dependencies.crossbeam-utils] +version = "0.8.18" +default-features = false + +[dev-dependencies.rand] +version = "0.8" + +[features] +alloc = [] +default = ["std"] +loom = [ + "loom-crate", + "crossbeam-utils/loom", +] +nightly = ["crossbeam-utils/nightly"] +std = [ + "alloc", + "crossbeam-utils/std", +] + +[target."cfg(crossbeam_loom)".dependencies.loom-crate] +version = "0.7.1" +optional = true +package = "loom" diff --git a/anneal/v2/vendor/crossbeam-epoch/Cargo.toml.orig b/anneal/v2/vendor/crossbeam-epoch/Cargo.toml.orig new file mode 100644 index 0000000000..0f87aed708 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/Cargo.toml.orig @@ -0,0 +1,56 @@ +[package] +name = "crossbeam-epoch" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md +# - Create "crossbeam-epoch-X.Y.Z" git tag +version = "0.9.18" +edition = "2021" +rust-version = "1.61" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch" +description = "Epoch-based garbage collection" +keywords = ["lock-free", "rcu", "atomic", "garbage"] +categories = ["concurrency", "memory-management", "no-std"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +std = ["alloc", "crossbeam-utils/std"] + +# Enable to use APIs that require `alloc`. +# This is enabled by default and also enabled if the `std` feature is enabled. +# +# NOTE: Disabling both `std` *and* `alloc` features is not supported yet. +alloc = [] + +# These features are no longer used. +# TODO: remove in the next major version. +# Enable to use of unstable functionality. +# This is disabled by default and requires recent nightly compiler. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +nightly = ["crossbeam-utils/nightly"] + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +loom = ["loom-crate", "crossbeam-utils/loom"] + +[dependencies] +crossbeam-utils = { version = "0.8.18", path = "../crossbeam-utils", default-features = false } + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +[target.'cfg(crossbeam_loom)'.dependencies] +loom-crate = { package = "loom", version = "0.7.1", optional = true } + +[dev-dependencies] +rand = "0.8" diff --git a/anneal/v2/vendor/crossbeam-epoch/LICENSE-APACHE b/anneal/v2/vendor/crossbeam-epoch/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/crossbeam-epoch/LICENSE-MIT b/anneal/v2/vendor/crossbeam-epoch/LICENSE-MIT new file mode 100644 index 0000000000..068d491fd5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/LICENSE-MIT @@ -0,0 +1,27 @@ +The MIT License (MIT) + +Copyright (c) 2019 The Crossbeam Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/crossbeam-epoch/README.md b/anneal/v2/vendor/crossbeam-epoch/README.md new file mode 100644 index 0000000000..ba74c7c75b --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/README.md @@ -0,0 +1,53 @@ +# Crossbeam Epoch + +[![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)]( +https://github.com/crossbeam-rs/crossbeam/actions) +[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)]( +https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch#license) +[![Cargo](https://img.shields.io/crates/v/crossbeam-epoch.svg)]( +https://crates.io/crates/crossbeam-epoch) +[![Documentation](https://docs.rs/crossbeam-epoch/badge.svg)]( +https://docs.rs/crossbeam-epoch) +[![Rust 1.61+](https://img.shields.io/badge/rust-1.61+-lightgray.svg)]( +https://www.rust-lang.org) +[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) + +This crate provides epoch-based garbage collection for building concurrent data structures. + +When a thread removes an object from a concurrent data structure, other threads +may be still using pointers to it at the same time, so it cannot be destroyed +immediately. Epoch-based GC is an efficient mechanism for deferring destruction of +shared objects until no pointers to them can exist. + +Everything in this crate except the global GC can be used in `no_std` environments, provided that +`alloc` feature is enabled. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +crossbeam-epoch = "0.9" +``` + +## Compatibility + +Crossbeam Epoch supports stable Rust releases going back at least six months, +and every time the minimum supported Rust version is increased, a new minor +version is released. Currently, the minimum supported Rust version is 1.61. + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +#### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/crossbeam-epoch/benches/defer.rs b/anneal/v2/vendor/crossbeam-epoch/benches/defer.rs new file mode 100644 index 0000000000..246f907988 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/benches/defer.rs @@ -0,0 +1,69 @@ +#![feature(test)] + +extern crate test; + +use crossbeam_epoch::{self as epoch, Owned}; +use crossbeam_utils::thread::scope; +use test::Bencher; + +#[bench] +fn single_alloc_defer_free(b: &mut Bencher) { + b.iter(|| { + let guard = &epoch::pin(); + let p = Owned::new(1).into_shared(guard); + unsafe { + guard.defer_destroy(p); + } + }); +} + +#[bench] +fn single_defer(b: &mut Bencher) { + b.iter(|| { + let guard = &epoch::pin(); + guard.defer(move || ()); + }); +} + +#[bench] +fn multi_alloc_defer_free(b: &mut Bencher) { + const THREADS: usize = 16; + const STEPS: usize = 10_000; + + b.iter(|| { + scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + for _ in 0..STEPS { + let guard = &epoch::pin(); + let p = Owned::new(1).into_shared(guard); + unsafe { + guard.defer_destroy(p); + } + } + }); + } + }) + .unwrap(); + }); +} + +#[bench] +fn multi_defer(b: &mut Bencher) { + const THREADS: usize = 16; + const STEPS: usize = 10_000; + + b.iter(|| { + scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + for _ in 0..STEPS { + let guard = &epoch::pin(); + guard.defer(move || ()); + } + }); + } + }) + .unwrap(); + }); +} diff --git a/anneal/v2/vendor/crossbeam-epoch/benches/flush.rs b/anneal/v2/vendor/crossbeam-epoch/benches/flush.rs new file mode 100644 index 0000000000..99aab19e1e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/benches/flush.rs @@ -0,0 +1,52 @@ +#![feature(test)] + +extern crate test; + +use std::sync::Barrier; + +use crossbeam_epoch as epoch; +use crossbeam_utils::thread::scope; +use test::Bencher; + +#[bench] +fn single_flush(b: &mut Bencher) { + const THREADS: usize = 16; + + let start = Barrier::new(THREADS + 1); + let end = Barrier::new(THREADS + 1); + + scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + epoch::pin(); + start.wait(); + end.wait(); + }); + } + + start.wait(); + b.iter(|| epoch::pin().flush()); + end.wait(); + }) + .unwrap(); +} + +#[bench] +fn multi_flush(b: &mut Bencher) { + const THREADS: usize = 16; + const STEPS: usize = 10_000; + + b.iter(|| { + scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + for _ in 0..STEPS { + let guard = &epoch::pin(); + guard.flush(); + } + }); + } + }) + .unwrap(); + }); +} diff --git a/anneal/v2/vendor/crossbeam-epoch/benches/pin.rs b/anneal/v2/vendor/crossbeam-epoch/benches/pin.rs new file mode 100644 index 0000000000..8bf87e9b73 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/benches/pin.rs @@ -0,0 +1,31 @@ +#![feature(test)] + +extern crate test; + +use crossbeam_epoch as epoch; +use crossbeam_utils::thread::scope; +use test::Bencher; + +#[bench] +fn single_pin(b: &mut Bencher) { + b.iter(epoch::pin); +} + +#[bench] +fn multi_pin(b: &mut Bencher) { + const THREADS: usize = 16; + const STEPS: usize = 100_000; + + b.iter(|| { + scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + for _ in 0..STEPS { + epoch::pin(); + } + }); + } + }) + .unwrap(); + }); +} diff --git a/anneal/v2/vendor/crossbeam-epoch/examples/sanitize.rs b/anneal/v2/vendor/crossbeam-epoch/examples/sanitize.rs new file mode 100644 index 0000000000..4109c34a8c --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/examples/sanitize.rs @@ -0,0 +1,66 @@ +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed}; +use std::sync::Arc; +use std::thread; +use std::time::{Duration, Instant}; + +use crossbeam_epoch::{self as epoch, Atomic, Collector, LocalHandle, Owned, Shared}; +use rand::Rng; + +fn worker(a: Arc>, handle: LocalHandle) -> usize { + let mut rng = rand::thread_rng(); + let mut sum = 0; + + if rng.gen() { + thread::sleep(Duration::from_millis(1)); + } + let timeout = Duration::from_millis(rng.gen_range(0..10)); + let now = Instant::now(); + + while now.elapsed() < timeout { + for _ in 0..100 { + let guard = &handle.pin(); + guard.flush(); + + let val = if rng.gen() { + let p = a.swap(Owned::new(AtomicUsize::new(sum)), AcqRel, guard); + unsafe { + guard.defer_destroy(p); + guard.flush(); + p.deref().load(Relaxed) + } + } else { + let p = a.load(Acquire, guard); + unsafe { p.deref().fetch_add(sum, Relaxed) } + }; + + sum = sum.wrapping_add(val); + } + } + + sum +} + +fn main() { + for _ in 0..100 { + let collector = Collector::new(); + let a = Arc::new(Atomic::new(AtomicUsize::new(777))); + + let threads = (0..16) + .map(|_| { + let a = a.clone(); + let c = collector.clone(); + thread::spawn(move || worker(a, c.register())) + }) + .collect::>(); + + for t in threads { + t.join().unwrap(); + } + + unsafe { + a.swap(Shared::null(), AcqRel, epoch::unprotected()) + .into_owned(); + } + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/atomic.rs b/anneal/v2/vendor/crossbeam-epoch/src/atomic.rs new file mode 100644 index 0000000000..41b4cd9102 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/atomic.rs @@ -0,0 +1,1702 @@ +use alloc::boxed::Box; +use core::alloc::Layout; +use core::borrow::{Borrow, BorrowMut}; +use core::cmp; +use core::fmt; +use core::marker::PhantomData; +use core::mem::{self, MaybeUninit}; +use core::ops::{Deref, DerefMut}; +use core::ptr; +use core::slice; + +use crate::guard::Guard; +use crate::primitive::sync::atomic::{AtomicUsize, Ordering}; +use crossbeam_utils::atomic::AtomicConsume; + +/// Given ordering for the success case in a compare-exchange operation, returns the strongest +/// appropriate ordering for the failure case. +#[inline] +fn strongest_failure_ordering(ord: Ordering) -> Ordering { + use self::Ordering::*; + match ord { + Relaxed | Release => Relaxed, + Acquire | AcqRel => Acquire, + _ => SeqCst, + } +} + +/// The error returned on failed compare-and-set operation. +// TODO: remove in the next major version. +#[deprecated(note = "Use `CompareExchangeError` instead")] +pub type CompareAndSetError<'g, T, P> = CompareExchangeError<'g, T, P>; + +/// The error returned on failed compare-and-swap operation. +pub struct CompareExchangeError<'g, T: ?Sized + Pointable, P: Pointer> { + /// The value in the atomic pointer at the time of the failed operation. + pub current: Shared<'g, T>, + + /// The new value, which the operation failed to store. + pub new: P, +} + +impl + fmt::Debug> fmt::Debug for CompareExchangeError<'_, T, P> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CompareExchangeError") + .field("current", &self.current) + .field("new", &self.new) + .finish() + } +} + +/// Memory orderings for compare-and-set operations. +/// +/// A compare-and-set operation can have different memory orderings depending on whether it +/// succeeds or fails. This trait generalizes different ways of specifying memory orderings. +/// +/// The two ways of specifying orderings for compare-and-set are: +/// +/// 1. Just one `Ordering` for the success case. In case of failure, the strongest appropriate +/// ordering is chosen. +/// 2. A pair of `Ordering`s. The first one is for the success case, while the second one is +/// for the failure case. +// TODO: remove in the next major version. +#[deprecated( + note = "`compare_and_set` and `compare_and_set_weak` that use this trait are deprecated, \ + use `compare_exchange` or `compare_exchange_weak instead`" +)] +pub trait CompareAndSetOrdering { + /// The ordering of the operation when it succeeds. + fn success(&self) -> Ordering; + + /// The ordering of the operation when it fails. + /// + /// The failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than + /// the success ordering. + fn failure(&self) -> Ordering; +} + +#[allow(deprecated)] +impl CompareAndSetOrdering for Ordering { + #[inline] + fn success(&self) -> Ordering { + *self + } + + #[inline] + fn failure(&self) -> Ordering { + strongest_failure_ordering(*self) + } +} + +#[allow(deprecated)] +impl CompareAndSetOrdering for (Ordering, Ordering) { + #[inline] + fn success(&self) -> Ordering { + self.0 + } + + #[inline] + fn failure(&self) -> Ordering { + self.1 + } +} + +/// Returns a bitmask containing the unused least significant bits of an aligned pointer to `T`. +#[inline] +fn low_bits() -> usize { + (1 << T::ALIGN.trailing_zeros()) - 1 +} + +/// Panics if the pointer is not properly unaligned. +#[inline] +fn ensure_aligned(raw: usize) { + assert_eq!(raw & low_bits::(), 0, "unaligned pointer"); +} + +/// Given a tagged pointer `data`, returns the same pointer, but tagged with `tag`. +/// +/// `tag` is truncated to fit into the unused bits of the pointer to `T`. +#[inline] +fn compose_tag(data: usize, tag: usize) -> usize { + (data & !low_bits::()) | (tag & low_bits::()) +} + +/// Decomposes a tagged pointer `data` into the pointer and the tag. +#[inline] +fn decompose_tag(data: usize) -> (usize, usize) { + (data & !low_bits::(), data & low_bits::()) +} + +/// Types that are pointed to by a single word. +/// +/// In concurrent programming, it is necessary to represent an object within a word because atomic +/// operations (e.g., reads, writes, read-modify-writes) support only single words. This trait +/// qualifies such types that are pointed to by a single word. +/// +/// The trait generalizes `Box` for a sized type `T`. In a box, an object of type `T` is +/// allocated in heap and it is owned by a single-word pointer. This trait is also implemented for +/// `[MaybeUninit]` by storing its size along with its elements and pointing to the pair of array +/// size and elements. +/// +/// Pointers to `Pointable` types can be stored in [`Atomic`], [`Owned`], and [`Shared`]. In +/// particular, Crossbeam supports dynamically sized slices as follows. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// use crossbeam_epoch::Owned; +/// +/// let o = Owned::<[MaybeUninit]>::init(10); // allocating [i32; 10] +/// ``` +pub trait Pointable { + /// The alignment of pointer. + const ALIGN: usize; + + /// The type for initializers. + type Init; + + /// Initializes a with the given initializer. + /// + /// # Safety + /// + /// The result should be a multiple of `ALIGN`. + unsafe fn init(init: Self::Init) -> usize; + + /// Dereferences the given pointer. + /// + /// # Safety + /// + /// - The given `ptr` should have been initialized with [`Pointable::init`]. + /// - `ptr` should not have yet been dropped by [`Pointable::drop`]. + /// - `ptr` should not be mutably dereferenced by [`Pointable::deref_mut`] concurrently. + unsafe fn deref<'a>(ptr: usize) -> &'a Self; + + /// Mutably dereferences the given pointer. + /// + /// # Safety + /// + /// - The given `ptr` should have been initialized with [`Pointable::init`]. + /// - `ptr` should not have yet been dropped by [`Pointable::drop`]. + /// - `ptr` should not be dereferenced by [`Pointable::deref`] or [`Pointable::deref_mut`] + /// concurrently. + unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self; + + /// Drops the object pointed to by the given pointer. + /// + /// # Safety + /// + /// - The given `ptr` should have been initialized with [`Pointable::init`]. + /// - `ptr` should not have yet been dropped by [`Pointable::drop`]. + /// - `ptr` should not be dereferenced by [`Pointable::deref`] or [`Pointable::deref_mut`] + /// concurrently. + unsafe fn drop(ptr: usize); +} + +impl Pointable for T { + const ALIGN: usize = mem::align_of::(); + + type Init = T; + + unsafe fn init(init: Self::Init) -> usize { + Box::into_raw(Box::new(init)) as usize + } + + unsafe fn deref<'a>(ptr: usize) -> &'a Self { + &*(ptr as *const T) + } + + unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self { + &mut *(ptr as *mut T) + } + + unsafe fn drop(ptr: usize) { + drop(Box::from_raw(ptr as *mut T)); + } +} + +/// Array with size. +/// +/// # Memory layout +/// +/// An array consisting of size and elements: +/// +/// ```text +/// elements +/// | +/// | +/// ------------------------------------ +/// | size | 0 | 1 | 2 | 3 | 4 | 5 | 6 | +/// ------------------------------------ +/// ``` +/// +/// Its memory layout is different from that of `Box<[T]>` in that size is in the allocation (not +/// along with pointer as in `Box<[T]>`). +/// +/// Elements are not present in the type, but they will be in the allocation. +/// ``` +#[repr(C)] +struct Array { + /// The number of elements (not the number of bytes). + len: usize, + elements: [MaybeUninit; 0], +} + +impl Array { + fn layout(len: usize) -> Layout { + Layout::new::() + .extend(Layout::array::>(len).unwrap()) + .unwrap() + .0 + .pad_to_align() + } +} + +impl Pointable for [MaybeUninit] { + const ALIGN: usize = mem::align_of::>(); + + type Init = usize; + + unsafe fn init(len: Self::Init) -> usize { + let layout = Array::::layout(len); + let ptr = alloc::alloc::alloc(layout).cast::>(); + if ptr.is_null() { + alloc::alloc::handle_alloc_error(layout); + } + ptr::addr_of_mut!((*ptr).len).write(len); + ptr as usize + } + + unsafe fn deref<'a>(ptr: usize) -> &'a Self { + let array = &*(ptr as *const Array); + slice::from_raw_parts(array.elements.as_ptr() as *const _, array.len) + } + + unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self { + let array = &*(ptr as *mut Array); + slice::from_raw_parts_mut(array.elements.as_ptr() as *mut _, array.len) + } + + unsafe fn drop(ptr: usize) { + let len = (*(ptr as *mut Array)).len; + let layout = Array::::layout(len); + alloc::alloc::dealloc(ptr as *mut u8, layout); + } +} + +/// An atomic pointer that can be safely shared between threads. +/// +/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused +/// least significant bits of the address. For example, the tag for a pointer to a sized type `T` +/// should be less than `(1 << mem::align_of::().trailing_zeros())`. +/// +/// Any method that loads the pointer must be passed a reference to a [`Guard`]. +/// +/// Crossbeam supports dynamically sized types. See [`Pointable`] for details. +pub struct Atomic { + data: AtomicUsize, + _marker: PhantomData<*mut T>, +} + +unsafe impl Send for Atomic {} +unsafe impl Sync for Atomic {} + +impl Atomic { + /// Allocates `value` on the heap and returns a new atomic pointer pointing to it. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Atomic; + /// + /// let a = Atomic::new(1234); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn new(init: T) -> Atomic { + Self::init(init) + } +} + +impl Atomic { + /// Allocates `value` on the heap and returns a new atomic pointer pointing to it. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Atomic; + /// + /// let a = Atomic::::init(1234); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn init(init: T::Init) -> Atomic { + Self::from(Owned::init(init)) + } + + /// Returns a new atomic pointer pointing to the tagged pointer `data`. + fn from_usize(data: usize) -> Self { + Self { + data: AtomicUsize::new(data), + _marker: PhantomData, + } + } + + /// Returns a new null atomic pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Atomic; + /// + /// let a = Atomic::::null(); + /// ``` + #[cfg(not(crossbeam_loom))] + pub const fn null() -> Atomic { + Self { + data: AtomicUsize::new(0), + _marker: PhantomData, + } + } + /// Returns a new null atomic pointer. + #[cfg(crossbeam_loom)] + pub fn null() -> Atomic { + Self { + data: AtomicUsize::new(0), + _marker: PhantomData, + } + } + + /// Loads a `Shared` from the atomic pointer. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// let p = a.load(SeqCst, guard); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn load<'g>(&self, ord: Ordering, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.load(ord)) } + } + + /// Loads a `Shared` from the atomic pointer using a "consume" memory ordering. + /// + /// This is similar to the "acquire" ordering, except that an ordering is + /// only guaranteed with operations that "depend on" the result of the load. + /// However consume loads are usually much faster than acquire loads on + /// architectures with a weak memory model since they don't require memory + /// fence instructions. + /// + /// The exact definition of "depend on" is a bit vague, but it works as you + /// would expect in practice since a lot of software, especially the Linux + /// kernel, rely on this behavior. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// let p = a.load_consume(guard); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn load_consume<'g>(&self, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.load_consume()) } + } + + /// Stores a `Shared` or `Owned` pointer into the atomic pointer. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{Atomic, Owned, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// # unsafe { drop(a.load(SeqCst, &crossbeam_epoch::pin()).into_owned()); } // avoid leak + /// a.store(Shared::null(), SeqCst); + /// a.store(Owned::new(1234), SeqCst); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn store>(&self, new: P, ord: Ordering) { + self.data.store(new.into_usize(), ord); + } + + /// Stores a `Shared` or `Owned` pointer into the atomic pointer, returning the previous + /// `Shared`. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// let p = a.swap(Shared::null(), SeqCst, guard); + /// # unsafe { drop(p.into_owned()); } // avoid leak + /// ``` + pub fn swap<'g, P: Pointer>(&self, new: P, ord: Ordering, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.swap(new.into_usize(), ord)) } + } + + /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current + /// value is the same as `current`. The tag is also taken into account, so two pointers to the + /// same object, but with different tags, will not be considered equal. + /// + /// The return value is a result indicating whether the new pointer was written. On success the + /// pointer that was written is returned. On failure the actual current value and `new` are + /// returned. + /// + /// This method takes two `Ordering` arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using `Acquire` as success ordering makes the store part + /// of this operation `Relaxed`, and using `Release` makes the successful load + /// `Relaxed`. The failure ordering can only be `SeqCst`, `Acquire` or `Relaxed` + /// and must be equivalent to or weaker than the success ordering. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// + /// let guard = &epoch::pin(); + /// let curr = a.load(SeqCst, guard); + /// let res1 = a.compare_exchange(curr, Shared::null(), SeqCst, SeqCst, guard); + /// let res2 = a.compare_exchange(curr, Owned::new(5678), SeqCst, SeqCst, guard); + /// # unsafe { drop(curr.into_owned()); } // avoid leak + /// ``` + pub fn compare_exchange<'g, P>( + &self, + current: Shared<'_, T>, + new: P, + success: Ordering, + failure: Ordering, + _: &'g Guard, + ) -> Result, CompareExchangeError<'g, T, P>> + where + P: Pointer, + { + let new = new.into_usize(); + self.data + .compare_exchange(current.into_usize(), new, success, failure) + .map(|_| unsafe { Shared::from_usize(new) }) + .map_err(|current| unsafe { + CompareExchangeError { + current: Shared::from_usize(current), + new: P::from_usize(new), + } + }) + } + + /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current + /// value is the same as `current`. The tag is also taken into account, so two pointers to the + /// same object, but with different tags, will not be considered equal. + /// + /// Unlike [`compare_exchange`], this method is allowed to spuriously fail even when comparison + /// succeeds, which can result in more efficient code on some platforms. The return value is a + /// result indicating whether the new pointer was written. On success the pointer that was + /// written is returned. On failure the actual current value and `new` are returned. + /// + /// This method takes two `Ordering` arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using `Acquire` as success ordering makes the store part + /// of this operation `Relaxed`, and using `Release` makes the successful load + /// `Relaxed`. The failure ordering can only be `SeqCst`, `Acquire` or `Relaxed` + /// and must be equivalent to or weaker than the success ordering. + /// + /// [`compare_exchange`]: Atomic::compare_exchange + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// + /// let mut new = Owned::new(5678); + /// let mut ptr = a.load(SeqCst, guard); + /// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak + /// loop { + /// match a.compare_exchange_weak(ptr, new, SeqCst, SeqCst, guard) { + /// Ok(p) => { + /// ptr = p; + /// break; + /// } + /// Err(err) => { + /// ptr = err.current; + /// new = err.new; + /// } + /// } + /// } + /// + /// let mut curr = a.load(SeqCst, guard); + /// loop { + /// match a.compare_exchange_weak(curr, Shared::null(), SeqCst, SeqCst, guard) { + /// Ok(_) => break, + /// Err(err) => curr = err.current, + /// } + /// } + /// # unsafe { drop(curr.into_owned()); } // avoid leak + /// ``` + pub fn compare_exchange_weak<'g, P>( + &self, + current: Shared<'_, T>, + new: P, + success: Ordering, + failure: Ordering, + _: &'g Guard, + ) -> Result, CompareExchangeError<'g, T, P>> + where + P: Pointer, + { + let new = new.into_usize(); + self.data + .compare_exchange_weak(current.into_usize(), new, success, failure) + .map(|_| unsafe { Shared::from_usize(new) }) + .map_err(|current| unsafe { + CompareExchangeError { + current: Shared::from_usize(current), + new: P::from_usize(new), + } + }) + } + + /// Fetches the pointer, and then applies a function to it that returns a new value. + /// Returns a `Result` of `Ok(previous_value)` if the function returned `Some`, else `Err(_)`. + /// + /// Note that the given function may be called multiple times if the value has been changed by + /// other threads in the meantime, as long as the function returns `Some(_)`, but the function + /// will have been applied only once to the stored value. + /// + /// `fetch_update` takes two [`Ordering`] arguments to describe the memory + /// ordering of this operation. The first describes the required ordering for + /// when the operation finally succeeds while the second describes the + /// required ordering for loads. These correspond to the success and failure + /// orderings of [`Atomic::compare_exchange`] respectively. + /// + /// Using [`Acquire`] as success ordering makes the store part of this + /// operation [`Relaxed`], and using [`Release`] makes the final successful + /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], + /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the + /// success ordering. + /// + /// [`Relaxed`]: Ordering::Relaxed + /// [`Acquire`]: Ordering::Acquire + /// [`Release`]: Ordering::Release + /// [`SeqCst`]: Ordering::SeqCst + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// + /// let res1 = a.fetch_update(SeqCst, SeqCst, guard, |x| Some(x.with_tag(1))); + /// assert!(res1.is_ok()); + /// + /// let res2 = a.fetch_update(SeqCst, SeqCst, guard, |x| None); + /// assert!(res2.is_err()); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn fetch_update<'g, F>( + &self, + set_order: Ordering, + fail_order: Ordering, + guard: &'g Guard, + mut func: F, + ) -> Result, Shared<'g, T>> + where + F: FnMut(Shared<'g, T>) -> Option>, + { + let mut prev = self.load(fail_order, guard); + while let Some(next) = func(prev) { + match self.compare_exchange_weak(prev, next, set_order, fail_order, guard) { + Ok(shared) => return Ok(shared), + Err(next_prev) => prev = next_prev.current, + } + } + Err(prev) + } + + /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current + /// value is the same as `current`. The tag is also taken into account, so two pointers to the + /// same object, but with different tags, will not be considered equal. + /// + /// The return value is a result indicating whether the new pointer was written. On success the + /// pointer that was written is returned. On failure the actual current value and `new` are + /// returned. + /// + /// This method takes a [`CompareAndSetOrdering`] argument which describes the memory + /// ordering of this operation. + /// + /// # Migrating to `compare_exchange` + /// + /// `compare_and_set` is equivalent to `compare_exchange` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// + /// let guard = &epoch::pin(); + /// let curr = a.load(SeqCst, guard); + /// let res1 = a.compare_and_set(curr, Shared::null(), SeqCst, guard); + /// let res2 = a.compare_and_set(curr, Owned::new(5678), SeqCst, guard); + /// # unsafe { drop(curr.into_owned()); } // avoid leak + /// ``` + // TODO: remove in the next major version. + #[allow(deprecated)] + #[deprecated(note = "Use `compare_exchange` instead")] + pub fn compare_and_set<'g, O, P>( + &self, + current: Shared<'_, T>, + new: P, + ord: O, + guard: &'g Guard, + ) -> Result, CompareAndSetError<'g, T, P>> + where + O: CompareAndSetOrdering, + P: Pointer, + { + self.compare_exchange(current, new, ord.success(), ord.failure(), guard) + } + + /// Stores the pointer `new` (either `Shared` or `Owned`) into the atomic pointer if the current + /// value is the same as `current`. The tag is also taken into account, so two pointers to the + /// same object, but with different tags, will not be considered equal. + /// + /// Unlike [`compare_and_set`], this method is allowed to spuriously fail even when comparison + /// succeeds, which can result in more efficient code on some platforms. The return value is a + /// result indicating whether the new pointer was written. On success the pointer that was + /// written is returned. On failure the actual current value and `new` are returned. + /// + /// This method takes a [`CompareAndSetOrdering`] argument which describes the memory + /// ordering of this operation. + /// + /// [`compare_and_set`]: Atomic::compare_and_set + /// + /// # Migrating to `compare_exchange_weak` + /// + /// `compare_and_set_weak` is equivalent to `compare_exchange_weak` with the following mapping for + /// memory orderings: + /// + /// Original | Success | Failure + /// -------- | ------- | ------- + /// Relaxed | Relaxed | Relaxed + /// Acquire | Acquire | Acquire + /// Release | Release | Relaxed + /// AcqRel | AcqRel | Acquire + /// SeqCst | SeqCst | SeqCst + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// use crossbeam_epoch::{self as epoch, Atomic, Owned, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// + /// let mut new = Owned::new(5678); + /// let mut ptr = a.load(SeqCst, guard); + /// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak + /// loop { + /// match a.compare_and_set_weak(ptr, new, SeqCst, guard) { + /// Ok(p) => { + /// ptr = p; + /// break; + /// } + /// Err(err) => { + /// ptr = err.current; + /// new = err.new; + /// } + /// } + /// } + /// + /// let mut curr = a.load(SeqCst, guard); + /// loop { + /// match a.compare_and_set_weak(curr, Shared::null(), SeqCst, guard) { + /// Ok(_) => break, + /// Err(err) => curr = err.current, + /// } + /// } + /// # unsafe { drop(curr.into_owned()); } // avoid leak + /// ``` + // TODO: remove in the next major version. + #[allow(deprecated)] + #[deprecated(note = "Use `compare_exchange_weak` instead")] + pub fn compare_and_set_weak<'g, O, P>( + &self, + current: Shared<'_, T>, + new: P, + ord: O, + guard: &'g Guard, + ) -> Result, CompareAndSetError<'g, T, P>> + where + O: CompareAndSetOrdering, + P: Pointer, + { + self.compare_exchange_weak(current, new, ord.success(), ord.failure(), guard) + } + + /// Bitwise "and" with the current tag. + /// + /// Performs a bitwise "and" operation on the current tag and the argument `val`, and sets the + /// new tag to the result. Returns the previous pointer. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::::from(Shared::null().with_tag(3)); + /// let guard = &epoch::pin(); + /// assert_eq!(a.fetch_and(2, SeqCst, guard).tag(), 3); + /// assert_eq!(a.load(SeqCst, guard).tag(), 2); + /// ``` + pub fn fetch_and<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.fetch_and(val | !low_bits::(), ord)) } + } + + /// Bitwise "or" with the current tag. + /// + /// Performs a bitwise "or" operation on the current tag and the argument `val`, and sets the + /// new tag to the result. Returns the previous pointer. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::::from(Shared::null().with_tag(1)); + /// let guard = &epoch::pin(); + /// assert_eq!(a.fetch_or(2, SeqCst, guard).tag(), 1); + /// assert_eq!(a.load(SeqCst, guard).tag(), 3); + /// ``` + pub fn fetch_or<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.fetch_or(val & low_bits::(), ord)) } + } + + /// Bitwise "xor" with the current tag. + /// + /// Performs a bitwise "xor" operation on the current tag and the argument `val`, and sets the + /// new tag to the result. Returns the previous pointer. + /// + /// This method takes an [`Ordering`] argument which describes the memory ordering of this + /// operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Shared}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::::from(Shared::null().with_tag(1)); + /// let guard = &epoch::pin(); + /// assert_eq!(a.fetch_xor(3, SeqCst, guard).tag(), 1); + /// assert_eq!(a.load(SeqCst, guard).tag(), 2); + /// ``` + pub fn fetch_xor<'g>(&self, val: usize, ord: Ordering, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.data.fetch_xor(val & low_bits::(), ord)) } + } + + /// Takes ownership of the pointee. + /// + /// This consumes the atomic and converts it into [`Owned`]. As [`Atomic`] doesn't have a + /// destructor and doesn't drop the pointee while [`Owned`] does, this is suitable for + /// destructors of data structures. + /// + /// # Panics + /// + /// Panics if this pointer is null, but only in debug mode. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object. + /// + /// # Examples + /// + /// ```rust + /// # use std::mem; + /// # use crossbeam_epoch::Atomic; + /// struct DataStructure { + /// ptr: Atomic, + /// } + /// + /// impl Drop for DataStructure { + /// fn drop(&mut self) { + /// // By now the DataStructure lives only in our thread and we are sure we don't hold + /// // any Shared or & to it ourselves. + /// unsafe { + /// drop(mem::replace(&mut self.ptr, Atomic::null()).into_owned()); + /// } + /// } + /// } + /// ``` + pub unsafe fn into_owned(self) -> Owned { + Owned::from_usize(self.data.into_inner()) + } + + /// Takes ownership of the pointee if it is non-null. + /// + /// This consumes the atomic and converts it into [`Owned`]. As [`Atomic`] doesn't have a + /// destructor and doesn't drop the pointee while [`Owned`] does, this is suitable for + /// destructors of data structures. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object, or the pointer is null. + /// + /// # Examples + /// + /// ```rust + /// # use std::mem; + /// # use crossbeam_epoch::Atomic; + /// struct DataStructure { + /// ptr: Atomic, + /// } + /// + /// impl Drop for DataStructure { + /// fn drop(&mut self) { + /// // By now the DataStructure lives only in our thread and we are sure we don't hold + /// // any Shared or & to it ourselves, but it may be null, so we have to be careful. + /// let old = mem::replace(&mut self.ptr, Atomic::null()); + /// unsafe { + /// if let Some(x) = old.try_into_owned() { + /// drop(x) + /// } + /// } + /// } + /// } + /// ``` + pub unsafe fn try_into_owned(self) -> Option> { + let data = self.data.into_inner(); + if decompose_tag::(data).0 == 0 { + None + } else { + Some(Owned::from_usize(data)) + } + } +} + +impl fmt::Debug for Atomic { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let data = self.data.load(Ordering::SeqCst); + let (raw, tag) = decompose_tag::(data); + + f.debug_struct("Atomic") + .field("raw", &raw) + .field("tag", &tag) + .finish() + } +} + +impl fmt::Pointer for Atomic { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let data = self.data.load(Ordering::SeqCst); + let (raw, _) = decompose_tag::(data); + fmt::Pointer::fmt(&(unsafe { T::deref(raw) as *const _ }), f) + } +} + +impl Clone for Atomic { + /// Returns a copy of the atomic value. + /// + /// Note that a `Relaxed` load is used here. If you need synchronization, use it with other + /// atomics or fences. + fn clone(&self) -> Self { + let data = self.data.load(Ordering::Relaxed); + Atomic::from_usize(data) + } +} + +impl Default for Atomic { + fn default() -> Self { + Atomic::null() + } +} + +impl From> for Atomic { + /// Returns a new atomic pointer pointing to `owned`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{Atomic, Owned}; + /// + /// let a = Atomic::::from(Owned::new(1234)); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + fn from(owned: Owned) -> Self { + let data = owned.data; + mem::forget(owned); + Self::from_usize(data) + } +} + +impl From> for Atomic { + fn from(b: Box) -> Self { + Self::from(Owned::from(b)) + } +} + +impl From for Atomic { + fn from(t: T) -> Self { + Self::new(t) + } +} + +impl<'g, T: ?Sized + Pointable> From> for Atomic { + /// Returns a new atomic pointer pointing to `ptr`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{Atomic, Shared}; + /// + /// let a = Atomic::::from(Shared::::null()); + /// ``` + fn from(ptr: Shared<'g, T>) -> Self { + Self::from_usize(ptr.data) + } +} + +impl From<*const T> for Atomic { + /// Returns a new atomic pointer pointing to `raw`. + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// use crossbeam_epoch::Atomic; + /// + /// let a = Atomic::::from(ptr::null::()); + /// ``` + fn from(raw: *const T) -> Self { + Self::from_usize(raw as usize) + } +} + +/// A trait for either `Owned` or `Shared` pointers. +pub trait Pointer { + /// Returns the machine representation of the pointer. + fn into_usize(self) -> usize; + + /// Returns a new pointer pointing to the tagged pointer `data`. + /// + /// # Safety + /// + /// The given `data` should have been created by `Pointer::into_usize()`, and one `data` should + /// not be converted back by `Pointer::from_usize()` multiple times. + unsafe fn from_usize(data: usize) -> Self; +} + +/// An owned heap-allocated object. +/// +/// This type is very similar to `Box`. +/// +/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused +/// least significant bits of the address. +pub struct Owned { + data: usize, + _marker: PhantomData>, +} + +impl Pointer for Owned { + #[inline] + fn into_usize(self) -> usize { + let data = self.data; + mem::forget(self); + data + } + + /// Returns a new pointer pointing to the tagged pointer `data`. + /// + /// # Panics + /// + /// Panics if the data is zero in debug mode. + #[inline] + unsafe fn from_usize(data: usize) -> Self { + debug_assert!(data != 0, "converting zero into `Owned`"); + Owned { + data, + _marker: PhantomData, + } + } +} + +impl Owned { + /// Returns a new owned pointer pointing to `raw`. + /// + /// This function is unsafe because improper use may lead to memory problems. Argument `raw` + /// must be a valid pointer. Also, a double-free may occur if the function is called twice on + /// the same raw pointer. + /// + /// # Panics + /// + /// Panics if `raw` is not properly aligned. + /// + /// # Safety + /// + /// The given `raw` should have been derived from `Owned`, and one `raw` should not be converted + /// back by `Owned::from_raw()` multiple times. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = unsafe { Owned::from_raw(Box::into_raw(Box::new(1234))) }; + /// ``` + pub unsafe fn from_raw(raw: *mut T) -> Owned { + let raw = raw as usize; + ensure_aligned::(raw); + Self::from_usize(raw) + } + + /// Converts the owned pointer into a `Box`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = Owned::new(1234); + /// let b: Box = o.into_box(); + /// assert_eq!(*b, 1234); + /// ``` + pub fn into_box(self) -> Box { + let (raw, _) = decompose_tag::(self.data); + mem::forget(self); + unsafe { Box::from_raw(raw as *mut _) } + } + + /// Allocates `value` on the heap and returns a new owned pointer pointing to it. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = Owned::new(1234); + /// ``` + pub fn new(init: T) -> Owned { + Self::init(init) + } +} + +impl Owned { + /// Allocates `value` on the heap and returns a new owned pointer pointing to it. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = Owned::::init(1234); + /// ``` + pub fn init(init: T::Init) -> Owned { + unsafe { Self::from_usize(T::init(init)) } + } + + /// Converts the owned pointer into a [`Shared`]. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Owned}; + /// + /// let o = Owned::new(1234); + /// let guard = &epoch::pin(); + /// let p = o.into_shared(guard); + /// # unsafe { drop(p.into_owned()); } // avoid leak + /// ``` + #[allow(clippy::needless_lifetimes)] + pub fn into_shared<'g>(self, _: &'g Guard) -> Shared<'g, T> { + unsafe { Shared::from_usize(self.into_usize()) } + } + + /// Returns the tag stored within the pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// assert_eq!(Owned::new(1234).tag(), 0); + /// ``` + pub fn tag(&self) -> usize { + let (_, tag) = decompose_tag::(self.data); + tag + } + + /// Returns the same pointer, but tagged with `tag`. `tag` is truncated to be fit into the + /// unused bits of the pointer to `T`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = Owned::new(0u64); + /// assert_eq!(o.tag(), 0); + /// let o = o.with_tag(2); + /// assert_eq!(o.tag(), 2); + /// ``` + pub fn with_tag(self, tag: usize) -> Owned { + let data = self.into_usize(); + unsafe { Self::from_usize(compose_tag::(data, tag)) } + } +} + +impl Drop for Owned { + fn drop(&mut self) { + let (raw, _) = decompose_tag::(self.data); + unsafe { + T::drop(raw); + } + } +} + +impl fmt::Debug for Owned { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (raw, tag) = decompose_tag::(self.data); + + f.debug_struct("Owned") + .field("raw", &raw) + .field("tag", &tag) + .finish() + } +} + +impl Clone for Owned { + fn clone(&self) -> Self { + Owned::new((**self).clone()).with_tag(self.tag()) + } +} + +impl Deref for Owned { + type Target = T; + + fn deref(&self) -> &T { + let (raw, _) = decompose_tag::(self.data); + unsafe { T::deref(raw) } + } +} + +impl DerefMut for Owned { + fn deref_mut(&mut self) -> &mut T { + let (raw, _) = decompose_tag::(self.data); + unsafe { T::deref_mut(raw) } + } +} + +impl From for Owned { + fn from(t: T) -> Self { + Owned::new(t) + } +} + +impl From> for Owned { + /// Returns a new owned pointer pointing to `b`. + /// + /// # Panics + /// + /// Panics if the pointer (the `Box`) is not properly aligned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Owned; + /// + /// let o = unsafe { Owned::from_raw(Box::into_raw(Box::new(1234))) }; + /// ``` + fn from(b: Box) -> Self { + unsafe { Self::from_raw(Box::into_raw(b)) } + } +} + +impl Borrow for Owned { + fn borrow(&self) -> &T { + self.deref() + } +} + +impl BorrowMut for Owned { + fn borrow_mut(&mut self) -> &mut T { + self.deref_mut() + } +} + +impl AsRef for Owned { + fn as_ref(&self) -> &T { + self.deref() + } +} + +impl AsMut for Owned { + fn as_mut(&mut self) -> &mut T { + self.deref_mut() + } +} + +/// A pointer to an object protected by the epoch GC. +/// +/// The pointer is valid for use only during the lifetime `'g`. +/// +/// The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused +/// least significant bits of the address. +pub struct Shared<'g, T: 'g + ?Sized + Pointable> { + data: usize, + _marker: PhantomData<(&'g (), *const T)>, +} + +impl Clone for Shared<'_, T> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for Shared<'_, T> {} + +impl Pointer for Shared<'_, T> { + #[inline] + fn into_usize(self) -> usize { + self.data + } + + #[inline] + unsafe fn from_usize(data: usize) -> Self { + Shared { + data, + _marker: PhantomData, + } + } +} + +impl<'g, T> Shared<'g, T> { + /// Converts the pointer to a raw pointer (without the tag). + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let o = Owned::new(1234); + /// let raw = &*o as *const _; + /// let a = Atomic::from(o); + /// + /// let guard = &epoch::pin(); + /// let p = a.load(SeqCst, guard); + /// assert_eq!(p.as_raw(), raw); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn as_raw(&self) -> *const T { + let (raw, _) = decompose_tag::(self.data); + raw as *const _ + } +} + +impl<'g, T: ?Sized + Pointable> Shared<'g, T> { + /// Returns a new null pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Shared; + /// + /// let p = Shared::::null(); + /// assert!(p.is_null()); + /// ``` + pub fn null() -> Shared<'g, T> { + Shared { + data: 0, + _marker: PhantomData, + } + } + + /// Returns `true` if the pointer is null. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::null(); + /// let guard = &epoch::pin(); + /// assert!(a.load(SeqCst, guard).is_null()); + /// a.store(Owned::new(1234), SeqCst); + /// assert!(!a.load(SeqCst, guard).is_null()); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn is_null(&self) -> bool { + let (raw, _) = decompose_tag::(self.data); + raw == 0 + } + + /// Dereferences the pointer. + /// + /// Returns a reference to the pointee that is valid during the lifetime `'g`. + /// + /// # Safety + /// + /// Dereferencing a pointer is unsafe because it could be pointing to invalid memory. + /// + /// Another concern is the possibility of data races due to lack of proper synchronization. + /// For example, consider the following scenario: + /// + /// 1. A thread creates a new object: `a.store(Owned::new(10), Relaxed)` + /// 2. Another thread reads it: `*a.load(Relaxed, guard).as_ref().unwrap()` + /// + /// The problem is that relaxed orderings don't synchronize initialization of the object with + /// the read from the second thread. This is a data race. A possible solution would be to use + /// `Release` and `Acquire` orderings. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// let p = a.load(SeqCst, guard); + /// unsafe { + /// assert_eq!(p.deref(), &1234); + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub unsafe fn deref(&self) -> &'g T { + let (raw, _) = decompose_tag::(self.data); + T::deref(raw) + } + + /// Dereferences the pointer. + /// + /// Returns a mutable reference to the pointee that is valid during the lifetime `'g`. + /// + /// # Safety + /// + /// * There is no guarantee that there are no more threads attempting to read/write from/to the + /// actual object at the same time. + /// + /// The user must know that there are no concurrent accesses towards the object itself. + /// + /// * Other than the above, all safety concerns of `deref()` applies here. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(vec![1, 2, 3, 4]); + /// let guard = &epoch::pin(); + /// + /// let mut p = a.load(SeqCst, guard); + /// unsafe { + /// assert!(!p.is_null()); + /// let b = p.deref_mut(); + /// assert_eq!(b, &vec![1, 2, 3, 4]); + /// b.push(5); + /// assert_eq!(b, &vec![1, 2, 3, 4, 5]); + /// } + /// + /// let p = a.load(SeqCst, guard); + /// unsafe { + /// assert_eq!(p.deref(), &vec![1, 2, 3, 4, 5]); + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub unsafe fn deref_mut(&mut self) -> &'g mut T { + let (raw, _) = decompose_tag::(self.data); + T::deref_mut(raw) + } + + /// Converts the pointer to a reference. + /// + /// Returns `None` if the pointer is null, or else a reference to the object wrapped in `Some`. + /// + /// # Safety + /// + /// Dereferencing a pointer is unsafe because it could be pointing to invalid memory. + /// + /// Another concern is the possibility of data races due to lack of proper synchronization. + /// For example, consider the following scenario: + /// + /// 1. A thread creates a new object: `a.store(Owned::new(10), Relaxed)` + /// 2. Another thread reads it: `*a.load(Relaxed, guard).as_ref().unwrap()` + /// + /// The problem is that relaxed orderings don't synchronize initialization of the object with + /// the read from the second thread. This is a data race. A possible solution would be to use + /// `Release` and `Acquire` orderings. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// let guard = &epoch::pin(); + /// let p = a.load(SeqCst, guard); + /// unsafe { + /// assert_eq!(p.as_ref(), Some(&1234)); + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub unsafe fn as_ref(&self) -> Option<&'g T> { + let (raw, _) = decompose_tag::(self.data); + if raw == 0 { + None + } else { + Some(T::deref(raw)) + } + } + + /// Takes ownership of the pointee. + /// + /// # Panics + /// + /// Panics if this pointer is null, but only in debug mode. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// unsafe { + /// let guard = &epoch::unprotected(); + /// let p = a.load(SeqCst, guard); + /// drop(p.into_owned()); + /// } + /// ``` + pub unsafe fn into_owned(self) -> Owned { + debug_assert!(!self.is_null(), "converting a null `Shared` into `Owned`"); + Owned::from_usize(self.data) + } + + /// Takes ownership of the pointee if it is not null. + /// + /// # Safety + /// + /// This method may be called only if the pointer is valid and nobody else is holding a + /// reference to the same object, or if the pointer is null. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(1234); + /// unsafe { + /// let guard = &epoch::unprotected(); + /// let p = a.load(SeqCst, guard); + /// if let Some(x) = p.try_into_owned() { + /// drop(x); + /// } + /// } + /// ``` + pub unsafe fn try_into_owned(self) -> Option> { + if self.is_null() { + None + } else { + Some(Owned::from_usize(self.data)) + } + } + + /// Returns the tag stored within the pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::::from(Owned::new(0u64).with_tag(2)); + /// let guard = &epoch::pin(); + /// let p = a.load(SeqCst, guard); + /// assert_eq!(p.tag(), 2); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn tag(&self) -> usize { + let (_, tag) = decompose_tag::(self.data); + tag + } + + /// Returns the same pointer, but tagged with `tag`. `tag` is truncated to be fit into the + /// unused bits of the pointer to `T`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(0u64); + /// let guard = &epoch::pin(); + /// let p1 = a.load(SeqCst, guard); + /// let p2 = p1.with_tag(2); + /// + /// assert_eq!(p1.tag(), 0); + /// assert_eq!(p2.tag(), 2); + /// assert_eq!(p1.as_raw(), p2.as_raw()); + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn with_tag(&self, tag: usize) -> Shared<'g, T> { + unsafe { Self::from_usize(compose_tag::(self.data, tag)) } + } +} + +impl From<*const T> for Shared<'_, T> { + /// Returns a new pointer pointing to `raw`. + /// + /// # Panics + /// + /// Panics if `raw` is not properly aligned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::Shared; + /// + /// let p = Shared::from(Box::into_raw(Box::new(1234)) as *const _); + /// assert!(!p.is_null()); + /// # unsafe { drop(p.into_owned()); } // avoid leak + /// ``` + fn from(raw: *const T) -> Self { + let raw = raw as usize; + ensure_aligned::(raw); + unsafe { Self::from_usize(raw) } + } +} + +impl<'g, T: ?Sized + Pointable> PartialEq> for Shared<'g, T> { + fn eq(&self, other: &Self) -> bool { + self.data == other.data + } +} + +impl Eq for Shared<'_, T> {} + +impl<'g, T: ?Sized + Pointable> PartialOrd> for Shared<'g, T> { + fn partial_cmp(&self, other: &Self) -> Option { + self.data.partial_cmp(&other.data) + } +} + +impl Ord for Shared<'_, T> { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.data.cmp(&other.data) + } +} + +impl fmt::Debug for Shared<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (raw, tag) = decompose_tag::(self.data); + + f.debug_struct("Shared") + .field("raw", &raw) + .field("tag", &tag) + .finish() + } +} + +impl fmt::Pointer for Shared<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(unsafe { self.deref() as *const _ }), f) + } +} + +impl Default for Shared<'_, T> { + fn default() -> Self { + Shared::null() + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use super::{Owned, Shared}; + use std::mem::MaybeUninit; + + #[test] + fn valid_tag_i8() { + Shared::::null().with_tag(0); + } + + #[test] + fn valid_tag_i64() { + Shared::::null().with_tag(7); + } + + #[test] + fn const_atomic_null() { + use super::Atomic; + static _U: Atomic = Atomic::::null(); + } + + #[test] + fn array_init() { + let owned = Owned::<[MaybeUninit]>::init(10); + let arr: &[MaybeUninit] = &owned; + assert_eq!(arr.len(), 10); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/collector.rs b/anneal/v2/vendor/crossbeam-epoch/src/collector.rs new file mode 100644 index 0000000000..12655d6cdb --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/collector.rs @@ -0,0 +1,464 @@ +/// Epoch-based garbage collector. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_epoch::Collector; +/// +/// let collector = Collector::new(); +/// +/// let handle = collector.register(); +/// drop(collector); // `handle` still works after dropping `collector` +/// +/// handle.pin().flush(); +/// ``` +use core::fmt; + +use crate::guard::Guard; +use crate::internal::{Global, Local}; +use crate::primitive::sync::Arc; + +/// An epoch-based garbage collector. +pub struct Collector { + pub(crate) global: Arc, +} + +unsafe impl Send for Collector {} +unsafe impl Sync for Collector {} + +impl Default for Collector { + fn default() -> Self { + Self { + global: Arc::new(Global::new()), + } + } +} + +impl Collector { + /// Creates a new collector. + pub fn new() -> Self { + Self::default() + } + + /// Registers a new handle for the collector. + pub fn register(&self) -> LocalHandle { + Local::register(self) + } +} + +impl Clone for Collector { + /// Creates another reference to the same garbage collector. + fn clone(&self) -> Self { + Collector { + global: self.global.clone(), + } + } +} + +impl fmt::Debug for Collector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Collector { .. }") + } +} + +impl PartialEq for Collector { + /// Checks if both handles point to the same collector. + fn eq(&self, rhs: &Collector) -> bool { + Arc::ptr_eq(&self.global, &rhs.global) + } +} +impl Eq for Collector {} + +/// A handle to a garbage collector. +pub struct LocalHandle { + pub(crate) local: *const Local, +} + +impl LocalHandle { + /// Pins the handle. + #[inline] + pub fn pin(&self) -> Guard { + unsafe { (*self.local).pin() } + } + + /// Returns `true` if the handle is pinned. + #[inline] + pub fn is_pinned(&self) -> bool { + unsafe { (*self.local).is_pinned() } + } + + /// Returns the `Collector` associated with this handle. + #[inline] + pub fn collector(&self) -> &Collector { + unsafe { (*self.local).collector() } + } +} + +impl Drop for LocalHandle { + #[inline] + fn drop(&mut self) { + unsafe { + Local::release_handle(&*self.local); + } + } +} + +impl fmt::Debug for LocalHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("LocalHandle { .. }") + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use std::mem::ManuallyDrop; + use std::sync::atomic::{AtomicUsize, Ordering}; + + use crossbeam_utils::thread; + + use crate::{Collector, Owned}; + + const NUM_THREADS: usize = 8; + + #[test] + fn pin_reentrant() { + let collector = Collector::new(); + let handle = collector.register(); + drop(collector); + + assert!(!handle.is_pinned()); + { + let _guard = &handle.pin(); + assert!(handle.is_pinned()); + { + let _guard = &handle.pin(); + assert!(handle.is_pinned()); + } + assert!(handle.is_pinned()); + } + assert!(!handle.is_pinned()); + } + + #[test] + fn flush_local_bag() { + let collector = Collector::new(); + let handle = collector.register(); + drop(collector); + + for _ in 0..100 { + let guard = &handle.pin(); + unsafe { + let a = Owned::new(7).into_shared(guard); + guard.defer_destroy(a); + + assert!(!(*guard.local).bag.with(|b| (*b).is_empty())); + + while !(*guard.local).bag.with(|b| (*b).is_empty()) { + guard.flush(); + } + } + } + } + + #[test] + fn garbage_buffering() { + let collector = Collector::new(); + let handle = collector.register(); + drop(collector); + + let guard = &handle.pin(); + unsafe { + for _ in 0..10 { + let a = Owned::new(7).into_shared(guard); + guard.defer_destroy(a); + } + assert!(!(*guard.local).bag.with(|b| (*b).is_empty())); + } + } + + #[test] + fn pin_holds_advance() { + #[cfg(miri)] + const N: usize = 500; + #[cfg(not(miri))] + const N: usize = 500_000; + + let collector = Collector::new(); + + thread::scope(|scope| { + for _ in 0..NUM_THREADS { + scope.spawn(|_| { + let handle = collector.register(); + for _ in 0..N { + let guard = &handle.pin(); + + let before = collector.global.epoch.load(Ordering::Relaxed); + collector.global.collect(guard); + let after = collector.global.epoch.load(Ordering::Relaxed); + + assert!(after.wrapping_sub(before) <= 2); + } + }); + } + }) + .unwrap(); + } + + #[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to `cfg(crossbeam_sanitize)` reduce `internal::MAX_OBJECTS` + #[test] + fn incremental() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + static DESTROYS: AtomicUsize = AtomicUsize::new(0); + + let collector = Collector::new(); + let handle = collector.register(); + + unsafe { + let guard = &handle.pin(); + for _ in 0..COUNT { + let a = Owned::new(7i32).into_shared(guard); + guard.defer_unchecked(move || { + drop(a.into_owned()); + DESTROYS.fetch_add(1, Ordering::Relaxed); + }); + } + guard.flush(); + } + + let mut last = 0; + + while last < COUNT { + let curr = DESTROYS.load(Ordering::Relaxed); + assert!(curr - last <= 1024); + last = curr; + + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert!(DESTROYS.load(Ordering::Relaxed) == COUNT); + } + + #[test] + fn buffering() { + const COUNT: usize = 10; + #[cfg(miri)] + const N: usize = 500; + #[cfg(not(miri))] + const N: usize = 100_000; + static DESTROYS: AtomicUsize = AtomicUsize::new(0); + + let collector = Collector::new(); + let handle = collector.register(); + + unsafe { + let guard = &handle.pin(); + for _ in 0..COUNT { + let a = Owned::new(7i32).into_shared(guard); + guard.defer_unchecked(move || { + drop(a.into_owned()); + DESTROYS.fetch_add(1, Ordering::Relaxed); + }); + } + } + + for _ in 0..N { + collector.global.collect(&handle.pin()); + } + assert!(DESTROYS.load(Ordering::Relaxed) < COUNT); + + handle.pin().flush(); + + while DESTROYS.load(Ordering::Relaxed) < COUNT { + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert_eq!(DESTROYS.load(Ordering::Relaxed), COUNT); + } + + #[test] + fn count_drops() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + static DROPS: AtomicUsize = AtomicUsize::new(0); + + struct Elem(#[allow(dead_code)] i32); + + impl Drop for Elem { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::Relaxed); + } + } + + let collector = Collector::new(); + let handle = collector.register(); + + unsafe { + let guard = &handle.pin(); + + for _ in 0..COUNT { + let a = Owned::new(Elem(7i32)).into_shared(guard); + guard.defer_destroy(a); + } + guard.flush(); + } + + while DROPS.load(Ordering::Relaxed) < COUNT { + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert_eq!(DROPS.load(Ordering::Relaxed), COUNT); + } + + #[test] + fn count_destroy() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + static DESTROYS: AtomicUsize = AtomicUsize::new(0); + + let collector = Collector::new(); + let handle = collector.register(); + + unsafe { + let guard = &handle.pin(); + + for _ in 0..COUNT { + let a = Owned::new(7i32).into_shared(guard); + guard.defer_unchecked(move || { + drop(a.into_owned()); + DESTROYS.fetch_add(1, Ordering::Relaxed); + }); + } + guard.flush(); + } + + while DESTROYS.load(Ordering::Relaxed) < COUNT { + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert_eq!(DESTROYS.load(Ordering::Relaxed), COUNT); + } + + #[test] + fn drop_array() { + const COUNT: usize = 700; + static DROPS: AtomicUsize = AtomicUsize::new(0); + + struct Elem(#[allow(dead_code)] i32); + + impl Drop for Elem { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::Relaxed); + } + } + + let collector = Collector::new(); + let handle = collector.register(); + + let mut guard = handle.pin(); + + let mut v = Vec::with_capacity(COUNT); + for i in 0..COUNT { + v.push(Elem(i as i32)); + } + + { + let a = Owned::new(v).into_shared(&guard); + unsafe { + guard.defer_destroy(a); + } + guard.flush(); + } + + while DROPS.load(Ordering::Relaxed) < COUNT { + guard.repin(); + collector.global.collect(&guard); + } + assert_eq!(DROPS.load(Ordering::Relaxed), COUNT); + } + + #[test] + fn destroy_array() { + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + static DESTROYS: AtomicUsize = AtomicUsize::new(0); + + let collector = Collector::new(); + let handle = collector.register(); + + unsafe { + let guard = &handle.pin(); + + let mut v = Vec::with_capacity(COUNT); + for i in 0..COUNT { + v.push(i as i32); + } + + let len = v.len(); + let cap = v.capacity(); + let ptr = ManuallyDrop::new(v).as_mut_ptr(); + guard.defer_unchecked(move || { + drop(Vec::from_raw_parts(ptr, len, cap)); + DESTROYS.fetch_add(len, Ordering::Relaxed); + }); + guard.flush(); + } + + while DESTROYS.load(Ordering::Relaxed) < COUNT { + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert_eq!(DESTROYS.load(Ordering::Relaxed), COUNT); + } + + #[test] + fn stress() { + const THREADS: usize = 8; + #[cfg(miri)] + const COUNT: usize = 500; + #[cfg(not(miri))] + const COUNT: usize = 100_000; + static DROPS: AtomicUsize = AtomicUsize::new(0); + + struct Elem(#[allow(dead_code)] i32); + + impl Drop for Elem { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::Relaxed); + } + } + + let collector = Collector::new(); + + thread::scope(|scope| { + for _ in 0..THREADS { + scope.spawn(|_| { + let handle = collector.register(); + for _ in 0..COUNT { + let guard = &handle.pin(); + unsafe { + let a = Owned::new(Elem(7i32)).into_shared(guard); + guard.defer_destroy(a); + } + } + }); + } + }) + .unwrap(); + + let handle = collector.register(); + while DROPS.load(Ordering::Relaxed) < COUNT * THREADS { + let guard = &handle.pin(); + collector.global.collect(guard); + } + assert_eq!(DROPS.load(Ordering::Relaxed), COUNT * THREADS); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/default.rs b/anneal/v2/vendor/crossbeam-epoch/src/default.rs new file mode 100644 index 0000000000..a9790a373a --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/default.rs @@ -0,0 +1,93 @@ +//! The default garbage collector. +//! +//! For each thread, a participant is lazily initialized on its first use, when the current thread +//! is registered in the default collector. If initialized, the thread's participant will get +//! destructed on thread exit, which in turn unregisters the thread. + +use crate::collector::{Collector, LocalHandle}; +use crate::guard::Guard; +use crate::primitive::thread_local; +#[cfg(not(crossbeam_loom))] +use crate::sync::once_lock::OnceLock; + +fn collector() -> &'static Collector { + #[cfg(not(crossbeam_loom))] + { + /// The global data for the default garbage collector. + static COLLECTOR: OnceLock = OnceLock::new(); + COLLECTOR.get_or_init(Collector::new) + } + // FIXME: loom does not currently provide the equivalent of Lazy: + // https://github.com/tokio-rs/loom/issues/263 + #[cfg(crossbeam_loom)] + { + loom::lazy_static! { + /// The global data for the default garbage collector. + static ref COLLECTOR: Collector = Collector::new(); + } + &COLLECTOR + } +} + +thread_local! { + /// The per-thread participant for the default garbage collector. + static HANDLE: LocalHandle = collector().register(); +} + +/// Pins the current thread. +#[inline] +pub fn pin() -> Guard { + with_handle(|handle| handle.pin()) +} + +/// Returns `true` if the current thread is pinned. +#[inline] +pub fn is_pinned() -> bool { + with_handle(|handle| handle.is_pinned()) +} + +/// Returns the default global collector. +pub fn default_collector() -> &'static Collector { + collector() +} + +#[inline] +fn with_handle(mut f: F) -> R +where + F: FnMut(&LocalHandle) -> R, +{ + HANDLE + .try_with(|h| f(h)) + .unwrap_or_else(|_| f(&collector().register())) +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use crossbeam_utils::thread; + + #[test] + fn pin_while_exiting() { + struct Foo; + + impl Drop for Foo { + fn drop(&mut self) { + // Pin after `HANDLE` has been dropped. This must not panic. + super::pin(); + } + } + + thread_local! { + static FOO: Foo = const { Foo }; + } + + thread::scope(|scope| { + scope.spawn(|_| { + // Initialize `FOO` and then `HANDLE`. + FOO.with(|_| ()); + super::pin(); + // At thread exit, `HANDLE` gets dropped first and `FOO` second. + }); + }) + .unwrap(); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/deferred.rs b/anneal/v2/vendor/crossbeam-epoch/src/deferred.rs new file mode 100644 index 0000000000..041955f52b --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/deferred.rs @@ -0,0 +1,146 @@ +use alloc::boxed::Box; +use core::fmt; +use core::marker::PhantomData; +use core::mem::{self, MaybeUninit}; +use core::ptr; + +/// Number of words a piece of `Data` can hold. +/// +/// Three words should be enough for the majority of cases. For example, you can fit inside it the +/// function pointer together with a fat pointer representing an object that needs to be destroyed. +const DATA_WORDS: usize = 3; + +/// Some space to keep a `FnOnce()` object on the stack. +type Data = [usize; DATA_WORDS]; + +/// A `FnOnce()` that is stored inline if small, or otherwise boxed on the heap. +/// +/// This is a handy way of keeping an unsized `FnOnce()` within a sized structure. +pub(crate) struct Deferred { + call: unsafe fn(*mut u8), + data: MaybeUninit, + _marker: PhantomData<*mut ()>, // !Send + !Sync +} + +impl fmt::Debug for Deferred { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.pad("Deferred { .. }") + } +} + +impl Deferred { + pub(crate) const NO_OP: Self = { + fn no_op_call(_raw: *mut u8) {} + Self { + call: no_op_call, + data: MaybeUninit::uninit(), + _marker: PhantomData, + } + }; + + /// Constructs a new `Deferred` from a `FnOnce()`. + pub(crate) fn new(f: F) -> Self { + let size = mem::size_of::(); + let align = mem::align_of::(); + + unsafe { + if size <= mem::size_of::() && align <= mem::align_of::() { + let mut data = MaybeUninit::::uninit(); + ptr::write(data.as_mut_ptr().cast::(), f); + + unsafe fn call(raw: *mut u8) { + let f: F = ptr::read(raw.cast::()); + f(); + } + + Deferred { + call: call::, + data, + _marker: PhantomData, + } + } else { + let b: Box = Box::new(f); + let mut data = MaybeUninit::::uninit(); + ptr::write(data.as_mut_ptr().cast::>(), b); + + unsafe fn call(raw: *mut u8) { + // It's safe to cast `raw` from `*mut u8` to `*mut Box`, because `raw` is + // originally derived from `*mut Box`. + let b: Box = ptr::read(raw.cast::>()); + (*b)(); + } + + Deferred { + call: call::, + data, + _marker: PhantomData, + } + } + } + } + + /// Calls the function. + #[inline] + pub(crate) fn call(mut self) { + let call = self.call; + unsafe { call(self.data.as_mut_ptr().cast::()) }; + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use super::Deferred; + use std::cell::Cell; + use std::convert::identity; + + #[test] + fn on_stack() { + let fired = &Cell::new(false); + let a = [0usize; 1]; + + let d = Deferred::new(move || { + let _ = identity(a); + fired.set(true); + }); + + assert!(!fired.get()); + d.call(); + assert!(fired.get()); + } + + #[test] + fn on_heap() { + let fired = &Cell::new(false); + let a = [0usize; 10]; + + let d = Deferred::new(move || { + let _ = identity(a); + fired.set(true); + }); + + assert!(!fired.get()); + d.call(); + assert!(fired.get()); + } + + #[test] + fn string() { + let a = "hello".to_string(); + let d = Deferred::new(move || assert_eq!(a, "hello")); + d.call(); + } + + #[test] + fn boxed_slice_i32() { + let a: Box<[i32]> = vec![2, 3, 5, 7].into_boxed_slice(); + let d = Deferred::new(move || assert_eq!(*a, [2, 3, 5, 7])); + d.call(); + } + + #[test] + fn long_slice_usize() { + let a: [usize; 5] = [2, 3, 5, 7, 11]; + let d = Deferred::new(move || assert_eq!(a, [2, 3, 5, 7, 11])); + d.call(); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/epoch.rs b/anneal/v2/vendor/crossbeam-epoch/src/epoch.rs new file mode 100644 index 0000000000..18d7418a10 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/epoch.rs @@ -0,0 +1,132 @@ +//! The global epoch +//! +//! The last bit in this number is unused and is always zero. Every so often the global epoch is +//! incremented, i.e. we say it "advances". A pinned participant may advance the global epoch only +//! if all currently pinned participants have been pinned in the current epoch. +//! +//! If an object became garbage in some epoch, then we can be sure that after two advancements no +//! participant will hold a reference to it. That is the crux of safe memory reclamation. + +use crate::primitive::sync::atomic::{AtomicUsize, Ordering}; + +/// An epoch that can be marked as pinned or unpinned. +/// +/// Internally, the epoch is represented as an integer that wraps around at some unspecified point +/// and a flag that represents whether it is pinned or unpinned. +#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)] +pub(crate) struct Epoch { + /// The least significant bit is set if pinned. The rest of the bits hold the epoch. + data: usize, +} + +impl Epoch { + /// Returns the starting epoch in unpinned state. + #[inline] + pub(crate) fn starting() -> Self { + Self::default() + } + + /// Returns the number of epochs `self` is ahead of `rhs`. + /// + /// Internally, epochs are represented as numbers in the range `(isize::MIN / 2) .. (isize::MAX + /// / 2)`, so the returned distance will be in the same interval. + pub(crate) fn wrapping_sub(self, rhs: Self) -> isize { + // The result is the same with `(self.data & !1).wrapping_sub(rhs.data & !1) as isize >> 1`, + // because the possible difference of LSB in `(self.data & !1).wrapping_sub(rhs.data & !1)` + // will be ignored in the shift operation. + self.data.wrapping_sub(rhs.data & !1) as isize >> 1 + } + + /// Returns `true` if the epoch is marked as pinned. + #[inline] + pub(crate) fn is_pinned(self) -> bool { + (self.data & 1) == 1 + } + + /// Returns the same epoch, but marked as pinned. + #[inline] + pub(crate) fn pinned(self) -> Epoch { + Epoch { + data: self.data | 1, + } + } + + /// Returns the same epoch, but marked as unpinned. + #[inline] + pub(crate) fn unpinned(self) -> Epoch { + Epoch { + data: self.data & !1, + } + } + + /// Returns the successor epoch. + /// + /// The returned epoch will be marked as pinned only if the previous one was as well. + #[inline] + pub(crate) fn successor(self) -> Epoch { + Epoch { + data: self.data.wrapping_add(2), + } + } +} + +/// An atomic value that holds an `Epoch`. +#[derive(Default, Debug)] +pub(crate) struct AtomicEpoch { + /// Since `Epoch` is just a wrapper around `usize`, an `AtomicEpoch` is similarly represented + /// using an `AtomicUsize`. + data: AtomicUsize, +} + +impl AtomicEpoch { + /// Creates a new atomic epoch. + #[inline] + pub(crate) fn new(epoch: Epoch) -> Self { + let data = AtomicUsize::new(epoch.data); + AtomicEpoch { data } + } + + /// Loads a value from the atomic epoch. + #[inline] + pub(crate) fn load(&self, ord: Ordering) -> Epoch { + Epoch { + data: self.data.load(ord), + } + } + + /// Stores a value into the atomic epoch. + #[inline] + pub(crate) fn store(&self, epoch: Epoch, ord: Ordering) { + self.data.store(epoch.data, ord); + } + + /// Stores a value into the atomic epoch if the current value is the same as `current`. + /// + /// The return value is a result indicating whether the new value was written and containing + /// the previous value. On success this value is guaranteed to be equal to `current`. + /// + /// This method takes two `Ordering` arguments to describe the memory + /// ordering of this operation. `success` describes the required ordering for the + /// read-modify-write operation that takes place if the comparison with `current` succeeds. + /// `failure` describes the required ordering for the load operation that takes place when + /// the comparison fails. Using `Acquire` as success ordering makes the store part + /// of this operation `Relaxed`, and using `Release` makes the successful load + /// `Relaxed`. The failure ordering can only be `SeqCst`, `Acquire` or `Relaxed` + /// and must be equivalent to or weaker than the success ordering. + #[inline] + pub(crate) fn compare_exchange( + &self, + current: Epoch, + new: Epoch, + success: Ordering, + failure: Ordering, + ) -> Result { + match self + .data + .compare_exchange(current.data, new.data, success, failure) + { + Ok(data) => Ok(Epoch { data }), + Err(data) => Err(Epoch { data }), + } + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/guard.rs b/anneal/v2/vendor/crossbeam-epoch/src/guard.rs new file mode 100644 index 0000000000..5fe33807c5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/guard.rs @@ -0,0 +1,523 @@ +use core::fmt; +use core::mem; + +use crate::atomic::Shared; +use crate::collector::Collector; +use crate::deferred::Deferred; +use crate::internal::Local; + +/// A guard that keeps the current thread pinned. +/// +/// # Pinning +/// +/// The current thread is pinned by calling [`pin`], which returns a new guard: +/// +/// ``` +/// use crossbeam_epoch as epoch; +/// +/// // It is often convenient to prefix a call to `pin` with a `&` in order to create a reference. +/// // This is not really necessary, but makes passing references to the guard a bit easier. +/// let guard = &epoch::pin(); +/// ``` +/// +/// When a guard gets dropped, the current thread is automatically unpinned. +/// +/// # Pointers on the stack +/// +/// Having a guard allows us to create pointers on the stack to heap-allocated objects. +/// For example: +/// +/// ``` +/// use crossbeam_epoch::{self as epoch, Atomic}; +/// use std::sync::atomic::Ordering::SeqCst; +/// +/// // Create a heap-allocated number. +/// let a = Atomic::new(777); +/// +/// // Pin the current thread. +/// let guard = &epoch::pin(); +/// +/// // Load the heap-allocated object and create pointer `p` on the stack. +/// let p = a.load(SeqCst, guard); +/// +/// // Dereference the pointer and print the value: +/// if let Some(num) = unsafe { p.as_ref() } { +/// println!("The number is {}.", num); +/// } +/// # unsafe { drop(a.into_owned()); } // avoid leak +/// ``` +/// +/// # Multiple guards +/// +/// Pinning is reentrant and it is perfectly legal to create multiple guards. In that case, the +/// thread will actually be pinned only when the first guard is created and unpinned when the last +/// one is dropped: +/// +/// ``` +/// use crossbeam_epoch as epoch; +/// +/// let guard1 = epoch::pin(); +/// let guard2 = epoch::pin(); +/// assert!(epoch::is_pinned()); +/// drop(guard1); +/// assert!(epoch::is_pinned()); +/// drop(guard2); +/// assert!(!epoch::is_pinned()); +/// ``` +/// +/// [`pin`]: super::pin +pub struct Guard { + pub(crate) local: *const Local, +} + +impl Guard { + /// Stores a function so that it can be executed at some point after all currently pinned + /// threads get unpinned. + /// + /// This method first stores `f` into the thread-local (or handle-local) cache. If this cache + /// becomes full, some functions are moved into the global cache. At the same time, some + /// functions from both local and global caches may get executed in order to incrementally + /// clean up the caches as they fill up. + /// + /// There is no guarantee when exactly `f` will be executed. The only guarantee is that it + /// won't be executed until all currently pinned threads get unpinned. In theory, `f` might + /// never run, but the epoch-based garbage collection will make an effort to execute it + /// reasonably soon. + /// + /// If this method is called from an [`unprotected`] guard, the function will simply be + /// executed immediately. + pub fn defer(&self, f: F) + where + F: FnOnce() -> R, + F: Send + 'static, + { + unsafe { + self.defer_unchecked(f); + } + } + + /// Stores a function so that it can be executed at some point after all currently pinned + /// threads get unpinned. + /// + /// This method first stores `f` into the thread-local (or handle-local) cache. If this cache + /// becomes full, some functions are moved into the global cache. At the same time, some + /// functions from both local and global caches may get executed in order to incrementally + /// clean up the caches as they fill up. + /// + /// There is no guarantee when exactly `f` will be executed. The only guarantee is that it + /// won't be executed until all currently pinned threads get unpinned. In theory, `f` might + /// never run, but the epoch-based garbage collection will make an effort to execute it + /// reasonably soon. + /// + /// If this method is called from an [`unprotected`] guard, the function will simply be + /// executed immediately. + /// + /// # Safety + /// + /// The given function must not hold reference onto the stack. It is highly recommended that + /// the passed function is **always** marked with `move` in order to prevent accidental + /// borrows. + /// + /// ``` + /// use crossbeam_epoch as epoch; + /// + /// let guard = &epoch::pin(); + /// let message = "Hello!"; + /// unsafe { + /// // ALWAYS use `move` when sending a closure into `defer_unchecked`. + /// guard.defer_unchecked(move || { + /// println!("{}", message); + /// }); + /// } + /// ``` + /// + /// Apart from that, keep in mind that another thread may execute `f`, so anything accessed by + /// the closure must be `Send`. + /// + /// We intentionally didn't require `F: Send`, because Rust's type systems usually cannot prove + /// `F: Send` for typical use cases. For example, consider the following code snippet, which + /// exemplifies the typical use case of deferring the deallocation of a shared reference: + /// + /// ```ignore + /// let shared = Owned::new(7i32).into_shared(guard); + /// guard.defer_unchecked(move || shared.into_owned()); // `Shared` is not `Send`! + /// ``` + /// + /// While `Shared` is not `Send`, it's safe for another thread to call the deferred function, + /// because it's called only after the grace period and `shared` is no longer shared with other + /// threads. But we don't expect type systems to prove this. + /// + /// # Examples + /// + /// When a heap-allocated object in a data structure becomes unreachable, it has to be + /// deallocated. However, the current thread and other threads may be still holding references + /// on the stack to that same object. Therefore it cannot be deallocated before those references + /// get dropped. This method can defer deallocation until all those threads get unpinned and + /// consequently drop all their references on the stack. + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new("foo"); + /// + /// // Now suppose that `a` is shared among multiple threads and concurrently + /// // accessed and modified... + /// + /// // Pin the current thread. + /// let guard = &epoch::pin(); + /// + /// // Steal the object currently stored in `a` and swap it with another one. + /// let p = a.swap(Owned::new("bar").into_shared(guard), SeqCst, guard); + /// + /// if !p.is_null() { + /// // The object `p` is pointing to is now unreachable. + /// // Defer its deallocation until all currently pinned threads get unpinned. + /// unsafe { + /// // ALWAYS use `move` when sending a closure into `defer_unchecked`. + /// guard.defer_unchecked(move || { + /// println!("{} is now being deallocated.", p.deref()); + /// // Now we have unique access to the object pointed to by `p` and can turn it + /// // into an `Owned`. Dropping the `Owned` will deallocate the object. + /// drop(p.into_owned()); + /// }); + /// } + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub unsafe fn defer_unchecked(&self, f: F) + where + F: FnOnce() -> R, + { + if let Some(local) = self.local.as_ref() { + local.defer(Deferred::new(move || drop(f())), self); + } else { + drop(f()); + } + } + + /// Stores a destructor for an object so that it can be deallocated and dropped at some point + /// after all currently pinned threads get unpinned. + /// + /// This method first stores the destructor into the thread-local (or handle-local) cache. If + /// this cache becomes full, some destructors are moved into the global cache. At the same + /// time, some destructors from both local and global caches may get executed in order to + /// incrementally clean up the caches as they fill up. + /// + /// There is no guarantee when exactly the destructor will be executed. The only guarantee is + /// that it won't be executed until all currently pinned threads get unpinned. In theory, the + /// destructor might never run, but the epoch-based garbage collection will make an effort to + /// execute it reasonably soon. + /// + /// If this method is called from an [`unprotected`] guard, the destructor will simply be + /// executed immediately. + /// + /// # Safety + /// + /// The object must not be reachable by other threads anymore, otherwise it might be still in + /// use when the destructor runs. + /// + /// Apart from that, keep in mind that another thread may execute the destructor, so the object + /// must be sendable to other threads. + /// + /// We intentionally didn't require `T: Send`, because Rust's type systems usually cannot prove + /// `T: Send` for typical use cases. For example, consider the following code snippet, which + /// exemplifies the typical use case of deferring the deallocation of a shared reference: + /// + /// ```ignore + /// let shared = Owned::new(7i32).into_shared(guard); + /// guard.defer_destroy(shared); // `Shared` is not `Send`! + /// ``` + /// + /// While `Shared` is not `Send`, it's safe for another thread to call the destructor, because + /// it's called only after the grace period and `shared` is no longer shared with other + /// threads. But we don't expect type systems to prove this. + /// + /// # Examples + /// + /// When a heap-allocated object in a data structure becomes unreachable, it has to be + /// deallocated. However, the current thread and other threads may be still holding references + /// on the stack to that same object. Therefore it cannot be deallocated before those references + /// get dropped. This method can defer deallocation until all those threads get unpinned and + /// consequently drop all their references on the stack. + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic, Owned}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new("foo"); + /// + /// // Now suppose that `a` is shared among multiple threads and concurrently + /// // accessed and modified... + /// + /// // Pin the current thread. + /// let guard = &epoch::pin(); + /// + /// // Steal the object currently stored in `a` and swap it with another one. + /// let p = a.swap(Owned::new("bar").into_shared(guard), SeqCst, guard); + /// + /// if !p.is_null() { + /// // The object `p` is pointing to is now unreachable. + /// // Defer its deallocation until all currently pinned threads get unpinned. + /// unsafe { + /// guard.defer_destroy(p); + /// } + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub unsafe fn defer_destroy(&self, ptr: Shared<'_, T>) { + self.defer_unchecked(move || ptr.into_owned()); + } + + /// Clears up the thread-local cache of deferred functions by executing them or moving into the + /// global cache. + /// + /// Call this method after deferring execution of a function if you want to get it executed as + /// soon as possible. Flushing will make sure it is residing in in the global cache, so that + /// any thread has a chance of taking the function and executing it. + /// + /// If this method is called from an [`unprotected`] guard, it is a no-op (nothing happens). + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch as epoch; + /// + /// let guard = &epoch::pin(); + /// guard.defer(move || { + /// println!("This better be printed as soon as possible!"); + /// }); + /// guard.flush(); + /// ``` + pub fn flush(&self) { + if let Some(local) = unsafe { self.local.as_ref() } { + local.flush(self); + } + } + + /// Unpins and then immediately re-pins the thread. + /// + /// This method is useful when you don't want delay the advancement of the global epoch by + /// holding an old epoch. For safety, you should not maintain any guard-based reference across + /// the call (the latter is enforced by `&mut self`). The thread will only be repinned if this + /// is the only active guard for the current thread. + /// + /// If this method is called from an [`unprotected`] guard, then the call will be just no-op. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// let a = Atomic::new(777); + /// let mut guard = epoch::pin(); + /// { + /// let p = a.load(SeqCst, &guard); + /// assert_eq!(unsafe { p.as_ref() }, Some(&777)); + /// } + /// guard.repin(); + /// { + /// let p = a.load(SeqCst, &guard); + /// assert_eq!(unsafe { p.as_ref() }, Some(&777)); + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn repin(&mut self) { + if let Some(local) = unsafe { self.local.as_ref() } { + local.repin(); + } + } + + /// Temporarily unpins the thread, executes the given function and then re-pins the thread. + /// + /// This method is useful when you need to perform a long-running operation (e.g. sleeping) + /// and don't need to maintain any guard-based reference across the call (the latter is enforced + /// by `&mut self`). The thread will only be unpinned if this is the only active guard for the + /// current thread. + /// + /// If this method is called from an [`unprotected`] guard, then the passed function is called + /// directly without unpinning the thread. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch::{self as epoch, Atomic}; + /// use std::sync::atomic::Ordering::SeqCst; + /// use std::thread; + /// use std::time::Duration; + /// + /// let a = Atomic::new(777); + /// let mut guard = epoch::pin(); + /// { + /// let p = a.load(SeqCst, &guard); + /// assert_eq!(unsafe { p.as_ref() }, Some(&777)); + /// } + /// guard.repin_after(|| thread::sleep(Duration::from_millis(50))); + /// { + /// let p = a.load(SeqCst, &guard); + /// assert_eq!(unsafe { p.as_ref() }, Some(&777)); + /// } + /// # unsafe { drop(a.into_owned()); } // avoid leak + /// ``` + pub fn repin_after(&mut self, f: F) -> R + where + F: FnOnce() -> R, + { + // Ensure the Guard is re-pinned even if the function panics + struct ScopeGuard(*const Local); + impl Drop for ScopeGuard { + fn drop(&mut self) { + if let Some(local) = unsafe { self.0.as_ref() } { + mem::forget(local.pin()); + local.release_handle(); + } + } + } + + if let Some(local) = unsafe { self.local.as_ref() } { + // We need to acquire a handle here to ensure the Local doesn't + // disappear from under us. + local.acquire_handle(); + local.unpin(); + } + + let _guard = ScopeGuard(self.local); + + f() + } + + /// Returns the `Collector` associated with this guard. + /// + /// This method is useful when you need to ensure that all guards used with + /// a data structure come from the same collector. + /// + /// If this method is called from an [`unprotected`] guard, then `None` is returned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_epoch as epoch; + /// + /// let guard1 = epoch::pin(); + /// let guard2 = epoch::pin(); + /// assert!(guard1.collector() == guard2.collector()); + /// ``` + pub fn collector(&self) -> Option<&Collector> { + unsafe { self.local.as_ref().map(|local| local.collector()) } + } +} + +impl Drop for Guard { + #[inline] + fn drop(&mut self) { + if let Some(local) = unsafe { self.local.as_ref() } { + local.unpin(); + } + } +} + +impl fmt::Debug for Guard { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Guard { .. }") + } +} + +/// Returns a reference to a dummy guard that allows unprotected access to [`Atomic`]s. +/// +/// This guard should be used in special occasions only. Note that it doesn't actually keep any +/// thread pinned - it's just a fake guard that allows loading from [`Atomic`]s unsafely. +/// +/// Note that calling [`defer`] with a dummy guard will not defer the function - it will just +/// execute the function immediately. +/// +/// If necessary, it's possible to create more dummy guards by cloning: `unprotected().clone()`. +/// +/// # Safety +/// +/// Loading and dereferencing data from an [`Atomic`] using this guard is safe only if the +/// [`Atomic`] is not being concurrently modified by other threads. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_epoch::{self as epoch, Atomic}; +/// use std::sync::atomic::Ordering::Relaxed; +/// +/// let a = Atomic::new(7); +/// +/// unsafe { +/// // Load `a` without pinning the current thread. +/// a.load(Relaxed, epoch::unprotected()); +/// +/// // It's possible to create more dummy guards. +/// let dummy = epoch::unprotected(); +/// +/// dummy.defer(move || { +/// println!("This gets executed immediately."); +/// }); +/// +/// // Dropping `dummy` doesn't affect the current thread - it's just a noop. +/// } +/// # unsafe { drop(a.into_owned()); } // avoid leak +/// ``` +/// +/// The most common use of this function is when constructing or destructing a data structure. +/// +/// For example, we can use a dummy guard in the destructor of a Treiber stack because at that +/// point no other thread could concurrently modify the [`Atomic`]s we are accessing. +/// +/// If we were to actually pin the current thread during destruction, that would just unnecessarily +/// delay garbage collection and incur some performance cost, so in cases like these `unprotected` +/// is very helpful. +/// +/// ``` +/// use crossbeam_epoch::{self as epoch, Atomic}; +/// use std::mem::ManuallyDrop; +/// use std::sync::atomic::Ordering::Relaxed; +/// +/// struct Stack { +/// head: Atomic>, +/// } +/// +/// struct Node { +/// data: ManuallyDrop, +/// next: Atomic>, +/// } +/// +/// impl Drop for Stack { +/// fn drop(&mut self) { +/// unsafe { +/// // Unprotected load. +/// let mut node = self.head.load(Relaxed, epoch::unprotected()); +/// +/// while let Some(n) = node.as_ref() { +/// // Unprotected load. +/// let next = n.next.load(Relaxed, epoch::unprotected()); +/// +/// // Take ownership of the node, then drop its data and deallocate it. +/// let mut o = node.into_owned(); +/// ManuallyDrop::drop(&mut o.data); +/// drop(o); +/// +/// node = next; +/// } +/// } +/// } +/// } +/// ``` +/// +/// [`Atomic`]: super::Atomic +/// [`defer`]: Guard::defer +#[inline] +pub unsafe fn unprotected() -> &'static Guard { + // An unprotected guard is just a `Guard` with its field `local` set to null. + // We make a newtype over `Guard` because `Guard` isn't `Sync`, so can't be directly stored in + // a `static` + struct GuardWrapper(Guard); + unsafe impl Sync for GuardWrapper {} + static UNPROTECTED: GuardWrapper = GuardWrapper(Guard { + local: core::ptr::null(), + }); + &UNPROTECTED.0 +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/internal.rs b/anneal/v2/vendor/crossbeam-epoch/src/internal.rs new file mode 100644 index 0000000000..b2e9e71bcb --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/internal.rs @@ -0,0 +1,600 @@ +//! The global data and participant for garbage collection. +//! +//! # Registration +//! +//! In order to track all participants in one place, we need some form of participant +//! registration. When a participant is created, it is registered to a global lock-free +//! singly-linked list of registries; and when a participant is leaving, it is unregistered from the +//! list. +//! +//! # Pinning +//! +//! Every participant contains an integer that tells whether the participant is pinned and if so, +//! what was the global epoch at the time it was pinned. Participants also hold a pin counter that +//! aids in periodic global epoch advancement. +//! +//! When a participant is pinned, a `Guard` is returned as a witness that the participant is pinned. +//! Guards are necessary for performing atomic operations, and for freeing/dropping locations. +//! +//! # Thread-local bag +//! +//! Objects that get unlinked from concurrent data structures must be stashed away until the global +//! epoch sufficiently advances so that they become safe for destruction. Pointers to such objects +//! are pushed into a thread-local bag, and when it becomes full, the bag is marked with the current +//! global epoch and pushed into the global queue of bags. We store objects in thread-local storages +//! for amortizing the synchronization cost of pushing the garbages to a global queue. +//! +//! # Global queue +//! +//! Whenever a bag is pushed into a queue, the objects in some bags in the queue are collected and +//! destroyed along the way. This design reduces contention on data structures. The global queue +//! cannot be explicitly accessed: the only way to interact with it is by calling functions +//! `defer()` that adds an object to the thread-local bag, or `collect()` that manually triggers +//! garbage collection. +//! +//! Ideally each instance of concurrent data structure may have its own queue that gets fully +//! destroyed as soon as the data structure gets dropped. + +use crate::primitive::cell::UnsafeCell; +use crate::primitive::sync::atomic::{self, Ordering}; +use core::cell::Cell; +use core::mem::{self, ManuallyDrop}; +use core::num::Wrapping; +use core::{fmt, ptr}; + +use crossbeam_utils::CachePadded; + +use crate::atomic::{Owned, Shared}; +use crate::collector::{Collector, LocalHandle}; +use crate::deferred::Deferred; +use crate::epoch::{AtomicEpoch, Epoch}; +use crate::guard::{unprotected, Guard}; +use crate::sync::list::{Entry, IsElement, IterError, List}; +use crate::sync::queue::Queue; + +/// Maximum number of objects a bag can contain. +#[cfg(not(any(crossbeam_sanitize, miri)))] +const MAX_OBJECTS: usize = 64; +// Makes it more likely to trigger any potential data races. +#[cfg(any(crossbeam_sanitize, miri))] +const MAX_OBJECTS: usize = 4; + +/// A bag of deferred functions. +pub(crate) struct Bag { + /// Stashed objects. + deferreds: [Deferred; MAX_OBJECTS], + len: usize, +} + +/// `Bag::try_push()` requires that it is safe for another thread to execute the given functions. +unsafe impl Send for Bag {} + +impl Bag { + /// Returns a new, empty bag. + pub(crate) fn new() -> Self { + Self::default() + } + + /// Returns `true` if the bag is empty. + pub(crate) fn is_empty(&self) -> bool { + self.len == 0 + } + + /// Attempts to insert a deferred function into the bag. + /// + /// Returns `Ok(())` if successful, and `Err(deferred)` for the given `deferred` if the bag is + /// full. + /// + /// # Safety + /// + /// It should be safe for another thread to execute the given function. + pub(crate) unsafe fn try_push(&mut self, deferred: Deferred) -> Result<(), Deferred> { + if self.len < MAX_OBJECTS { + self.deferreds[self.len] = deferred; + self.len += 1; + Ok(()) + } else { + Err(deferred) + } + } + + /// Seals the bag with the given epoch. + fn seal(self, epoch: Epoch) -> SealedBag { + SealedBag { epoch, _bag: self } + } +} + +impl Default for Bag { + fn default() -> Self { + Bag { + len: 0, + deferreds: [Deferred::NO_OP; MAX_OBJECTS], + } + } +} + +impl Drop for Bag { + fn drop(&mut self) { + // Call all deferred functions. + for deferred in &mut self.deferreds[..self.len] { + let no_op = Deferred::NO_OP; + let owned_deferred = mem::replace(deferred, no_op); + owned_deferred.call(); + } + } +} + +// can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long +impl fmt::Debug for Bag { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Bag") + .field("deferreds", &&self.deferreds[..self.len]) + .finish() + } +} + +/// A pair of an epoch and a bag. +#[derive(Default, Debug)] +struct SealedBag { + epoch: Epoch, + _bag: Bag, +} + +/// It is safe to share `SealedBag` because `is_expired` only inspects the epoch. +unsafe impl Sync for SealedBag {} + +impl SealedBag { + /// Checks if it is safe to drop the bag w.r.t. the given global epoch. + fn is_expired(&self, global_epoch: Epoch) -> bool { + // A pinned participant can witness at most one epoch advancement. Therefore, any bag that + // is within one epoch of the current one cannot be destroyed yet. + global_epoch.wrapping_sub(self.epoch) >= 2 + } +} + +/// The global data for a garbage collector. +pub(crate) struct Global { + /// The intrusive linked list of `Local`s. + locals: List, + + /// The global queue of bags of deferred functions. + queue: Queue, + + /// The global epoch. + pub(crate) epoch: CachePadded, +} + +impl Global { + /// Number of bags to destroy. + const COLLECT_STEPS: usize = 8; + + /// Creates a new global data for garbage collection. + #[inline] + pub(crate) fn new() -> Self { + Self { + locals: List::new(), + queue: Queue::new(), + epoch: CachePadded::new(AtomicEpoch::new(Epoch::starting())), + } + } + + /// Pushes the bag into the global queue and replaces the bag with a new empty bag. + pub(crate) fn push_bag(&self, bag: &mut Bag, guard: &Guard) { + let bag = mem::replace(bag, Bag::new()); + + atomic::fence(Ordering::SeqCst); + + let epoch = self.epoch.load(Ordering::Relaxed); + self.queue.push(bag.seal(epoch), guard); + } + + /// Collects several bags from the global queue and executes deferred functions in them. + /// + /// Note: This may itself produce garbage and in turn allocate new bags. + /// + /// `pin()` rarely calls `collect()`, so we want the compiler to place that call on a cold + /// path. In other words, we want the compiler to optimize branching for the case when + /// `collect()` is not called. + #[cold] + pub(crate) fn collect(&self, guard: &Guard) { + let global_epoch = self.try_advance(guard); + + let steps = if cfg!(crossbeam_sanitize) { + usize::max_value() + } else { + Self::COLLECT_STEPS + }; + + for _ in 0..steps { + match self.queue.try_pop_if( + &|sealed_bag: &SealedBag| sealed_bag.is_expired(global_epoch), + guard, + ) { + None => break, + Some(sealed_bag) => drop(sealed_bag), + } + } + } + + /// Attempts to advance the global epoch. + /// + /// The global epoch can advance only if all currently pinned participants have been pinned in + /// the current epoch. + /// + /// Returns the current global epoch. + /// + /// `try_advance()` is annotated `#[cold]` because it is rarely called. + #[cold] + pub(crate) fn try_advance(&self, guard: &Guard) -> Epoch { + let global_epoch = self.epoch.load(Ordering::Relaxed); + atomic::fence(Ordering::SeqCst); + + // TODO(stjepang): `Local`s are stored in a linked list because linked lists are fairly + // easy to implement in a lock-free manner. However, traversal can be slow due to cache + // misses and data dependencies. We should experiment with other data structures as well. + for local in self.locals.iter(guard) { + match local { + Err(IterError::Stalled) => { + // A concurrent thread stalled this iteration. That thread might also try to + // advance the epoch, in which case we leave the job to it. Otherwise, the + // epoch will not be advanced. + return global_epoch; + } + Ok(local) => { + let local_epoch = local.epoch.load(Ordering::Relaxed); + + // If the participant was pinned in a different epoch, we cannot advance the + // global epoch just yet. + if local_epoch.is_pinned() && local_epoch.unpinned() != global_epoch { + return global_epoch; + } + } + } + } + atomic::fence(Ordering::Acquire); + + // All pinned participants were pinned in the current global epoch. + // Now let's advance the global epoch... + // + // Note that if another thread already advanced it before us, this store will simply + // overwrite the global epoch with the same value. This is true because `try_advance` was + // called from a thread that was pinned in `global_epoch`, and the global epoch cannot be + // advanced two steps ahead of it. + let new_epoch = global_epoch.successor(); + self.epoch.store(new_epoch, Ordering::Release); + new_epoch + } +} + +/// Participant for garbage collection. +#[repr(C)] // Note: `entry` must be the first field +pub(crate) struct Local { + /// A node in the intrusive linked list of `Local`s. + entry: Entry, + + /// A reference to the global data. + /// + /// When all guards and handles get dropped, this reference is destroyed. + collector: UnsafeCell>, + + /// The local bag of deferred functions. + pub(crate) bag: UnsafeCell, + + /// The number of guards keeping this participant pinned. + guard_count: Cell, + + /// The number of active handles. + handle_count: Cell, + + /// Total number of pinnings performed. + /// + /// This is just an auxiliary counter that sometimes kicks off collection. + pin_count: Cell>, + + /// The local epoch. + epoch: CachePadded, +} + +// Make sure `Local` is less than or equal to 2048 bytes. +// https://github.com/crossbeam-rs/crossbeam/issues/551 +#[cfg(not(any(crossbeam_sanitize, miri)))] // `crossbeam_sanitize` and `miri` reduce the size of `Local` +#[test] +fn local_size() { + // TODO: https://github.com/crossbeam-rs/crossbeam/issues/869 + // assert!( + // core::mem::size_of::() <= 2048, + // "An allocation of `Local` should be <= 2048 bytes." + // ); +} + +impl Local { + /// Number of pinnings after which a participant will execute some deferred functions from the + /// global queue. + const PINNINGS_BETWEEN_COLLECT: usize = 128; + + /// Registers a new `Local` in the provided `Global`. + pub(crate) fn register(collector: &Collector) -> LocalHandle { + unsafe { + // Since we dereference no pointers in this block, it is safe to use `unprotected`. + + let local = Owned::new(Local { + entry: Entry::default(), + collector: UnsafeCell::new(ManuallyDrop::new(collector.clone())), + bag: UnsafeCell::new(Bag::new()), + guard_count: Cell::new(0), + handle_count: Cell::new(1), + pin_count: Cell::new(Wrapping(0)), + epoch: CachePadded::new(AtomicEpoch::new(Epoch::starting())), + }) + .into_shared(unprotected()); + collector.global.locals.insert(local, unprotected()); + LocalHandle { + local: local.as_raw(), + } + } + } + + /// Returns a reference to the `Global` in which this `Local` resides. + #[inline] + pub(crate) fn global(&self) -> &Global { + &self.collector().global + } + + /// Returns a reference to the `Collector` in which this `Local` resides. + #[inline] + pub(crate) fn collector(&self) -> &Collector { + self.collector.with(|c| unsafe { &**c }) + } + + /// Returns `true` if the current participant is pinned. + #[inline] + pub(crate) fn is_pinned(&self) -> bool { + self.guard_count.get() > 0 + } + + /// Adds `deferred` to the thread-local bag. + /// + /// # Safety + /// + /// It should be safe for another thread to execute the given function. + pub(crate) unsafe fn defer(&self, mut deferred: Deferred, guard: &Guard) { + let bag = self.bag.with_mut(|b| &mut *b); + + while let Err(d) = bag.try_push(deferred) { + self.global().push_bag(bag, guard); + deferred = d; + } + } + + pub(crate) fn flush(&self, guard: &Guard) { + let bag = self.bag.with_mut(|b| unsafe { &mut *b }); + + if !bag.is_empty() { + self.global().push_bag(bag, guard); + } + + self.global().collect(guard); + } + + /// Pins the `Local`. + #[inline] + pub(crate) fn pin(&self) -> Guard { + let guard = Guard { local: self }; + + let guard_count = self.guard_count.get(); + self.guard_count.set(guard_count.checked_add(1).unwrap()); + + if guard_count == 0 { + let global_epoch = self.global().epoch.load(Ordering::Relaxed); + let new_epoch = global_epoch.pinned(); + + // Now we must store `new_epoch` into `self.epoch` and execute a `SeqCst` fence. + // The fence makes sure that any future loads from `Atomic`s will not happen before + // this store. + if cfg!(all( + any(target_arch = "x86", target_arch = "x86_64"), + not(miri) + )) { + // HACK(stjepang): On x86 architectures there are two different ways of executing + // a `SeqCst` fence. + // + // 1. `atomic::fence(SeqCst)`, which compiles into a `mfence` instruction. + // 2. `_.compare_exchange(_, _, SeqCst, SeqCst)`, which compiles into a `lock cmpxchg` + // instruction. + // + // Both instructions have the effect of a full barrier, but benchmarks have shown + // that the second one makes pinning faster in this particular case. It is not + // clear that this is permitted by the C++ memory model (SC fences work very + // differently from SC accesses), but experimental evidence suggests that this + // works fine. Using inline assembly would be a viable (and correct) alternative, + // but alas, that is not possible on stable Rust. + let current = Epoch::starting(); + let res = self.epoch.compare_exchange( + current, + new_epoch, + Ordering::SeqCst, + Ordering::SeqCst, + ); + debug_assert!(res.is_ok(), "participant was expected to be unpinned"); + // We add a compiler fence to make it less likely for LLVM to do something wrong + // here. Formally, this is not enough to get rid of data races; practically, + // it should go a long way. + atomic::compiler_fence(Ordering::SeqCst); + } else { + self.epoch.store(new_epoch, Ordering::Relaxed); + atomic::fence(Ordering::SeqCst); + } + + // Increment the pin counter. + let count = self.pin_count.get(); + self.pin_count.set(count + Wrapping(1)); + + // After every `PINNINGS_BETWEEN_COLLECT` try advancing the epoch and collecting + // some garbage. + if count.0 % Self::PINNINGS_BETWEEN_COLLECT == 0 { + self.global().collect(&guard); + } + } + + guard + } + + /// Unpins the `Local`. + #[inline] + pub(crate) fn unpin(&self) { + let guard_count = self.guard_count.get(); + self.guard_count.set(guard_count - 1); + + if guard_count == 1 { + self.epoch.store(Epoch::starting(), Ordering::Release); + + if self.handle_count.get() == 0 { + self.finalize(); + } + } + } + + /// Unpins and then pins the `Local`. + #[inline] + pub(crate) fn repin(&self) { + let guard_count = self.guard_count.get(); + + // Update the local epoch only if there's only one guard. + if guard_count == 1 { + let epoch = self.epoch.load(Ordering::Relaxed); + let global_epoch = self.global().epoch.load(Ordering::Relaxed).pinned(); + + // Update the local epoch only if the global epoch is greater than the local epoch. + if epoch != global_epoch { + // We store the new epoch with `Release` because we need to ensure any memory + // accesses from the previous epoch do not leak into the new one. + self.epoch.store(global_epoch, Ordering::Release); + + // However, we don't need a following `SeqCst` fence, because it is safe for memory + // accesses from the new epoch to be executed before updating the local epoch. At + // worse, other threads will see the new epoch late and delay GC slightly. + } + } + } + + /// Increments the handle count. + #[inline] + pub(crate) fn acquire_handle(&self) { + let handle_count = self.handle_count.get(); + debug_assert!(handle_count >= 1); + self.handle_count.set(handle_count + 1); + } + + /// Decrements the handle count. + #[inline] + pub(crate) fn release_handle(&self) { + let guard_count = self.guard_count.get(); + let handle_count = self.handle_count.get(); + debug_assert!(handle_count >= 1); + self.handle_count.set(handle_count - 1); + + if guard_count == 0 && handle_count == 1 { + self.finalize(); + } + } + + /// Removes the `Local` from the global linked list. + #[cold] + fn finalize(&self) { + debug_assert_eq!(self.guard_count.get(), 0); + debug_assert_eq!(self.handle_count.get(), 0); + + // Temporarily increment handle count. This is required so that the following call to `pin` + // doesn't call `finalize` again. + self.handle_count.set(1); + unsafe { + // Pin and move the local bag into the global queue. It's important that `push_bag` + // doesn't defer destruction on any new garbage. + let guard = &self.pin(); + self.global() + .push_bag(self.bag.with_mut(|b| &mut *b), guard); + } + // Revert the handle count back to zero. + self.handle_count.set(0); + + unsafe { + // Take the reference to the `Global` out of this `Local`. Since we're not protected + // by a guard at this time, it's crucial that the reference is read before marking the + // `Local` as deleted. + let collector: Collector = ptr::read(self.collector.with(|c| &*(*c))); + + // Mark this node in the linked list as deleted. + self.entry.delete(unprotected()); + + // Finally, drop the reference to the global. Note that this might be the last reference + // to the `Global`. If so, the global data will be destroyed and all deferred functions + // in its queue will be executed. + drop(collector); + } + } +} + +impl IsElement for Local { + fn entry_of(local: &Self) -> &Entry { + // SAFETY: `Local` is `repr(C)` and `entry` is the first field of it. + unsafe { + let entry_ptr = (local as *const Self).cast::(); + &*entry_ptr + } + } + + unsafe fn element_of(entry: &Entry) -> &Self { + // SAFETY: `Local` is `repr(C)` and `entry` is the first field of it. + let local_ptr = (entry as *const Entry).cast::(); + &*local_ptr + } + + unsafe fn finalize(entry: &Entry, guard: &Guard) { + guard.defer_destroy(Shared::from(Self::element_of(entry) as *const _)); + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use std::sync::atomic::{AtomicUsize, Ordering}; + + use super::*; + + #[test] + fn check_defer() { + static FLAG: AtomicUsize = AtomicUsize::new(0); + fn set() { + FLAG.store(42, Ordering::Relaxed); + } + + let d = Deferred::new(set); + assert_eq!(FLAG.load(Ordering::Relaxed), 0); + d.call(); + assert_eq!(FLAG.load(Ordering::Relaxed), 42); + } + + #[test] + fn check_bag() { + static FLAG: AtomicUsize = AtomicUsize::new(0); + fn incr() { + FLAG.fetch_add(1, Ordering::Relaxed); + } + + let mut bag = Bag::new(); + assert!(bag.is_empty()); + + for _ in 0..MAX_OBJECTS { + assert!(unsafe { bag.try_push(Deferred::new(incr)).is_ok() }); + assert!(!bag.is_empty()); + assert_eq!(FLAG.load(Ordering::Relaxed), 0); + } + + let result = unsafe { bag.try_push(Deferred::new(incr)) }; + assert!(result.is_err()); + assert!(!bag.is_empty()); + assert_eq!(FLAG.load(Ordering::Relaxed), 0); + + drop(bag); + assert_eq!(FLAG.load(Ordering::Relaxed), MAX_OBJECTS); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/lib.rs b/anneal/v2/vendor/crossbeam-epoch/src/lib.rs new file mode 100644 index 0000000000..fd4d74bedb --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/lib.rs @@ -0,0 +1,166 @@ +//! Epoch-based memory reclamation. +//! +//! An interesting problem concurrent collections deal with comes from the remove operation. +//! Suppose that a thread removes an element from a lock-free map, while another thread is reading +//! that same element at the same time. The first thread must wait until the second thread stops +//! reading the element. Only then it is safe to destruct it. +//! +//! Programming languages that come with garbage collectors solve this problem trivially. The +//! garbage collector will destruct the removed element when no thread can hold a reference to it +//! anymore. +//! +//! This crate implements a basic memory reclamation mechanism, which is based on epochs. When an +//! element gets removed from a concurrent collection, it is inserted into a pile of garbage and +//! marked with the current epoch. Every time a thread accesses a collection, it checks the current +//! epoch, attempts to increment it, and destructs some garbage that became so old that no thread +//! can be referencing it anymore. +//! +//! That is the general mechanism behind epoch-based memory reclamation, but the details are a bit +//! more complicated. Anyhow, memory reclamation is designed to be fully automatic and something +//! users of concurrent collections don't have to worry much about. +//! +//! # Pointers +//! +//! Concurrent collections are built using atomic pointers. This module provides [`Atomic`], which +//! is just a shared atomic pointer to a heap-allocated object. Loading an [`Atomic`] yields a +//! [`Shared`], which is an epoch-protected pointer through which the loaded object can be safely +//! read. +//! +//! # Pinning +//! +//! Before an [`Atomic`] can be loaded, a participant must be [`pin`]ned. By pinning a participant +//! we declare that any object that gets removed from now on must not be destructed just +//! yet. Garbage collection of newly removed objects is suspended until the participant gets +//! unpinned. +//! +//! # Garbage +//! +//! Objects that get removed from concurrent collections must be stashed away until all currently +//! pinned participants get unpinned. Such objects can be stored into a thread-local or global +//! storage, where they are kept until the right time for their destruction comes. +//! +//! There is a global shared instance of garbage queue. You can [`defer`](Guard::defer) the execution of an +//! arbitrary function until the global epoch is advanced enough. Most notably, concurrent data +//! structures may defer the deallocation of an object. +//! +//! # APIs +//! +//! For majority of use cases, just use the default garbage collector by invoking [`pin`]. If you +//! want to create your own garbage collector, use the [`Collector`] API. + +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn( + missing_docs, + missing_debug_implementations, + rust_2018_idioms, + unreachable_pub +)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(crossbeam_loom)] +extern crate loom_crate as loom; + +#[cfg(crossbeam_loom)] +#[allow(unused_imports, dead_code)] +mod primitive { + pub(crate) mod cell { + pub(crate) use loom::cell::UnsafeCell; + } + pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use loom::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering}; + + // FIXME: loom does not support compiler_fence at the moment. + // https://github.com/tokio-rs/loom/issues/117 + // we use fence as a stand-in for compiler_fence for the time being. + // this may miss some races since fence is stronger than compiler_fence, + // but it's the best we can do for the time being. + pub(crate) use self::fence as compiler_fence; + } + pub(crate) use loom::sync::Arc; + } + pub(crate) use loom::thread_local; +} +#[cfg(target_has_atomic = "ptr")] +#[cfg(not(crossbeam_loom))] +#[allow(unused_imports, dead_code)] +mod primitive { + pub(crate) mod cell { + #[derive(Debug)] + #[repr(transparent)] + pub(crate) struct UnsafeCell(::core::cell::UnsafeCell); + + // loom's UnsafeCell has a slightly different API than the standard library UnsafeCell. + // Since we want the rest of the code to be agnostic to whether it's running under loom or + // not, we write this small wrapper that provides the loom-supported API for the standard + // library UnsafeCell. This is also what the loom documentation recommends: + // https://github.com/tokio-rs/loom#handling-loom-api-differences + impl UnsafeCell { + #[inline] + pub(crate) const fn new(data: T) -> UnsafeCell { + UnsafeCell(::core::cell::UnsafeCell::new(data)) + } + + #[inline] + pub(crate) fn with(&self, f: impl FnOnce(*const T) -> R) -> R { + f(self.0.get()) + } + + #[inline] + pub(crate) fn with_mut(&self, f: impl FnOnce(*mut T) -> R) -> R { + f(self.0.get()) + } + } + } + pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use core::sync::atomic::{ + compiler_fence, fence, AtomicPtr, AtomicUsize, Ordering, + }; + } + #[cfg(feature = "alloc")] + pub(crate) use alloc::sync::Arc; + } + + #[cfg(feature = "std")] + pub(crate) use std::thread_local; +} + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +extern crate alloc; + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod atomic; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod collector; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod deferred; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod epoch; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod guard; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod internal; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +mod sync; + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +#[allow(deprecated)] +pub use crate::atomic::{CompareAndSetError, CompareAndSetOrdering}; +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +pub use crate::{ + atomic::{Atomic, CompareExchangeError, Owned, Pointable, Pointer, Shared}, + collector::{Collector, LocalHandle}, + guard::{unprotected, Guard}, +}; + +#[cfg(feature = "std")] +mod default; +#[cfg(feature = "std")] +pub use crate::default::{default_collector, is_pinned, pin}; diff --git a/anneal/v2/vendor/crossbeam-epoch/src/sync/list.rs b/anneal/v2/vendor/crossbeam-epoch/src/sync/list.rs new file mode 100644 index 0000000000..52ffd6fca4 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/sync/list.rs @@ -0,0 +1,487 @@ +//! Lock-free intrusive linked list. +//! +//! Ideas from Michael. High Performance Dynamic Lock-Free Hash Tables and List-Based Sets. SPAA +//! 2002. + +use core::marker::PhantomData; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; + +use crate::{unprotected, Atomic, Guard, Shared}; + +/// An entry in a linked list. +/// +/// An Entry is accessed from multiple threads, so it would be beneficial to put it in a different +/// cache-line than thread-local data in terms of performance. +#[derive(Debug)] +pub(crate) struct Entry { + /// The next entry in the linked list. + /// If the tag is 1, this entry is marked as deleted. + next: Atomic, +} + +/// Implementing this trait asserts that the type `T` can be used as an element in the intrusive +/// linked list defined in this module. `T` has to contain (or otherwise be linked to) an instance +/// of `Entry`. +/// +/// # Example +/// +/// ```ignore +/// struct A { +/// entry: Entry, +/// data: usize, +/// } +/// +/// impl IsElement for A { +/// fn entry_of(a: &A) -> &Entry { +/// let entry_ptr = ((a as usize) + offset_of!(A, entry)) as *const Entry; +/// unsafe { &*entry_ptr } +/// } +/// +/// unsafe fn element_of(entry: &Entry) -> &T { +/// let elem_ptr = ((entry as usize) - offset_of!(A, entry)) as *const T; +/// &*elem_ptr +/// } +/// +/// unsafe fn finalize(entry: &Entry, guard: &Guard) { +/// guard.defer_destroy(Shared::from(Self::element_of(entry) as *const _)); +/// } +/// } +/// ``` +/// +/// This trait is implemented on a type separate from `T` (although it can be just `T`), because +/// one type might be placeable into multiple lists, in which case it would require multiple +/// implementations of `IsElement`. In such cases, each struct implementing `IsElement` +/// represents a distinct `Entry` in `T`. +/// +/// For example, we can insert the following struct into two lists using `entry1` for one +/// and `entry2` for the other: +/// +/// ```ignore +/// struct B { +/// entry1: Entry, +/// entry2: Entry, +/// data: usize, +/// } +/// ``` +/// +pub(crate) trait IsElement { + /// Returns a reference to this element's `Entry`. + fn entry_of(_: &T) -> &Entry; + + /// Given a reference to an element's entry, returns that element. + /// + /// ```ignore + /// let elem = ListElement::new(); + /// assert_eq!(elem.entry_of(), + /// unsafe { ListElement::element_of(elem.entry_of()) } ); + /// ``` + /// + /// # Safety + /// + /// The caller has to guarantee that the `Entry` is called with was retrieved from an instance + /// of the element type (`T`). + unsafe fn element_of(_: &Entry) -> &T; + + /// The function that is called when an entry is unlinked from list. + /// + /// # Safety + /// + /// The caller has to guarantee that the `Entry` is called with was retrieved from an instance + /// of the element type (`T`). + unsafe fn finalize(_: &Entry, _: &Guard); +} + +/// A lock-free, intrusive linked list of type `T`. +#[derive(Debug)] +pub(crate) struct List = T> { + /// The head of the linked list. + head: Atomic, + + /// The phantom data for using `T` and `C`. + _marker: PhantomData<(T, C)>, +} + +/// An iterator used for retrieving values from the list. +pub(crate) struct Iter<'g, T, C: IsElement> { + /// The guard that protects the iteration. + guard: &'g Guard, + + /// Pointer from the predecessor to the current entry. + pred: &'g Atomic, + + /// The current entry. + curr: Shared<'g, Entry>, + + /// The list head, needed for restarting iteration. + head: &'g Atomic, + + /// Logically, we store a borrow of an instance of `T` and + /// use the type information from `C`. + _marker: PhantomData<(&'g T, C)>, +} + +/// An error that occurs during iteration over the list. +#[derive(PartialEq, Debug)] +pub(crate) enum IterError { + /// A concurrent thread modified the state of the list at the same place that this iterator + /// was inspecting. Subsequent iteration will restart from the beginning of the list. + Stalled, +} + +impl Default for Entry { + /// Returns the empty entry. + fn default() -> Self { + Self { + next: Atomic::null(), + } + } +} + +impl Entry { + /// Marks this entry as deleted, deferring the actual deallocation to a later iteration. + /// + /// # Safety + /// + /// The entry should be a member of a linked list, and it should not have been deleted. + /// It should be safe to call `C::finalize` on the entry after the `guard` is dropped, where `C` + /// is the associated helper for the linked list. + pub(crate) unsafe fn delete(&self, guard: &Guard) { + self.next.fetch_or(1, Release, guard); + } +} + +impl> List { + /// Returns a new, empty linked list. + pub(crate) fn new() -> Self { + Self { + head: Atomic::null(), + _marker: PhantomData, + } + } + + /// Inserts `entry` into the head of the list. + /// + /// # Safety + /// + /// You should guarantee that: + /// + /// - `container` is not null + /// - `container` is immovable, e.g. inside an `Owned` + /// - the same `Entry` is not inserted more than once + /// - the inserted object will be removed before the list is dropped + pub(crate) unsafe fn insert<'g>(&'g self, container: Shared<'g, T>, guard: &'g Guard) { + // Insert right after head, i.e. at the beginning of the list. + let to = &self.head; + // Get the intrusively stored Entry of the new element to insert. + let entry: &Entry = C::entry_of(container.deref()); + // Make a Shared ptr to that Entry. + let entry_ptr = Shared::from(entry as *const _); + // Read the current successor of where we want to insert. + let mut next = to.load(Relaxed, guard); + + loop { + // Set the Entry of the to-be-inserted element to point to the previous successor of + // `to`. + entry.next.store(next, Relaxed); + match to.compare_exchange_weak(next, entry_ptr, Release, Relaxed, guard) { + Ok(_) => break, + // We lost the race or weak CAS failed spuriously. Update the successor and try + // again. + Err(err) => next = err.current, + } + } + } + + /// Returns an iterator over all objects. + /// + /// # Caveat + /// + /// Every object that is inserted at the moment this function is called and persists at least + /// until the end of iteration will be returned. Since this iterator traverses a lock-free + /// linked list that may be concurrently modified, some additional caveats apply: + /// + /// 1. If a new object is inserted during iteration, it may or may not be returned. + /// 2. If an object is deleted during iteration, it may or may not be returned. + /// 3. The iteration may be aborted when it lost in a race condition. In this case, the winning + /// thread will continue to iterate over the same list. + pub(crate) fn iter<'g>(&'g self, guard: &'g Guard) -> Iter<'g, T, C> { + Iter { + guard, + pred: &self.head, + curr: self.head.load(Acquire, guard), + head: &self.head, + _marker: PhantomData, + } + } +} + +impl> Drop for List { + fn drop(&mut self) { + unsafe { + let guard = unprotected(); + let mut curr = self.head.load(Relaxed, guard); + while let Some(c) = curr.as_ref() { + let succ = c.next.load(Relaxed, guard); + // Verify that all elements have been removed from the list. + assert_eq!(succ.tag(), 1); + + C::finalize(curr.deref(), guard); + curr = succ; + } + } + } +} + +impl<'g, T: 'g, C: IsElement> Iterator for Iter<'g, T, C> { + type Item = Result<&'g T, IterError>; + + fn next(&mut self) -> Option { + while let Some(c) = unsafe { self.curr.as_ref() } { + let succ = c.next.load(Acquire, self.guard); + + if succ.tag() == 1 { + // This entry was removed. Try unlinking it from the list. + let succ = succ.with_tag(0); + + // The tag should always be zero, because removing a node after a logically deleted + // node leaves the list in an invalid state. + debug_assert!(self.curr.tag() == 0); + + // Try to unlink `curr` from the list, and get the new value of `self.pred`. + let succ = match self + .pred + .compare_exchange(self.curr, succ, Acquire, Acquire, self.guard) + { + Ok(_) => { + // We succeeded in unlinking `curr`, so we have to schedule + // deallocation. Deferred drop is okay, because `list.delete()` can only be + // called if `T: 'static`. + unsafe { + C::finalize(self.curr.deref(), self.guard); + } + + // `succ` is the new value of `self.pred`. + succ + } + Err(e) => { + // `e.current` is the current value of `self.pred`. + e.current + } + }; + + // If the predecessor node is already marked as deleted, we need to restart from + // `head`. + if succ.tag() != 0 { + self.pred = self.head; + self.curr = self.head.load(Acquire, self.guard); + + return Some(Err(IterError::Stalled)); + } + + // Move over the removed by only advancing `curr`, not `pred`. + self.curr = succ; + continue; + } + + // Move one step forward. + self.pred = &c.next; + self.curr = succ; + + return Some(Ok(unsafe { C::element_of(c) })); + } + + // We reached the end of the list. + None + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod tests { + use super::*; + use crate::{Collector, Owned}; + use crossbeam_utils::thread; + use std::sync::Barrier; + + impl IsElement for Entry { + fn entry_of(entry: &Entry) -> &Entry { + entry + } + + unsafe fn element_of(entry: &Entry) -> &Entry { + entry + } + + unsafe fn finalize(entry: &Entry, guard: &Guard) { + guard.defer_destroy(Shared::from(Self::element_of(entry) as *const _)); + } + } + + /// Checks whether the list retains inserted elements + /// and returns them in the correct order. + #[test] + fn insert() { + let collector = Collector::new(); + let handle = collector.register(); + let guard = handle.pin(); + + let l: List = List::new(); + + let e1 = Owned::new(Entry::default()).into_shared(&guard); + let e2 = Owned::new(Entry::default()).into_shared(&guard); + let e3 = Owned::new(Entry::default()).into_shared(&guard); + + unsafe { + l.insert(e1, &guard); + l.insert(e2, &guard); + l.insert(e3, &guard); + } + + let mut iter = l.iter(&guard); + let maybe_e3 = iter.next(); + assert!(maybe_e3.is_some()); + assert!(maybe_e3.unwrap().unwrap() as *const Entry == e3.as_raw()); + let maybe_e2 = iter.next(); + assert!(maybe_e2.is_some()); + assert!(maybe_e2.unwrap().unwrap() as *const Entry == e2.as_raw()); + let maybe_e1 = iter.next(); + assert!(maybe_e1.is_some()); + assert!(maybe_e1.unwrap().unwrap() as *const Entry == e1.as_raw()); + assert!(iter.next().is_none()); + + unsafe { + e1.as_ref().unwrap().delete(&guard); + e2.as_ref().unwrap().delete(&guard); + e3.as_ref().unwrap().delete(&guard); + } + } + + /// Checks whether elements can be removed from the list and whether + /// the correct elements are removed. + #[test] + fn delete() { + let collector = Collector::new(); + let handle = collector.register(); + let guard = handle.pin(); + + let l: List = List::new(); + + let e1 = Owned::new(Entry::default()).into_shared(&guard); + let e2 = Owned::new(Entry::default()).into_shared(&guard); + let e3 = Owned::new(Entry::default()).into_shared(&guard); + unsafe { + l.insert(e1, &guard); + l.insert(e2, &guard); + l.insert(e3, &guard); + e2.as_ref().unwrap().delete(&guard); + } + + let mut iter = l.iter(&guard); + let maybe_e3 = iter.next(); + assert!(maybe_e3.is_some()); + assert!(maybe_e3.unwrap().unwrap() as *const Entry == e3.as_raw()); + let maybe_e1 = iter.next(); + assert!(maybe_e1.is_some()); + assert!(maybe_e1.unwrap().unwrap() as *const Entry == e1.as_raw()); + assert!(iter.next().is_none()); + + unsafe { + e1.as_ref().unwrap().delete(&guard); + e3.as_ref().unwrap().delete(&guard); + } + + let mut iter = l.iter(&guard); + assert!(iter.next().is_none()); + } + + const THREADS: usize = 8; + const ITERS: usize = 512; + + /// Contends the list on insert and delete operations to make sure they can run concurrently. + #[test] + fn insert_delete_multi() { + let collector = Collector::new(); + + let l: List = List::new(); + let b = Barrier::new(THREADS); + + thread::scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + b.wait(); + + let handle = collector.register(); + let guard: Guard = handle.pin(); + let mut v = Vec::with_capacity(ITERS); + + for _ in 0..ITERS { + let e = Owned::new(Entry::default()).into_shared(&guard); + v.push(e); + unsafe { + l.insert(e, &guard); + } + } + + for e in v { + unsafe { + e.as_ref().unwrap().delete(&guard); + } + } + }); + } + }) + .unwrap(); + + let handle = collector.register(); + let guard = handle.pin(); + + let mut iter = l.iter(&guard); + assert!(iter.next().is_none()); + } + + /// Contends the list on iteration to make sure that it can be iterated over concurrently. + #[test] + fn iter_multi() { + let collector = Collector::new(); + + let l: List = List::new(); + let b = Barrier::new(THREADS); + + thread::scope(|s| { + for _ in 0..THREADS { + s.spawn(|_| { + b.wait(); + + let handle = collector.register(); + let guard: Guard = handle.pin(); + let mut v = Vec::with_capacity(ITERS); + + for _ in 0..ITERS { + let e = Owned::new(Entry::default()).into_shared(&guard); + v.push(e); + unsafe { + l.insert(e, &guard); + } + } + + let mut iter = l.iter(&guard); + for _ in 0..ITERS { + assert!(iter.next().is_some()); + } + + for e in v { + unsafe { + e.as_ref().unwrap().delete(&guard); + } + } + }); + } + }) + .unwrap(); + + let handle = collector.register(); + let guard = handle.pin(); + + let mut iter = l.iter(&guard); + assert!(iter.next().is_none()); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/sync/mod.rs b/anneal/v2/vendor/crossbeam-epoch/src/sync/mod.rs new file mode 100644 index 0000000000..08981be257 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/sync/mod.rs @@ -0,0 +1,7 @@ +//! Synchronization primitives. + +pub(crate) mod list; +#[cfg(feature = "std")] +#[cfg(not(crossbeam_loom))] +pub(crate) mod once_lock; +pub(crate) mod queue; diff --git a/anneal/v2/vendor/crossbeam-epoch/src/sync/once_lock.rs b/anneal/v2/vendor/crossbeam-epoch/src/sync/once_lock.rs new file mode 100644 index 0000000000..e057aca7d5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/sync/once_lock.rs @@ -0,0 +1,88 @@ +// Based on unstable std::sync::OnceLock. +// +// Source: https://github.com/rust-lang/rust/blob/8e9c93df464b7ada3fc7a1c8ccddd9dcb24ee0a0/library/std/src/sync/once_lock.rs + +use core::cell::UnsafeCell; +use core::mem::MaybeUninit; +use std::sync::Once; + +pub(crate) struct OnceLock { + once: Once, + value: UnsafeCell>, + // Unlike std::sync::OnceLock, we don't need PhantomData here because + // we don't use #[may_dangle]. +} + +unsafe impl Sync for OnceLock {} +unsafe impl Send for OnceLock {} + +impl OnceLock { + /// Creates a new empty cell. + #[must_use] + pub(crate) const fn new() -> Self { + Self { + once: Once::new(), + value: UnsafeCell::new(MaybeUninit::uninit()), + } + } + + /// Gets the contents of the cell, initializing it with `f` if the cell + /// was empty. + /// + /// Many threads may call `get_or_init` concurrently with different + /// initializing functions, but it is guaranteed that only one function + /// will be executed. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. The + /// exact outcome is unspecified. Current implementation deadlocks, but + /// this may be changed to a panic in the future. + pub(crate) fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + // Fast path check + if self.once.is_completed() { + // SAFETY: The inner value has been initialized + return unsafe { self.get_unchecked() }; + } + self.initialize(f); + + // SAFETY: The inner value has been initialized + unsafe { self.get_unchecked() } + } + + #[cold] + fn initialize(&self, f: F) + where + F: FnOnce() -> T, + { + let slot = self.value.get(); + + self.once.call_once(|| { + let value = f(); + unsafe { slot.write(MaybeUninit::new(value)) } + }); + } + + /// # Safety + /// + /// The value must be initialized + unsafe fn get_unchecked(&self) -> &T { + debug_assert!(self.once.is_completed()); + &*self.value.get().cast::() + } +} + +impl Drop for OnceLock { + fn drop(&mut self) { + if self.once.is_completed() { + // SAFETY: The inner value has been initialized + unsafe { (*self.value.get()).assume_init_drop() }; + } + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/src/sync/queue.rs b/anneal/v2/vendor/crossbeam-epoch/src/sync/queue.rs new file mode 100644 index 0000000000..76c326beb3 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/src/sync/queue.rs @@ -0,0 +1,468 @@ +//! Michael-Scott lock-free queue. +//! +//! Usable with any number of producers and consumers. +//! +//! Michael and Scott. Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue +//! Algorithms. PODC 1996. +//! +//! Simon Doherty, Lindsay Groves, Victor Luchangco, and Mark Moir. 2004b. Formal Verification of a +//! Practical Lock-Free Queue Algorithm. + +use core::mem::MaybeUninit; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; + +use crossbeam_utils::CachePadded; + +use crate::{unprotected, Atomic, Guard, Owned, Shared}; + +// The representation here is a singly-linked list, with a sentinel node at the front. In general +// the `tail` pointer may lag behind the actual tail. Non-sentinel nodes are either all `Data` or +// all `Blocked` (requests for data from blocked threads). +#[derive(Debug)] +pub(crate) struct Queue { + head: CachePadded>>, + tail: CachePadded>>, +} + +struct Node { + /// The slot in which a value of type `T` can be stored. + /// + /// The type of `data` is `MaybeUninit` because a `Node` doesn't always contain a `T`. + /// For example, the sentinel node in a queue never contains a value: its slot is always empty. + /// Other nodes start their life with a push operation and contain a value until it gets popped + /// out. After that such empty nodes get added to the collector for destruction. + data: MaybeUninit, + + next: Atomic>, +} + +// Any particular `T` should never be accessed concurrently, so no need for `Sync`. +unsafe impl Sync for Queue {} +unsafe impl Send for Queue {} + +impl Queue { + /// Create a new, empty queue. + pub(crate) fn new() -> Queue { + let q = Queue { + head: CachePadded::new(Atomic::null()), + tail: CachePadded::new(Atomic::null()), + }; + let sentinel = Owned::new(Node { + data: MaybeUninit::uninit(), + next: Atomic::null(), + }); + unsafe { + let guard = unprotected(); + let sentinel = sentinel.into_shared(guard); + q.head.store(sentinel, Relaxed); + q.tail.store(sentinel, Relaxed); + q + } + } + + /// Attempts to atomically place `n` into the `next` pointer of `onto`, and returns `true` on + /// success. The queue's `tail` pointer may be updated. + #[inline(always)] + fn push_internal( + &self, + onto: Shared<'_, Node>, + new: Shared<'_, Node>, + guard: &Guard, + ) -> bool { + // is `onto` the actual tail? + let o = unsafe { onto.deref() }; + let next = o.next.load(Acquire, guard); + if unsafe { next.as_ref().is_some() } { + // if not, try to "help" by moving the tail pointer forward + let _ = self + .tail + .compare_exchange(onto, next, Release, Relaxed, guard); + false + } else { + // looks like the actual tail; attempt to link in `n` + let result = o + .next + .compare_exchange(Shared::null(), new, Release, Relaxed, guard) + .is_ok(); + if result { + // try to move the tail pointer forward + let _ = self + .tail + .compare_exchange(onto, new, Release, Relaxed, guard); + } + result + } + } + + /// Adds `t` to the back of the queue, possibly waking up threads blocked on `pop`. + pub(crate) fn push(&self, t: T, guard: &Guard) { + let new = Owned::new(Node { + data: MaybeUninit::new(t), + next: Atomic::null(), + }); + let new = Owned::into_shared(new, guard); + + loop { + // We push onto the tail, so we'll start optimistically by looking there first. + let tail = self.tail.load(Acquire, guard); + + // Attempt to push onto the `tail` snapshot; fails if `tail.next` has changed. + if self.push_internal(tail, new, guard) { + break; + } + } + } + + /// Attempts to pop a data node. `Ok(None)` if queue is empty; `Err(())` if lost race to pop. + #[inline(always)] + fn pop_internal(&self, guard: &Guard) -> Result, ()> { + let head = self.head.load(Acquire, guard); + let h = unsafe { head.deref() }; + let next = h.next.load(Acquire, guard); + match unsafe { next.as_ref() } { + Some(n) => unsafe { + self.head + .compare_exchange(head, next, Release, Relaxed, guard) + .map(|_| { + let tail = self.tail.load(Relaxed, guard); + // Advance the tail so that we don't retire a pointer to a reachable node. + if head == tail { + let _ = self + .tail + .compare_exchange(tail, next, Release, Relaxed, guard); + } + guard.defer_destroy(head); + Some(n.data.assume_init_read()) + }) + .map_err(|_| ()) + }, + None => Ok(None), + } + } + + /// Attempts to pop a data node, if the data satisfies the given condition. `Ok(None)` if queue + /// is empty or the data does not satisfy the condition; `Err(())` if lost race to pop. + #[inline(always)] + fn pop_if_internal(&self, condition: F, guard: &Guard) -> Result, ()> + where + T: Sync, + F: Fn(&T) -> bool, + { + let head = self.head.load(Acquire, guard); + let h = unsafe { head.deref() }; + let next = h.next.load(Acquire, guard); + match unsafe { next.as_ref() } { + Some(n) if condition(unsafe { &*n.data.as_ptr() }) => unsafe { + self.head + .compare_exchange(head, next, Release, Relaxed, guard) + .map(|_| { + let tail = self.tail.load(Relaxed, guard); + // Advance the tail so that we don't retire a pointer to a reachable node. + if head == tail { + let _ = self + .tail + .compare_exchange(tail, next, Release, Relaxed, guard); + } + guard.defer_destroy(head); + Some(n.data.assume_init_read()) + }) + .map_err(|_| ()) + }, + None | Some(_) => Ok(None), + } + } + + /// Attempts to dequeue from the front. + /// + /// Returns `None` if the queue is observed to be empty. + pub(crate) fn try_pop(&self, guard: &Guard) -> Option { + loop { + if let Ok(head) = self.pop_internal(guard) { + return head; + } + } + } + + /// Attempts to dequeue from the front, if the item satisfies the given condition. + /// + /// Returns `None` if the queue is observed to be empty, or the head does not satisfy the given + /// condition. + pub(crate) fn try_pop_if(&self, condition: F, guard: &Guard) -> Option + where + T: Sync, + F: Fn(&T) -> bool, + { + loop { + if let Ok(head) = self.pop_if_internal(&condition, guard) { + return head; + } + } + } +} + +impl Drop for Queue { + fn drop(&mut self) { + unsafe { + let guard = unprotected(); + + while self.try_pop(guard).is_some() {} + + // Destroy the remaining sentinel node. + let sentinel = self.head.load(Relaxed, guard); + drop(sentinel.into_owned()); + } + } +} + +#[cfg(all(test, not(crossbeam_loom)))] +mod test { + use super::*; + use crate::pin; + use crossbeam_utils::thread; + + struct Queue { + queue: super::Queue, + } + + impl Queue { + pub(crate) fn new() -> Queue { + Queue { + queue: super::Queue::new(), + } + } + + pub(crate) fn push(&self, t: T) { + let guard = &pin(); + self.queue.push(t, guard); + } + + pub(crate) fn is_empty(&self) -> bool { + let guard = &pin(); + let head = self.queue.head.load(Acquire, guard); + let h = unsafe { head.deref() }; + h.next.load(Acquire, guard).is_null() + } + + pub(crate) fn try_pop(&self) -> Option { + let guard = &pin(); + self.queue.try_pop(guard) + } + + pub(crate) fn pop(&self) -> T { + loop { + match self.try_pop() { + None => continue, + Some(t) => return t, + } + } + } + } + + #[cfg(miri)] + const CONC_COUNT: i64 = 1000; + #[cfg(not(miri))] + const CONC_COUNT: i64 = 1000000; + + #[test] + fn push_try_pop_1() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + q.push(37); + assert!(!q.is_empty()); + assert_eq!(q.try_pop(), Some(37)); + assert!(q.is_empty()); + } + + #[test] + fn push_try_pop_2() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + q.push(37); + q.push(48); + assert_eq!(q.try_pop(), Some(37)); + assert!(!q.is_empty()); + assert_eq!(q.try_pop(), Some(48)); + assert!(q.is_empty()); + } + + #[test] + fn push_try_pop_many_seq() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + for i in 0..200 { + q.push(i) + } + assert!(!q.is_empty()); + for i in 0..200 { + assert_eq!(q.try_pop(), Some(i)); + } + assert!(q.is_empty()); + } + + #[test] + fn push_pop_1() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + q.push(37); + assert!(!q.is_empty()); + assert_eq!(q.pop(), 37); + assert!(q.is_empty()); + } + + #[test] + fn push_pop_2() { + let q: Queue = Queue::new(); + q.push(37); + q.push(48); + assert_eq!(q.pop(), 37); + assert_eq!(q.pop(), 48); + } + + #[test] + fn push_pop_many_seq() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + for i in 0..200 { + q.push(i) + } + assert!(!q.is_empty()); + for i in 0..200 { + assert_eq!(q.pop(), i); + } + assert!(q.is_empty()); + } + + #[test] + fn push_try_pop_many_spsc() { + let q: Queue = Queue::new(); + assert!(q.is_empty()); + + thread::scope(|scope| { + scope.spawn(|_| { + let mut next = 0; + + while next < CONC_COUNT { + if let Some(elem) = q.try_pop() { + assert_eq!(elem, next); + next += 1; + } + } + }); + + for i in 0..CONC_COUNT { + q.push(i) + } + }) + .unwrap(); + } + + #[test] + fn push_try_pop_many_spmc() { + fn recv(_t: i32, q: &Queue) { + let mut cur = -1; + for _i in 0..CONC_COUNT { + if let Some(elem) = q.try_pop() { + assert!(elem > cur); + cur = elem; + + if cur == CONC_COUNT - 1 { + break; + } + } + } + } + + let q: Queue = Queue::new(); + assert!(q.is_empty()); + thread::scope(|scope| { + for i in 0..3 { + let q = &q; + scope.spawn(move |_| recv(i, q)); + } + + scope.spawn(|_| { + for i in 0..CONC_COUNT { + q.push(i); + } + }); + }) + .unwrap(); + } + + #[test] + fn push_try_pop_many_mpmc() { + enum LR { + Left(i64), + Right(i64), + } + + let q: Queue = Queue::new(); + assert!(q.is_empty()); + + thread::scope(|scope| { + for _t in 0..2 { + scope.spawn(|_| { + for i in CONC_COUNT - 1..CONC_COUNT { + q.push(LR::Left(i)) + } + }); + scope.spawn(|_| { + for i in CONC_COUNT - 1..CONC_COUNT { + q.push(LR::Right(i)) + } + }); + scope.spawn(|_| { + let mut vl = vec![]; + let mut vr = vec![]; + for _i in 0..CONC_COUNT { + match q.try_pop() { + Some(LR::Left(x)) => vl.push(x), + Some(LR::Right(x)) => vr.push(x), + _ => {} + } + } + + let mut vl2 = vl.clone(); + let mut vr2 = vr.clone(); + vl2.sort_unstable(); + vr2.sort_unstable(); + + assert_eq!(vl, vl2); + assert_eq!(vr, vr2); + }); + } + }) + .unwrap(); + } + + #[test] + fn push_pop_many_spsc() { + let q: Queue = Queue::new(); + + thread::scope(|scope| { + scope.spawn(|_| { + let mut next = 0; + while next < CONC_COUNT { + assert_eq!(q.pop(), next); + next += 1; + } + }); + + for i in 0..CONC_COUNT { + q.push(i) + } + }) + .unwrap(); + assert!(q.is_empty()); + } + + #[test] + fn is_empty_dont_pop() { + let q: Queue = Queue::new(); + q.push(20); + q.push(20); + assert!(!q.is_empty()); + assert!(!q.is_empty()); + assert!(q.try_pop().is_some()); + } +} diff --git a/anneal/v2/vendor/crossbeam-epoch/tests/loom.rs b/anneal/v2/vendor/crossbeam-epoch/tests/loom.rs new file mode 100644 index 0000000000..4e56acdbca --- /dev/null +++ b/anneal/v2/vendor/crossbeam-epoch/tests/loom.rs @@ -0,0 +1,157 @@ +#![cfg(crossbeam_loom)] + +use crossbeam_epoch as epoch; +use loom_crate as loom; + +use epoch::*; +use epoch::{Atomic, Owned}; +use loom::sync::atomic::Ordering::{self, Acquire, Relaxed, Release}; +use loom::sync::Arc; +use loom::thread::spawn; +use std::mem::ManuallyDrop; +use std::ptr; + +#[test] +fn it_works() { + loom::model(|| { + let collector = Collector::new(); + let item: Atomic = Atomic::from(Owned::new(String::from("boom"))); + let item2 = item.clone(); + let collector2 = collector.clone(); + let guard = collector.register().pin(); + + let jh = loom::thread::spawn(move || { + let guard = collector2.register().pin(); + guard.defer(move || { + // this isn't really safe, since other threads may still have pointers to the + // value, but in this limited test scenario it's okay, since we know the test won't + // access item after all the pins are released. + let mut item = unsafe { item2.into_owned() }; + // mutate it as a second measure to make sure the assert_eq below would fail + item.retain(|c| c == 'o'); + drop(item); + }); + }); + + let item = item.load(Ordering::SeqCst, &guard); + // we pinned strictly before the call to defer_destroy, + // so item cannot have been dropped yet + assert_eq!(*unsafe { item.deref() }, "boom"); + drop(guard); + + jh.join().unwrap(); + + drop(collector); + }) +} + +#[test] +fn treiber_stack() { + /// Treiber's lock-free stack. + /// + /// Usable with any number of producers and consumers. + #[derive(Debug)] + pub struct TreiberStack { + head: Atomic>, + } + + #[derive(Debug)] + struct Node { + data: ManuallyDrop, + next: Atomic>, + } + + impl TreiberStack { + /// Creates a new, empty stack. + pub fn new() -> TreiberStack { + TreiberStack { + head: Atomic::null(), + } + } + + /// Pushes a value on top of the stack. + pub fn push(&self, t: T) { + let mut n = Owned::new(Node { + data: ManuallyDrop::new(t), + next: Atomic::null(), + }); + + let guard = epoch::pin(); + + loop { + let head = self.head.load(Relaxed, &guard); + n.next.store(head, Relaxed); + + match self + .head + .compare_exchange(head, n, Release, Relaxed, &guard) + { + Ok(_) => break, + Err(e) => n = e.new, + } + } + } + + /// Attempts to pop the top element from the stack. + /// + /// Returns `None` if the stack is empty. + pub fn pop(&self) -> Option { + let guard = epoch::pin(); + loop { + let head = self.head.load(Acquire, &guard); + + match unsafe { head.as_ref() } { + Some(h) => { + let next = h.next.load(Relaxed, &guard); + + if self + .head + .compare_exchange(head, next, Relaxed, Relaxed, &guard) + .is_ok() + { + unsafe { + guard.defer_destroy(head); + return Some(ManuallyDrop::into_inner(ptr::read(&(*h).data))); + } + } + } + None => return None, + } + } + } + + /// Returns `true` if the stack is empty. + pub fn is_empty(&self) -> bool { + let guard = epoch::pin(); + self.head.load(Acquire, &guard).is_null() + } + } + + impl Drop for TreiberStack { + fn drop(&mut self) { + while self.pop().is_some() {} + } + } + + loom::model(|| { + let stack1 = Arc::new(TreiberStack::new()); + let stack2 = Arc::clone(&stack1); + + // use 5 since it's greater than the 4 used for the sanitize feature + let jh = spawn(move || { + for i in 0..5 { + stack2.push(i); + assert!(stack2.pop().is_some()); + } + }); + + for i in 0..5 { + stack1.push(i); + assert!(stack1.pop().is_some()); + } + + jh.join().unwrap(); + assert!(stack1.pop().is_none()); + assert!(stack1.is_empty()); + }); +} diff --git a/anneal/v2/vendor/crossbeam-utils/.cargo-checksum.json b/anneal/v2/vendor/crossbeam-utils/.cargo-checksum.json new file mode 100644 index 0000000000..32c3420a24 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"d43f49dbbe655cb91dcd62c862552f2ca4520eaff2e4bee391e01b0df968e358","CHANGELOG.md":"366caba01b88f421c71b97f61b9806abbf05e1ba0d24e4bf034191c1f8aa03b8","Cargo.toml":"961aa297754d8fdbae9e23d15bbbcfdcd2b50b2db56becddb84e8cba4f730713","Cargo.toml.orig":"6697cafee3a273f8c04e25c8606621b2fff8a779e3e1d01f9c08d225a0f36fc5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"3c82bbb994f54ab76a9ed30a42dfd095c6e636258d379b9be3fbf66324310e71","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build-common.rs":"502cb7494549bed6fa10ac7bea36e880eeb60290dc69b679ac5c92b376469562","build.rs":"7a7f9e56ea7fb4f78c4e532b84b9d27be719d600e85eaeb3a2f4b79a4f0b419c","no_atomic.rs":"fc1baa4489d9842988bacaaa545a7d7d0e2f8b93cfa0b7d1ae31f21256e4cb0a","src/atomic/atomic_cell.rs":"6d8b83b65c73644abc10ec88a1442c8db531ae140de79197901510fcaea45966","src/atomic/consume.rs":"381c2a8b13312ca0525d53ca1b7d0d4f525ddb154951fa3e216b061ad22012ff","src/atomic/mod.rs":"712e2337e710c07116e977154ea4247a1c065bf5599e6bf368138e715b403f6d","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"8715f0303ec91d1847c8ac3fc24bcc002a22a7284ade610e5eff4181f85827c7","src/cache_padded.rs":"b6ff04ecf6de9124c0069c014d35f37de543cff1c4bfc1f260586aa49a5af6d8","src/lib.rs":"060dabc6dc07de92a7afa57dcbc47222a95ef5819d543ad854858c3b329d6637","src/sync/mod.rs":"eca73c04f821859b8434d2b93db87d160dc6a3f65498ca201cd40d732ca4c134","src/sync/once_lock.rs":"aa8f957604d1119c4fc7038a18c14a6281230e81005f31201c099acff284ad4b","src/sync/parker.rs":"698996e7530da1f3815df11c89df7d916155229cbfd022cccbd555f1d1d31985","src/sync/sharded_lock.rs":"f96d536f5622fe2a0a0f7d8117be31e4b1ed607544c52c7e2ffcd1f51a6b93a1","src/sync/wait_group.rs":"3e339aab014f50e214fea535c841755113ea058153378ed54e50a4acb403c937","src/thread.rs":"04610787ba88f1f59549874a13fc037f2dcf4d8b5f1daaf08378f05c2b3c0039","tests/atomic_cell.rs":"716c864d4e103039dc5cd8bf6110da4cbabafc7e4e03819aa197828e8fb0a9c7","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"314adeb8a651a28935f7a49c9a261b8fa1fd82bf6a16c865a5aced6216d7e40b","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"2a41533a5f7f113d19cd2bdafcc2abf86509109652274156efdd74abd00896b6"},"package":"d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-utils/.cargo_vcs_info.json b/anneal/v2/vendor/crossbeam-utils/.cargo_vcs_info.json new file mode 100644 index 0000000000..87108da095 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ccd83ac4108a2a1b41e9c6e79c87267167d18dfa" + }, + "path_in_vcs": "crossbeam-utils" +} \ No newline at end of file diff --git a/anneal/v2/vendor/crossbeam-utils/CHANGELOG.md b/anneal/v2/vendor/crossbeam-utils/CHANGELOG.md new file mode 100644 index 0000000000..5aa1967e71 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/CHANGELOG.md @@ -0,0 +1,243 @@ +# Version 0.8.21 + +- Improve implementation of `CachePadded`. (#1152) + +# Version 0.8.20 + +- Implement `Display` for `CachePadded`. (#1097) + +# Version 0.8.19 + +- Remove dependency on `cfg-if`. (#1072) + +# Version 0.8.18 + +- Relax the minimum supported Rust version to 1.60. (#1056) +- Improve scalability of `AtomicCell` fallback. (#1055) + +# Version 0.8.17 + +- Bump the minimum supported Rust version to 1.61. (#1037) +- Improve support for targets without atomic CAS or 64-bit atomic. (#1037) +- Always implement `UnwindSafe` and `RefUnwindSafe` for `AtomicCell`. (#1045) +- Improve compatibility with Miri, TSan, and loom. (#995, #1003) +- Improve compatibility with unstable `oom=panic`. (#1045) +- Improve implementation of `CachePadded`. (#1014, #1025) +- Update `loom` dependency to 0.7. + +# Version 0.8.16 + +- Improve implementation of `CachePadded`. (#967) + +# Version 0.8.15 + +- Add `#[clippy::has_significant_drop]` to `ShardedLock{Read,Write}Guard`. (#958) +- Improve handling of very large timeout. (#953) +- Soft-deprecate `thread::scope()` in favor of the more efficient `std::thread::scope` that stabilized in Rust 1.63. (#954) + +# Version 0.8.14 + +- Fix build script bug introduced in 0.8.13. (#932) + +# Version 0.8.13 + +**Note:** This release has been yanked due to regression fixed in 0.8.14. + +- Improve support for custom targets. (#922) + +# Version 0.8.12 + +- Removes the dependency on the `once_cell` crate to restore the MSRV. (#913) +- Work around [rust-lang#98302](https://github.com/rust-lang/rust/issues/98302), which causes compile error on windows-gnu when LTO is enabled. (#913) + +# Version 0.8.11 + +- Bump the minimum supported Rust version to 1.38. (#877) + +# Version 0.8.10 + +- Fix unsoundness of `AtomicCell` on types containing niches. (#834) + This fix contains breaking changes, but they are allowed because this is a soundness bug fix. See #834 for more. + +# Version 0.8.9 + +- Replace lazy_static with once_cell. (#817) + +# Version 0.8.8 + +- Fix a bug when unstable `loom` support is enabled. (#787) + +# Version 0.8.7 + +- Add `AtomicCell<{i*,u*}>::{fetch_max,fetch_min}`. (#785) +- Add `AtomicCell<{i*,u*,bool}>::fetch_nand`. (#785) +- Fix unsoundness of `AtomicCell<{i,u}64>` arithmetics on 32-bit targets that support `Atomic{I,U}64` (#781) + +# Version 0.8.6 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Re-add `AtomicCell<{i,u}64>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0 on targets that do not support `Atomic{I,U}64`. (#767) +- Re-add `AtomicCell<{i,u}128>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0. (#767) + +# Version 0.8.5 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Add `AtomicCell::fetch_update`. (#704) +- Support targets that do not have atomic CAS on stable Rust. (#698) + +# Version 0.8.4 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Bump `loom` dependency to version 0.5. (#686) + +# Version 0.8.3 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Make `loom` dependency optional. (#666) + +# Version 0.8.2 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Deprecate `AtomicCell::compare_and_swap`. Use `AtomicCell::compare_exchange` instead. (#619) +- Add `Parker::park_deadline`. (#563) +- Improve implementation of `CachePadded`. (#636) +- Add unstable support for `loom`. (#487) + +# Version 0.8.1 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Make `AtomicCell::is_lock_free` always const fn. (#600) +- Fix a bug in `seq_lock_wide`. (#596) +- Remove `const_fn` dependency. (#600) +- `crossbeam-utils` no longer fails to compile if unable to determine rustc version. Instead, it now displays a warning. (#604) + +# Version 0.8.0 + +**Note:** This release has been yanked. See [GHSA-qc84-gqf4-9926](https://github.com/crossbeam-rs/crossbeam/security/advisories/GHSA-qc84-gqf4-9926) for details. + +- Bump the minimum supported Rust version to 1.36. +- Remove deprecated `AtomicCell::get_mut()` and `Backoff::is_complete()` methods. +- Remove `alloc` feature. +- Make `CachePadded::new()` const function. +- Make `AtomicCell::is_lock_free()` const function at 1.46+. +- Implement `From` for `AtomicCell`. + +# Version 0.7.2 + +- Fix bug in release (yanking 0.7.1) + +# Version 0.7.1 + +- Bump `autocfg` dependency to version 1.0. (#460) +- Make `AtomicCell` lockfree for u8, u16, u32, u64 sized values at 1.34+. (#454) + +# Version 0.7.0 + +- Bump the minimum required version to 1.28. +- Fix breakage with nightly feature due to rust-lang/rust#65214. +- Apply `#[repr(transparent)]` to `AtomicCell`. +- Make `AtomicCell::new()` const function at 1.31+. + +# Version 0.6.6 + +- Add `UnwindSafe` and `RefUnwindSafe` impls for `AtomicCell`. +- Add `AtomicCell::as_ptr()`. +- Add `AtomicCell::take()`. +- Fix a bug in `AtomicCell::compare_exchange()` and `AtomicCell::compare_and_swap()`. +- Various documentation improvements. + +# Version 0.6.5 + +- Rename `Backoff::is_complete()` to `Backoff::is_completed()`. + +# Version 0.6.4 + +- Add `WaitGroup`, `ShardedLock`, and `Backoff`. +- Add `fetch_*` methods for `AtomicCell` and `AtomicCell`. +- Expand documentation. + +# Version 0.6.3 + +- Add `AtomicCell`. +- Improve documentation. + +# Version 0.6.2 + +- Add `Parker`. +- Improve documentation. + +# Version 0.6.1 + +- Fix a soundness bug in `Scope::spawn()`. +- Remove the `T: 'scope` bound on `ScopedJoinHandle`. + +# Version 0.6.0 + +- Move `AtomicConsume` to `atomic` module. +- `scope()` returns a `Result` of thread joins. +- Remove `spawn_unchecked`. +- Fix a soundness bug due to incorrect lifetimes. +- Improve documentation. +- Support nested scoped spawns. +- Implement `Copy`, `Hash`, `PartialEq`, and `Eq` for `CachePadded`. +- Add `CachePadded::into_inner()`. + +# Version 0.5.0 + +- Reorganize sub-modules and rename functions. + +# Version 0.4.1 + +- Fix a documentation link. + +# Version 0.4.0 + +- `CachePadded` supports types bigger than 64 bytes. +- Fix a bug in scoped threads where unitialized memory was being dropped. +- Minimum required Rust version is now 1.25. + +# Version 0.3.2 + +- Mark `load_consume` with `#[inline]`. + +# Version 0.3.1 + +- `load_consume` on ARM and AArch64. + +# Version 0.3.0 + +- Add `join` for scoped thread API. +- Add `load_consume` for atomic load-consume memory ordering. +- Remove `AtomicOption`. + +# Version 0.2.2 + +- Support Rust 1.12.1. +- Call `T::clone` when cloning a `CachePadded`. + +# Version 0.2.1 + +- Add `use_std` feature. + +# Version 0.2.0 + +- Add `nightly` feature. +- Use `repr(align(64))` on `CachePadded` with the `nightly` feature. +- Implement `Drop` for `CachePadded`. +- Implement `Clone` for `CachePadded`. +- Implement `From` for `CachePadded`. +- Implement better `Debug` for `CachePadded`. +- Write more tests. +- Add this changelog. +- Change cache line length to 64 bytes. +- Remove `ZerosValid`. + +# Version 0.1.0 + +- Old implementation of `CachePadded` from `crossbeam` version 0.3.0 diff --git a/anneal/v2/vendor/crossbeam-utils/Cargo.toml b/anneal/v2/vendor/crossbeam-utils/Cargo.toml new file mode 100644 index 0000000000..c93dc2f275 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/Cargo.toml @@ -0,0 +1,101 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "crossbeam-utils" +version = "0.8.21" +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Utilities for concurrent programming" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils" +readme = "README.md" +keywords = [ + "scoped", + "thread", + "atomic", + "cache", +] +categories = [ + "algorithms", + "concurrency", + "data-structures", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" + +[lib] +name = "crossbeam_utils" +path = "src/lib.rs" + +[[test]] +name = "atomic_cell" +path = "tests/atomic_cell.rs" + +[[test]] +name = "cache_padded" +path = "tests/cache_padded.rs" + +[[test]] +name = "parker" +path = "tests/parker.rs" + +[[test]] +name = "sharded_lock" +path = "tests/sharded_lock.rs" + +[[test]] +name = "thread" +path = "tests/thread.rs" + +[[test]] +name = "wait_group" +path = "tests/wait_group.rs" + +[[bench]] +name = "atomic_cell" +path = "benches/atomic_cell.rs" + +[dependencies] + +[dev-dependencies.rand] +version = "0.8" + +[features] +default = ["std"] +nightly = [] +std = [] + +[target."cfg(crossbeam_loom)".dependencies.loom] +version = "0.7.1" +optional = true + +[lints.clippy.declare_interior_mutable_const] +level = "allow" +priority = 1 + +[lints.clippy.lint_groups_priority] +level = "allow" +priority = 1 + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(crossbeam_loom)", + "cfg(crossbeam_sanitize)", +] diff --git a/anneal/v2/vendor/crossbeam-utils/Cargo.toml.orig b/anneal/v2/vendor/crossbeam-utils/Cargo.toml.orig new file mode 100644 index 0000000000..3a95baea25 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/Cargo.toml.orig @@ -0,0 +1,46 @@ +[package] +name = "crossbeam-utils" +# When publishing a new version: +# - Update CHANGELOG.md +# - Update README.md (when increasing major or minor version) +# - Run './tools/publish.sh crossbeam-utils ' +version = "0.8.21" +edition = "2021" +rust-version = "1.60" +license = "MIT OR Apache-2.0" +repository = "https://github.com/crossbeam-rs/crossbeam" +homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils" +description = "Utilities for concurrent programming" +keywords = ["scoped", "thread", "atomic", "cache"] +categories = ["algorithms", "concurrency", "data-structures", "no-std"] + +[features] +default = ["std"] + +# Enable to use APIs that require `std`. +# This is enabled by default. +std = [] + +# These features are no longer used. +# TODO: remove in the next major version. +# Enable to use of unstable functionality. +# This is disabled by default and requires recent nightly compiler. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +nightly = [] + +[dependencies] + +# Enable the use of loom for concurrency testing. +# +# NOTE: This feature is outside of the normal semver guarantees and minor or +# patch versions of crossbeam may make breaking changes to them at any time. +[target.'cfg(crossbeam_loom)'.dependencies] +loom = { version = "0.7.1", optional = true } + +[dev-dependencies] +rand = "0.8" + +[lints] +workspace = true diff --git a/anneal/v2/vendor/crossbeam-utils/LICENSE-APACHE b/anneal/v2/vendor/crossbeam-utils/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/crossbeam-utils/LICENSE-MIT b/anneal/v2/vendor/crossbeam-utils/LICENSE-MIT new file mode 100644 index 0000000000..068d491fd5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/LICENSE-MIT @@ -0,0 +1,27 @@ +The MIT License (MIT) + +Copyright (c) 2019 The Crossbeam Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/crossbeam-utils/README.md b/anneal/v2/vendor/crossbeam-utils/README.md new file mode 100644 index 0000000000..7d6a679487 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/README.md @@ -0,0 +1,73 @@ +# Crossbeam Utils + +[![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)]( +https://github.com/crossbeam-rs/crossbeam/actions) +[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)]( +https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils#license) +[![Cargo](https://img.shields.io/crates/v/crossbeam-utils.svg)]( +https://crates.io/crates/crossbeam-utils) +[![Documentation](https://docs.rs/crossbeam-utils/badge.svg)]( +https://docs.rs/crossbeam-utils) +[![Rust 1.60+](https://img.shields.io/badge/rust-1.60+-lightgray.svg)]( +https://www.rust-lang.org) +[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ) + +This crate provides miscellaneous tools for concurrent programming: + +#### Atomics + +* [`AtomicCell`], a thread-safe mutable memory location.(no_std) +* [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.(no_std) + +#### Thread synchronization + +* [`Parker`], a thread parking primitive. +* [`ShardedLock`], a sharded reader-writer lock with fast concurrent reads. +* [`WaitGroup`], for synchronizing the beginning or end of some computation. + +#### Utilities + +* [`Backoff`], for exponential backoff in spin loops.(no_std) +* [`CachePadded`], for padding and aligning a value to the length of a cache line.(no_std) +* [`scope`], for spawning threads that borrow local variables from the stack. + +*Features marked with (no_std) can be used in `no_std` environments.*
+ +[`AtomicCell`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/atomic/struct.AtomicCell.html +[`AtomicConsume`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/atomic/trait.AtomicConsume.html +[`Parker`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/sync/struct.Parker.html +[`ShardedLock`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/sync/struct.ShardedLock.html +[`WaitGroup`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/sync/struct.WaitGroup.html +[`Backoff`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/struct.Backoff.html +[`CachePadded`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/struct.CachePadded.html +[`scope`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/thread/fn.scope.html + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +crossbeam-utils = "0.8" +``` + +## Compatibility + +Crossbeam Utils supports stable Rust releases going back at least six months, +and every time the minimum supported Rust version is increased, a new minor +version is released. Currently, the minimum supported Rust version is 1.60. + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +#### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/anneal/v2/vendor/crossbeam-utils/benches/atomic_cell.rs b/anneal/v2/vendor/crossbeam-utils/benches/atomic_cell.rs new file mode 100644 index 0000000000..844f7c02b6 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/benches/atomic_cell.rs @@ -0,0 +1,156 @@ +#![feature(test)] + +extern crate test; + +use std::sync::Barrier; + +use crossbeam_utils::atomic::AtomicCell; +use crossbeam_utils::thread; + +#[bench] +fn load_u8(b: &mut test::Bencher) { + let a = AtomicCell::new(0u8); + let mut sum = 0; + b.iter(|| sum += a.load()); + test::black_box(sum); +} + +#[bench] +fn store_u8(b: &mut test::Bencher) { + let a = AtomicCell::new(0u8); + b.iter(|| a.store(1)); +} + +#[bench] +fn fetch_add_u8(b: &mut test::Bencher) { + let a = AtomicCell::new(0u8); + b.iter(|| a.fetch_add(1)); +} + +#[bench] +fn compare_exchange_u8(b: &mut test::Bencher) { + let a = AtomicCell::new(0u8); + let mut i = 0; + b.iter(|| { + let _ = a.compare_exchange(i, i.wrapping_add(1)); + i = i.wrapping_add(1); + }); +} + +#[bench] +fn concurrent_load_u8(b: &mut test::Bencher) { + const THREADS: usize = 2; + const STEPS: usize = 1_000_000; + + let start = Barrier::new(THREADS + 1); + let end = Barrier::new(THREADS + 1); + let exit = AtomicCell::new(false); + + let a = AtomicCell::new(0u8); + + thread::scope(|scope| { + for _ in 0..THREADS { + scope.spawn(|_| loop { + start.wait(); + + let mut sum = 0; + for _ in 0..STEPS { + sum += a.load(); + } + test::black_box(sum); + + end.wait(); + if exit.load() { + break; + } + }); + } + + start.wait(); + end.wait(); + + b.iter(|| { + start.wait(); + end.wait(); + }); + + start.wait(); + exit.store(true); + end.wait(); + }) + .unwrap(); +} + +#[bench] +fn load_usize(b: &mut test::Bencher) { + let a = AtomicCell::new(0usize); + let mut sum = 0; + b.iter(|| sum += a.load()); + test::black_box(sum); +} + +#[bench] +fn store_usize(b: &mut test::Bencher) { + let a = AtomicCell::new(0usize); + b.iter(|| a.store(1)); +} + +#[bench] +fn fetch_add_usize(b: &mut test::Bencher) { + let a = AtomicCell::new(0usize); + b.iter(|| a.fetch_add(1)); +} + +#[bench] +fn compare_exchange_usize(b: &mut test::Bencher) { + let a = AtomicCell::new(0usize); + let mut i = 0; + b.iter(|| { + let _ = a.compare_exchange(i, i.wrapping_add(1)); + i = i.wrapping_add(1); + }); +} + +#[bench] +fn concurrent_load_usize(b: &mut test::Bencher) { + const THREADS: usize = 2; + const STEPS: usize = 1_000_000; + + let start = Barrier::new(THREADS + 1); + let end = Barrier::new(THREADS + 1); + let exit = AtomicCell::new(false); + + let a = AtomicCell::new(0usize); + + thread::scope(|scope| { + for _ in 0..THREADS { + scope.spawn(|_| loop { + start.wait(); + + let mut sum = 0; + for _ in 0..STEPS { + sum += a.load(); + } + test::black_box(sum); + + end.wait(); + if exit.load() { + break; + } + }); + } + + start.wait(); + end.wait(); + + b.iter(|| { + start.wait(); + end.wait(); + }); + + start.wait(); + exit.store(true); + end.wait(); + }) + .unwrap(); +} diff --git a/anneal/v2/vendor/crossbeam-utils/build-common.rs b/anneal/v2/vendor/crossbeam-utils/build-common.rs new file mode 100644 index 0000000000..e91bb4d471 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/build-common.rs @@ -0,0 +1,13 @@ +// The target triplets have the form of 'arch-vendor-system'. +// +// When building for Linux (e.g. the 'system' part is +// 'linux-something'), replace the vendor with 'unknown' +// so that mapping to rust standard targets happens correctly. +fn convert_custom_linux_target(target: String) -> String { + let mut parts: Vec<&str> = target.split('-').collect(); + let system = parts.get(2); + if system == Some(&"linux") { + parts[1] = "unknown"; + }; + parts.join("-") +} diff --git a/anneal/v2/vendor/crossbeam-utils/build.rs b/anneal/v2/vendor/crossbeam-utils/build.rs new file mode 100644 index 0000000000..ff7e81f949 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/build.rs @@ -0,0 +1,48 @@ +// The rustc-cfg listed below are considered public API, but it is *unstable* +// and outside of the normal semver guarantees: +// +// - `crossbeam_no_atomic` +// Assume the target does *not* support any atomic operations. +// This is usually detected automatically by the build script, but you may +// need to enable it manually when building for custom targets or using +// non-cargo build systems that don't run the build script. +// +// With the exceptions mentioned above, the rustc-cfg emitted by the build +// script are *not* public API. + +#![warn(rust_2018_idioms)] + +use std::env; + +include!("no_atomic.rs"); +include!("build-common.rs"); + +fn main() { + println!("cargo:rerun-if-changed=no_atomic.rs"); + println!("cargo:rustc-check-cfg=cfg(crossbeam_no_atomic,crossbeam_sanitize_thread)"); + + let target = match env::var("TARGET") { + Ok(target) => convert_custom_linux_target(target), + Err(e) => { + println!( + "cargo:warning={}: unable to get TARGET environment variable: {}", + env!("CARGO_PKG_NAME"), + e + ); + return; + } + }; + + // Note that this is `no_`*, not `has_*`. This allows treating as the latest + // stable rustc is used when the build script doesn't run. This is useful + // for non-cargo build systems that don't run the build script. + if NO_ATOMIC.contains(&&*target) { + println!("cargo:rustc-cfg=crossbeam_no_atomic"); + } + + // `cfg(sanitize = "..")` is not stabilized. + let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); + if sanitize.contains("thread") { + println!("cargo:rustc-cfg=crossbeam_sanitize_thread"); + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/no_atomic.rs b/anneal/v2/vendor/crossbeam-utils/no_atomic.rs new file mode 100644 index 0000000000..f7e6d2fa42 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/no_atomic.rs @@ -0,0 +1,9 @@ +// This file is @generated by no_atomic.sh. +// It is not intended for manual editing. + +const NO_ATOMIC: &[&str] = &[ + "bpfeb-unknown-none", + "bpfel-unknown-none", + "mipsel-sony-psx", + "msp430-none-elf", +]; diff --git a/anneal/v2/vendor/crossbeam-utils/src/atomic/atomic_cell.rs b/anneal/v2/vendor/crossbeam-utils/src/atomic/atomic_cell.rs new file mode 100644 index 0000000000..47472534c8 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/atomic/atomic_cell.rs @@ -0,0 +1,1182 @@ +// Necessary for implementing atomic methods for `AtomicUnit` +#![allow(clippy::unit_arg)] + +use crate::primitive::sync::atomic::{self, Ordering}; +use crate::CachePadded; +use core::cell::UnsafeCell; +use core::cmp; +use core::fmt; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::panic::{RefUnwindSafe, UnwindSafe}; +use core::ptr; + +use super::seq_lock::SeqLock; + +/// A thread-safe mutable memory location. +/// +/// This type is equivalent to [`Cell`], except it can also be shared among multiple threads. +/// +/// Operations on `AtomicCell`s use atomic instructions whenever possible, and synchronize using +/// global locks otherwise. You can call [`AtomicCell::::is_lock_free()`] to check whether +/// atomic instructions or locks will be used. +/// +/// Atomic loads use the [`Acquire`] ordering and atomic stores use the [`Release`] ordering. +/// +/// [`Cell`]: std::cell::Cell +/// [`AtomicCell::::is_lock_free()`]: AtomicCell::is_lock_free +/// [`Acquire`]: std::sync::atomic::Ordering::Acquire +/// [`Release`]: std::sync::atomic::Ordering::Release +#[repr(transparent)] +pub struct AtomicCell { + /// The inner value. + /// + /// If this value can be transmuted into a primitive atomic type, it will be treated as such. + /// Otherwise, all potentially concurrent operations on this data will be protected by a global + /// lock. + /// + /// Using MaybeUninit to prevent code outside the cell from observing partially initialized state: + /// + /// (This rustc bug has been fixed in Rust 1.64.) + /// + /// Note: + /// - we'll never store uninitialized `T` due to our API only using initialized `T`. + /// - this `MaybeUninit` does *not* fix . + value: UnsafeCell>, +} + +unsafe impl Send for AtomicCell {} +unsafe impl Sync for AtomicCell {} + +impl UnwindSafe for AtomicCell {} +impl RefUnwindSafe for AtomicCell {} + +impl AtomicCell { + /// Creates a new atomic cell initialized with `val`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// ``` + pub const fn new(val: T) -> AtomicCell { + AtomicCell { + value: UnsafeCell::new(MaybeUninit::new(val)), + } + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// let v = a.into_inner(); + /// + /// assert_eq!(v, 7); + /// ``` + pub fn into_inner(self) -> T { + let this = ManuallyDrop::new(self); + // SAFETY: + // - passing `self` by value guarantees that no other threads are concurrently + // accessing the atomic data + // - the raw pointer passed in is valid because we got it from an owned value. + // - `ManuallyDrop` prevents double dropping `T` + unsafe { this.as_ptr().read() } + } + + /// Returns `true` if operations on values of this type are lock-free. + /// + /// If the compiler or the platform doesn't support the necessary atomic instructions, + /// `AtomicCell` will use global locks for every potentially concurrent atomic operation. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// // This type is internally represented as `AtomicUsize` so we can just use atomic + /// // operations provided by it. + /// assert_eq!(AtomicCell::::is_lock_free(), true); + /// + /// // A wrapper struct around `isize`. + /// struct Foo { + /// bar: isize, + /// } + /// // `AtomicCell` will be internally represented as `AtomicIsize`. + /// assert_eq!(AtomicCell::::is_lock_free(), true); + /// + /// // Operations on zero-sized types are always lock-free. + /// assert_eq!(AtomicCell::<()>::is_lock_free(), true); + /// + /// // Very large types cannot be represented as any of the standard atomic types, so atomic + /// // operations on them will have to use global locks for synchronization. + /// assert_eq!(AtomicCell::<[u8; 1000]>::is_lock_free(), false); + /// ``` + pub const fn is_lock_free() -> bool { + atomic_is_lock_free::() + } + + /// Stores `val` into the atomic cell. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// + /// assert_eq!(a.load(), 7); + /// a.store(8); + /// assert_eq!(a.load(), 8); + /// ``` + pub fn store(&self, val: T) { + if mem::needs_drop::() { + drop(self.swap(val)); + } else { + unsafe { + atomic_store(self.as_ptr(), val); + } + } + } + + /// Stores `val` into the atomic cell and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// + /// assert_eq!(a.load(), 7); + /// assert_eq!(a.swap(8), 7); + /// assert_eq!(a.load(), 8); + /// ``` + pub fn swap(&self, val: T) -> T { + unsafe { atomic_swap(self.as_ptr(), val) } + } + + /// Returns a raw pointer to the underlying data in this atomic cell. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(5); + /// + /// let ptr = a.as_ptr(); + /// ``` + #[inline] + pub fn as_ptr(&self) -> *mut T { + self.value.get().cast::() + } +} + +impl AtomicCell { + /// Takes the value of the atomic cell, leaving `Default::default()` in its place. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(5); + /// let five = a.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(a.into_inner(), 0); + /// ``` + pub fn take(&self) -> T { + self.swap(Default::default()) + } +} + +impl AtomicCell { + /// Loads a value from the atomic cell. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// + /// assert_eq!(a.load(), 7); + /// ``` + pub fn load(&self) -> T { + unsafe { atomic_load(self.as_ptr()) } + } +} + +impl AtomicCell { + /// If the current value equals `current`, stores `new` into the atomic cell. + /// + /// The return value is always the previous value. If it is equal to `current`, then the value + /// was updated. + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(1); + /// + /// assert_eq!(a.compare_and_swap(2, 3), 1); + /// assert_eq!(a.load(), 1); + /// + /// assert_eq!(a.compare_and_swap(1, 2), 1); + /// assert_eq!(a.load(), 2); + /// ``` + // TODO: remove in the next major version. + #[deprecated(note = "Use `compare_exchange` instead")] + pub fn compare_and_swap(&self, current: T, new: T) -> T { + match self.compare_exchange(current, new) { + Ok(v) => v, + Err(v) => v, + } + } + + /// If the current value equals `current`, stores `new` into the atomic cell. + /// + /// The return value is a result indicating whether the new value was written and containing + /// the previous value. On success this value is guaranteed to be equal to `current`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(1); + /// + /// assert_eq!(a.compare_exchange(2, 3), Err(1)); + /// assert_eq!(a.load(), 1); + /// + /// assert_eq!(a.compare_exchange(1, 2), Ok(1)); + /// assert_eq!(a.load(), 2); + /// ``` + pub fn compare_exchange(&self, current: T, new: T) -> Result { + unsafe { atomic_compare_exchange_weak(self.as_ptr(), current, new) } + } + + /// Fetches the value, and applies a function to it that returns an optional + /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else + /// `Err(previous_value)`. + /// + /// Note: This may call the function multiple times if the value has been changed from other threads in + /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied + /// only once to the stored value. + /// + /// # Examples + /// + /// ```rust + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(7); + /// assert_eq!(a.fetch_update(|_| None), Err(7)); + /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7)); + /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8)); + /// assert_eq!(a.load(), 9); + /// ``` + #[inline] + pub fn fetch_update(&self, mut f: F) -> Result + where + F: FnMut(T) -> Option, + { + let mut prev = self.load(); + while let Some(next) = f(prev) { + match self.compare_exchange(prev, next) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) + } +} + +// `MaybeUninit` prevents `T` from being dropped, so we need to implement `Drop` +// for `AtomicCell` to avoid leaks of non-`Copy` types. +impl Drop for AtomicCell { + fn drop(&mut self) { + if mem::needs_drop::() { + // SAFETY: + // - the mutable reference guarantees that no other threads are concurrently accessing the atomic data + // - the raw pointer passed in is valid because we got it from a reference + // - `MaybeUninit` prevents double dropping `T` + unsafe { + self.as_ptr().drop_in_place(); + } + } + } +} + +macro_rules! atomic { + // If values of type `$t` can be transmuted into values of the primitive atomic type `$atomic`, + // declares variable `$a` of type `$atomic` and executes `$atomic_op`, breaking out of the loop. + (@check, $t:ty, $atomic:ty, $a:ident, $atomic_op:expr) => { + if can_transmute::<$t, $atomic>() { + let $a: &$atomic; + break $atomic_op; + } + }; + + // If values of type `$t` can be transmuted into values of a primitive atomic type, declares + // variable `$a` of that type and executes `$atomic_op`. Otherwise, just executes + // `$fallback_op`. + ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => { + loop { + atomic!(@check, $t, AtomicUnit, $a, $atomic_op); + + atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op); + atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op); + atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op); + #[cfg(target_has_atomic = "64")] + atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op); + // TODO: AtomicU128 is unstable + // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op); + + break $fallback_op; + } + }; +} + +macro_rules! impl_arithmetic { + ($t:ty, fallback, $example:tt) => { + impl AtomicCell<$t> { + /// Increments the current value by `val` and returns the previous value. + /// + /// The addition wraps on overflow. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_add(3), 7); + /// assert_eq!(a.load(), 10); + /// ``` + #[inline] + pub fn fetch_add(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_add(val); + old + } + + /// Decrements the current value by `val` and returns the previous value. + /// + /// The subtraction wraps on overflow. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_sub(3), 7); + /// assert_eq!(a.load(), 4); + /// ``` + #[inline] + pub fn fetch_sub(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_sub(val); + old + } + + /// Applies bitwise "and" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_and(3), 7); + /// assert_eq!(a.load(), 3); + /// ``` + #[inline] + pub fn fetch_and(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value &= val; + old + } + + /// Applies bitwise "nand" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_nand(3), 7); + /// assert_eq!(a.load(), !(7 & 3)); + /// ``` + #[inline] + pub fn fetch_nand(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = !(old & val); + old + } + + /// Applies bitwise "or" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_or(16), 7); + /// assert_eq!(a.load(), 23); + /// ``` + #[inline] + pub fn fetch_or(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value |= val; + old + } + + /// Applies bitwise "xor" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_xor(2), 7); + /// assert_eq!(a.load(), 5); + /// ``` + #[inline] + pub fn fetch_xor(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value ^= val; + old + } + + /// Compares and sets the maximum of the current value and `val`, + /// and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_max(2), 7); + /// assert_eq!(a.load(), 7); + /// ``` + #[inline] + pub fn fetch_max(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::max(old, val); + old + } + + /// Compares and sets the minimum of the current value and `val`, + /// and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_min(2), 7); + /// assert_eq!(a.load(), 2); + /// ``` + #[inline] + pub fn fetch_min(&self, val: $t) -> $t { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::min(old, val); + old + } + } + }; + ($t:ty, $atomic:ident, $example:tt) => { + impl AtomicCell<$t> { + /// Increments the current value by `val` and returns the previous value. + /// + /// The addition wraps on overflow. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_add(3), 7); + /// assert_eq!(a.load(), 10); + /// ``` + #[inline] + pub fn fetch_add(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_add(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_add(val); + old + } + } + } + + /// Decrements the current value by `val` and returns the previous value. + /// + /// The subtraction wraps on overflow. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_sub(3), 7); + /// assert_eq!(a.load(), 4); + /// ``` + #[inline] + pub fn fetch_sub(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_sub(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = value.wrapping_sub(val); + old + } + } + } + + /// Applies bitwise "and" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_and(3), 7); + /// assert_eq!(a.load(), 3); + /// ``` + #[inline] + pub fn fetch_and(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_and(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value &= val; + old + } + } + } + + /// Applies bitwise "nand" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_nand(3), 7); + /// assert_eq!(a.load(), !(7 & 3)); + /// ``` + #[inline] + pub fn fetch_nand(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_nand(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = !(old & val); + old + } + } + } + + /// Applies bitwise "or" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_or(16), 7); + /// assert_eq!(a.load(), 23); + /// ``` + #[inline] + pub fn fetch_or(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_or(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value |= val; + old + } + } + } + + /// Applies bitwise "xor" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_xor(2), 7); + /// assert_eq!(a.load(), 5); + /// ``` + #[inline] + pub fn fetch_xor(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_xor(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value ^= val; + old + } + } + } + + /// Compares and sets the maximum of the current value and `val`, + /// and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_max(9), 7); + /// assert_eq!(a.load(), 9); + /// ``` + #[inline] + pub fn fetch_max(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_max(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::max(old, val); + old + } + } + } + + /// Compares and sets the minimum of the current value and `val`, + /// and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + #[doc = $example] + /// + /// assert_eq!(a.fetch_min(2), 7); + /// assert_eq!(a.load(), 2); + /// ``` + #[inline] + pub fn fetch_min(&self, val: $t) -> $t { + atomic! { + $t, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) }; + a.fetch_min(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = cmp::min(old, val); + old + } + } + } + } + }; +} + +impl_arithmetic!(u8, AtomicU8, "let a = AtomicCell::new(7u8);"); +impl_arithmetic!(i8, AtomicI8, "let a = AtomicCell::new(7i8);"); +impl_arithmetic!(u16, AtomicU16, "let a = AtomicCell::new(7u16);"); +impl_arithmetic!(i16, AtomicI16, "let a = AtomicCell::new(7i16);"); + +impl_arithmetic!(u32, AtomicU32, "let a = AtomicCell::new(7u32);"); +impl_arithmetic!(i32, AtomicI32, "let a = AtomicCell::new(7i32);"); + +#[cfg(target_has_atomic = "64")] +impl_arithmetic!(u64, AtomicU64, "let a = AtomicCell::new(7u64);"); +#[cfg(target_has_atomic = "64")] +impl_arithmetic!(i64, AtomicI64, "let a = AtomicCell::new(7i64);"); +#[cfg(not(target_has_atomic = "64"))] +impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);"); +#[cfg(not(target_has_atomic = "64"))] +impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);"); + +// TODO: AtomicU128 is unstable +// impl_arithmetic!(u128, AtomicU128, "let a = AtomicCell::new(7u128);"); +// impl_arithmetic!(i128, AtomicI128, "let a = AtomicCell::new(7i128);"); +impl_arithmetic!(u128, fallback, "let a = AtomicCell::new(7u128);"); +impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);"); + +impl_arithmetic!(usize, AtomicUsize, "let a = AtomicCell::new(7usize);"); +impl_arithmetic!(isize, AtomicIsize, "let a = AtomicCell::new(7isize);"); + +impl AtomicCell { + /// Applies logical "and" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(true); + /// + /// assert_eq!(a.fetch_and(true), true); + /// assert_eq!(a.load(), true); + /// + /// assert_eq!(a.fetch_and(false), true); + /// assert_eq!(a.load(), false); + /// ``` + #[inline] + pub fn fetch_and(&self, val: bool) -> bool { + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_and(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value &= val; + old + } + } + } + + /// Applies logical "nand" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(true); + /// + /// assert_eq!(a.fetch_nand(false), true); + /// assert_eq!(a.load(), true); + /// + /// assert_eq!(a.fetch_nand(true), true); + /// assert_eq!(a.load(), false); + /// + /// assert_eq!(a.fetch_nand(false), false); + /// assert_eq!(a.load(), true); + /// ``` + #[inline] + pub fn fetch_nand(&self, val: bool) -> bool { + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_nand(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value = !(old & val); + old + } + } + } + + /// Applies logical "or" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(false); + /// + /// assert_eq!(a.fetch_or(false), false); + /// assert_eq!(a.load(), false); + /// + /// assert_eq!(a.fetch_or(true), false); + /// assert_eq!(a.load(), true); + /// ``` + #[inline] + pub fn fetch_or(&self, val: bool) -> bool { + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_or(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value |= val; + old + } + } + } + + /// Applies logical "xor" to the current value and returns the previous value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::atomic::AtomicCell; + /// + /// let a = AtomicCell::new(true); + /// + /// assert_eq!(a.fetch_xor(false), true); + /// assert_eq!(a.load(), true); + /// + /// assert_eq!(a.fetch_xor(true), true); + /// assert_eq!(a.load(), false); + /// ``` + #[inline] + pub fn fetch_xor(&self, val: bool) -> bool { + atomic! { + bool, _a, + { + let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) }; + a.fetch_xor(val, Ordering::AcqRel) + }, + { + let _guard = lock(self.as_ptr() as usize).write(); + let value = unsafe { &mut *(self.as_ptr()) }; + let old = *value; + *value ^= val; + old + } + } + } +} + +impl Default for AtomicCell { + fn default() -> AtomicCell { + AtomicCell::new(T::default()) + } +} + +impl From for AtomicCell { + #[inline] + fn from(val: T) -> AtomicCell { + AtomicCell::new(val) + } +} + +impl fmt::Debug for AtomicCell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AtomicCell") + .field("value", &self.load()) + .finish() + } +} + +/// Returns `true` if values of type `A` can be transmuted into values of type `B`. +const fn can_transmute() -> bool { + // Sizes must be equal, but alignment of `A` must be greater or equal than that of `B`. + (mem::size_of::
() == mem::size_of::()) & (mem::align_of::() >= mem::align_of::()) +} + +/// Returns a reference to the global lock associated with the `AtomicCell` at address `addr`. +/// +/// This function is used to protect atomic data which doesn't fit into any of the primitive atomic +/// types in `std::sync::atomic`. Operations on such atomics must therefore use a global lock. +/// +/// However, there is not only one global lock but an array of many locks, and one of them is +/// picked based on the given address. Having many locks reduces contention and improves +/// scalability. +#[inline] +#[must_use] +fn lock(addr: usize) -> &'static SeqLock { + // The number of locks is a prime number because we want to make sure `addr % LEN` gets + // dispersed across all locks. + // + // Note that addresses are always aligned to some power of 2, depending on type `T` in + // `AtomicCell`. If `LEN` was an even number, then `addr % LEN` would be an even number, + // too, which means only half of the locks would get utilized! + // + // It is also possible for addresses to accidentally get aligned to a number that is not a + // power of 2. Consider this example: + // + // ``` + // #[repr(C)] + // struct Foo { + // a: AtomicCell, + // b: u8, + // c: u8, + // } + // ``` + // + // Now, if we have a slice of type `&[Foo]`, it is possible that field `a` in all items gets + // stored at addresses that are multiples of 3. It'd be too bad if `LEN` was divisible by 3. + // In order to protect from such cases, we simply choose a large prime number for `LEN`. + const LEN: usize = 67; + const L: CachePadded = CachePadded::new(SeqLock::new()); + static LOCKS: [CachePadded; LEN] = [L; LEN]; + + // If the modulus is a constant number, the compiler will use crazy math to transform this into + // a sequence of cheap arithmetic operations rather than using the slow modulo instruction. + &LOCKS[addr % LEN] +} + +/// An atomic `()`. +/// +/// All operations are noops. +struct AtomicUnit; + +impl AtomicUnit { + #[inline] + fn load(&self, _order: Ordering) {} + + #[inline] + fn store(&self, _val: (), _order: Ordering) {} + + #[inline] + fn swap(&self, _val: (), _order: Ordering) {} + + #[inline] + fn compare_exchange_weak( + &self, + _current: (), + _new: (), + _success: Ordering, + _failure: Ordering, + ) -> Result<(), ()> { + Ok(()) + } +} + +/// Returns `true` if operations on `AtomicCell` are lock-free. +const fn atomic_is_lock_free() -> bool { + atomic! { T, _a, true, false } +} + +/// Atomically reads data from `src`. +/// +/// This operation uses the `Acquire` ordering. If possible, an atomic instructions is used, and a +/// global lock otherwise. +unsafe fn atomic_load(src: *mut T) -> T +where + T: Copy, +{ + atomic! { + T, a, + { + a = &*(src as *const _ as *const _); + mem::transmute_copy(&a.load(Ordering::Acquire)) + }, + { + let lock = lock(src as usize); + + // Try doing an optimistic read first. + if let Some(stamp) = lock.optimistic_read() { + // We need a volatile read here because other threads might concurrently modify the + // value. In theory, data races are *always* UB, even if we use volatile reads and + // discard the data when a data race is detected. The proper solution would be to + // do atomic reads and atomic writes, but we can't atomically read and write all + // kinds of data since `AtomicU8` is not available on stable Rust yet. + // Load as `MaybeUninit` because we may load a value that is not valid as `T`. + let val = ptr::read_volatile(src.cast::>()); + + if lock.validate_read(stamp) { + return val.assume_init(); + } + } + + // Grab a regular write lock so that writers don't starve this load. + let guard = lock.write(); + let val = ptr::read(src); + // The value hasn't been changed. Drop the guard without incrementing the stamp. + guard.abort(); + val + } + } +} + +/// Atomically writes `val` to `dst`. +/// +/// This operation uses the `Release` ordering. If possible, an atomic instructions is used, and a +/// global lock otherwise. +unsafe fn atomic_store(dst: *mut T, val: T) { + atomic! { + T, a, + { + a = &*(dst as *const _ as *const _); + a.store(mem::transmute_copy(&val), Ordering::Release); + mem::forget(val); + }, + { + let _guard = lock(dst as usize).write(); + ptr::write(dst, val); + } + } +} + +/// Atomically swaps data at `dst` with `val`. +/// +/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a +/// global lock otherwise. +unsafe fn atomic_swap(dst: *mut T, val: T) -> T { + atomic! { + T, a, + { + a = &*(dst as *const _ as *const _); + let res = mem::transmute_copy(&a.swap(mem::transmute_copy(&val), Ordering::AcqRel)); + mem::forget(val); + res + }, + { + let _guard = lock(dst as usize).write(); + ptr::replace(dst, val) + } + } +} + +/// Atomically compares data at `dst` to `current` and, if equal byte-for-byte, exchanges data at +/// `dst` with `new`. +/// +/// Returns the old value on success, or the current value at `dst` on failure. +/// +/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a +/// global lock otherwise. +#[allow(clippy::let_unit_value)] +unsafe fn atomic_compare_exchange_weak(dst: *mut T, mut current: T, new: T) -> Result +where + T: Copy + Eq, +{ + atomic! { + T, a, + { + a = &*(dst as *const _ as *const _); + let mut current_raw = mem::transmute_copy(¤t); + let new_raw = mem::transmute_copy(&new); + + loop { + match a.compare_exchange_weak( + current_raw, + new_raw, + Ordering::AcqRel, + Ordering::Acquire, + ) { + Ok(_) => break Ok(current), + Err(previous_raw) => { + let previous = mem::transmute_copy(&previous_raw); + + if !T::eq(&previous, ¤t) { + break Err(previous); + } + + // The compare-exchange operation has failed and didn't store `new`. The + // failure is either spurious, or `previous` was semantically equal to + // `current` but not byte-equal. Let's retry with `previous` as the new + // `current`. + current = previous; + current_raw = previous_raw; + } + } + } + }, + { + let guard = lock(dst as usize).write(); + + if T::eq(&*dst, ¤t) { + Ok(ptr::replace(dst, new)) + } else { + let val = ptr::read(dst); + // The value hasn't been changed. Drop the guard without incrementing the stamp. + guard.abort(); + Err(val) + } + } + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/atomic/consume.rs b/anneal/v2/vendor/crossbeam-utils/src/atomic/consume.rs new file mode 100644 index 0000000000..ff8e316b2c --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/atomic/consume.rs @@ -0,0 +1,111 @@ +#[cfg(not(crossbeam_no_atomic))] +use core::sync::atomic::Ordering; + +/// Trait which allows reading from primitive atomic types with "consume" ordering. +pub trait AtomicConsume { + /// Type returned by `load_consume`. + type Val; + + /// Loads a value from the atomic using a "consume" memory ordering. + /// + /// This is similar to the "acquire" ordering, except that an ordering is + /// only guaranteed with operations that "depend on" the result of the load. + /// However consume loads are usually much faster than acquire loads on + /// architectures with a weak memory model since they don't require memory + /// fence instructions. + /// + /// The exact definition of "depend on" is a bit vague, but it works as you + /// would expect in practice since a lot of software, especially the Linux + /// kernel, rely on this behavior. + /// + /// This is currently only implemented on ARM and AArch64, where a fence + /// can be avoided. On other architectures this will fall back to a simple + /// `load(Ordering::Acquire)`. + fn load_consume(&self) -> Self::Val; +} + +#[cfg(not(crossbeam_no_atomic))] +// Miri and Loom don't support "consume" ordering and ThreadSanitizer doesn't treat +// load(Relaxed) + compiler_fence(Acquire) as "consume" load. +// LLVM generates machine code equivalent to fence(Acquire) in compiler_fence(Acquire) +// on PowerPC, MIPS, etc. (https://godbolt.org/z/hffvjvW7h), so for now the fence +// can be actually avoided here only on ARM and AArch64. See also +// https://github.com/rust-lang/rust/issues/62256. +#[cfg(all( + any(target_arch = "arm", target_arch = "aarch64"), + not(any(miri, crossbeam_loom, crossbeam_sanitize_thread)), +))] +macro_rules! impl_consume { + () => { + #[inline] + fn load_consume(&self) -> Self::Val { + use crate::primitive::sync::atomic::compiler_fence; + let result = self.load(Ordering::Relaxed); + compiler_fence(Ordering::Acquire); + result + } + }; +} + +#[cfg(not(crossbeam_no_atomic))] +#[cfg(not(all( + any(target_arch = "arm", target_arch = "aarch64"), + not(any(miri, crossbeam_loom, crossbeam_sanitize_thread)), +)))] +macro_rules! impl_consume { + () => { + #[inline] + fn load_consume(&self) -> Self::Val { + self.load(Ordering::Acquire) + } + }; +} + +macro_rules! impl_atomic { + ($atomic:ident, $val:ty) => { + #[cfg(not(crossbeam_no_atomic))] + impl AtomicConsume for core::sync::atomic::$atomic { + type Val = $val; + impl_consume!(); + } + #[cfg(crossbeam_loom)] + impl AtomicConsume for loom::sync::atomic::$atomic { + type Val = $val; + impl_consume!(); + } + }; +} + +impl_atomic!(AtomicBool, bool); +impl_atomic!(AtomicUsize, usize); +impl_atomic!(AtomicIsize, isize); +impl_atomic!(AtomicU8, u8); +impl_atomic!(AtomicI8, i8); +impl_atomic!(AtomicU16, u16); +impl_atomic!(AtomicI16, i16); +#[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] +impl_atomic!(AtomicU32, u32); +#[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] +impl_atomic!(AtomicI32, i32); +#[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), +))] +impl_atomic!(AtomicU64, u64); +#[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), +))] +impl_atomic!(AtomicI64, i64); + +#[cfg(not(crossbeam_no_atomic))] +impl AtomicConsume for core::sync::atomic::AtomicPtr { + type Val = *mut T; + impl_consume!(); +} + +#[cfg(crossbeam_loom)] +impl AtomicConsume for loom::sync::atomic::AtomicPtr { + type Val = *mut T; + impl_consume!(); +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/atomic/mod.rs b/anneal/v2/vendor/crossbeam-utils/src/atomic/mod.rs new file mode 100644 index 0000000000..8662ded564 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/atomic/mod.rs @@ -0,0 +1,32 @@ +//! Atomic types. +//! +//! * [`AtomicCell`], a thread-safe mutable memory location. +//! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering. + +#[cfg(target_has_atomic = "ptr")] +#[cfg(not(crossbeam_loom))] +// Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap +// around. +// +// In narrow architectures (pointer width <= 16), the counter is still <= 32-bit and may be +// vulnerable to wrap around. But it's mostly okay, since in such a primitive hardware, the +// counter will not be increased that fast. +// Note that Rust (and C99) pointers must be at least 16-bit (i.e., 8-bit targets are impossible): https://github.com/rust-lang/rust/pull/49305 +#[cfg_attr( + any(target_pointer_width = "16", target_pointer_width = "32"), + path = "seq_lock_wide.rs" +)] +mod seq_lock; + +#[cfg(target_has_atomic = "ptr")] +// We cannot provide AtomicCell under cfg(crossbeam_loom) because loom's atomic +// types have a different in-memory representation than the underlying type. +// TODO: The latest loom supports fences, so fallback using seqlock may be available. +#[cfg(not(crossbeam_loom))] +mod atomic_cell; +#[cfg(target_has_atomic = "ptr")] +#[cfg(not(crossbeam_loom))] +pub use atomic_cell::AtomicCell; + +mod consume; +pub use consume::AtomicConsume; diff --git a/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock.rs b/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock.rs new file mode 100644 index 0000000000..ff8defd26d --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock.rs @@ -0,0 +1,112 @@ +use core::mem; +use core::sync::atomic::{self, AtomicUsize, Ordering}; + +use crate::Backoff; + +/// A simple stamped lock. +pub(crate) struct SeqLock { + /// The current state of the lock. + /// + /// All bits except the least significant one hold the current stamp. When locked, the state + /// equals 1 and doesn't contain a valid stamp. + state: AtomicUsize, +} + +impl SeqLock { + pub(crate) const fn new() -> Self { + Self { + state: AtomicUsize::new(0), + } + } + + /// If not locked, returns the current stamp. + /// + /// This method should be called before optimistic reads. + #[inline] + pub(crate) fn optimistic_read(&self) -> Option { + let state = self.state.load(Ordering::Acquire); + if state == 1 { + None + } else { + Some(state) + } + } + + /// Returns `true` if the current stamp is equal to `stamp`. + /// + /// This method should be called after optimistic reads to check whether they are valid. The + /// argument `stamp` should correspond to the one returned by method `optimistic_read`. + #[inline] + pub(crate) fn validate_read(&self, stamp: usize) -> bool { + atomic::fence(Ordering::Acquire); + self.state.load(Ordering::Relaxed) == stamp + } + + /// Grabs the lock for writing. + #[inline] + pub(crate) fn write(&'static self) -> SeqLockWriteGuard { + let backoff = Backoff::new(); + loop { + let previous = self.state.swap(1, Ordering::Acquire); + + if previous != 1 { + atomic::fence(Ordering::Release); + + return SeqLockWriteGuard { + lock: self, + state: previous, + }; + } + + backoff.snooze(); + } + } +} + +/// An RAII guard that releases the lock and increments the stamp when dropped. +pub(crate) struct SeqLockWriteGuard { + /// The parent lock. + lock: &'static SeqLock, + + /// The stamp before locking. + state: usize, +} + +impl SeqLockWriteGuard { + /// Releases the lock without incrementing the stamp. + #[inline] + pub(crate) fn abort(self) { + self.lock.state.store(self.state, Ordering::Release); + + // We specifically don't want to call drop(), since that's + // what increments the stamp. + mem::forget(self); + } +} + +impl Drop for SeqLockWriteGuard { + #[inline] + fn drop(&mut self) { + // Release the lock and increment the stamp. + self.lock + .state + .store(self.state.wrapping_add(2), Ordering::Release); + } +} + +#[cfg(test)] +mod tests { + use super::SeqLock; + + #[test] + fn test_abort() { + static LK: SeqLock = SeqLock::new(); + let before = LK.optimistic_read().unwrap(); + { + let guard = LK.write(); + guard.abort(); + } + let after = LK.optimistic_read().unwrap(); + assert_eq!(before, after, "aborted write does not update the stamp"); + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock_wide.rs b/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock_wide.rs new file mode 100644 index 0000000000..ef5d94a454 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/atomic/seq_lock_wide.rs @@ -0,0 +1,155 @@ +use core::mem; +use core::sync::atomic::{self, AtomicUsize, Ordering}; + +use crate::Backoff; + +/// A simple stamped lock. +/// +/// The state is represented as two `AtomicUsize`: `state_hi` for high bits and `state_lo` for low +/// bits. +pub(crate) struct SeqLock { + /// The high bits of the current state of the lock. + state_hi: AtomicUsize, + + /// The low bits of the current state of the lock. + /// + /// All bits except the least significant one hold the current stamp. When locked, the state_lo + /// equals 1 and doesn't contain a valid stamp. + state_lo: AtomicUsize, +} + +impl SeqLock { + pub(crate) const fn new() -> Self { + Self { + state_hi: AtomicUsize::new(0), + state_lo: AtomicUsize::new(0), + } + } + + /// If not locked, returns the current stamp. + /// + /// This method should be called before optimistic reads. + #[inline] + pub(crate) fn optimistic_read(&self) -> Option<(usize, usize)> { + // The acquire loads from `state_hi` and `state_lo` synchronize with the release stores in + // `SeqLockWriteGuard::drop`. + // + // As a consequence, we can make sure that (1) all writes within the era of `state_hi - 1` + // happens before now; and therefore, (2) if `state_lo` is even, all writes within the + // critical section of (`state_hi`, `state_lo`) happens before now. + let state_hi = self.state_hi.load(Ordering::Acquire); + let state_lo = self.state_lo.load(Ordering::Acquire); + if state_lo == 1 { + None + } else { + Some((state_hi, state_lo)) + } + } + + /// Returns `true` if the current stamp is equal to `stamp`. + /// + /// This method should be called after optimistic reads to check whether they are valid. The + /// argument `stamp` should correspond to the one returned by method `optimistic_read`. + #[inline] + pub(crate) fn validate_read(&self, stamp: (usize, usize)) -> bool { + // Thanks to the fence, if we're noticing any modification to the data at the critical + // section of `(a, b)`, then the critical section's write of 1 to state_lo should be + // visible. + atomic::fence(Ordering::Acquire); + + // So if `state_lo` coincides with `stamp.1`, then either (1) we're noticing no modification + // to the data after the critical section of `(stamp.0, stamp.1)`, or (2) `state_lo` wrapped + // around. + // + // If (2) is the case, the acquire ordering ensures we see the new value of `state_hi`. + let state_lo = self.state_lo.load(Ordering::Acquire); + + // If (2) is the case and `state_hi` coincides with `stamp.0`, then `state_hi` also wrapped + // around, which we give up to correctly validate the read. + let state_hi = self.state_hi.load(Ordering::Relaxed); + + // Except for the case that both `state_hi` and `state_lo` wrapped around, the following + // condition implies that we're noticing no modification to the data after the critical + // section of `(stamp.0, stamp.1)`. + (state_hi, state_lo) == stamp + } + + /// Grabs the lock for writing. + #[inline] + pub(crate) fn write(&'static self) -> SeqLockWriteGuard { + let backoff = Backoff::new(); + loop { + let previous = self.state_lo.swap(1, Ordering::Acquire); + + if previous != 1 { + // To synchronize with the acquire fence in `validate_read` via any modification to + // the data at the critical section of `(state_hi, previous)`. + atomic::fence(Ordering::Release); + + return SeqLockWriteGuard { + lock: self, + state_lo: previous, + }; + } + + backoff.snooze(); + } + } +} + +/// An RAII guard that releases the lock and increments the stamp when dropped. +pub(crate) struct SeqLockWriteGuard { + /// The parent lock. + lock: &'static SeqLock, + + /// The stamp before locking. + state_lo: usize, +} + +impl SeqLockWriteGuard { + /// Releases the lock without incrementing the stamp. + #[inline] + pub(crate) fn abort(self) { + self.lock.state_lo.store(self.state_lo, Ordering::Release); + mem::forget(self); + } +} + +impl Drop for SeqLockWriteGuard { + #[inline] + fn drop(&mut self) { + let state_lo = self.state_lo.wrapping_add(2); + + // Increase the high bits if the low bits wrap around. + // + // Release ordering for synchronizing with `optimistic_read`. + if state_lo == 0 { + let state_hi = self.lock.state_hi.load(Ordering::Relaxed); + self.lock + .state_hi + .store(state_hi.wrapping_add(1), Ordering::Release); + } + + // Release the lock and increment the stamp. + // + // Release ordering for synchronizing with `optimistic_read`. + self.lock.state_lo.store(state_lo, Ordering::Release); + } +} + +#[cfg(test)] +mod tests { + use super::SeqLock; + + #[test] + fn test_abort() { + static LK: SeqLock = SeqLock::new(); + let before = LK.optimistic_read().unwrap(); + { + let guard = LK.write(); + guard.abort(); + } + let after = LK.optimistic_read().unwrap(); + assert_eq!(before, after, "aborted write does not update the stamp"); + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/backoff.rs b/anneal/v2/vendor/crossbeam-utils/src/backoff.rs new file mode 100644 index 0000000000..7a505ed614 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/backoff.rs @@ -0,0 +1,287 @@ +use crate::primitive::hint; +use core::cell::Cell; +use core::fmt; + +const SPIN_LIMIT: u32 = 6; +const YIELD_LIMIT: u32 = 10; + +/// Performs exponential backoff in spin loops. +/// +/// Backing off in spin loops reduces contention and improves overall performance. +/// +/// This primitive can execute *YIELD* and *PAUSE* instructions, yield the current thread to the OS +/// scheduler, and tell when is a good time to block the thread using a different synchronization +/// mechanism. Each step of the back off procedure takes roughly twice as long as the previous +/// step. +/// +/// # Examples +/// +/// Backing off in a lock-free loop: +/// +/// ``` +/// use crossbeam_utils::Backoff; +/// use std::sync::atomic::AtomicUsize; +/// use std::sync::atomic::Ordering::SeqCst; +/// +/// fn fetch_mul(a: &AtomicUsize, b: usize) -> usize { +/// let backoff = Backoff::new(); +/// loop { +/// let val = a.load(SeqCst); +/// if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() { +/// return val; +/// } +/// backoff.spin(); +/// } +/// } +/// ``` +/// +/// Waiting for an [`AtomicBool`] to become `true`: +/// +/// ``` +/// use crossbeam_utils::Backoff; +/// use std::sync::atomic::AtomicBool; +/// use std::sync::atomic::Ordering::SeqCst; +/// +/// fn spin_wait(ready: &AtomicBool) { +/// let backoff = Backoff::new(); +/// while !ready.load(SeqCst) { +/// backoff.snooze(); +/// } +/// } +/// ``` +/// +/// Waiting for an [`AtomicBool`] to become `true` and parking the thread after a long wait. +/// Note that whoever sets the atomic variable to `true` must notify the parked thread by calling +/// [`unpark()`]: +/// +/// ``` +/// use crossbeam_utils::Backoff; +/// use std::sync::atomic::AtomicBool; +/// use std::sync::atomic::Ordering::SeqCst; +/// use std::thread; +/// +/// fn blocking_wait(ready: &AtomicBool) { +/// let backoff = Backoff::new(); +/// while !ready.load(SeqCst) { +/// if backoff.is_completed() { +/// thread::park(); +/// } else { +/// backoff.snooze(); +/// } +/// } +/// } +/// ``` +/// +/// [`is_completed`]: Backoff::is_completed +/// [`std::thread::park()`]: std::thread::park +/// [`Condvar`]: std::sync::Condvar +/// [`AtomicBool`]: std::sync::atomic::AtomicBool +/// [`unpark()`]: std::thread::Thread::unpark +pub struct Backoff { + step: Cell, +} + +impl Backoff { + /// Creates a new `Backoff`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::Backoff; + /// + /// let backoff = Backoff::new(); + /// ``` + #[inline] + pub fn new() -> Self { + Backoff { step: Cell::new(0) } + } + + /// Resets the `Backoff`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::Backoff; + /// + /// let backoff = Backoff::new(); + /// backoff.reset(); + /// ``` + #[inline] + pub fn reset(&self) { + self.step.set(0); + } + + /// Backs off in a lock-free loop. + /// + /// This method should be used when we need to retry an operation because another thread made + /// progress. + /// + /// The processor may yield using the *YIELD* or *PAUSE* instruction. + /// + /// # Examples + /// + /// Backing off in a lock-free loop: + /// + /// ``` + /// use crossbeam_utils::Backoff; + /// use std::sync::atomic::AtomicUsize; + /// use std::sync::atomic::Ordering::SeqCst; + /// + /// fn fetch_mul(a: &AtomicUsize, b: usize) -> usize { + /// let backoff = Backoff::new(); + /// loop { + /// let val = a.load(SeqCst); + /// if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() { + /// return val; + /// } + /// backoff.spin(); + /// } + /// } + /// + /// let a = AtomicUsize::new(7); + /// assert_eq!(fetch_mul(&a, 8), 7); + /// assert_eq!(a.load(SeqCst), 56); + /// ``` + #[inline] + pub fn spin(&self) { + for _ in 0..1 << self.step.get().min(SPIN_LIMIT) { + hint::spin_loop(); + } + + if self.step.get() <= SPIN_LIMIT { + self.step.set(self.step.get() + 1); + } + } + + /// Backs off in a blocking loop. + /// + /// This method should be used when we need to wait for another thread to make progress. + /// + /// The processor may yield using the *YIELD* or *PAUSE* instruction and the current thread + /// may yield by giving up a timeslice to the OS scheduler. + /// + /// In `#[no_std]` environments, this method is equivalent to [`spin`]. + /// + /// If possible, use [`is_completed`] to check when it is advised to stop using backoff and + /// block the current thread using a different synchronization mechanism instead. + /// + /// [`spin`]: Backoff::spin + /// [`is_completed`]: Backoff::is_completed + /// + /// # Examples + /// + /// Waiting for an [`AtomicBool`] to become `true`: + /// + /// ``` + /// use crossbeam_utils::Backoff; + /// use std::sync::Arc; + /// use std::sync::atomic::AtomicBool; + /// use std::sync::atomic::Ordering::SeqCst; + /// use std::thread; + /// use std::time::Duration; + /// + /// fn spin_wait(ready: &AtomicBool) { + /// let backoff = Backoff::new(); + /// while !ready.load(SeqCst) { + /// backoff.snooze(); + /// } + /// } + /// + /// let ready = Arc::new(AtomicBool::new(false)); + /// let ready2 = ready.clone(); + /// + /// thread::spawn(move || { + /// thread::sleep(Duration::from_millis(100)); + /// ready2.store(true, SeqCst); + /// }); + /// + /// assert_eq!(ready.load(SeqCst), false); + /// spin_wait(&ready); + /// assert_eq!(ready.load(SeqCst), true); + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + /// + /// [`AtomicBool`]: std::sync::atomic::AtomicBool + #[inline] + pub fn snooze(&self) { + if self.step.get() <= SPIN_LIMIT { + for _ in 0..1 << self.step.get() { + hint::spin_loop(); + } + } else { + #[cfg(not(feature = "std"))] + for _ in 0..1 << self.step.get() { + hint::spin_loop(); + } + + #[cfg(feature = "std")] + ::std::thread::yield_now(); + } + + if self.step.get() <= YIELD_LIMIT { + self.step.set(self.step.get() + 1); + } + } + + /// Returns `true` if exponential backoff has completed and blocking the thread is advised. + /// + /// # Examples + /// + /// Waiting for an [`AtomicBool`] to become `true` and parking the thread after a long wait: + /// + /// ``` + /// use crossbeam_utils::Backoff; + /// use std::sync::Arc; + /// use std::sync::atomic::AtomicBool; + /// use std::sync::atomic::Ordering::SeqCst; + /// use std::thread; + /// use std::time::Duration; + /// + /// fn blocking_wait(ready: &AtomicBool) { + /// let backoff = Backoff::new(); + /// while !ready.load(SeqCst) { + /// if backoff.is_completed() { + /// thread::park(); + /// } else { + /// backoff.snooze(); + /// } + /// } + /// } + /// + /// let ready = Arc::new(AtomicBool::new(false)); + /// let ready2 = ready.clone(); + /// let waiter = thread::current(); + /// + /// thread::spawn(move || { + /// thread::sleep(Duration::from_millis(100)); + /// ready2.store(true, SeqCst); + /// waiter.unpark(); + /// }); + /// + /// assert_eq!(ready.load(SeqCst), false); + /// blocking_wait(&ready); + /// assert_eq!(ready.load(SeqCst), true); + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + /// + /// [`AtomicBool`]: std::sync::atomic::AtomicBool + #[inline] + pub fn is_completed(&self) -> bool { + self.step.get() > YIELD_LIMIT + } +} + +impl fmt::Debug for Backoff { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Backoff") + .field("step", &self.step) + .field("is_completed", &self.is_completed()) + .finish() + } +} + +impl Default for Backoff { + fn default() -> Backoff { + Backoff::new() + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/cache_padded.rs b/anneal/v2/vendor/crossbeam-utils/src/cache_padded.rs new file mode 100644 index 0000000000..6c930c6f3f --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/cache_padded.rs @@ -0,0 +1,217 @@ +use core::fmt; +use core::ops::{Deref, DerefMut}; + +/// Pads and aligns a value to the length of a cache line. +/// +/// In concurrent programming, sometimes it is desirable to make sure commonly accessed pieces of +/// data are not placed into the same cache line. Updating an atomic value invalidates the whole +/// cache line it belongs to, which makes the next access to the same cache line slower for other +/// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other +/// cached data. +/// +/// # Size and alignment +/// +/// Cache lines are assumed to be N bytes long, depending on the architecture: +/// +/// * On x86-64, aarch64, and powerpc64, N = 128. +/// * On arm, mips, mips64, sparc, and hexagon, N = 32. +/// * On m68k, N = 16. +/// * On s390x, N = 256. +/// * On all others, N = 64. +/// +/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line +/// length of the machine the program is running on. On modern Intel architectures, spatial +/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that +/// cache lines are 128 bytes long. +/// +/// The size of `CachePadded` is the smallest multiple of N bytes large enough to accommodate +/// a value of type `T`. +/// +/// The alignment of `CachePadded` is the maximum of N bytes and the alignment of `T`. +/// +/// # Examples +/// +/// Alignment and padding: +/// +/// ``` +/// use crossbeam_utils::CachePadded; +/// +/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)]; +/// let addr1 = &*array[0] as *const i8 as usize; +/// let addr2 = &*array[1] as *const i8 as usize; +/// +/// assert!(addr2 - addr1 >= 32); +/// assert_eq!(addr1 % 32, 0); +/// assert_eq!(addr2 % 32, 0); +/// ``` +/// +/// When building a concurrent queue with a head and a tail index, it is wise to place them in +/// different cache lines so that concurrent threads pushing and popping elements don't invalidate +/// each other's cache lines: +/// +/// ``` +/// use crossbeam_utils::CachePadded; +/// use std::sync::atomic::AtomicUsize; +/// +/// struct Queue { +/// head: CachePadded, +/// tail: CachePadded, +/// buffer: *mut T, +/// } +/// ``` +#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)] +// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache +// lines at a time, so we have to align to 128 bytes rather than 64. +// +// Sources: +// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf +// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107 +// +// aarch64/arm64ec's big.LITTLE architecture has asymmetric cores and "big" cores have 128-byte cache line size. +// +// Sources: +// - https://www.mono-project.com/news/2016/09/12/arm64-icache/ +// +// powerpc64 has 128-byte cache line size. +// +// Sources: +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/powerpc/include/asm/cache.h#L26 +#[cfg_attr( + any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "powerpc64", + ), + repr(align(128)) +)] +// arm, mips, mips64, sparc, and hexagon have 32-byte cache line size. +// +// Sources: +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L17 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/hexagon/include/asm/cache.h#L12 +#[cfg_attr( + any( + target_arch = "arm", + target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "sparc", + target_arch = "hexagon", + ), + repr(align(32)) +)] +// m68k has 16-byte cache line size. +// +// Sources: +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/m68k/include/asm/cache.h#L9 +#[cfg_attr(target_arch = "m68k", repr(align(16)))] +// s390x has 256-byte cache line size. +// +// Sources: +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/s390/include/asm/cache.h#L13 +#[cfg_attr(target_arch = "s390x", repr(align(256)))] +// x86, wasm, riscv, and sparc64 have 64-byte cache line size. +// +// Sources: +// - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9 +// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/riscv/include/asm/cache.h#L10 +// - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L19 +// +// All others are assumed to have 64-byte cache line size. +#[cfg_attr( + not(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "arm64ec", + target_arch = "powerpc64", + target_arch = "arm", + target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "sparc", + target_arch = "hexagon", + target_arch = "m68k", + target_arch = "s390x", + )), + repr(align(64)) +)] +pub struct CachePadded { + value: T, +} + +unsafe impl Send for CachePadded {} +unsafe impl Sync for CachePadded {} + +impl CachePadded { + /// Pads and aligns a value to the length of a cache line. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::CachePadded; + /// + /// let padded_value = CachePadded::new(1); + /// ``` + pub const fn new(t: T) -> CachePadded { + CachePadded:: { value: t } + } + + /// Returns the inner value. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::CachePadded; + /// + /// let padded_value = CachePadded::new(7); + /// let value = padded_value.into_inner(); + /// assert_eq!(value, 7); + /// ``` + pub fn into_inner(self) -> T { + self.value + } +} + +impl Deref for CachePadded { + type Target = T; + + fn deref(&self) -> &T { + &self.value + } +} + +impl DerefMut for CachePadded { + fn deref_mut(&mut self) -> &mut T { + &mut self.value + } +} + +impl fmt::Debug for CachePadded { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CachePadded") + .field("value", &self.value) + .finish() + } +} + +impl From for CachePadded { + fn from(t: T) -> Self { + CachePadded::new(t) + } +} + +impl fmt::Display for CachePadded { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.value, f) + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/lib.rs b/anneal/v2/vendor/crossbeam-utils/src/lib.rs new file mode 100644 index 0000000000..6f124f9700 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/lib.rs @@ -0,0 +1,110 @@ +//! Miscellaneous tools for concurrent programming. +//! +//! ## Atomics +//! +//! * [`AtomicCell`], a thread-safe mutable memory location. +//! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering. +//! +//! ## Thread synchronization +//! +//! * [`Parker`], a thread parking primitive. +//! * [`ShardedLock`], a sharded reader-writer lock with fast concurrent reads. +//! * [`WaitGroup`], for synchronizing the beginning or end of some computation. +//! +//! ## Utilities +//! +//! * [`Backoff`], for exponential backoff in spin loops. +//! * [`CachePadded`], for padding and aligning a value to the length of a cache line. +//! * [`scope`], for spawning threads that borrow local variables from the stack. +//! +//! [`AtomicCell`]: atomic::AtomicCell +//! [`AtomicConsume`]: atomic::AtomicConsume +//! [`Parker`]: sync::Parker +//! [`ShardedLock`]: sync::ShardedLock +//! [`WaitGroup`]: sync::WaitGroup +//! [`scope`]: thread::scope + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms), + allow(dead_code, unused_assignments, unused_variables) + ) +))] +#![warn( + missing_docs, + missing_debug_implementations, + rust_2018_idioms, + unreachable_pub +)] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(crossbeam_loom)] +#[allow(unused_imports)] +mod primitive { + pub(crate) mod hint { + pub(crate) use loom::hint::spin_loop; + } + pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use loom::sync::atomic::{ + AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, + AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering, + }; + + // FIXME: loom does not support compiler_fence at the moment. + // https://github.com/tokio-rs/loom/issues/117 + // we use fence as a stand-in for compiler_fence for the time being. + // this may miss some races since fence is stronger than compiler_fence, + // but it's the best we can do for the time being. + pub(crate) use loom::sync::atomic::fence as compiler_fence; + } + pub(crate) use loom::sync::{Arc, Condvar, Mutex}; + } +} +#[cfg(not(crossbeam_loom))] +#[allow(unused_imports)] +mod primitive { + pub(crate) mod hint { + pub(crate) use core::hint::spin_loop; + } + pub(crate) mod sync { + pub(crate) mod atomic { + pub(crate) use core::sync::atomic::{compiler_fence, Ordering}; + #[cfg(not(crossbeam_no_atomic))] + pub(crate) use core::sync::atomic::{ + AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicU16, AtomicU8, AtomicUsize, + }; + #[cfg(not(crossbeam_no_atomic))] + #[cfg(any(target_has_atomic = "32", not(target_pointer_width = "16")))] + pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32}; + #[cfg(not(crossbeam_no_atomic))] + #[cfg(any( + target_has_atomic = "64", + not(any(target_pointer_width = "16", target_pointer_width = "32")), + ))] + pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64}; + } + + #[cfg(feature = "std")] + pub(crate) use std::sync::{Arc, Condvar, Mutex}; + } +} + +pub mod atomic; + +mod cache_padded; +pub use crate::cache_padded::CachePadded; + +mod backoff; +pub use crate::backoff::Backoff; + +#[cfg(feature = "std")] +pub mod sync; + +#[cfg(feature = "std")] +#[cfg(not(crossbeam_loom))] +pub mod thread; diff --git a/anneal/v2/vendor/crossbeam-utils/src/sync/mod.rs b/anneal/v2/vendor/crossbeam-utils/src/sync/mod.rs new file mode 100644 index 0000000000..f9eec71fb3 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/sync/mod.rs @@ -0,0 +1,17 @@ +//! Thread synchronization primitives. +//! +//! * [`Parker`], a thread parking primitive. +//! * [`ShardedLock`], a sharded reader-writer lock with fast concurrent reads. +//! * [`WaitGroup`], for synchronizing the beginning or end of some computation. + +#[cfg(not(crossbeam_loom))] +mod once_lock; +mod parker; +#[cfg(not(crossbeam_loom))] +mod sharded_lock; +mod wait_group; + +pub use self::parker::{Parker, Unparker}; +#[cfg(not(crossbeam_loom))] +pub use self::sharded_lock::{ShardedLock, ShardedLockReadGuard, ShardedLockWriteGuard}; +pub use self::wait_group::WaitGroup; diff --git a/anneal/v2/vendor/crossbeam-utils/src/sync/once_lock.rs b/anneal/v2/vendor/crossbeam-utils/src/sync/once_lock.rs new file mode 100644 index 0000000000..e057aca7d5 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/sync/once_lock.rs @@ -0,0 +1,88 @@ +// Based on unstable std::sync::OnceLock. +// +// Source: https://github.com/rust-lang/rust/blob/8e9c93df464b7ada3fc7a1c8ccddd9dcb24ee0a0/library/std/src/sync/once_lock.rs + +use core::cell::UnsafeCell; +use core::mem::MaybeUninit; +use std::sync::Once; + +pub(crate) struct OnceLock { + once: Once, + value: UnsafeCell>, + // Unlike std::sync::OnceLock, we don't need PhantomData here because + // we don't use #[may_dangle]. +} + +unsafe impl Sync for OnceLock {} +unsafe impl Send for OnceLock {} + +impl OnceLock { + /// Creates a new empty cell. + #[must_use] + pub(crate) const fn new() -> Self { + Self { + once: Once::new(), + value: UnsafeCell::new(MaybeUninit::uninit()), + } + } + + /// Gets the contents of the cell, initializing it with `f` if the cell + /// was empty. + /// + /// Many threads may call `get_or_init` concurrently with different + /// initializing functions, but it is guaranteed that only one function + /// will be executed. + /// + /// # Panics + /// + /// If `f` panics, the panic is propagated to the caller, and the cell + /// remains uninitialized. + /// + /// It is an error to reentrantly initialize the cell from `f`. The + /// exact outcome is unspecified. Current implementation deadlocks, but + /// this may be changed to a panic in the future. + pub(crate) fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + // Fast path check + if self.once.is_completed() { + // SAFETY: The inner value has been initialized + return unsafe { self.get_unchecked() }; + } + self.initialize(f); + + // SAFETY: The inner value has been initialized + unsafe { self.get_unchecked() } + } + + #[cold] + fn initialize(&self, f: F) + where + F: FnOnce() -> T, + { + let slot = self.value.get(); + + self.once.call_once(|| { + let value = f(); + unsafe { slot.write(MaybeUninit::new(value)) } + }); + } + + /// # Safety + /// + /// The value must be initialized + unsafe fn get_unchecked(&self) -> &T { + debug_assert!(self.once.is_completed()); + &*self.value.get().cast::() + } +} + +impl Drop for OnceLock { + fn drop(&mut self) { + if self.once.is_completed() { + // SAFETY: The inner value has been initialized + unsafe { (*self.value.get()).assume_init_drop() }; + } + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/sync/parker.rs b/anneal/v2/vendor/crossbeam-utils/src/sync/parker.rs new file mode 100644 index 0000000000..971981d2b7 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/sync/parker.rs @@ -0,0 +1,415 @@ +use crate::primitive::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::primitive::sync::{Arc, Condvar, Mutex}; +use std::fmt; +use std::marker::PhantomData; +use std::time::{Duration, Instant}; + +/// A thread parking primitive. +/// +/// Conceptually, each `Parker` has an associated token which is initially not present: +/// +/// * The [`park`] method blocks the current thread unless or until the token is available, at +/// which point it automatically consumes the token. +/// +/// * The [`park_timeout`] and [`park_deadline`] methods work the same as [`park`], but block for +/// a specified maximum time. +/// +/// * The [`unpark`] method atomically makes the token available if it wasn't already. Because the +/// token is initially absent, [`unpark`] followed by [`park`] will result in the second call +/// returning immediately. +/// +/// In other words, each `Parker` acts a bit like a spinlock that can be locked and unlocked using +/// [`park`] and [`unpark`]. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::time::Duration; +/// use crossbeam_utils::sync::Parker; +/// +/// let p = Parker::new(); +/// let u = p.unparker().clone(); +/// +/// // Make the token available. +/// u.unpark(); +/// // Wakes up immediately and consumes the token. +/// p.park(); +/// +/// thread::spawn(move || { +/// thread::sleep(Duration::from_millis(500)); +/// u.unpark(); +/// }); +/// +/// // Wakes up when `u.unpark()` provides the token. +/// p.park(); +/// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 +/// ``` +/// +/// [`park`]: Parker::park +/// [`park_timeout`]: Parker::park_timeout +/// [`park_deadline`]: Parker::park_deadline +/// [`unpark`]: Unparker::unpark +pub struct Parker { + unparker: Unparker, + _marker: PhantomData<*const ()>, +} + +unsafe impl Send for Parker {} + +impl Default for Parker { + fn default() -> Self { + Self { + unparker: Unparker { + inner: Arc::new(Inner { + state: AtomicUsize::new(EMPTY), + lock: Mutex::new(()), + cvar: Condvar::new(), + }), + }, + _marker: PhantomData, + } + } +} + +impl Parker { + /// Creates a new `Parker`. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// ``` + /// + pub fn new() -> Parker { + Self::default() + } + + /// Blocks the current thread until the token is made available. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let u = p.unparker().clone(); + /// + /// // Make the token available. + /// u.unpark(); + /// + /// // Wakes up immediately and consumes the token. + /// p.park(); + /// ``` + pub fn park(&self) { + self.unparker.inner.park(None); + } + + /// Blocks the current thread until the token is made available, but only for a limited time. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// + /// // Waits for the token to become available, but will not wait longer than 500 ms. + /// p.park_timeout(Duration::from_millis(500)); + /// ``` + pub fn park_timeout(&self, timeout: Duration) { + match Instant::now().checked_add(timeout) { + Some(deadline) => self.park_deadline(deadline), + None => self.park(), + } + } + + /// Blocks the current thread until the token is made available, or until a certain deadline. + /// + /// # Examples + /// + /// ``` + /// use std::time::{Duration, Instant}; + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let deadline = Instant::now() + Duration::from_millis(500); + /// + /// // Waits for the token to become available, but will not wait longer than 500 ms. + /// p.park_deadline(deadline); + /// ``` + pub fn park_deadline(&self, deadline: Instant) { + self.unparker.inner.park(Some(deadline)) + } + + /// Returns a reference to an associated [`Unparker`]. + /// + /// The returned [`Unparker`] doesn't have to be used by reference - it can also be cloned. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let u = p.unparker().clone(); + /// + /// // Make the token available. + /// u.unpark(); + /// // Wakes up immediately and consumes the token. + /// p.park(); + /// ``` + /// + /// [`park`]: Parker::park + /// [`park_timeout`]: Parker::park_timeout + pub fn unparker(&self) -> &Unparker { + &self.unparker + } + + /// Converts a `Parker` into a raw pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let raw = Parker::into_raw(p); + /// # let _ = unsafe { Parker::from_raw(raw) }; + /// ``` + pub fn into_raw(this: Parker) -> *const () { + Unparker::into_raw(this.unparker) + } + + /// Converts a raw pointer into a `Parker`. + /// + /// # Safety + /// + /// This method is safe to use only with pointers returned by [`Parker::into_raw`]. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let raw = Parker::into_raw(p); + /// let p = unsafe { Parker::from_raw(raw) }; + /// ``` + pub unsafe fn from_raw(ptr: *const ()) -> Parker { + Parker { + unparker: Unparker::from_raw(ptr), + _marker: PhantomData, + } + } +} + +impl fmt::Debug for Parker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Parker { .. }") + } +} + +/// Unparks a thread parked by the associated [`Parker`]. +pub struct Unparker { + inner: Arc, +} + +unsafe impl Send for Unparker {} +unsafe impl Sync for Unparker {} + +impl Unparker { + /// Atomically makes the token available if it is not already. + /// + /// This method will wake up the thread blocked on [`park`] or [`park_timeout`], if there is + /// any. + /// + /// # Examples + /// + /// ``` + /// use std::thread; + /// use std::time::Duration; + /// use crossbeam_utils::sync::Parker; + /// + /// let p = Parker::new(); + /// let u = p.unparker().clone(); + /// + /// thread::spawn(move || { + /// thread::sleep(Duration::from_millis(500)); + /// u.unpark(); + /// }); + /// + /// // Wakes up when `u.unpark()` provides the token. + /// p.park(); + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + /// + /// [`park`]: Parker::park + /// [`park_timeout`]: Parker::park_timeout + pub fn unpark(&self) { + self.inner.unpark() + } + + /// Converts an `Unparker` into a raw pointer. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::{Parker, Unparker}; + /// + /// let p = Parker::new(); + /// let u = p.unparker().clone(); + /// let raw = Unparker::into_raw(u); + /// # let _ = unsafe { Unparker::from_raw(raw) }; + /// ``` + pub fn into_raw(this: Unparker) -> *const () { + Arc::into_raw(this.inner).cast::<()>() + } + + /// Converts a raw pointer into an `Unparker`. + /// + /// # Safety + /// + /// This method is safe to use only with pointers returned by [`Unparker::into_raw`]. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::{Parker, Unparker}; + /// + /// let p = Parker::new(); + /// let u = p.unparker().clone(); + /// + /// let raw = Unparker::into_raw(u); + /// let u = unsafe { Unparker::from_raw(raw) }; + /// ``` + pub unsafe fn from_raw(ptr: *const ()) -> Unparker { + Unparker { + inner: Arc::from_raw(ptr.cast::()), + } + } +} + +impl fmt::Debug for Unparker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Unparker { .. }") + } +} + +impl Clone for Unparker { + fn clone(&self) -> Unparker { + Unparker { + inner: self.inner.clone(), + } + } +} + +const EMPTY: usize = 0; +const PARKED: usize = 1; +const NOTIFIED: usize = 2; + +struct Inner { + state: AtomicUsize, + lock: Mutex<()>, + cvar: Condvar, +} + +impl Inner { + fn park(&self, deadline: Option) { + // If we were previously notified then we consume this notification and return quickly. + if self + .state + .compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) + .is_ok() + { + return; + } + + // If the timeout is zero, then there is no need to actually block. + if let Some(deadline) = deadline { + if deadline <= Instant::now() { + return; + } + } + + // Otherwise we need to coordinate going to sleep. + let mut m = self.lock.lock().unwrap(); + + match self.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { + Ok(_) => {} + // Consume this notification to avoid spurious wakeups in the next park. + Err(NOTIFIED) => { + // We must read `state` here, even though we know it will be `NOTIFIED`. This is + // because `unpark` may have been called again since we read `NOTIFIED` in the + // `compare_exchange` above. We must perform an acquire operation that synchronizes + // with that `unpark` to observe any writes it made before the call to `unpark`. To + // do that we must read from the write it made to `state`. + let old = self.state.swap(EMPTY, SeqCst); + assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); + return; + } + Err(n) => panic!("inconsistent park_timeout state: {}", n), + } + + loop { + // Block the current thread on the conditional variable. + m = match deadline { + None => self.cvar.wait(m).unwrap(), + Some(deadline) => { + let now = Instant::now(); + if now < deadline { + // We could check for a timeout here, in the return value of wait_timeout, + // but in the case that a timeout and an unpark arrive simultaneously, we + // prefer to report the former. + self.cvar.wait_timeout(m, deadline - now).unwrap().0 + } else { + // We've timed out; swap out the state back to empty on our way out + match self.state.swap(EMPTY, SeqCst) { + NOTIFIED | PARKED => return, + n => panic!("inconsistent park_timeout state: {}", n), + }; + } + } + }; + + if self + .state + .compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) + .is_ok() + { + // got a notification + return; + } + + // Spurious wakeup, go back to sleep. Alternatively, if we timed out, it will be caught + // in the branch above, when we discover the deadline is in the past + } + } + + pub(crate) fn unpark(&self) { + // To ensure the unparked thread will observe any writes we made before this call, we must + // perform a release operation that `park` can synchronize with. To do that we must write + // `NOTIFIED` even if `state` is already `NOTIFIED`. That is why this must be a swap rather + // than a compare-and-swap that returns if it reads `NOTIFIED` on failure. + match self.state.swap(NOTIFIED, SeqCst) { + EMPTY => return, // no one was waiting + NOTIFIED => return, // already unparked + PARKED => {} // gotta go wake someone up + _ => panic!("inconsistent state in unpark"), + } + + // There is a period between when the parked thread sets `state` to `PARKED` (or last + // checked `state` in the case of a spurious wakeup) and when it actually waits on `cvar`. + // If we were to notify during this period it would be ignored and then when the parked + // thread went to sleep it would never wake up. Fortunately, it has `lock` locked at this + // stage so we can acquire `lock` to wait until it is ready to receive the notification. + // + // Releasing `lock` before the call to `notify_one` means that when the parked thread wakes + // it doesn't get woken only to have to wait for us to release `lock`. + drop(self.lock.lock().unwrap()); + self.cvar.notify_one(); + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/sync/sharded_lock.rs b/anneal/v2/vendor/crossbeam-utils/src/sync/sharded_lock.rs new file mode 100644 index 0000000000..629b97598e --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/sync/sharded_lock.rs @@ -0,0 +1,638 @@ +use std::boxed::Box; +use std::cell::UnsafeCell; +use std::collections::HashMap; +use std::fmt; +use std::marker::PhantomData; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::panic::{RefUnwindSafe, UnwindSafe}; +use std::sync::{LockResult, PoisonError, TryLockError, TryLockResult}; +use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use std::thread::{self, ThreadId}; +use std::vec::Vec; + +use crate::sync::once_lock::OnceLock; +use crate::CachePadded; + +/// The number of shards per sharded lock. Must be a power of two. +const NUM_SHARDS: usize = 8; + +/// A shard containing a single reader-writer lock. +struct Shard { + /// The inner reader-writer lock. + lock: RwLock<()>, + + /// The write-guard keeping this shard locked. + /// + /// Write operations will lock each shard and store the guard here. These guards get dropped at + /// the same time the big guard is dropped. + write_guard: UnsafeCell>>, +} + +/// A sharded reader-writer lock. +/// +/// This lock is equivalent to [`RwLock`], except read operations are faster and write operations +/// are slower. +/// +/// A `ShardedLock` is internally made of a list of *shards*, each being a [`RwLock`] occupying a +/// single cache line. Read operations will pick one of the shards depending on the current thread +/// and lock it. Write operations need to lock all shards in succession. +/// +/// By splitting the lock into shards, concurrent read operations will in most cases choose +/// different shards and thus update different cache lines, which is good for scalability. However, +/// write operations need to do more work and are therefore slower than usual. +/// +/// The priority policy of the lock is dependent on the underlying operating system's +/// implementation, and this type does not guarantee that any particular policy will be used. +/// +/// # Poisoning +/// +/// A `ShardedLock`, like [`RwLock`], will become poisoned on a panic. Note that it may only be +/// poisoned if a panic occurs while a write operation is in progress. If a panic occurs in any +/// read operation, the lock will not be poisoned. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_utils::sync::ShardedLock; +/// +/// let lock = ShardedLock::new(5); +/// +/// // Any number of read locks can be held at once. +/// { +/// let r1 = lock.read().unwrap(); +/// let r2 = lock.read().unwrap(); +/// assert_eq!(*r1, 5); +/// assert_eq!(*r2, 5); +/// } // Read locks are dropped at this point. +/// +/// // However, only one write lock may be held. +/// { +/// let mut w = lock.write().unwrap(); +/// *w += 1; +/// assert_eq!(*w, 6); +/// } // Write lock is dropped here. +/// ``` +/// +/// [`RwLock`]: std::sync::RwLock +pub struct ShardedLock { + /// A list of locks protecting the internal data. + shards: Box<[CachePadded]>, + + /// The internal data. + value: UnsafeCell, +} + +unsafe impl Send for ShardedLock {} +unsafe impl Sync for ShardedLock {} + +impl UnwindSafe for ShardedLock {} +impl RefUnwindSafe for ShardedLock {} + +impl ShardedLock { + /// Creates a new sharded reader-writer lock. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let lock = ShardedLock::new(5); + /// ``` + pub fn new(value: T) -> ShardedLock { + ShardedLock { + shards: (0..NUM_SHARDS) + .map(|_| { + CachePadded::new(Shard { + lock: RwLock::new(()), + write_guard: UnsafeCell::new(None), + }) + }) + .collect::>(), + value: UnsafeCell::new(value), + } + } + + /// Consumes this lock, returning the underlying data. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let lock = ShardedLock::new(String::new()); + /// { + /// let mut s = lock.write().unwrap(); + /// *s = "modified".to_owned(); + /// } + /// assert_eq!(lock.into_inner().unwrap(), "modified"); + /// ``` + pub fn into_inner(self) -> LockResult { + let is_poisoned = self.is_poisoned(); + let inner = self.value.into_inner(); + + if is_poisoned { + Err(PoisonError::new(inner)) + } else { + Ok(inner) + } + } +} + +impl ShardedLock { + /// Returns `true` if the lock is poisoned. + /// + /// If another thread can still access the lock, it may become poisoned at any time. A `false` + /// result should not be trusted without additional synchronization. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let lock = Arc::new(ShardedLock::new(0)); + /// let c_lock = lock.clone(); + /// + /// let _ = thread::spawn(move || { + /// let _lock = c_lock.write().unwrap(); + /// panic!(); // the lock gets poisoned + /// }).join(); + /// assert_eq!(lock.is_poisoned(), true); + /// ``` + pub fn is_poisoned(&self) -> bool { + self.shards[0].lock.is_poisoned() + } + + /// Returns a mutable reference to the underlying data. + /// + /// Since this call borrows the lock mutably, no actual locking needs to take place. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let mut lock = ShardedLock::new(0); + /// *lock.get_mut().unwrap() = 10; + /// assert_eq!(*lock.read().unwrap(), 10); + /// ``` + pub fn get_mut(&mut self) -> LockResult<&mut T> { + let is_poisoned = self.is_poisoned(); + let inner = unsafe { &mut *self.value.get() }; + + if is_poisoned { + Err(PoisonError::new(inner)) + } else { + Ok(inner) + } + } + + /// Attempts to acquire this lock with shared read access. + /// + /// If the access could not be granted at this time, an error is returned. Otherwise, a guard + /// is returned which will release the shared access when it is dropped. This method does not + /// provide any guarantees with respect to the ordering of whether contentious readers or + /// writers will acquire the lock first. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let lock = ShardedLock::new(1); + /// + /// match lock.try_read() { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; + /// ``` + pub fn try_read(&self) -> TryLockResult> { + // Take the current thread index and map it to a shard index. Thread indices will tend to + // distribute shards among threads equally, thus reducing contention due to read-locking. + let current_index = current_index().unwrap_or(0); + let shard_index = current_index & (self.shards.len() - 1); + + match self.shards[shard_index].lock.try_read() { + Ok(guard) => Ok(ShardedLockReadGuard { + lock: self, + _guard: guard, + _marker: PhantomData, + }), + Err(TryLockError::Poisoned(err)) => { + let guard = ShardedLockReadGuard { + lock: self, + _guard: err.into_inner(), + _marker: PhantomData, + }; + Err(TryLockError::Poisoned(PoisonError::new(guard))) + } + Err(TryLockError::WouldBlock) => Err(TryLockError::WouldBlock), + } + } + + /// Locks with shared read access, blocking the current thread until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers which hold the lock. + /// There may be other readers currently inside the lock when this method returns. This method + /// does not provide any guarantees with respect to the ordering of whether contentious readers + /// or writers will acquire the lock first. + /// + /// Returns a guard which will release the shared access when dropped. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Panics + /// + /// This method might panic when called if the lock is already held by the current thread. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// use std::sync::Arc; + /// use std::thread; + /// + /// let lock = Arc::new(ShardedLock::new(1)); + /// let c_lock = lock.clone(); + /// + /// let n = lock.read().unwrap(); + /// assert_eq!(*n, 1); + /// + /// thread::spawn(move || { + /// let r = c_lock.read(); + /// assert!(r.is_ok()); + /// }).join().unwrap(); + /// ``` + pub fn read(&self) -> LockResult> { + // Take the current thread index and map it to a shard index. Thread indices will tend to + // distribute shards among threads equally, thus reducing contention due to read-locking. + let current_index = current_index().unwrap_or(0); + let shard_index = current_index & (self.shards.len() - 1); + + match self.shards[shard_index].lock.read() { + Ok(guard) => Ok(ShardedLockReadGuard { + lock: self, + _guard: guard, + _marker: PhantomData, + }), + Err(err) => Err(PoisonError::new(ShardedLockReadGuard { + lock: self, + _guard: err.into_inner(), + _marker: PhantomData, + })), + } + } + + /// Attempts to acquire this lock with exclusive write access. + /// + /// If the access could not be granted at this time, an error is returned. Otherwise, a guard + /// is returned which will release the exclusive access when it is dropped. This method does + /// not provide any guarantees with respect to the ordering of whether contentious readers or + /// writers will acquire the lock first. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let lock = ShardedLock::new(1); + /// + /// let n = lock.read().unwrap(); + /// assert_eq!(*n, 1); + /// + /// assert!(lock.try_write().is_err()); + /// ``` + pub fn try_write(&self) -> TryLockResult> { + let mut poisoned = false; + let mut blocked = None; + + // Write-lock each shard in succession. + for (i, shard) in self.shards.iter().enumerate() { + let guard = match shard.lock.try_write() { + Ok(guard) => guard, + Err(TryLockError::Poisoned(err)) => { + poisoned = true; + err.into_inner() + } + Err(TryLockError::WouldBlock) => { + blocked = Some(i); + break; + } + }; + + // Store the guard into the shard. + unsafe { + let guard: RwLockWriteGuard<'static, ()> = mem::transmute(guard); + let dest: *mut _ = shard.write_guard.get(); + *dest = Some(guard); + } + } + + if let Some(i) = blocked { + // Unlock the shards in reverse order of locking. + for shard in self.shards[0..i].iter().rev() { + unsafe { + let dest: *mut _ = shard.write_guard.get(); + let guard = (*dest).take(); + drop(guard); + } + } + Err(TryLockError::WouldBlock) + } else if poisoned { + let guard = ShardedLockWriteGuard { + lock: self, + _marker: PhantomData, + }; + Err(TryLockError::Poisoned(PoisonError::new(guard))) + } else { + Ok(ShardedLockWriteGuard { + lock: self, + _marker: PhantomData, + }) + } + } + + /// Locks with exclusive write access, blocking the current thread until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers which hold the lock. + /// There may be other readers currently inside the lock when this method returns. This method + /// does not provide any guarantees with respect to the ordering of whether contentious readers + /// or writers will acquire the lock first. + /// + /// Returns a guard which will release the exclusive access when dropped. + /// + /// # Errors + /// + /// This method will return an error if the lock is poisoned. A lock gets poisoned when a write + /// operation panics. + /// + /// # Panics + /// + /// This method might panic when called if the lock is already held by the current thread. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::ShardedLock; + /// + /// let lock = ShardedLock::new(1); + /// + /// let mut n = lock.write().unwrap(); + /// *n = 2; + /// + /// assert!(lock.try_read().is_err()); + /// ``` + pub fn write(&self) -> LockResult> { + let mut poisoned = false; + + // Write-lock each shard in succession. + for shard in self.shards.iter() { + let guard = match shard.lock.write() { + Ok(guard) => guard, + Err(err) => { + poisoned = true; + err.into_inner() + } + }; + + // Store the guard into the shard. + unsafe { + let guard: RwLockWriteGuard<'_, ()> = guard; + let guard: RwLockWriteGuard<'static, ()> = mem::transmute(guard); + let dest: *mut _ = shard.write_guard.get(); + *dest = Some(guard); + } + } + + if poisoned { + Err(PoisonError::new(ShardedLockWriteGuard { + lock: self, + _marker: PhantomData, + })) + } else { + Ok(ShardedLockWriteGuard { + lock: self, + _marker: PhantomData, + }) + } + } +} + +impl fmt::Debug for ShardedLock { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.try_read() { + Ok(guard) => f + .debug_struct("ShardedLock") + .field("data", &&*guard) + .finish(), + Err(TryLockError::Poisoned(err)) => f + .debug_struct("ShardedLock") + .field("data", &&**err.get_ref()) + .finish(), + Err(TryLockError::WouldBlock) => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("") + } + } + f.debug_struct("ShardedLock") + .field("data", &LockedPlaceholder) + .finish() + } + } + } +} + +impl Default for ShardedLock { + fn default() -> ShardedLock { + ShardedLock::new(Default::default()) + } +} + +impl From for ShardedLock { + fn from(t: T) -> Self { + ShardedLock::new(t) + } +} + +/// A guard used to release the shared read access of a [`ShardedLock`] when dropped. +#[clippy::has_significant_drop] +pub struct ShardedLockReadGuard<'a, T: ?Sized> { + lock: &'a ShardedLock, + _guard: RwLockReadGuard<'a, ()>, + _marker: PhantomData>, +} + +unsafe impl Sync for ShardedLockReadGuard<'_, T> {} + +impl Deref for ShardedLockReadGuard<'_, T> { + type Target = T; + + fn deref(&self) -> &T { + unsafe { &*self.lock.value.get() } + } +} + +impl fmt::Debug for ShardedLockReadGuard<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ShardedLockReadGuard") + .field("lock", &self.lock) + .finish() + } +} + +impl fmt::Display for ShardedLockReadGuard<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +/// A guard used to release the exclusive write access of a [`ShardedLock`] when dropped. +#[clippy::has_significant_drop] +pub struct ShardedLockWriteGuard<'a, T: ?Sized> { + lock: &'a ShardedLock, + _marker: PhantomData>, +} + +unsafe impl Sync for ShardedLockWriteGuard<'_, T> {} + +impl Drop for ShardedLockWriteGuard<'_, T> { + fn drop(&mut self) { + // Unlock the shards in reverse order of locking. + for shard in self.lock.shards.iter().rev() { + unsafe { + let dest: *mut _ = shard.write_guard.get(); + let guard = (*dest).take(); + drop(guard); + } + } + } +} + +impl fmt::Debug for ShardedLockWriteGuard<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ShardedLockWriteGuard") + .field("lock", &self.lock) + .finish() + } +} + +impl fmt::Display for ShardedLockWriteGuard<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl Deref for ShardedLockWriteGuard<'_, T> { + type Target = T; + + fn deref(&self) -> &T { + unsafe { &*self.lock.value.get() } + } +} + +impl DerefMut for ShardedLockWriteGuard<'_, T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.lock.value.get() } + } +} + +/// Returns a `usize` that identifies the current thread. +/// +/// Each thread is associated with an 'index'. While there are no particular guarantees, indices +/// usually tend to be consecutive numbers between 0 and the number of running threads. +/// +/// Since this function accesses TLS, `None` might be returned if the current thread's TLS is +/// tearing down. +#[inline] +fn current_index() -> Option { + REGISTRATION.try_with(|reg| reg.index).ok() +} + +/// The global registry keeping track of registered threads and indices. +struct ThreadIndices { + /// Mapping from `ThreadId` to thread index. + mapping: HashMap, + + /// A list of free indices. + free_list: Vec, + + /// The next index to allocate if the free list is empty. + next_index: usize, +} + +fn thread_indices() -> &'static Mutex { + static THREAD_INDICES: OnceLock> = OnceLock::new(); + fn init() -> Mutex { + Mutex::new(ThreadIndices { + mapping: HashMap::new(), + free_list: Vec::new(), + next_index: 0, + }) + } + THREAD_INDICES.get_or_init(init) +} + +/// A registration of a thread with an index. +/// +/// When dropped, unregisters the thread and frees the reserved index. +struct Registration { + index: usize, + thread_id: ThreadId, +} + +impl Drop for Registration { + fn drop(&mut self) { + let mut indices = thread_indices().lock().unwrap(); + indices.mapping.remove(&self.thread_id); + indices.free_list.push(self.index); + } +} + +std::thread_local! { + static REGISTRATION: Registration = { + let thread_id = thread::current().id(); + let mut indices = thread_indices().lock().unwrap(); + + let index = match indices.free_list.pop() { + Some(i) => i, + None => { + let i = indices.next_index; + indices.next_index += 1; + i + } + }; + indices.mapping.insert(thread_id, index); + + Registration { + index, + thread_id, + } + }; +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/sync/wait_group.rs b/anneal/v2/vendor/crossbeam-utils/src/sync/wait_group.rs new file mode 100644 index 0000000000..19d6074157 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/sync/wait_group.rs @@ -0,0 +1,145 @@ +use crate::primitive::sync::{Arc, Condvar, Mutex}; +use std::fmt; + +/// Enables threads to synchronize the beginning or end of some computation. +/// +/// # Wait groups vs barriers +/// +/// `WaitGroup` is very similar to [`Barrier`], but there are a few differences: +/// +/// * [`Barrier`] needs to know the number of threads at construction, while `WaitGroup` is cloned to +/// register more threads. +/// +/// * A [`Barrier`] can be reused even after all threads have synchronized, while a `WaitGroup` +/// synchronizes threads only once. +/// +/// * All threads wait for others to reach the [`Barrier`]. With `WaitGroup`, each thread can choose +/// to either wait for other threads or to continue without blocking. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_utils::sync::WaitGroup; +/// use std::thread; +/// +/// // Create a new wait group. +/// let wg = WaitGroup::new(); +/// +/// for _ in 0..4 { +/// // Create another reference to the wait group. +/// let wg = wg.clone(); +/// +/// thread::spawn(move || { +/// // Do some work. +/// +/// // Drop the reference to the wait group. +/// drop(wg); +/// }); +/// } +/// +/// // Block until all threads have finished their work. +/// wg.wait(); +/// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 +/// ``` +/// +/// [`Barrier`]: std::sync::Barrier +pub struct WaitGroup { + inner: Arc, +} + +/// Inner state of a `WaitGroup`. +struct Inner { + cvar: Condvar, + count: Mutex, +} + +impl Default for WaitGroup { + fn default() -> Self { + Self { + inner: Arc::new(Inner { + cvar: Condvar::new(), + count: Mutex::new(1), + }), + } + } +} + +impl WaitGroup { + /// Creates a new wait group and returns the single reference to it. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::WaitGroup; + /// + /// let wg = WaitGroup::new(); + /// ``` + pub fn new() -> Self { + Self::default() + } + + /// Drops this reference and waits until all other references are dropped. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::sync::WaitGroup; + /// use std::thread; + /// + /// let wg = WaitGroup::new(); + /// + /// thread::spawn({ + /// let wg = wg.clone(); + /// move || { + /// // Block until both threads have reached `wait()`. + /// wg.wait(); + /// } + /// }); + /// + /// // Block until both threads have reached `wait()`. + /// wg.wait(); + /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 + /// ``` + pub fn wait(self) { + if *self.inner.count.lock().unwrap() == 1 { + return; + } + + let inner = self.inner.clone(); + drop(self); + + let mut count = inner.count.lock().unwrap(); + while *count > 0 { + count = inner.cvar.wait(count).unwrap(); + } + } +} + +impl Drop for WaitGroup { + fn drop(&mut self) { + let mut count = self.inner.count.lock().unwrap(); + *count -= 1; + + if *count == 0 { + self.inner.cvar.notify_all(); + } + } +} + +impl Clone for WaitGroup { + fn clone(&self) -> WaitGroup { + let mut count = self.inner.count.lock().unwrap(); + *count += 1; + + WaitGroup { + inner: self.inner.clone(), + } + } +} + +impl fmt::Debug for WaitGroup { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let count: &usize = &*self.inner.count.lock().unwrap(); + f.debug_struct("WaitGroup").field("count", count).finish() + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/src/thread.rs b/anneal/v2/vendor/crossbeam-utils/src/thread.rs new file mode 100644 index 0000000000..847f4cf112 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/src/thread.rs @@ -0,0 +1,611 @@ +//! Threads that can borrow variables from the stack. +//! +//! Create a scope when spawned threads need to access variables on the stack: +//! +//! ``` +//! use crossbeam_utils::thread; +//! +//! let people = vec![ +//! "Alice".to_string(), +//! "Bob".to_string(), +//! "Carol".to_string(), +//! ]; +//! +//! thread::scope(|s| { +//! for person in &people { +//! s.spawn(move |_| { +//! println!("Hello, {}!", person); +//! }); +//! } +//! }).unwrap(); +//! ``` +//! +//! # Why scoped threads? +//! +//! Suppose we wanted to re-write the previous example using plain threads: +//! +//! ```compile_fail,E0597 +//! use std::thread; +//! +//! let people = vec![ +//! "Alice".to_string(), +//! "Bob".to_string(), +//! "Carol".to_string(), +//! ]; +//! +//! let mut threads = Vec::new(); +//! +//! for person in &people { +//! threads.push(thread::spawn(move || { +//! println!("Hello, {}!", person); +//! })); +//! } +//! +//! for thread in threads { +//! thread.join().unwrap(); +//! } +//! ``` +//! +//! This doesn't work because the borrow checker complains about `people` not living long enough: +//! +//! ```text +//! error[E0597]: `people` does not live long enough +//! --> src/main.rs:12:20 +//! | +//! 12 | for person in &people { +//! | ^^^^^^ borrowed value does not live long enough +//! ... +//! 21 | } +//! | - borrowed value only lives until here +//! | +//! = note: borrowed value must be valid for the static lifetime... +//! ``` +//! +//! The problem here is that spawned threads are not allowed to borrow variables on stack because +//! the compiler cannot prove they will be joined before `people` is destroyed. +//! +//! Scoped threads are a mechanism to guarantee to the compiler that spawned threads will be joined +//! before the scope ends. +//! +//! # How scoped threads work +//! +//! If a variable is borrowed by a thread, the thread must complete before the variable is +//! destroyed. Threads spawned using [`std::thread::spawn`] can only borrow variables with the +//! `'static` lifetime because the borrow checker cannot be sure when the thread will complete. +//! +//! A scope creates a clear boundary between variables outside the scope and threads inside the +//! scope. Whenever a scope spawns a thread, it promises to join the thread before the scope ends. +//! This way we guarantee to the borrow checker that scoped threads only live within the scope and +//! can safely access variables outside it. +//! +//! # Nesting scoped threads +//! +//! Sometimes scoped threads need to spawn more threads within the same scope. This is a little +//! tricky because argument `s` lives *inside* the invocation of `thread::scope()` and as such +//! cannot be borrowed by scoped threads: +//! +//! ```compile_fail,E0521 +//! use crossbeam_utils::thread; +//! +//! thread::scope(|s| { +//! s.spawn(|_| { +//! // Not going to compile because we're trying to borrow `s`, +//! // which lives *inside* the scope! :( +//! s.spawn(|_| println!("nested thread")); +//! }); +//! }); +//! ``` +//! +//! Fortunately, there is a solution. Every scoped thread is passed a reference to its scope as an +//! argument, which can be used for spawning nested threads: +//! +//! ``` +//! use crossbeam_utils::thread; +//! +//! thread::scope(|s| { +//! // Note the `|s|` here. +//! s.spawn(|s| { +//! // Yay, this works because we're using a fresh argument `s`! :) +//! s.spawn(|_| println!("nested thread")); +//! }); +//! }).unwrap(); +//! ``` + +use std::boxed::Box; +use std::fmt; +use std::io; +use std::marker::PhantomData; +use std::mem; +use std::panic; +use std::string::String; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::vec::Vec; + +use crate::sync::WaitGroup; + +type SharedVec = Arc>>; +type SharedOption = Arc>>; + +/// Creates a new scope for spawning threads. +/// +/// All child threads that haven't been manually joined will be automatically joined just before +/// this function invocation ends. If all joined threads have successfully completed, `Ok` is +/// returned with the return value of `f`. If any of the joined threads has panicked, an `Err` is +/// returned containing errors from panicked threads. Note that if panics are implemented by +/// aborting the process, no error is returned; see the notes of [std::panic::catch_unwind]. +/// +/// **Note:** Since Rust 1.63, this function is soft-deprecated in favor of the more efficient [`std::thread::scope`]. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_utils::thread; +/// +/// let var = vec![1, 2, 3]; +/// +/// thread::scope(|s| { +/// s.spawn(|_| { +/// println!("A child thread borrowing `var`: {:?}", var); +/// }); +/// }).unwrap(); +/// ``` +pub fn scope<'env, F, R>(f: F) -> thread::Result +where + F: FnOnce(&Scope<'env>) -> R, +{ + struct AbortOnPanic; + impl Drop for AbortOnPanic { + fn drop(&mut self) { + if thread::panicking() { + std::process::abort(); + } + } + } + + let wg = WaitGroup::new(); + let scope = Scope::<'env> { + handles: SharedVec::default(), + wait_group: wg.clone(), + _marker: PhantomData, + }; + + // Execute the scoped function, but catch any panics. + let result = panic::catch_unwind(panic::AssertUnwindSafe(|| f(&scope))); + + // If an unwinding panic occurs before all threads are joined + // promote it to an aborting panic to prevent any threads from escaping the scope. + let guard = AbortOnPanic; + + // Wait until all nested scopes are dropped. + drop(scope.wait_group); + wg.wait(); + + // Join all remaining spawned threads. + let panics: Vec<_> = scope + .handles + .lock() + .unwrap() + // Filter handles that haven't been joined, join them, and collect errors. + .drain(..) + .filter_map(|handle| handle.lock().unwrap().take()) + .filter_map(|handle| handle.join().err()) + .collect(); + + mem::forget(guard); + + // If `f` has panicked, resume unwinding. + // If any of the child threads have panicked, return the panic errors. + // Otherwise, everything is OK and return the result of `f`. + match result { + Err(err) => panic::resume_unwind(err), + Ok(res) => { + if panics.is_empty() { + Ok(res) + } else { + Err(Box::new(panics)) + } + } + } +} + +/// A scope for spawning threads. +pub struct Scope<'env> { + /// The list of the thread join handles. + handles: SharedVec>>, + + /// Used to wait until all subscopes all dropped. + wait_group: WaitGroup, + + /// Borrows data with invariant lifetime `'env`. + _marker: PhantomData<&'env mut &'env ()>, +} + +unsafe impl Sync for Scope<'_> {} + +impl<'env> Scope<'env> { + /// Spawns a scoped thread. + /// + /// This method is similar to the [`spawn`] function in Rust's standard library. The difference + /// is that this thread is scoped, meaning it's guaranteed to terminate before the scope exits, + /// allowing it to reference variables outside the scope. + /// + /// The scoped thread is passed a reference to this scope as an argument, which can be used for + /// spawning nested threads. + /// + /// The returned [handle](ScopedJoinHandle) can be used to manually + /// [join](ScopedJoinHandle::join) the thread before the scope exits. + /// + /// This will create a thread using default parameters of [`ScopedThreadBuilder`], if you want to specify the + /// stack size or the name of the thread, use this API instead. + /// + /// [`spawn`]: std::thread::spawn + /// + /// # Panics + /// + /// Panics if the OS fails to create a thread; use [`ScopedThreadBuilder::spawn`] + /// to recover from such errors. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// let handle = s.spawn(|_| { + /// println!("A child thread is running"); + /// 42 + /// }); + /// + /// // Join the thread and retrieve its result. + /// let res = handle.join().unwrap(); + /// assert_eq!(res, 42); + /// }).unwrap(); + /// ``` + pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T> + where + F: FnOnce(&Scope<'env>) -> T, + F: Send + 'env, + T: Send + 'env, + { + self.builder() + .spawn(f) + .expect("failed to spawn scoped thread") + } + + /// Creates a builder that can configure a thread before spawning. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// s.builder() + /// .spawn(|_| println!("A child thread is running")) + /// .unwrap(); + /// }).unwrap(); + /// ``` + pub fn builder<'scope>(&'scope self) -> ScopedThreadBuilder<'scope, 'env> { + ScopedThreadBuilder { + scope: self, + builder: thread::Builder::new(), + } + } +} + +impl fmt::Debug for Scope<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("Scope { .. }") + } +} + +/// Configures the properties of a new thread. +/// +/// The two configurable properties are: +/// +/// - [`name`]: Specifies an [associated name for the thread][naming-threads]. +/// - [`stack_size`]: Specifies the [desired stack size for the thread][stack-size]. +/// +/// The [`spawn`] method will take ownership of the builder and return an [`io::Result`] of the +/// thread handle with the given configuration. +/// +/// The [`Scope::spawn`] method uses a builder with default configuration and unwraps its return +/// value. You may want to use this builder when you want to recover from a failure to launch a +/// thread. +/// +/// # Examples +/// +/// ``` +/// use crossbeam_utils::thread; +/// +/// thread::scope(|s| { +/// s.builder() +/// .spawn(|_| println!("Running a child thread")) +/// .unwrap(); +/// }).unwrap(); +/// ``` +/// +/// [`name`]: ScopedThreadBuilder::name +/// [`stack_size`]: ScopedThreadBuilder::stack_size +/// [`spawn`]: ScopedThreadBuilder::spawn +/// [`io::Result`]: std::io::Result +/// [naming-threads]: std::thread#naming-threads +/// [stack-size]: std::thread#stack-size +#[derive(Debug)] +pub struct ScopedThreadBuilder<'scope, 'env> { + scope: &'scope Scope<'env>, + builder: thread::Builder, +} + +impl<'scope, 'env> ScopedThreadBuilder<'scope, 'env> { + /// Sets the name for the new thread. + /// + /// The name must not contain null bytes (`\0`). + /// + /// For more information about named threads, see [here][naming-threads]. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// use std::thread::current; + /// + /// thread::scope(|s| { + /// s.builder() + /// .name("my thread".to_string()) + /// .spawn(|_| assert_eq!(current().name(), Some("my thread"))) + /// .unwrap(); + /// }).unwrap(); + /// ``` + /// + /// [naming-threads]: std::thread#naming-threads + pub fn name(mut self, name: String) -> ScopedThreadBuilder<'scope, 'env> { + self.builder = self.builder.name(name); + self + } + + /// Sets the size of the stack for the new thread. + /// + /// The stack size is measured in bytes. + /// + /// For more information about the stack size for threads, see [here][stack-size]. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// s.builder() + /// .stack_size(32 * 1024) + /// .spawn(|_| println!("Running a child thread")) + /// .unwrap(); + /// }).unwrap(); + /// ``` + /// + /// [stack-size]: std::thread#stack-size + pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'scope, 'env> { + self.builder = self.builder.stack_size(size); + self + } + + /// Spawns a scoped thread with this configuration. + /// + /// The scoped thread is passed a reference to this scope as an argument, which can be used for + /// spawning nested threads. + /// + /// The returned handle can be used to manually join the thread before the scope exits. + /// + /// # Errors + /// + /// Unlike the [`Scope::spawn`] method, this method yields an + /// [`io::Result`] to capture any failure to create the thread at + /// the OS level. + /// + /// [`io::Result`]: std::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// let handle = s.builder() + /// .spawn(|_| { + /// println!("A child thread is running"); + /// 42 + /// }) + /// .unwrap(); + /// + /// // Join the thread and retrieve its result. + /// let res = handle.join().unwrap(); + /// assert_eq!(res, 42); + /// }).unwrap(); + /// ``` + pub fn spawn(self, f: F) -> io::Result> + where + F: FnOnce(&Scope<'env>) -> T, + F: Send + 'env, + T: Send + 'env, + { + // The result of `f` will be stored here. + let result = SharedOption::default(); + + // Spawn the thread and grab its join handle and thread handle. + let (handle, thread) = { + let result = Arc::clone(&result); + + // A clone of the scope that will be moved into the new thread. + let scope = Scope::<'env> { + handles: Arc::clone(&self.scope.handles), + wait_group: self.scope.wait_group.clone(), + _marker: PhantomData, + }; + + // Spawn the thread. + let handle = { + let closure = move || { + // Make sure the scope is inside the closure with the proper `'env` lifetime. + let scope: Scope<'env> = scope; + + // Run the closure. + let res = f(&scope); + + // Store the result if the closure didn't panic. + *result.lock().unwrap() = Some(res); + }; + + // Allocate `closure` on the heap and erase the `'env` bound. + let closure: Box = Box::new(closure); + let closure: Box = + unsafe { mem::transmute(closure) }; + + // Finally, spawn the closure. + self.builder.spawn(closure)? + }; + + let thread = handle.thread().clone(); + let handle = Arc::new(Mutex::new(Some(handle))); + (handle, thread) + }; + + // Add the handle to the shared list of join handles. + self.scope.handles.lock().unwrap().push(Arc::clone(&handle)); + + Ok(ScopedJoinHandle { + handle, + result, + thread, + _marker: PhantomData, + }) + } +} + +unsafe impl Send for ScopedJoinHandle<'_, T> {} +unsafe impl Sync for ScopedJoinHandle<'_, T> {} + +/// A handle that can be used to join its scoped thread. +/// +/// This struct is created by the [`Scope::spawn`] method and the +/// [`ScopedThreadBuilder::spawn`] method. +pub struct ScopedJoinHandle<'scope, T> { + /// A join handle to the spawned thread. + handle: SharedOption>, + + /// Holds the result of the inner closure. + result: SharedOption, + + /// A handle to the spawned thread. + thread: thread::Thread, + + /// Borrows the parent scope with lifetime `'scope`. + _marker: PhantomData<&'scope ()>, +} + +impl ScopedJoinHandle<'_, T> { + /// Waits for the thread to finish and returns its result. + /// + /// If the child thread panics, an error is returned. Note that if panics are implemented by + /// aborting the process, no error is returned; see the notes of [std::panic::catch_unwind]. + /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join itself or otherwise + /// may create a deadlock with joining threads. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// let handle1 = s.spawn(|_| println!("I'm a happy thread :)")); + /// let handle2 = s.spawn(|_| panic!("I'm a sad thread :(")); + /// + /// // Join the first thread and verify that it succeeded. + /// let res = handle1.join(); + /// assert!(res.is_ok()); + /// + /// // Join the second thread and verify that it panicked. + /// let res = handle2.join(); + /// assert!(res.is_err()); + /// }).unwrap(); + /// ``` + pub fn join(self) -> thread::Result { + // Take out the handle. The handle will surely be available because the root scope waits + // for nested scopes before joining remaining threads. + let handle = self.handle.lock().unwrap().take().unwrap(); + + // Join the thread and then take the result out of its inner closure. + handle + .join() + .map(|()| self.result.lock().unwrap().take().unwrap()) + } + + /// Returns a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_utils::thread; + /// + /// thread::scope(|s| { + /// let handle = s.spawn(|_| println!("A child thread is running")); + /// println!("The child thread ID: {:?}", handle.thread().id()); + /// }).unwrap(); + /// ``` + pub fn thread(&self) -> &thread::Thread { + &self.thread + } +} + +/// Unix-specific extensions. +#[cfg(unix)] +mod unix { + use super::ScopedJoinHandle; + use std::os::unix::thread::{JoinHandleExt, RawPthread}; + + impl JoinHandleExt for ScopedJoinHandle<'_, T> { + fn as_pthread_t(&self) -> RawPthread { + // Borrow the handle. The handle will surely be available because the root scope waits + // for nested scopes before joining remaining threads. + let handle = self.handle.lock().unwrap(); + handle.as_ref().unwrap().as_pthread_t() + } + fn into_pthread_t(self) -> RawPthread { + self.as_pthread_t() + } + } +} +/// Windows-specific extensions. +#[cfg(windows)] +mod windows { + use super::ScopedJoinHandle; + use std::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; + + impl AsRawHandle for ScopedJoinHandle<'_, T> { + fn as_raw_handle(&self) -> RawHandle { + // Borrow the handle. The handle will surely be available because the root scope waits + // for nested scopes before joining remaining threads. + let handle = self.handle.lock().unwrap(); + handle.as_ref().unwrap().as_raw_handle() + } + } + + impl IntoRawHandle for ScopedJoinHandle<'_, T> { + fn into_raw_handle(self) -> RawHandle { + self.as_raw_handle() + } + } +} + +impl fmt::Debug for ScopedJoinHandle<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("ScopedJoinHandle { .. }") + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/atomic_cell.rs b/anneal/v2/vendor/crossbeam-utils/tests/atomic_cell.rs new file mode 100644 index 0000000000..9fe69328df --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/atomic_cell.rs @@ -0,0 +1,374 @@ +use std::mem; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; + +use crossbeam_utils::atomic::AtomicCell; + +#[test] +fn is_lock_free() { + struct UsizeWrap(#[allow(dead_code)] usize); + struct U8Wrap(#[allow(dead_code)] bool); + struct I16Wrap(#[allow(dead_code)] i16); + #[repr(align(8))] + struct U64Align8(#[allow(dead_code)] u64); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::<()>::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + assert!(AtomicCell::::is_lock_free()); + assert!(AtomicCell::::is_lock_free()); + + // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than + // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment + // of `AtomicU64` is `8`, so `AtomicCell` is not lock-free. + assert_eq!( + AtomicCell::::is_lock_free(), + cfg!(target_has_atomic = "64") && std::mem::align_of::() == 8 + ); + assert_eq!(mem::size_of::(), 8); + assert_eq!(mem::align_of::(), 8); + assert_eq!( + AtomicCell::::is_lock_free(), + cfg!(target_has_atomic = "64") + ); + + // AtomicU128 is unstable + assert!(!AtomicCell::::is_lock_free()); +} + +#[test] +fn const_is_lock_free() { + const _U: bool = AtomicCell::::is_lock_free(); + const _I: bool = AtomicCell::::is_lock_free(); +} + +#[test] +fn drops_unit() { + static CNT: AtomicUsize = AtomicUsize::new(0); + CNT.store(0, SeqCst); + + #[derive(Debug, PartialEq, Eq)] + struct Foo(); + + impl Foo { + fn new() -> Foo { + CNT.fetch_add(1, SeqCst); + Foo() + } + } + + impl Drop for Foo { + fn drop(&mut self) { + CNT.fetch_sub(1, SeqCst); + } + } + + impl Default for Foo { + fn default() -> Foo { + Foo::new() + } + } + + let a = AtomicCell::new(Foo::new()); + + assert_eq!(a.swap(Foo::new()), Foo::new()); + assert_eq!(CNT.load(SeqCst), 1); + + a.store(Foo::new()); + assert_eq!(CNT.load(SeqCst), 1); + + assert_eq!(a.swap(Foo::default()), Foo::new()); + assert_eq!(CNT.load(SeqCst), 1); + + drop(a); + assert_eq!(CNT.load(SeqCst), 0); +} + +#[test] +fn drops_u8() { + static CNT: AtomicUsize = AtomicUsize::new(0); + CNT.store(0, SeqCst); + + #[derive(Debug, PartialEq, Eq)] + struct Foo(u8); + + impl Foo { + fn new(val: u8) -> Foo { + CNT.fetch_add(1, SeqCst); + Foo(val) + } + } + + impl Drop for Foo { + fn drop(&mut self) { + CNT.fetch_sub(1, SeqCst); + } + } + + impl Default for Foo { + fn default() -> Foo { + Foo::new(0) + } + } + + let a = AtomicCell::new(Foo::new(5)); + + assert_eq!(a.swap(Foo::new(6)), Foo::new(5)); + assert_eq!(a.swap(Foo::new(1)), Foo::new(6)); + assert_eq!(CNT.load(SeqCst), 1); + + a.store(Foo::new(2)); + assert_eq!(CNT.load(SeqCst), 1); + + assert_eq!(a.swap(Foo::default()), Foo::new(2)); + assert_eq!(CNT.load(SeqCst), 1); + + assert_eq!(a.swap(Foo::default()), Foo::new(0)); + assert_eq!(CNT.load(SeqCst), 1); + + drop(a); + assert_eq!(CNT.load(SeqCst), 0); +} + +#[test] +fn drops_usize() { + static CNT: AtomicUsize = AtomicUsize::new(0); + CNT.store(0, SeqCst); + + #[derive(Debug, PartialEq, Eq)] + struct Foo(usize); + + impl Foo { + fn new(val: usize) -> Foo { + CNT.fetch_add(1, SeqCst); + Foo(val) + } + } + + impl Drop for Foo { + fn drop(&mut self) { + CNT.fetch_sub(1, SeqCst); + } + } + + impl Default for Foo { + fn default() -> Foo { + Foo::new(0) + } + } + + let a = AtomicCell::new(Foo::new(5)); + + assert_eq!(a.swap(Foo::new(6)), Foo::new(5)); + assert_eq!(a.swap(Foo::new(1)), Foo::new(6)); + assert_eq!(CNT.load(SeqCst), 1); + + a.store(Foo::new(2)); + assert_eq!(CNT.load(SeqCst), 1); + + assert_eq!(a.swap(Foo::default()), Foo::new(2)); + assert_eq!(CNT.load(SeqCst), 1); + + assert_eq!(a.swap(Foo::default()), Foo::new(0)); + assert_eq!(CNT.load(SeqCst), 1); + + drop(a); + assert_eq!(CNT.load(SeqCst), 0); +} + +#[test] +fn modular_u8() { + #[derive(Clone, Copy, Eq, Debug, Default)] + struct Foo(u8); + + impl PartialEq for Foo { + fn eq(&self, other: &Foo) -> bool { + self.0 % 5 == other.0 % 5 + } + } + + let a = AtomicCell::new(Foo(1)); + + assert_eq!(a.load(), Foo(1)); + assert_eq!(a.swap(Foo(2)), Foo(11)); + assert_eq!(a.load(), Foo(52)); + + a.store(Foo(0)); + assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100))); + assert_eq!(a.load().0, 5); + assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100))); + assert_eq!(a.load().0, 15); +} + +#[test] +fn modular_usize() { + #[derive(Clone, Copy, Eq, Debug, Default)] + struct Foo(usize); + + impl PartialEq for Foo { + fn eq(&self, other: &Foo) -> bool { + self.0 % 5 == other.0 % 5 + } + } + + let a = AtomicCell::new(Foo(1)); + + assert_eq!(a.load(), Foo(1)); + assert_eq!(a.swap(Foo(2)), Foo(11)); + assert_eq!(a.load(), Foo(52)); + + a.store(Foo(0)); + assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100))); + assert_eq!(a.load().0, 5); + assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100))); + assert_eq!(a.load().0, 15); +} + +#[test] +fn garbage_padding() { + #[derive(Copy, Clone, Eq, PartialEq)] + struct Object { + a: i64, + b: i32, + } + + let cell = AtomicCell::new(Object { a: 0, b: 0 }); + let _garbage = [0xfe, 0xfe, 0xfe, 0xfe, 0xfe]; // Needed + let next = Object { a: 0, b: 0 }; + + let prev = cell.load(); + assert!(cell.compare_exchange(prev, next).is_ok()); + println!(); +} + +#[test] +fn const_atomic_cell_new() { + static CELL: AtomicCell = AtomicCell::new(0); + + CELL.store(1); + assert_eq!(CELL.load(), 1); +} + +// https://github.com/crossbeam-rs/crossbeam/pull/767 +macro_rules! test_arithmetic { + ($test_name:ident, $ty:ident) => { + #[test] + fn $test_name() { + let a: AtomicCell<$ty> = AtomicCell::new(7); + + assert_eq!(a.fetch_add(3), 7); + assert_eq!(a.load(), 10); + + assert_eq!(a.fetch_sub(3), 10); + assert_eq!(a.load(), 7); + + assert_eq!(a.fetch_and(3), 7); + assert_eq!(a.load(), 3); + + assert_eq!(a.fetch_or(16), 3); + assert_eq!(a.load(), 19); + + assert_eq!(a.fetch_xor(2), 19); + assert_eq!(a.load(), 17); + + assert_eq!(a.fetch_max(18), 17); + assert_eq!(a.load(), 18); + + assert_eq!(a.fetch_min(17), 18); + assert_eq!(a.load(), 17); + + assert_eq!(a.fetch_nand(7), 17); + assert_eq!(a.load(), !(17 & 7)); + } + }; +} +test_arithmetic!(arithmetic_u8, u8); +test_arithmetic!(arithmetic_i8, i8); +test_arithmetic!(arithmetic_u16, u16); +test_arithmetic!(arithmetic_i16, i16); +test_arithmetic!(arithmetic_u32, u32); +test_arithmetic!(arithmetic_i32, i32); +test_arithmetic!(arithmetic_u64, u64); +test_arithmetic!(arithmetic_i64, i64); +test_arithmetic!(arithmetic_u128, u128); +test_arithmetic!(arithmetic_i128, i128); + +// https://github.com/crossbeam-rs/crossbeam/issues/748 +#[cfg_attr(miri, ignore)] // TODO +#[test] +fn issue_748() { + #[allow(dead_code)] + #[repr(align(8))] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + enum Test { + Field(u32), + FieldLess, + } + + assert_eq!(mem::size_of::(), 8); + assert_eq!( + AtomicCell::::is_lock_free(), + cfg!(target_has_atomic = "64") + ); + let x = AtomicCell::new(Test::FieldLess); + assert_eq!(x.load(), Test::FieldLess); +} + +// https://github.com/crossbeam-rs/crossbeam/issues/833 +#[test] +fn issue_833() { + use std::num::NonZeroU128; + use std::sync::atomic::{AtomicBool, Ordering}; + use std::thread; + + #[cfg(miri)] + const N: usize = 10_000; + #[cfg(not(miri))] + const N: usize = 1_000_000; + + #[allow(dead_code)] + enum Enum { + NeverConstructed, + Cell(AtomicCell), + } + + static STATIC: Enum = Enum::Cell(AtomicCell::new(match NonZeroU128::new(1) { + Some(nonzero) => nonzero, + None => unreachable!(), + })); + static FINISHED: AtomicBool = AtomicBool::new(false); + + let handle = thread::spawn(|| { + let cell = match &STATIC { + Enum::NeverConstructed => unreachable!(), + Enum::Cell(cell) => cell, + }; + let x = NonZeroU128::new(0xFFFF_FFFF_FFFF_FFFF_0000_0000_0000_0000).unwrap(); + let y = NonZeroU128::new(0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF).unwrap(); + while !FINISHED.load(Ordering::Relaxed) { + cell.store(x); + cell.store(y); + } + }); + + for _ in 0..N { + if let Enum::NeverConstructed = STATIC { + unreachable!(":("); + } + } + + FINISHED.store(true, Ordering::Relaxed); + handle.join().unwrap(); +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/cache_padded.rs b/anneal/v2/vendor/crossbeam-utils/tests/cache_padded.rs new file mode 100644 index 0000000000..86e9a7709c --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/cache_padded.rs @@ -0,0 +1,113 @@ +use std::cell::Cell; +use std::mem; + +use crossbeam_utils::CachePadded; + +#[test] +fn default() { + let x: CachePadded = Default::default(); + assert_eq!(*x, 0); +} + +#[test] +fn store_u64() { + let x: CachePadded = CachePadded::new(17); + assert_eq!(*x, 17); +} + +#[test] +fn store_pair() { + let x: CachePadded<(u64, u64)> = CachePadded::new((17, 37)); + assert_eq!(x.0, 17); + assert_eq!(x.1, 37); +} + +#[test] +fn distance() { + let arr = [CachePadded::new(17u8), CachePadded::new(37u8)]; + let a = &*arr[0] as *const u8; + let b = &*arr[1] as *const u8; + let align = mem::align_of::>(); + assert!(align >= 32); + assert_eq!(unsafe { a.add(align) }, b); +} + +#[test] +fn different_sizes() { + CachePadded::new(17u8); + CachePadded::new(17u16); + CachePadded::new(17u32); + CachePadded::new([17u64; 0]); + CachePadded::new([17u64; 1]); + CachePadded::new([17u64; 2]); + CachePadded::new([17u64; 3]); + CachePadded::new([17u64; 4]); + CachePadded::new([17u64; 5]); + CachePadded::new([17u64; 6]); + CachePadded::new([17u64; 7]); + CachePadded::new([17u64; 8]); +} + +#[test] +fn large() { + let a = [17u64; 9]; + let b = CachePadded::new(a); + assert!(mem::size_of_val(&a) <= mem::size_of_val(&b)); +} + +#[test] +fn debug() { + assert_eq!( + format!("{:?}", CachePadded::new(17u64)), + "CachePadded { value: 17 }" + ); +} + +#[test] +fn drops() { + let count = Cell::new(0); + + struct Foo<'a>(&'a Cell); + + impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } + } + + let a = CachePadded::new(Foo(&count)); + let b = CachePadded::new(Foo(&count)); + + assert_eq!(count.get(), 0); + drop(a); + assert_eq!(count.get(), 1); + drop(b); + assert_eq!(count.get(), 2); +} + +#[allow(clippy::clone_on_copy)] // This is intentional. +#[test] +fn clone() { + let a = CachePadded::new(17); + let b = a.clone(); + assert_eq!(*a, *b); +} + +#[test] +fn runs_custom_clone() { + let count = Cell::new(0); + + struct Foo<'a>(&'a Cell); + + impl<'a> Clone for Foo<'a> { + fn clone(&self) -> Foo<'a> { + self.0.set(self.0.get() + 1); + Foo::<'a>(self.0) + } + } + + let a = CachePadded::new(Foo(&count)); + let _ = a.clone(); + + assert_eq!(count.get(), 1); +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/parker.rs b/anneal/v2/vendor/crossbeam-utils/tests/parker.rs new file mode 100644 index 0000000000..2bf9c37d49 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/parker.rs @@ -0,0 +1,41 @@ +use std::thread::sleep; +use std::time::Duration; +use std::u32; + +use crossbeam_utils::sync::Parker; +use crossbeam_utils::thread; + +#[test] +fn park_timeout_unpark_before() { + let p = Parker::new(); + for _ in 0..10 { + p.unparker().unpark(); + p.park_timeout(Duration::from_millis(u32::MAX as u64)); + } +} + +#[test] +fn park_timeout_unpark_not_called() { + let p = Parker::new(); + for _ in 0..10 { + p.park_timeout(Duration::from_millis(10)) + } +} + +#[test] +fn park_timeout_unpark_called_other_thread() { + for _ in 0..10 { + let p = Parker::new(); + let u = p.unparker().clone(); + + thread::scope(|scope| { + scope.spawn(move |_| { + sleep(Duration::from_millis(50)); + u.unpark(); + }); + + p.park_timeout(Duration::from_millis(u32::MAX as u64)) + }) + .unwrap(); + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/sharded_lock.rs b/anneal/v2/vendor/crossbeam-utils/tests/sharded_lock.rs new file mode 100644 index 0000000000..002f7f5e19 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/sharded_lock.rs @@ -0,0 +1,252 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::channel; +use std::sync::{Arc, TryLockError}; +use std::thread; + +use crossbeam_utils::sync::ShardedLock; +use rand::Rng; + +#[derive(Eq, PartialEq, Debug)] +struct NonCopy(i32); + +#[test] +fn smoke() { + let l = ShardedLock::new(()); + drop(l.read().unwrap()); + drop(l.write().unwrap()); + drop((l.read().unwrap(), l.read().unwrap())); + drop(l.write().unwrap()); +} + +#[test] +fn frob() { + const N: u32 = 10; + #[cfg(miri)] + const M: usize = 50; + #[cfg(not(miri))] + const M: usize = 1000; + + let r = Arc::new(ShardedLock::new(())); + + let (tx, rx) = channel::<()>(); + for _ in 0..N { + let tx = tx.clone(); + let r = r.clone(); + thread::spawn(move || { + let mut rng = rand::thread_rng(); + for _ in 0..M { + if rng.gen_bool(1.0 / (N as f64)) { + drop(r.write().unwrap()); + } else { + drop(r.read().unwrap()); + } + } + drop(tx); + }); + } + drop(tx); + let _ = rx.recv(); +} + +#[test] +fn arc_poison_wr() { + let arc = Arc::new(ShardedLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let _lock = arc2.write().unwrap(); + panic!(); + }) + .join(); + assert!(arc.read().is_err()); +} + +#[test] +fn arc_poison_ww() { + let arc = Arc::new(ShardedLock::new(1)); + assert!(!arc.is_poisoned()); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let _lock = arc2.write().unwrap(); + panic!(); + }) + .join(); + assert!(arc.write().is_err()); + assert!(arc.is_poisoned()); +} + +#[test] +fn arc_no_poison_rr() { + let arc = Arc::new(ShardedLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let _lock = arc2.read().unwrap(); + panic!(); + }) + .join(); + let lock = arc.read().unwrap(); + assert_eq!(*lock, 1); +} +#[test] +fn arc_no_poison_sl() { + let arc = Arc::new(ShardedLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let _lock = arc2.read().unwrap(); + panic!() + }) + .join(); + let lock = arc.write().unwrap(); + assert_eq!(*lock, 1); +} + +#[test] +fn arc() { + let arc = Arc::new(ShardedLock::new(0)); + let arc2 = arc.clone(); + let (tx, rx) = channel(); + + thread::spawn(move || { + let mut lock = arc2.write().unwrap(); + for _ in 0..10 { + let tmp = *lock; + *lock = -1; + thread::yield_now(); + *lock = tmp + 1; + } + tx.send(()).unwrap(); + }); + + // Readers try to catch the writer in the act + let mut children = Vec::new(); + for _ in 0..5 { + let arc3 = arc.clone(); + children.push(thread::spawn(move || { + let lock = arc3.read().unwrap(); + assert!(*lock >= 0); + })); + } + + // Wait for children to pass their asserts + for r in children { + assert!(r.join().is_ok()); + } + + // Wait for writer to finish + rx.recv().unwrap(); + let lock = arc.read().unwrap(); + assert_eq!(*lock, 10); +} + +#[test] +fn arc_access_in_unwind() { + let arc = Arc::new(ShardedLock::new(1)); + let arc2 = arc.clone(); + let _ = thread::spawn(move || { + struct Unwinder { + i: Arc>, + } + impl Drop for Unwinder { + fn drop(&mut self) { + let mut lock = self.i.write().unwrap(); + *lock += 1; + } + } + let _u = Unwinder { i: arc2 }; + panic!(); + }) + .join(); + let lock = arc.read().unwrap(); + assert_eq!(*lock, 2); +} + +#[test] +fn unsized_type() { + let sl: &ShardedLock<[i32]> = &ShardedLock::new([1, 2, 3]); + { + let b = &mut *sl.write().unwrap(); + b[0] = 4; + b[2] = 5; + } + let comp: &[i32] = &[4, 2, 5]; + assert_eq!(&*sl.read().unwrap(), comp); +} + +#[test] +fn try_write() { + let lock = ShardedLock::new(0isize); + let read_guard = lock.read().unwrap(); + + let write_result = lock.try_write(); + match write_result { + Err(TryLockError::WouldBlock) => (), + Ok(_) => panic!("try_write should not succeed while read_guard is in scope"), + Err(_) => panic!("unexpected error"), + } + + drop(read_guard); +} + +#[test] +fn test_into_inner() { + let m = ShardedLock::new(NonCopy(10)); + assert_eq!(m.into_inner().unwrap(), NonCopy(10)); +} + +#[test] +fn test_into_inner_drop() { + struct Foo(Arc); + impl Drop for Foo { + fn drop(&mut self) { + self.0.fetch_add(1, Ordering::SeqCst); + } + } + let num_drops = Arc::new(AtomicUsize::new(0)); + let m = ShardedLock::new(Foo(num_drops.clone())); + assert_eq!(num_drops.load(Ordering::SeqCst), 0); + { + let _inner = m.into_inner().unwrap(); + assert_eq!(num_drops.load(Ordering::SeqCst), 0); + } + assert_eq!(num_drops.load(Ordering::SeqCst), 1); +} + +#[test] +fn test_into_inner_poison() { + let m = Arc::new(ShardedLock::new(NonCopy(10))); + let m2 = m.clone(); + let _ = thread::spawn(move || { + let _lock = m2.write().unwrap(); + panic!("test panic in inner thread to poison ShardedLock"); + }) + .join(); + + assert!(m.is_poisoned()); + match Arc::try_unwrap(m).unwrap().into_inner() { + Err(e) => assert_eq!(e.into_inner(), NonCopy(10)), + Ok(x) => panic!("into_inner of poisoned ShardedLock is Ok: {:?}", x), + } +} + +#[test] +fn test_get_mut() { + let mut m = ShardedLock::new(NonCopy(10)); + *m.get_mut().unwrap() = NonCopy(20); + assert_eq!(m.into_inner().unwrap(), NonCopy(20)); +} + +#[test] +fn test_get_mut_poison() { + let m = Arc::new(ShardedLock::new(NonCopy(10))); + let m2 = m.clone(); + let _ = thread::spawn(move || { + let _lock = m2.write().unwrap(); + panic!("test panic in inner thread to poison ShardedLock"); + }) + .join(); + + assert!(m.is_poisoned()); + match Arc::try_unwrap(m).unwrap().get_mut() { + Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)), + Ok(x) => panic!("get_mut of poisoned ShardedLock is Ok: {:?}", x), + } +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/thread.rs b/anneal/v2/vendor/crossbeam-utils/tests/thread.rs new file mode 100644 index 0000000000..0dfad90bd6 --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/thread.rs @@ -0,0 +1,215 @@ +use std::any::Any; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread::sleep; +use std::time::Duration; + +use crossbeam_utils::thread; + +const THREADS: usize = 10; +const SMALL_STACK_SIZE: usize = 20; + +#[test] +fn join() { + let counter = AtomicUsize::new(0); + thread::scope(|scope| { + let handle = scope.spawn(|_| { + counter.store(1, Ordering::Relaxed); + }); + assert!(handle.join().is_ok()); + + let panic_handle = scope.spawn(|_| { + panic!("\"My honey is running out!\", said Pooh."); + }); + assert!(panic_handle.join().is_err()); + }) + .unwrap(); + + // There should be sufficient synchronization. + assert_eq!(1, counter.load(Ordering::Relaxed)); +} + +#[test] +fn counter() { + let counter = AtomicUsize::new(0); + thread::scope(|scope| { + for _ in 0..THREADS { + scope.spawn(|_| { + counter.fetch_add(1, Ordering::Relaxed); + }); + } + }) + .unwrap(); + + assert_eq!(THREADS, counter.load(Ordering::Relaxed)); +} + +#[test] +fn counter_builder() { + let counter = AtomicUsize::new(0); + thread::scope(|scope| { + for i in 0..THREADS { + scope + .builder() + .name(format!("child-{}", i)) + .stack_size(SMALL_STACK_SIZE) + .spawn(|_| { + counter.fetch_add(1, Ordering::Relaxed); + }) + .unwrap(); + } + }) + .unwrap(); + + assert_eq!(THREADS, counter.load(Ordering::Relaxed)); +} + +#[test] +fn counter_panic() { + let counter = AtomicUsize::new(0); + let result = thread::scope(|scope| { + scope.spawn(|_| { + panic!("\"My honey is running out!\", said Pooh."); + }); + sleep(Duration::from_millis(100)); + + for _ in 0..THREADS { + scope.spawn(|_| { + counter.fetch_add(1, Ordering::Relaxed); + }); + } + }); + + assert_eq!(THREADS, counter.load(Ordering::Relaxed)); + assert!(result.is_err()); +} + +#[test] +fn panic_twice() { + let result = thread::scope(|scope| { + scope.spawn(|_| { + sleep(Duration::from_millis(500)); + panic!("thread #1"); + }); + scope.spawn(|_| { + panic!("thread #2"); + }); + }); + + let err = result.unwrap_err(); + let vec = err + .downcast_ref::>>() + .unwrap(); + assert_eq!(2, vec.len()); + + let first = vec[0].downcast_ref::<&str>().unwrap(); + let second = vec[1].downcast_ref::<&str>().unwrap(); + assert_eq!("thread #1", *first); + assert_eq!("thread #2", *second) +} + +#[test] +fn panic_many() { + let result = thread::scope(|scope| { + scope.spawn(|_| panic!("deliberate panic #1")); + scope.spawn(|_| panic!("deliberate panic #2")); + scope.spawn(|_| panic!("deliberate panic #3")); + }); + + let err = result.unwrap_err(); + let vec = err + .downcast_ref::>>() + .unwrap(); + assert_eq!(3, vec.len()); + + for panic in vec.iter() { + let panic = panic.downcast_ref::<&str>().unwrap(); + assert!( + *panic == "deliberate panic #1" + || *panic == "deliberate panic #2" + || *panic == "deliberate panic #3" + ); + } +} + +#[test] +fn nesting() { + let var = "foo".to_string(); + + struct Wrapper<'a> { + var: &'a String, + } + + impl<'a> Wrapper<'a> { + fn recurse(&'a self, scope: &thread::Scope<'a>, depth: usize) { + assert_eq!(self.var, "foo"); + + if depth > 0 { + scope.spawn(move |scope| { + self.recurse(scope, depth - 1); + }); + } + } + } + + let wrapper = Wrapper { var: &var }; + + thread::scope(|scope| { + scope.spawn(|scope| { + scope.spawn(|scope| { + wrapper.recurse(scope, 5); + }); + }); + }) + .unwrap(); +} + +#[test] +fn join_nested() { + thread::scope(|scope| { + scope.spawn(|scope| { + let handle = scope.spawn(|_| 7); + + sleep(Duration::from_millis(200)); + handle.join().unwrap(); + }); + + sleep(Duration::from_millis(100)); + }) + .unwrap(); +} + +#[test] +fn scope_returns_ok() { + let result = thread::scope(|scope| scope.spawn(|_| 1234).join().unwrap()).unwrap(); + assert_eq!(result, 1234); +} + +#[cfg(unix)] +#[test] +fn as_pthread_t() { + use std::os::unix::thread::JoinHandleExt; + thread::scope(|scope| { + let handle = scope.spawn(|_scope| { + sleep(Duration::from_millis(100)); + 42 + }); + let _pthread_t = handle.as_pthread_t(); + handle.join().unwrap(); + }) + .unwrap(); +} + +#[cfg(windows)] +#[test] +fn as_raw_handle() { + use std::os::windows::io::AsRawHandle; + thread::scope(|scope| { + let handle = scope.spawn(|_scope| { + sleep(Duration::from_millis(100)); + 42 + }); + let _raw_handle = handle.as_raw_handle(); + handle.join().unwrap(); + }) + .unwrap(); +} diff --git a/anneal/v2/vendor/crossbeam-utils/tests/wait_group.rs b/anneal/v2/vendor/crossbeam-utils/tests/wait_group.rs new file mode 100644 index 0000000000..5b549b849c --- /dev/null +++ b/anneal/v2/vendor/crossbeam-utils/tests/wait_group.rs @@ -0,0 +1,67 @@ +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +use crossbeam_utils::sync::WaitGroup; + +const THREADS: usize = 10; + +#[test] +fn wait() { + let wg = WaitGroup::new(); + let (tx, rx) = mpsc::channel(); + + for _ in 0..THREADS { + let wg = wg.clone(); + let tx = tx.clone(); + + thread::spawn(move || { + wg.wait(); + tx.send(()).unwrap(); + }); + } + + thread::sleep(Duration::from_millis(100)); + + // At this point, all spawned threads should be blocked, so we shouldn't get anything from the + // channel. + assert!(rx.try_recv().is_err()); + + wg.wait(); + + // Now, the wait group is cleared and we should receive messages. + for _ in 0..THREADS { + rx.recv().unwrap(); + } +} + +#[test] +fn wait_and_drop() { + let wg = WaitGroup::new(); + let wg2 = WaitGroup::new(); + let (tx, rx) = mpsc::channel(); + + for _ in 0..THREADS { + let wg = wg.clone(); + let wg2 = wg2.clone(); + let tx = tx.clone(); + + thread::spawn(move || { + wg2.wait(); + tx.send(()).unwrap(); + drop(wg); + }); + } + + // At this point, no thread has gotten past `wg2.wait()`, so we shouldn't get anything from the + // channel. + assert!(rx.try_recv().is_err()); + drop(wg2); + + wg.wait(); + + // Now, the wait group is cleared and we should receive messages. + for _ in 0..THREADS { + rx.try_recv().unwrap(); + } +} diff --git a/anneal/v2/vendor/crypto-common-0.1.7/.cargo-checksum.json b/anneal/v2/vendor/crypto-common-0.1.7/.cargo-checksum.json new file mode 100644 index 0000000000..1cef1f6c96 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"9f3d25eba4f1c16015148d4da6ad033aea9122b6da6908480f823226c7b03498","CHANGELOG.md":"6fcfa84d237ac5900879ebd2a91b41f680088e741ca95c965d205880382d94cb","Cargo.lock":"84137644c70a3fe92e7dd56883631a040268acbb11cd2d9869eddd69d5c73691","Cargo.toml":"303682a6a66fdc98de8a011ac275e18c523f1535ed8de2a291a4fcad91de8348","Cargo.toml.orig":"50ba74f640a7452553988619a4ecec442ab60a1047731304b8493193a0e202b2","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"3521672491a3479422d5fe1aca6645dd2984090f85da6e5205abfb18fb7a6897","README.md":"3451ce2bc0b658041902a8e792023d9874700e9292eac9153c45f203430e24a0","src/lib.rs":"5dd00d7ea362d1e4fc06141aae07a0f15166a0b8836ac8e8713f7d7f31d26a1e"},"package":"78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"} \ No newline at end of file diff --git a/anneal/v2/vendor/crypto-common-0.1.7/.cargo_vcs_info.json b/anneal/v2/vendor/crypto-common-0.1.7/.cargo_vcs_info.json new file mode 100644 index 0000000000..d742023230 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "66a997ccf5776ce873da5a48e2885a9908e940f6" + }, + "path_in_vcs": "crypto-common" +} \ No newline at end of file diff --git a/anneal/v2/vendor/crypto-common-0.1.7/CHANGELOG.md b/anneal/v2/vendor/crypto-common-0.1.7/CHANGELOG.md new file mode 100644 index 0000000000..136a4db348 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.1.7 (2025-11-12) +### Changed +- Pin `generic-array` to v0.14.7 ([#2088]) + +[#2088]: https://github.com/RustCrypto/traits/pull/2088 + +## 0.1.6 (2022-07-16) +### Added +- Move `ParBlocks`/`ParBlocksSizeUser` from `cipher` crate ([#1052]) + +[#1052]: https://github.com/RustCrypto/traits/pull/1052 + +## 0.1.5 (2022-07-09) +### Fixed +- Support on-label MSRV ([#1049]) + +[#1049]: https://github.com/RustCrypto/traits/pull/1049 + +## 0.1.4 (2022-07-02) +### Added +- `getrandom` feature ([#1034]) + +[#1034]: https://github.com/RustCrypto/traits/pull/1034 + +## 0.1.3 (2022-02-16) +### Fixed +- Minimal versions build ([#940]) + +[#940]: https://github.com/RustCrypto/traits/pull/940 + +## 0.1.2 (2022-02-10) +### Added +- Re-export `generic-array` and `typenum`. Enable `more_lengths` feature on +`generic-array`. Add `key_size`, `iv_size`, `block_size`, and `output_size` +helper methods. ([#849]) + +[#849]: https://github.com/RustCrypto/traits/pull/849 + +## 0.1.1 (2021-12-14) +### Added +- `rand_core` re-export and proper exposure of key/IV generation methods on docs.rs ([#847]) + +[#847]: https://github.com/RustCrypto/traits/pull/847 + +## 0.1.0 (2021-12-07) +- Initial release diff --git a/anneal/v2/vendor/crypto-common-0.1.7/Cargo.lock b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.lock new file mode 100644 index 0000000000..f8d3abf853 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.lock @@ -0,0 +1,72 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crypto-common" +version = "0.1.7" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml new file mode 100644 index 0000000000..a2a2d3ee2e --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml @@ -0,0 +1,62 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "crypto-common" +version = "0.1.7" +authors = ["RustCrypto Developers"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Common cryptographic traits" +documentation = "https://docs.rs/crypto-common" +readme = "README.md" +keywords = [ + "crypto", + "traits", +] +categories = [ + "cryptography", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RustCrypto/traits" +resolver = "2" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[features] +getrandom = ["rand_core/getrandom"] +std = [] + +[lib] +name = "crypto_common" +path = "src/lib.rs" + +[dependencies.generic-array] +version = "=0.14.7" +features = ["more_lengths"] + +[dependencies.rand_core] +version = "0.6" +optional = true + +[dependencies.typenum] +version = "1.14" diff --git a/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml.orig b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml.orig new file mode 100644 index 0000000000..12542dce20 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/Cargo.toml.orig @@ -0,0 +1,27 @@ +[package] +name = "crypto-common" +description = "Common cryptographic traits" +version = "0.1.7" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/crypto-common" +repository = "https://github.com/RustCrypto/traits" +keywords = ["crypto", "traits"] +categories = ["cryptography", "no-std"] + +[dependencies] +generic-array = { version = "=0.14.7", features = ["more_lengths"] } +typenum = "1.14" # earlier versions of typenum don't satisfy the 'static bound on U* types + +# optional dependencies +rand_core = { version = "0.6", optional = true } + +[features] +std = [] +getrandom = ["rand_core/getrandom"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-APACHE b/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-APACHE new file mode 100644 index 0000000000..78173fa2e7 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-MIT b/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-MIT new file mode 100644 index 0000000000..efb0b5f8b0 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2021 RustCrypto Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/crypto-common-0.1.7/README.md b/anneal/v2/vendor/crypto-common-0.1.7/README.md new file mode 100644 index 0000000000..70ca758cd8 --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/README.md @@ -0,0 +1,53 @@ +# RustCrypto: Common Cryptographic Traits + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Common traits used by cryptographic algorithms. Users should generally use +higher-level trait crates instead of this one. + +[Documentation][docs-link] + +## Minimum Supported Rust Version + +Rust **1.41** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/crypto-common.svg +[crate-link]: https://crates.io/crates/crypto-common +[docs-image]: https://docs.rs/crypto-common/badge.svg +[docs-link]: https://docs.rs/crypto-common/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes +[build-image]: https://github.com/RustCrypto/traits/workflows/crypto-common/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/traits/actions?query=workflow%3Acrypto-common diff --git a/anneal/v2/vendor/crypto-common-0.1.7/src/lib.rs b/anneal/v2/vendor/crypto-common-0.1.7/src/lib.rs new file mode 100644 index 0000000000..c49984cd2e --- /dev/null +++ b/anneal/v2/vendor/crypto-common-0.1.7/src/lib.rs @@ -0,0 +1,311 @@ +//! Common cryptographic traits. + +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![forbid(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms)] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "rand_core")] +pub use rand_core; + +pub use generic_array; +pub use generic_array::typenum; + +use core::fmt; +use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; +#[cfg(feature = "rand_core")] +use rand_core::{CryptoRng, RngCore}; + +/// Block on which [`BlockSizeUser`] implementors operate. +pub type Block = GenericArray::BlockSize>; + +/// Parallel blocks on which [`ParBlocksSizeUser`] implementors operate. +pub type ParBlocks = GenericArray, ::ParBlocksSize>; + +/// Output array of [`OutputSizeUser`] implementors. +pub type Output = GenericArray::OutputSize>; + +/// Key used by [`KeySizeUser`] implementors. +pub type Key = GenericArray::KeySize>; + +/// Initialization vector (nonce) used by [`IvSizeUser`] implementors. +pub type Iv = GenericArray::IvSize>; + +/// Types which process data in blocks. +pub trait BlockSizeUser { + /// Size of the block in bytes. + type BlockSize: ArrayLength + 'static; + + /// Return block size in bytes. + fn block_size() -> usize { + Self::BlockSize::USIZE + } +} + +impl BlockSizeUser for &T { + type BlockSize = T::BlockSize; +} + +impl BlockSizeUser for &mut T { + type BlockSize = T::BlockSize; +} + +/// Types which can process blocks in parallel. +pub trait ParBlocksSizeUser: BlockSizeUser { + /// Number of blocks which can be processed in parallel. + type ParBlocksSize: ArrayLength>; +} + +/// Types which return data with the given size. +pub trait OutputSizeUser { + /// Size of the output in bytes. + type OutputSize: ArrayLength + 'static; + + /// Return output size in bytes. + fn output_size() -> usize { + Self::OutputSize::USIZE + } +} + +/// Types which use key for initialization. +/// +/// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`]. +pub trait KeySizeUser { + /// Key size in bytes. + type KeySize: ArrayLength + 'static; + + /// Return key size in bytes. + fn key_size() -> usize { + Self::KeySize::USIZE + } +} + +/// Types which use initialization vector (nonce) for initialization. +/// +/// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`]. +pub trait IvSizeUser { + /// Initialization vector size in bytes. + type IvSize: ArrayLength + 'static; + + /// Return IV size in bytes. + fn iv_size() -> usize { + Self::IvSize::USIZE + } +} + +/// Types which use another type for initialization. +/// +/// Generally it's used indirectly via [`InnerInit`] or [`InnerIvInit`]. +pub trait InnerUser { + /// Inner type. + type Inner; +} + +/// Resettable types. +pub trait Reset { + /// Reset state to its initial value. + fn reset(&mut self); +} + +/// Trait which stores algorithm name constant, used in `Debug` implementations. +pub trait AlgorithmName { + /// Write algorithm name into `f`. + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result; +} + +/// Types which can be initialized from key. +pub trait KeyInit: KeySizeUser + Sized { + /// Create new value from fixed size key. + fn new(key: &Key) -> Self; + + /// Create new value from variable size key. + fn new_from_slice(key: &[u8]) -> Result { + if key.len() != Self::KeySize::to_usize() { + Err(InvalidLength) + } else { + Ok(Self::new(Key::::from_slice(key))) + } + } + + /// Generate random key using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key { + let mut key = Key::::default(); + rng.fill_bytes(&mut key); + key + } +} + +/// Types which can be initialized from key and initialization vector (nonce). +pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized { + /// Create new value from fixed length key and nonce. + fn new(key: &Key, iv: &Iv) -> Self; + + /// Create new value from variable length key and nonce. + #[inline] + fn new_from_slices(key: &[u8], iv: &[u8]) -> Result { + let key_len = Self::KeySize::USIZE; + let iv_len = Self::IvSize::USIZE; + if key.len() != key_len || iv.len() != iv_len { + Err(InvalidLength) + } else { + Ok(Self::new( + Key::::from_slice(key), + Iv::::from_slice(iv), + )) + } + } + + /// Generate random key using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key { + let mut key = Key::::default(); + rng.fill_bytes(&mut key); + key + } + + /// Generate random IV using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv { + let mut iv = Iv::::default(); + rng.fill_bytes(&mut iv); + iv + } + + /// Generate random key and nonce using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key_iv(mut rng: impl CryptoRng + RngCore) -> (Key, Iv) { + (Self::generate_key(&mut rng), Self::generate_iv(&mut rng)) + } +} + +/// Types which can be initialized from another type (usually block ciphers). +/// +/// Usually used for initializing types from block ciphers. +pub trait InnerInit: InnerUser + Sized { + /// Initialize value from the `inner`. + fn inner_init(inner: Self::Inner) -> Self; +} + +/// Types which can be initialized from another type and additional initialization +/// vector/nonce. +/// +/// Usually used for initializing types from block ciphers. +pub trait InnerIvInit: InnerUser + IvSizeUser + Sized { + /// Initialize value using `inner` and `iv` array. + fn inner_iv_init(inner: Self::Inner, iv: &Iv) -> Self; + + /// Initialize value using `inner` and `iv` slice. + fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result { + if iv.len() != Self::IvSize::to_usize() { + Err(InvalidLength) + } else { + Ok(Self::inner_iv_init(inner, Iv::::from_slice(iv))) + } + } + + /// Generate random IV using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv { + let mut iv = Iv::::default(); + rng.fill_bytes(&mut iv); + iv + } +} + +impl KeySizeUser for T +where + T: InnerUser, + T::Inner: KeySizeUser, +{ + type KeySize = ::KeySize; +} + +impl KeyIvInit for T +where + T: InnerIvInit, + T::Inner: KeyInit, +{ + #[inline] + fn new(key: &Key, iv: &Iv) -> Self { + Self::inner_iv_init(T::Inner::new(key), iv) + } + + #[inline] + fn new_from_slices(key: &[u8], iv: &[u8]) -> Result { + T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv)) + } +} + +impl KeyInit for T +where + T: InnerInit, + T::Inner: KeyInit, +{ + #[inline] + fn new(key: &Key) -> Self { + Self::inner_init(T::Inner::new(key)) + } + + #[inline] + fn new_from_slice(key: &[u8]) -> Result { + T::Inner::new_from_slice(key) + .map_err(|_| InvalidLength) + .map(Self::inner_init) + } +} + +// Unfortunately this blanket impl is impossible without mutually +// exclusive traits, see: https://github.com/rust-lang/rfcs/issues/1053 +// or at the very least without: https://github.com/rust-lang/rust/issues/20400 +/* +impl KeyIvInit for T +where + T: InnerInit, + T::Inner: KeyIvInit, +{ + #[inline] + fn new(key: &Key, iv: &Iv) -> Self { + Self::inner_init(T::Inner::new(key, iv)) + } + + #[inline] + fn new_from_slices(key: &[u8], iv: &[u8]) -> Result { + T::Inner::new_from_slice(key) + .map_err(|_| InvalidLength) + .map(Self::inner_init) + } +} +*/ + +/// The error type returned when key and/or IV used in the [`KeyInit`], +/// [`KeyIvInit`], and [`InnerIvInit`] slice-based methods had +/// an invalid length. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct InvalidLength; + +impl fmt::Display for InvalidLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Invalid Length") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidLength {} diff --git a/anneal/v2/vendor/digest-0.10.7/.cargo-checksum.json b/anneal/v2/vendor/digest-0.10.7/.cargo-checksum.json new file mode 100644 index 0000000000..5743210289 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"502c194bd5d933bbfd4878b4b899b5a530457b360c5f5445c949d91f0608922b","CHANGELOG.md":"e89e1b904ddcb022d2413bf6eb0cc14418c0177f669c4da5520c2566ebb3800c","Cargo.toml":"f0cc2fc18c6e7f3533658b9e59d71b55e641e7d8226e5d1b915a5e7c0a1d3f36","Cargo.toml.orig":"392589a36b44e59e13c815d47584682c5b0b26864bab89992c1e42bb73aa6b93","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","README.md":"edf9f16c57466b06d201b8646182b7332324c7aba28f832dde7f57d03249637d","src/core_api.rs":"b52728aba8a84f980f3f9cc8a94a64d3a97f1eb5f4db144904822c2f8eefb1f8","src/core_api/ct_variable.rs":"703bd62fb693a437e319d1192988bd674f9127a6b76f73b4c58c71afc79bc013","src/core_api/rt_variable.rs":"b57f89bf3991a313e2ddde09c701375e23539e7df74d685a161707ba1fbc99e4","src/core_api/wrapper.rs":"033777bed7d140b158e15d50fda8a6e06557ce89bd0738fcca692be2c39e8b8a","src/core_api/xof_reader.rs":"f33ca7b2c17eb99d84ea460d5567af68690e4fa6c2d94069a5d6748f8c8620eb","src/dev.rs":"cbaeab07489efcadec917d7b7bcf2fdade79e78a4839ab3c3d8ad442f8f82833","src/dev/fixed.rs":"1cbabc651645c1e781d31825791132b4e3741f426e99d7e40988e2a5ee49bddd","src/dev/mac.rs":"e8837d3b99dc8b6ddb398e7fad5731c2ed36931f851ed625d3ae59fb31244165","src/dev/rng.rs":"156f42e9eb8fb2083cd12dc4a9bff9d57a321d33367efe6cd42cdc02c17ed2dc","src/dev/variable.rs":"51939602b43f5a813fc725bc603a34246bbf76facaa7930cb7bf78c283ec94a7","src/dev/xof.rs":"b3971175e50f615247e4158cba87d77c369461eda22751d888725cec45b61985","src/digest.rs":"8beab74640774c9f6811daa6dac9b5a8867f5beeb0b552a9b5ddbc5cfc196ed0","src/lib.rs":"5128199102bf0f7638fba0bbcf42b23822e31065841fb0c4304b64f681fde961","src/mac.rs":"6303caa2c5b76513346c082dd600e007354179ad440fc83dad3d7f4240281803"},"package":"9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"} \ No newline at end of file diff --git a/anneal/v2/vendor/digest-0.10.7/.cargo_vcs_info.json b/anneal/v2/vendor/digest-0.10.7/.cargo_vcs_info.json new file mode 100644 index 0000000000..2a5097ca61 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "344389411fd9718a0742435152e933a9e71461ee" + }, + "path_in_vcs": "digest" +} \ No newline at end of file diff --git a/anneal/v2/vendor/digest-0.10.7/CHANGELOG.md b/anneal/v2/vendor/digest-0.10.7/CHANGELOG.md new file mode 100644 index 0000000000..1c8b9d18c7 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/CHANGELOG.md @@ -0,0 +1,137 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.10.7 (2023-05-19) +### Changed +- Loosen `subtle` version requirement ([#1260]) + +[#1260]: https://github.com/RustCrypto/traits/pull/1260 + +## 0.10.6 (2022-11-17) +### Added +- `Mac::verify_reset` and `Mac::verify_slice_reset` methods ([#1154]) + +[#1154]: https://github.com/RustCrypto/traits/pull/1154 + +## 0.10.5 (2022-09-16) +### Fixed +- MSRV build ([#1117]) + +[#1117]: https://github.com/RustCrypto/traits/pull/1117 + +## 0.10.4 (2022-09-16) +### Added +- Feature-gated implementation of the `const_oid::AssociatedOid` trait +for the core wrappers. ([#1098]) + +[#1098]: https://github.com/RustCrypto/traits/pull/1098 + +## 0.10.3 (2022-02-16) +### Fixed +- Minimal versions build ([#940]) + +[#940]: https://github.com/RustCrypto/traits/pull/940 + +## 0.10.2 (2022-02-10) +### Changed +- Relax bounds on the `Mac` trait ([#849]) + +[#849]: https://github.com/RustCrypto/traits/pull/849 + +## 0.10.1 (2021-12-14) [YANKED] +### Added +- `Update::chain` and `Digest::new_with_prefix` methods. ([#846]) +- `Mac::generate_key` method. ([#847]) + +### Fixed +- Doc cfg attribute for `CtOutput` and `MacError`. ([#842]) +- Expose `KeyInit::generate_key` method in docs. ([#847]) + +[#842]: https://github.com/RustCrypto/traits/pull/842 +[#846]: https://github.com/RustCrypto/traits/pull/846 +[#847]: https://github.com/RustCrypto/traits/pull/847 + +## 0.10.0 (2021-12-07) [YANKED] +### Changed +- Dirty traits are removed and instead block-level traits are introduced. +Variable output traits reworked and now support both run and compile time selection of output size. ([#380], [#819]) +- The `crypto-mac` traits are reworked and merged in. ([#819]) + +[#819]: https://github.com/RustCrypto/traits/pull/819 +[#380]: https://github.com/RustCrypto/traits/pull/380 + +## 0.9.0 (2020-06-09) +### Added +- `ExtendableOutputDirty` and `VariableOutputDirty` traits ([#183]) +- `FixedOutputDirty` trait + `finalize_into*` ([#180]) +- `XofReader::read_boxed` method ([#178], [#181], [#182]) +- `alloc` feature ([#163]) +- Re-export `typenum::consts` as `consts` ([#123]) +- `Output` type alias ([#115]) + +### Changed +- Rename `*result*` methods to `finalize` ala IUF ([#161]) +- Use `impl AsRef<[u8]>` instead of generic params on methods ([#112]) +- Rename `Input::input` to `Update::update` ala IUF ([#111]) +- Upgrade to Rust 2018 edition ([#109]) +- Bump `generic-array` to v0.14 ([#95]) + +[#183]: https://github.com/RustCrypto/traits/pull/183 +[#181]: https://github.com/RustCrypto/traits/pull/181 +[#182]: https://github.com/RustCrypto/traits/pull/182 +[#180]: https://github.com/RustCrypto/traits/pull/180 +[#178]: https://github.com/RustCrypto/traits/pull/178 +[#163]: https://github.com/RustCrypto/traits/pull/163 +[#161]: https://github.com/RustCrypto/traits/pull/161 +[#123]: https://github.com/RustCrypto/traits/pull/123 +[#115]: https://github.com/RustCrypto/traits/pull/115 +[#111]: https://github.com/RustCrypto/traits/pull/111 +[#112]: https://github.com/RustCrypto/traits/pull/112 +[#109]: https://github.com/RustCrypto/traits/pull/109 +[#95]: https://github.com/RustCrypto/traits/pull/95 + +## 0.8.1 (2019-06-30) + +## 0.8.0 (2018-10-01) + +## 0.7.6 (2018-09-21) + +## 0.7.5 (2018-07-13) + +## 0.7.4 (2018-06-21) + +## 0.7.3 (2018-06-20) + +## 0.7.2 (2017-11-17) + +## 0.7.1 (2017-11-15) + +## 0.7.0 (2017-11-14) + +## 0.6.2 (2017-07-24) + +## 0.6.1 (2017-06-18) + +## 0.6.0 (2017-06-12) + +## 0.5.2 (2017-05-02) + +## 0.5.1 (2017-05-02) + +## 0.5.0 (2017-04-06) + +## 0.4.0 (2016-12-24) + +## 0.3.1 (2016-12-16) + +## 0.3.0 (2016-11-17) + +## 0.2.1 (2016-10-14) + +## 0.2.0 (2016-10-14) + +## 0.1.0 (2016-10-06) diff --git a/anneal/v2/vendor/digest-0.10.7/Cargo.toml b/anneal/v2/vendor/digest-0.10.7/Cargo.toml new file mode 100644 index 0000000000..290ba752ba --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/Cargo.toml @@ -0,0 +1,70 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "digest" +version = "0.10.7" +authors = ["RustCrypto Developers"] +description = "Traits for cryptographic hash functions and message authentication codes" +documentation = "https://docs.rs/digest" +readme = "README.md" +keywords = [ + "digest", + "crypto", + "hash", +] +categories = [ + "cryptography", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RustCrypto/traits" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[dependencies.blobby] +version = "0.3" +optional = true + +[dependencies.block-buffer] +version = "0.10" +optional = true + +[dependencies.const-oid] +version = "0.9" +optional = true + +[dependencies.crypto-common] +version = "0.1.3" + +[dependencies.subtle] +version = "2.4" +optional = true +default-features = false + +[features] +alloc = [] +core-api = ["block-buffer"] +default = ["core-api"] +dev = ["blobby"] +mac = ["subtle"] +oid = ["const-oid"] +rand_core = ["crypto-common/rand_core"] +std = [ + "alloc", + "crypto-common/std", +] diff --git a/anneal/v2/vendor/digest-0.10.7/Cargo.toml.orig b/anneal/v2/vendor/digest-0.10.7/Cargo.toml.orig new file mode 100644 index 0000000000..9caa10e967 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/Cargo.toml.orig @@ -0,0 +1,35 @@ +[package] +name = "digest" +description = "Traits for cryptographic hash functions and message authentication codes" +version = "0.10.7" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2018" +documentation = "https://docs.rs/digest" +repository = "https://github.com/RustCrypto/traits" +keywords = ["digest", "crypto", "hash"] +categories = ["cryptography", "no-std"] + +[dependencies] +crypto-common = { version = "0.1.3", path = "../crypto-common" } + +# optional dependencies +block-buffer = { version = "0.10", optional = true } +subtle = { version = "2.4", default-features = false, optional = true } +blobby = { version = "0.3", optional = true } +const-oid = { version = "0.9", optional = true } + +[features] +default = ["core-api"] +core-api = ["block-buffer"] # Enable Core API traits +mac = ["subtle"] # Enable MAC traits +rand_core = ["crypto-common/rand_core"] # Enable random key generation methods +oid = ["const-oid"] # OID support. WARNING: Bumps MSRV to 1.57 +alloc = [] +std = ["alloc", "crypto-common/std"] +dev = ["blobby"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/anneal/v2/vendor/digest-0.10.7/LICENSE-APACHE b/anneal/v2/vendor/digest-0.10.7/LICENSE-APACHE new file mode 100644 index 0000000000..78173fa2e7 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/digest-0.10.7/LICENSE-MIT b/anneal/v2/vendor/digest-0.10.7/LICENSE-MIT new file mode 100644 index 0000000000..8dcb85b302 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2017 Artyom Pavlov + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/digest-0.10.7/README.md b/anneal/v2/vendor/digest-0.10.7/README.md new file mode 100644 index 0000000000..9f68559cd2 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/README.md @@ -0,0 +1,164 @@ +# RustCrypto: Digest Algorithm Traits + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Traits which describe functionality of [cryptographic hash functions][0], a.k.a. +digest algorithms. + +See [RustCrypto/hashes][1] for implementations which use this trait. + +[Documentation][docs-link] + +## Minimum Supported Rust Version + +Rust **1.41** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## Usage + +Let us demonstrate how to use crates in this repository using Sha256 as an +example. + +First add the `sha2` crate to your `Cargo.toml`: + +```toml +[dependencies] +sha2 = "0.10" +``` + +`sha2` and other crates re-export `digest` crate and `Digest` trait for +convenience, so you don't have to add `digest` crate as an explicit dependency. + +Now you can write the following code: + +```rust +use sha2::{Sha256, Digest}; + +let mut hasher = Sha256::new(); +let data = b"Hello world!"; +hasher.update(data); +// `input` can be called repeatedly and is generic over `AsRef<[u8]>` +hasher.update("String data"); +// Note that calling `finalize()` consumes hasher +let hash = hasher.finalize(); +println!("Result: {:x}", hash); +``` + +In this example `hash` has type [`GenericArray`][2], which is a generic +alternative to `[u8; 64]`. + +Alternatively you can use chained approach, which is equivalent to the previous +example: + +```rust +let hash = Sha256::new() + .chain_update(b"Hello world!") + .chain_update("String data") + .finalize(); + +println!("Result: {:x}", hash); +``` + +If the whole message is available you also can use convenience `digest` method: + +```rust +let hash = Sha256::digest(b"my message"); +println!("Result: {:x}", hash); +``` + +### Hashing `Read`-able objects + +If you want to hash data from [`Read`][3] trait (e.g. from file) you can rely on +implementation of [`Write`][4] trait (requires enabled-by-default `std` feature): + +```rust +use sha2::{Sha256, Digest}; +use std::{fs, io}; + +let mut file = fs::File::open(&path)?; +let mut hasher = Sha256::new(); +let n = io::copy(&mut file, &mut hasher)?; +let hash = hasher.finalize(); + +println!("Path: {}", path); +println!("Bytes processed: {}", n); +println!("Hash value: {:x}", hash); +``` + +### Generic code + +You can write generic code over `Digest` (or other traits from `digest` crate) +trait which will work over different hash functions: + +```rust +use digest::Digest; + +// Toy example, do not use it in practice! +// Instead use crates from: https://github.com/RustCrypto/password-hashing +fn hash_password(password: &str, salt: &str, output: &mut [u8]) { + let mut hasher = D::new(); + hasher.update(password.as_bytes()); + hasher.update(b"$"); + hasher.update(salt.as_bytes()); + output.copy_from_slice(hasher.finalize().as_slice()) +} + +let mut buf1 = [0u8; 32]; +let mut buf2 = [0u8; 64]; + +hash_password::("my_password", "abcd", &mut buf1); +hash_password::("my_password", "abcd", &mut buf2); +``` + +If you want to use hash functions with trait objects, use `digest::DynDigest` +trait. + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/digest.svg +[crate-link]: https://crates.io/crates/digest +[docs-image]: https://docs.rs/digest/badge.svg +[docs-link]: https://docs.rs/digest/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes +[build-image]: https://github.com/RustCrypto/traits/workflows/digest/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/traits/actions?query=workflow%3Adigest + +[//]: # (general links) + +[0]: https://en.wikipedia.org/wiki/Cryptographic_hash_function +[1]: https://github.com/RustCrypto/hashes +[2]: https://docs.rs/generic-array +[3]: https://doc.rust-lang.org/std/io/trait.Read.html +[4]: https://doc.rust-lang.org/std/io/trait.Write.html +[5]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code +[6]: https://github.com/RustCrypto/MACs diff --git a/anneal/v2/vendor/digest-0.10.7/src/core_api.rs b/anneal/v2/vendor/digest-0.10.7/src/core_api.rs new file mode 100644 index 0000000000..2cf384efe7 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/core_api.rs @@ -0,0 +1,119 @@ +//! Low-level traits operating on blocks and wrappers around them. +//! +//! Usage of traits in this module in user code is discouraged. Instead use +//! core algorithm wrapped by the wrapper types, which implement the +//! higher-level traits. +use crate::InvalidOutputSize; + +pub use crypto_common::{AlgorithmName, Block, BlockSizeUser, OutputSizeUser, Reset}; + +use block_buffer::{BlockBuffer, BufferKind}; +use crypto_common::{ + typenum::{IsLess, Le, NonZero, U256}, + Output, +}; + +mod ct_variable; +mod rt_variable; +mod wrapper; +mod xof_reader; + +pub use ct_variable::CtVariableCoreWrapper; +pub use rt_variable::RtVariableCoreWrapper; +pub use wrapper::{CoreProxy, CoreWrapper}; +pub use xof_reader::XofReaderCoreWrapper; + +/// Buffer type used by type which implements [`BufferKindUser`]. +pub type Buffer = + BlockBuffer<::BlockSize, ::BufferKind>; + +/// Types which consume data in blocks. +pub trait UpdateCore: BlockSizeUser { + /// Update state using the provided data blocks. + fn update_blocks(&mut self, blocks: &[Block]); +} + +/// Types which use [`BlockBuffer`] functionality. +pub trait BufferKindUser: BlockSizeUser { + /// Block buffer kind over which type operates. + type BufferKind: BufferKind; +} + +/// Core trait for hash functions with fixed output size. +pub trait FixedOutputCore: UpdateCore + BufferKindUser + OutputSizeUser +where + Self::BlockSize: IsLess, + Le: NonZero, +{ + /// Finalize state using remaining data stored in the provided block buffer, + /// write result into provided array and leave `self` in a dirty state. + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output); +} + +/// Core trait for hash functions with extendable (XOF) output size. +pub trait ExtendableOutputCore: UpdateCore + BufferKindUser +where + Self::BlockSize: IsLess, + Le: NonZero, +{ + /// XOF reader core state. + type ReaderCore: XofReaderCore; + + /// Retrieve XOF reader using remaining data stored in the block buffer + /// and leave hasher in a dirty state. + fn finalize_xof_core(&mut self, buffer: &mut Buffer) -> Self::ReaderCore; +} + +/// Core reader trait for extendable-output function (XOF) result. +pub trait XofReaderCore: BlockSizeUser { + /// Read next XOF block. + fn read_block(&mut self) -> Block; +} + +/// Core trait for hash functions with variable output size. +/// +/// Maximum output size is equal to [`OutputSizeUser::OutputSize`]. +/// Users are expected to truncate result returned by the +/// [`finalize_variable_core`] to `output_size` passed to the [`new`] method +/// during construction. Truncation side is defined by the [`TRUNC_SIDE`] +/// associated constant. +/// +/// [`finalize_variable_core`]: VariableOutputCore::finalize_variable_core +/// [`new`]: VariableOutputCore::new +/// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE +pub trait VariableOutputCore: UpdateCore + OutputSizeUser + BufferKindUser + Sized +where + Self::BlockSize: IsLess, + Le: NonZero, +{ + /// Side which should be used in a truncated result. + const TRUNC_SIDE: TruncSide; + + /// Initialize hasher state for given output size. + /// + /// Returns [`InvalidOutputSize`] if `output_size` is not valid for + /// the algorithm, e.g. if it's bigger than the [`OutputSize`] + /// associated type. + /// + /// [`OutputSize`]: OutputSizeUser::OutputSize + fn new(output_size: usize) -> Result; + + /// Finalize hasher and write full hashing result into the `out` buffer. + /// + /// The result must be truncated to `output_size` used during hasher + /// construction. Truncation side is defined by the [`TRUNC_SIDE`] + /// associated constant. + /// + /// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE + fn finalize_variable_core(&mut self, buffer: &mut Buffer, out: &mut Output); +} + +/// Type which used for defining truncation side in the [`VariableOutputCore`] +/// trait. +#[derive(Copy, Clone, Debug)] +pub enum TruncSide { + /// Truncate left side, i.e. `&out[..n]`. + Left, + /// Truncate right side, i.e. `&out[m..]`. + Right, +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/core_api/ct_variable.rs b/anneal/v2/vendor/digest-0.10.7/src/core_api/ct_variable.rs new file mode 100644 index 0000000000..7ee1bed0af --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/core_api/ct_variable.rs @@ -0,0 +1,204 @@ +use super::{ + AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore, + VariableOutputCore, +}; +use crate::HashMarker; +#[cfg(feature = "mac")] +use crate::MacMarker; +#[cfg(feature = "oid")] +use const_oid::{AssociatedOid, ObjectIdentifier}; +use core::{fmt, marker::PhantomData}; +use crypto_common::{ + generic_array::{ArrayLength, GenericArray}, + typenum::{IsLess, IsLessOrEqual, Le, LeEq, NonZero, U256}, + Block, BlockSizeUser, OutputSizeUser, +}; + +/// Dummy type used with [`CtVariableCoreWrapper`] in cases when +/// resulting hash does not have a known OID. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct NoOid; + +/// Wrapper around [`VariableOutputCore`] which selects output size +/// at compile time. +#[derive(Clone)] +pub struct CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + inner: T, + _out: PhantomData<(OutSize, O)>, +} + +impl HashMarker for CtVariableCoreWrapper +where + T: VariableOutputCore + HashMarker, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +#[cfg(feature = "mac")] +impl MacMarker for CtVariableCoreWrapper +where + T: VariableOutputCore + MacMarker, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +impl BlockSizeUser for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + type BlockSize = T::BlockSize; +} + +impl UpdateCore for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.inner.update_blocks(blocks); + } +} + +impl OutputSizeUser for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual + 'static, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + type OutputSize = OutSize; +} + +impl BufferKindUser for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + type BufferKind = T::BufferKind; +} + +impl FixedOutputCore for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual + 'static, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn finalize_fixed_core( + &mut self, + buffer: &mut Buffer, + out: &mut GenericArray, + ) { + let mut full_res = Default::default(); + self.inner.finalize_variable_core(buffer, &mut full_res); + let n = out.len(); + let m = full_res.len() - n; + match T::TRUNC_SIDE { + TruncSide::Left => out.copy_from_slice(&full_res[..n]), + TruncSide::Right => out.copy_from_slice(&full_res[m..]), + } + } +} + +impl Default for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn default() -> Self { + Self { + inner: T::new(OutSize::USIZE).unwrap(), + _out: PhantomData, + } + } +} + +impl Reset for CtVariableCoreWrapper +where + T: VariableOutputCore, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for CtVariableCoreWrapper +where + T: VariableOutputCore + AlgorithmName, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::write_alg_name(f)?; + f.write_str("_")?; + write!(f, "{}", OutSize::USIZE) + } +} + +#[cfg(feature = "oid")] +#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] +impl AssociatedOid for CtVariableCoreWrapper +where + T: VariableOutputCore, + O: AssociatedOid, + OutSize: ArrayLength + IsLessOrEqual, + LeEq: NonZero, + T::BlockSize: IsLess, + Le: NonZero, +{ + const OID: ObjectIdentifier = O::OID; +} + +/// Implement dummy type with hidden docs which is used to "carry" hasher +/// OID for [`CtVariableCoreWrapper`]. +#[macro_export] +macro_rules! impl_oid_carrier { + ($name:ident, $oid:literal) => { + #[doc(hidden)] + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] + pub struct $name; + + #[cfg(feature = "oid")] + impl AssociatedOid for $name { + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap($oid); + } + }; +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/core_api/rt_variable.rs b/anneal/v2/vendor/digest-0.10.7/src/core_api/rt_variable.rs new file mode 100644 index 0000000000..3dae748f5c --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/core_api/rt_variable.rs @@ -0,0 +1,166 @@ +use super::{AlgorithmName, TruncSide, UpdateCore, VariableOutputCore}; +#[cfg(feature = "mac")] +use crate::MacMarker; +use crate::{HashMarker, InvalidBufferSize}; +use crate::{InvalidOutputSize, Reset, Update, VariableOutput, VariableOutputReset}; +use block_buffer::BlockBuffer; +use core::fmt; +use crypto_common::typenum::{IsLess, Le, NonZero, Unsigned, U256}; + +/// Wrapper around [`VariableOutputCore`] which selects output size +/// at run time. +#[derive(Clone)] +pub struct RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + core: T, + buffer: BlockBuffer, + output_size: usize, +} + +impl RtVariableCoreWrapper +where + T: VariableOutputCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn finalize_dirty(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + let Self { + core, + buffer, + output_size, + } = self; + if out.len() != *output_size || out.len() > Self::MAX_OUTPUT_SIZE { + return Err(InvalidBufferSize); + } + let mut full_res = Default::default(); + core.finalize_variable_core(buffer, &mut full_res); + let n = out.len(); + let m = full_res.len() - n; + match T::TRUNC_SIDE { + TruncSide::Left => out.copy_from_slice(&full_res[..n]), + TruncSide::Right => out.copy_from_slice(&full_res[m..]), + } + Ok(()) + } +} + +impl HashMarker for RtVariableCoreWrapper +where + T: VariableOutputCore + HashMarker, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +#[cfg(feature = "mac")] +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +impl MacMarker for RtVariableCoreWrapper +where + T: VariableOutputCore + MacMarker, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +impl Reset for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore + Reset, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn reset(&mut self) { + self.buffer.reset(); + self.core.reset(); + } +} + +impl Update for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { core, buffer, .. } = self; + buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); + } +} + +impl VariableOutput for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + const MAX_OUTPUT_SIZE: usize = T::OutputSize::USIZE; + + fn new(output_size: usize) -> Result { + let buffer = Default::default(); + T::new(output_size).map(|core| Self { + core, + buffer, + output_size, + }) + } + + fn output_size(&self) -> usize { + self.output_size + } + + fn finalize_variable(mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + self.finalize_dirty(out) + } +} + +impl VariableOutputReset for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore + Reset, + T::BlockSize: IsLess, + Le: NonZero, +{ + fn finalize_variable_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize> { + self.finalize_dirty(out)?; + self.core.reset(); + self.buffer.reset(); + Ok(()) + } +} + +impl fmt::Debug for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore + AlgorithmName, + T::BlockSize: IsLess, + Le: NonZero, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + T::write_alg_name(f)?; + f.write_str(" { .. }") + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::io::Write for RtVariableCoreWrapper +where + T: VariableOutputCore + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + Update::update(self, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/core_api/wrapper.rs b/anneal/v2/vendor/digest-0.10.7/src/core_api/wrapper.rs new file mode 100644 index 0000000000..ca977381e2 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/core_api/wrapper.rs @@ -0,0 +1,290 @@ +use super::{ + AlgorithmName, Buffer, BufferKindUser, ExtendableOutputCore, FixedOutputCore, OutputSizeUser, + Reset, UpdateCore, XofReaderCoreWrapper, +}; +use crate::{ + ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, HashMarker, Update, +}; +use block_buffer::BlockBuffer; +use core::fmt; +use crypto_common::{ + typenum::{IsLess, Le, NonZero, U256}, + BlockSizeUser, InvalidLength, Key, KeyInit, KeySizeUser, Output, +}; + +#[cfg(feature = "mac")] +use crate::MacMarker; +#[cfg(feature = "oid")] +use const_oid::{AssociatedOid, ObjectIdentifier}; + +/// Wrapper around [`BufferKindUser`]. +/// +/// It handles data buffering and implements the slice-based traits. +#[derive(Clone, Default)] +pub struct CoreWrapper +where + T: BufferKindUser, + T::BlockSize: IsLess, + Le: NonZero, +{ + core: T, + buffer: BlockBuffer, +} + +impl HashMarker for CoreWrapper +where + T: BufferKindUser + HashMarker, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +#[cfg(feature = "mac")] +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +impl MacMarker for CoreWrapper +where + T: BufferKindUser + MacMarker, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +// this blanket impl is needed for HMAC +impl BlockSizeUser for CoreWrapper +where + T: BufferKindUser + HashMarker, + T::BlockSize: IsLess, + Le: NonZero, +{ + type BlockSize = T::BlockSize; +} + +impl CoreWrapper +where + T: BufferKindUser, + T::BlockSize: IsLess, + Le: NonZero, +{ + /// Create new wrapper from `core`. + #[inline] + pub fn from_core(core: T) -> Self { + let buffer = Default::default(); + Self { core, buffer } + } + + /// Decompose wrapper into inner parts. + #[inline] + pub fn decompose(self) -> (T, Buffer) { + let Self { core, buffer } = self; + (core, buffer) + } +} + +impl KeySizeUser for CoreWrapper +where + T: BufferKindUser + KeySizeUser, + T::BlockSize: IsLess, + Le: NonZero, +{ + type KeySize = T::KeySize; +} + +impl KeyInit for CoreWrapper +where + T: BufferKindUser + KeyInit, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn new(key: &Key) -> Self { + Self { + core: T::new(key), + buffer: Default::default(), + } + } + + #[inline] + fn new_from_slice(key: &[u8]) -> Result { + Ok(Self { + core: T::new_from_slice(key)?, + buffer: Default::default(), + }) + } +} + +impl fmt::Debug for CoreWrapper +where + T: BufferKindUser + AlgorithmName, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + T::write_alg_name(f)?; + f.write_str(" { .. }") + } +} + +impl Reset for CoreWrapper +where + T: BufferKindUser + Reset, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn reset(&mut self) { + self.core.reset(); + self.buffer.reset(); + } +} + +impl Update for CoreWrapper +where + T: BufferKindUser + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { core, buffer } = self; + buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); + } +} + +impl OutputSizeUser for CoreWrapper +where + T: BufferKindUser + OutputSizeUser, + T::BlockSize: IsLess, + Le: NonZero, +{ + type OutputSize = T::OutputSize; +} + +impl FixedOutput for CoreWrapper +where + T: FixedOutputCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn finalize_into(mut self, out: &mut Output) { + let Self { core, buffer } = &mut self; + core.finalize_fixed_core(buffer, out); + } +} + +impl FixedOutputReset for CoreWrapper +where + T: FixedOutputCore + Reset, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn finalize_into_reset(&mut self, out: &mut Output) { + let Self { core, buffer } = self; + core.finalize_fixed_core(buffer, out); + core.reset(); + buffer.reset(); + } +} + +impl ExtendableOutput for CoreWrapper +where + T: ExtendableOutputCore, + T::BlockSize: IsLess, + Le: NonZero, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + type Reader = XofReaderCoreWrapper; + + #[inline] + fn finalize_xof(self) -> Self::Reader { + let (mut core, mut buffer) = self.decompose(); + let core = core.finalize_xof_core(&mut buffer); + let buffer = Default::default(); + Self::Reader { core, buffer } + } +} + +impl ExtendableOutputReset for CoreWrapper +where + T: ExtendableOutputCore + Reset, + T::BlockSize: IsLess, + Le: NonZero, + ::BlockSize: IsLess, + Le<::BlockSize, U256>: NonZero, +{ + #[inline] + fn finalize_xof_reset(&mut self) -> Self::Reader { + let Self { core, buffer } = self; + let reader_core = core.finalize_xof_core(buffer); + core.reset(); + buffer.reset(); + let buffer = Default::default(); + Self::Reader { + core: reader_core, + buffer, + } + } +} + +#[cfg(feature = "oid")] +#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] +impl AssociatedOid for CoreWrapper +where + T: BufferKindUser + AssociatedOid, + T::BlockSize: IsLess, + Le: NonZero, +{ + const OID: ObjectIdentifier = T::OID; +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::io::Write for CoreWrapper +where + T: BufferKindUser + UpdateCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + Update::update(self, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +/// A proxy trait to a core type implemented by [`CoreWrapper`] +// TODO: replace with an inherent associated type on stabilization: +// https://github.com/rust-lang/rust/issues/8995 +pub trait CoreProxy: sealed::Sealed { + /// Type wrapped by [`CoreWrapper`]. + type Core; +} + +mod sealed { + pub trait Sealed {} +} + +impl sealed::Sealed for CoreWrapper +where + T: BufferKindUser, + T::BlockSize: IsLess, + Le: NonZero, +{ +} + +impl CoreProxy for CoreWrapper +where + T: BufferKindUser, + T::BlockSize: IsLess, + Le: NonZero, +{ + type Core = T; +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/core_api/xof_reader.rs b/anneal/v2/vendor/digest-0.10.7/src/core_api/xof_reader.rs new file mode 100644 index 0000000000..e18ac133a6 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/core_api/xof_reader.rs @@ -0,0 +1,63 @@ +use super::{AlgorithmName, XofReaderCore}; +use crate::XofReader; +use block_buffer::EagerBuffer; +use core::fmt; +use crypto_common::typenum::{IsLess, Le, NonZero, U256}; + +/// Wrapper around [`XofReaderCore`] implementations. +/// +/// It handles data buffering and implements the mid-level traits. +#[derive(Clone, Default)] +pub struct XofReaderCoreWrapper +where + T: XofReaderCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + pub(super) core: T, + pub(super) buffer: EagerBuffer, +} + +impl fmt::Debug for XofReaderCoreWrapper +where + T: XofReaderCore + AlgorithmName, + T::BlockSize: IsLess, + Le: NonZero, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + T::write_alg_name(f)?; + f.write_str(" { .. }") + } +} + +impl XofReader for XofReaderCoreWrapper +where + T: XofReaderCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn read(&mut self, buffer: &mut [u8]) { + let Self { core, buffer: buf } = self; + buf.set_data(buffer, |blocks| { + for block in blocks { + *block = core.read_block(); + } + }); + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::io::Read for XofReaderCoreWrapper +where + T: XofReaderCore, + T::BlockSize: IsLess, + Le: NonZero, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + XofReader::read(self, buf); + Ok(buf.len()) + } +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev.rs b/anneal/v2/vendor/digest-0.10.7/src/dev.rs new file mode 100644 index 0000000000..4380895747 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev.rs @@ -0,0 +1,78 @@ +//! Development-related functionality + +pub use blobby; + +mod fixed; +mod mac; +mod rng; +mod variable; +mod xof; + +pub use fixed::*; +pub use mac::*; +pub use variable::*; +pub use xof::*; + +/// Define hash function test +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! new_test { + ($name:ident, $test_name:expr, $hasher:ty, $test_func:ident $(,)?) => { + #[test] + fn $name() { + use digest::dev::blobby::Blob2Iterator; + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + + for (i, row) in Blob2Iterator::new(data).unwrap().enumerate() { + let [input, output] = row.unwrap(); + if let Some(desc) = $test_func::<$hasher>(input, output) { + panic!( + "\n\ + Failed test №{}: {}\n\ + input:\t{:?}\n\ + output:\t{:?}\n", + i, desc, input, output, + ); + } + } + } + }; +} + +/// Define [`Update`][crate::Update] impl benchmark +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! bench_update { + ( + $init:expr; + $($name:ident $bs:expr;)* + ) => { + $( + #[bench] + fn $name(b: &mut Bencher) { + let mut d = $init; + let data = [0; $bs]; + + b.iter(|| { + digest::Update::update(&mut d, &data[..]); + }); + + b.bytes = $bs; + } + )* + }; +} + +/// Feed ~1 MiB of pseudorandom data to an updatable state. +pub fn feed_rand_16mib(d: &mut D) { + let buf = &mut [0u8; 1024]; + let mut rng = rng::RNG; + let n = 16 * (1 << 20) / buf.len(); + for _ in 0..n { + rng.fill(buf); + d.update(buf); + // additional byte, so size of fed data + // will not be multiple of block size + d.update(&[42]); + } +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev/fixed.rs b/anneal/v2/vendor/digest-0.10.7/src/dev/fixed.rs new file mode 100644 index 0000000000..24f380112d --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev/fixed.rs @@ -0,0 +1,65 @@ +use crate::{Digest, FixedOutput, FixedOutputReset, HashMarker, Update}; +use core::fmt::Debug; + +/// Fixed-output resettable digest test via the `Digest` trait +pub fn fixed_reset_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: FixedOutputReset + Debug + Clone + Default + Update + HashMarker, +{ + let mut hasher = D::new(); + // Test that it works when accepting the message all at once + hasher.update(input); + let mut hasher2 = hasher.clone(); + if hasher.finalize()[..] != output[..] { + return Some("whole message"); + } + + // Test if reset works correctly + hasher2.reset(); + hasher2.update(input); + if hasher2.finalize_reset()[..] != output[..] { + return Some("whole message after reset"); + } + + // Test that it works when accepting the message in chunks + for n in 1..core::cmp::min(17, input.len()) { + let mut hasher = D::new(); + for chunk in input.chunks(n) { + hasher.update(chunk); + hasher2.update(chunk); + } + if hasher.finalize()[..] != output[..] { + return Some("message in chunks"); + } + if hasher2.finalize_reset()[..] != output[..] { + return Some("message in chunks"); + } + } + + None +} + +/// Variable-output resettable digest test +pub fn fixed_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: FixedOutput + Default + Debug + Clone, +{ + let mut hasher = D::default(); + // Test that it works when accepting the message all at once + hasher.update(input); + if hasher.finalize_fixed()[..] != output[..] { + return Some("whole message"); + } + + // Test that it works when accepting the message in chunks + for n in 1..core::cmp::min(17, input.len()) { + let mut hasher = D::default(); + for chunk in input.chunks(n) { + hasher.update(chunk); + } + if hasher.finalize_fixed()[..] != output[..] { + return Some("message in chunks"); + } + } + None +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev/mac.rs b/anneal/v2/vendor/digest-0.10.7/src/dev/mac.rs new file mode 100644 index 0000000000..0d4a37dfce --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev/mac.rs @@ -0,0 +1,159 @@ +/// Define MAC test +#[macro_export] +#[cfg(feature = "mac")] +#[cfg_attr(docsrs, doc(cfg(all(feature = "dev", feature = "mac"))))] +macro_rules! new_mac_test { + ($name:ident, $test_name:expr, $mac:ty $(,)?) => { + digest::new_mac_test!($name, $test_name, $mac, ""); + }; + ($name:ident, $test_name:expr, $mac:ty, trunc_left $(,)?) => { + digest::new_mac_test!($name, $test_name, $mac, "left"); + }; + ($name:ident, $test_name:expr, $mac:ty, trunc_right $(,)?) => { + digest::new_mac_test!($name, $test_name, $mac, "right"); + }; + ($name:ident, $test_name:expr, $mac:ty, $trunc:expr $(,)?) => { + #[test] + fn $name() { + use core::cmp::min; + use digest::dev::blobby::Blob3Iterator; + use digest::Mac; + + fn run_test(key: &[u8], input: &[u8], tag: &[u8]) -> Option<&'static str> { + let mac0 = <$mac as Mac>::new_from_slice(key).unwrap(); + + let mut mac = mac0.clone(); + mac.update(input); + let result = mac.finalize().into_bytes(); + let n = tag.len(); + let result_bytes = match $trunc { + "left" => &result[..n], + "right" => &result[result.len() - n..], + _ => &result[..], + }; + if result_bytes != tag { + return Some("whole message"); + } + + // test reading different chunk sizes + for chunk_size in 1..min(64, input.len()) { + let mut mac = mac0.clone(); + for chunk in input.chunks(chunk_size) { + mac.update(chunk); + } + let res = match $trunc { + "left" => mac.verify_truncated_left(tag), + "right" => mac.verify_truncated_right(tag), + _ => mac.verify_slice(tag), + }; + if res.is_err() { + return Some("chunked message"); + } + } + + None + } + + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + + for (i, row) in Blob3Iterator::new(data).unwrap().enumerate() { + let [key, input, tag] = row.unwrap(); + if let Some(desc) = run_test(key, input, tag) { + panic!( + "\n\ + Failed test №{}: {}\n\ + key:\t{:?}\n\ + input:\t{:?}\n\ + tag:\t{:?}\n", + i, desc, key, input, tag, + ); + } + } + } + }; +} + +/// Define resettable MAC test +#[macro_export] +#[cfg(feature = "mac")] +#[cfg_attr(docsrs, doc(cfg(all(feature = "dev", feature = "mac"))))] +macro_rules! new_resettable_mac_test { + ($name:ident, $test_name:expr, $mac:ty $(,)?) => { + digest::new_resettable_mac_test!($name, $test_name, $mac, ""); + }; + ($name:ident, $test_name:expr, $mac:ty, trunc_left $(,)?) => { + digest::new_resettable_mac_test!($name, $test_name, $mac, "left"); + }; + ($name:ident, $test_name:expr, $mac:ty, trunc_right $(,)?) => { + digest::new_resettable_mac_test!($name, $test_name, $mac, "right"); + }; + ($name:ident, $test_name:expr, $mac:ty, $trunc:expr $(,)?) => { + #[test] + fn $name() { + use core::cmp::min; + use digest::dev::blobby::Blob3Iterator; + use digest::Mac; + + fn run_test(key: &[u8], input: &[u8], tag: &[u8]) -> Option<&'static str> { + let mac0 = <$mac as Mac>::new_from_slice(key).unwrap(); + + let mut mac = mac0.clone(); + mac.update(input); + let result = mac.finalize_reset().into_bytes(); + let n = tag.len(); + let result_bytes = match $trunc { + "left" => &result[..n], + "right" => &result[result.len() - n..], + _ => &result[..], + }; + if result_bytes != tag { + return Some("whole message"); + } + + // test if reset worked correctly + mac.update(input); + let res = match $trunc { + "left" => mac.verify_truncated_left(tag), + "right" => mac.verify_truncated_right(tag), + _ => mac.verify_slice(tag), + }; + if res.is_err() { + return Some("after reset"); + } + + // test reading different chunk sizes + for chunk_size in 1..min(64, input.len()) { + let mut mac = mac0.clone(); + for chunk in input.chunks(chunk_size) { + mac.update(chunk); + } + let res = match $trunc { + "left" => mac.verify_truncated_left(tag), + "right" => mac.verify_truncated_right(tag), + _ => mac.verify_slice(tag), + }; + if res.is_err() { + return Some("chunked message"); + } + } + None + } + + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + + for (i, row) in Blob3Iterator::new(data).unwrap().enumerate() { + let [key, input, tag] = row.unwrap(); + if let Some(desc) = run_test(key, input, tag) { + panic!( + "\n\ + Failed test №{}: {}\n\ + key:\t{:?}\n\ + input:\t{:?}\n\ + tag:\t{:?}\n", + i, desc, key, input, tag, + ); + } + } + } + }; +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev/rng.rs b/anneal/v2/vendor/digest-0.10.7/src/dev/rng.rs new file mode 100644 index 0000000000..d34a1cf31f --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev/rng.rs @@ -0,0 +1,38 @@ +//! Xorshift RNG used for tests. Based on the `rand_xorshift` crate. +use core::num::Wrapping; + +/// Initial RNG state used in tests. +// chosen by fair dice roll. guaranteed to be random. +pub(crate) const RNG: XorShiftRng = XorShiftRng { + x: Wrapping(0x0787_3B4A), + y: Wrapping(0xFAAB_8FFE), + z: Wrapping(0x1745_980F), + w: Wrapping(0xB0AD_B4F3), +}; + +/// Xorshift RNG instance/ +pub(crate) struct XorShiftRng { + x: Wrapping, + y: Wrapping, + z: Wrapping, + w: Wrapping, +} + +impl XorShiftRng { + pub(crate) fn fill(&mut self, buf: &mut [u8; 1024]) { + for chunk in buf.chunks_exact_mut(4) { + chunk.copy_from_slice(&self.next_u32().to_le_bytes()); + } + } + + fn next_u32(&mut self) -> u32 { + let x = self.x; + let t = x ^ (x << 11); + self.x = self.y; + self.y = self.z; + self.z = self.w; + let w = self.w; + self.w = w ^ (w >> 19) ^ (t ^ (t >> 8)); + self.w.0 + } +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev/variable.rs b/anneal/v2/vendor/digest-0.10.7/src/dev/variable.rs new file mode 100644 index 0000000000..ed8ff88280 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev/variable.rs @@ -0,0 +1,82 @@ +use crate::{VariableOutput, VariableOutputReset}; +use core::fmt::Debug; + +/// Variable-output resettable digest test +pub fn variable_reset_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: VariableOutputReset + Debug + Clone, +{ + let mut hasher = D::new(output.len()).unwrap(); + let mut buf = [0u8; 128]; + let buf = &mut buf[..output.len()]; + // Test that it works when accepting the message all at once + hasher.update(input); + let mut hasher2 = hasher.clone(); + hasher.finalize_variable(buf).unwrap(); + if buf != output { + return Some("whole message"); + } + buf.iter_mut().for_each(|b| *b = 0); + + // Test if reset works correctly + hasher2.reset(); + hasher2.update(input); + hasher2.finalize_variable_reset(buf).unwrap(); + if buf != output { + return Some("whole message after reset"); + } + buf.iter_mut().for_each(|b| *b = 0); + + // Test that it works when accepting the message in chunks + for n in 1..core::cmp::min(17, input.len()) { + let mut hasher = D::new(output.len()).unwrap(); + for chunk in input.chunks(n) { + hasher.update(chunk); + hasher2.update(chunk); + } + hasher.finalize_variable(buf).unwrap(); + if buf != output { + return Some("message in chunks"); + } + buf.iter_mut().for_each(|b| *b = 0); + + hasher2.finalize_variable_reset(buf).unwrap(); + if buf != output { + return Some("message in chunks"); + } + buf.iter_mut().for_each(|b| *b = 0); + } + + None +} + +/// Variable-output resettable digest test +pub fn variable_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: VariableOutput + Debug + Clone, +{ + let mut hasher = D::new(output.len()).unwrap(); + let mut buf = [0u8; 128]; + let buf = &mut buf[..output.len()]; + // Test that it works when accepting the message all at once + hasher.update(input); + hasher.finalize_variable(buf).unwrap(); + if buf != output { + return Some("whole message"); + } + buf.iter_mut().for_each(|b| *b = 0); + + // Test that it works when accepting the message in chunks + for n in 1..core::cmp::min(17, input.len()) { + let mut hasher = D::new(output.len()).unwrap(); + for chunk in input.chunks(n) { + hasher.update(chunk); + } + hasher.finalize_variable(buf).unwrap(); + if buf != output { + return Some("message in chunks"); + } + buf.iter_mut().for_each(|b| *b = 0); + } + None +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/dev/xof.rs b/anneal/v2/vendor/digest-0.10.7/src/dev/xof.rs new file mode 100644 index 0000000000..9e5d07a09b --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/dev/xof.rs @@ -0,0 +1,51 @@ +use crate::ExtendableOutputReset; +use core::fmt::Debug; + +/// Resettable XOF test +pub fn xof_reset_test(input: &[u8], output: &[u8]) -> Option<&'static str> +where + D: ExtendableOutputReset + Default + Debug + Clone, +{ + let mut hasher = D::default(); + let mut buf = [0u8; 1024]; + let buf = &mut buf[..output.len()]; + // Test that it works when accepting the message all at once + hasher.update(input); + let mut hasher2 = hasher.clone(); + hasher.finalize_xof_into(buf); + if buf != output { + return Some("whole message"); + } + buf.iter_mut().for_each(|b| *b = 0); + + // Test if reset works correctly + hasher2.reset(); + hasher2.update(input); + hasher2.finalize_xof_reset_into(buf); + if buf != output { + return Some("whole message after reset"); + } + buf.iter_mut().for_each(|b| *b = 0); + + // Test that it works when accepting the message in chunks + for n in 1..core::cmp::min(17, input.len()) { + let mut hasher = D::default(); + for chunk in input.chunks(n) { + hasher.update(chunk); + hasher2.update(chunk); + } + hasher.finalize_xof_into(buf); + if buf != output { + return Some("message in chunks"); + } + buf.iter_mut().for_each(|b| *b = 0); + + hasher2.finalize_xof_reset_into(buf); + if buf != output { + return Some("message in chunks"); + } + buf.iter_mut().for_each(|b| *b = 0); + } + + None +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/digest.rs b/anneal/v2/vendor/digest-0.10.7/src/digest.rs new file mode 100644 index 0000000000..9373550ca0 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/digest.rs @@ -0,0 +1,236 @@ +use super::{FixedOutput, FixedOutputReset, InvalidBufferSize, Reset, Update}; +use crypto_common::{typenum::Unsigned, Output, OutputSizeUser}; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +/// Marker trait for cryptographic hash functions. +pub trait HashMarker {} + +/// Convenience wrapper trait covering functionality of cryptographic hash +/// functions with fixed output size. +/// +/// This trait wraps [`Update`], [`FixedOutput`], [`Default`], and +/// [`HashMarker`] traits and provides additional convenience methods. +pub trait Digest: OutputSizeUser { + /// Create new hasher instance. + fn new() -> Self; + + /// Create new hasher instance which has processed the provided data. + fn new_with_prefix(data: impl AsRef<[u8]>) -> Self; + + /// Process data, updating the internal state. + fn update(&mut self, data: impl AsRef<[u8]>); + + /// Process input data in a chained manner. + #[must_use] + fn chain_update(self, data: impl AsRef<[u8]>) -> Self; + + /// Retrieve result and consume hasher instance. + fn finalize(self) -> Output; + + /// Write result into provided array and consume the hasher instance. + fn finalize_into(self, out: &mut Output); + + /// Retrieve result and reset hasher instance. + fn finalize_reset(&mut self) -> Output + where + Self: FixedOutputReset; + + /// Write result into provided array and reset the hasher instance. + fn finalize_into_reset(&mut self, out: &mut Output) + where + Self: FixedOutputReset; + + /// Reset hasher instance to its initial state. + fn reset(&mut self) + where + Self: Reset; + + /// Get output size of the hasher + fn output_size() -> usize; + + /// Compute hash of `data`. + fn digest(data: impl AsRef<[u8]>) -> Output; +} + +impl Digest for D { + #[inline] + fn new() -> Self { + Self::default() + } + + #[inline] + fn new_with_prefix(data: impl AsRef<[u8]>) -> Self + where + Self: Default + Sized, + { + let mut h = Self::default(); + h.update(data.as_ref()); + h + } + + #[inline] + fn update(&mut self, data: impl AsRef<[u8]>) { + Update::update(self, data.as_ref()); + } + + #[inline] + fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self { + Update::update(&mut self, data.as_ref()); + self + } + + #[inline] + fn finalize(self) -> Output { + FixedOutput::finalize_fixed(self) + } + + #[inline] + fn finalize_into(self, out: &mut Output) { + FixedOutput::finalize_into(self, out); + } + + #[inline] + fn finalize_reset(&mut self) -> Output + where + Self: FixedOutputReset, + { + FixedOutputReset::finalize_fixed_reset(self) + } + + #[inline] + fn finalize_into_reset(&mut self, out: &mut Output) + where + Self: FixedOutputReset, + { + FixedOutputReset::finalize_into_reset(self, out); + } + + #[inline] + fn reset(&mut self) + where + Self: Reset, + { + Reset::reset(self) + } + + #[inline] + fn output_size() -> usize { + Self::OutputSize::to_usize() + } + + #[inline] + fn digest(data: impl AsRef<[u8]>) -> Output { + let mut hasher = Self::default(); + hasher.update(data.as_ref()); + hasher.finalize() + } +} + +/// Modification of the [`Digest`] trait suitable for trait objects. +pub trait DynDigest { + /// Digest input data. + /// + /// This method can be called repeatedly for use with streaming messages. + fn update(&mut self, data: &[u8]); + + /// Retrieve result and reset hasher instance + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn finalize_reset(&mut self) -> Box<[u8]> { + let mut result = vec![0; self.output_size()]; + self.finalize_into_reset(&mut result).unwrap(); + result.into_boxed_slice() + } + + /// Retrieve result and consume boxed hasher instance + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + #[allow(clippy::boxed_local)] + fn finalize(mut self: Box) -> Box<[u8]> { + let mut result = vec![0; self.output_size()]; + self.finalize_into_reset(&mut result).unwrap(); + result.into_boxed_slice() + } + + /// Write result into provided array and consume the hasher instance. + /// + /// Returns error if buffer length is not equal to `output_size`. + fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>; + + /// Write result into provided array and reset the hasher instance. + /// + /// Returns error if buffer length is not equal to `output_size`. + fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>; + + /// Reset hasher instance to its initial state. + fn reset(&mut self); + + /// Get output size of the hasher + fn output_size(&self) -> usize; + + /// Clone hasher state into a boxed trait object + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn box_clone(&self) -> Box; +} + +impl DynDigest for D { + fn update(&mut self, data: &[u8]) { + Update::update(self, data); + } + + #[cfg(feature = "alloc")] + fn finalize_reset(&mut self) -> Box<[u8]> { + FixedOutputReset::finalize_fixed_reset(self) + .to_vec() + .into_boxed_slice() + } + + #[cfg(feature = "alloc")] + fn finalize(self: Box) -> Box<[u8]> { + FixedOutput::finalize_fixed(*self) + .to_vec() + .into_boxed_slice() + } + + fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> { + if buf.len() == self.output_size() { + FixedOutput::finalize_into(self, Output::::from_mut_slice(buf)); + Ok(()) + } else { + Err(InvalidBufferSize) + } + } + + fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> { + if buf.len() == self.output_size() { + FixedOutputReset::finalize_into_reset(self, Output::::from_mut_slice(buf)); + Ok(()) + } else { + Err(InvalidBufferSize) + } + } + + fn reset(&mut self) { + Reset::reset(self); + } + + fn output_size(&self) -> usize { + ::OutputSize::to_usize() + } + + #[cfg(feature = "alloc")] + fn box_clone(&self) -> Box { + Box::new(self.clone()) + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl Clone for Box { + fn clone(&self) -> Self { + self.box_clone() + } +} diff --git a/anneal/v2/vendor/digest-0.10.7/src/lib.rs b/anneal/v2/vendor/digest-0.10.7/src/lib.rs new file mode 100644 index 0000000000..fc82e2e3ad --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/lib.rs @@ -0,0 +1,301 @@ +//! This crate provides traits which describe functionality of cryptographic hash +//! functions and Message Authentication algorithms. +//! +//! Traits in this repository are organized into the following levels: +//! +//! - **High-level convenience traits**: [`Digest`], [`DynDigest`], [`Mac`]. +//! Wrappers around lower-level traits for most common use-cases. Users should +//! usually prefer using these traits. +//! - **Mid-level traits**: [`Update`], [`FixedOutput`], [`FixedOutputReset`], +//! [`ExtendableOutput`], [`ExtendableOutputReset`], [`XofReader`], +//! [`VariableOutput`], [`Reset`], [`KeyInit`], and [`InnerInit`]. These +//! traits atomically describe available functionality of an algorithm. +//! - **Marker traits**: [`HashMarker`], [`MacMarker`]. Used to distinguish +//! different algorithm classes. +//! - **Low-level traits** defined in the [`core_api`] module. These traits +//! operate at a block-level and do not contain any built-in buffering. +//! They are intended to be implemented by low-level algorithm providers only. +//! Usually they should not be used in application-level code. +//! +//! Additionally hash functions implement traits from the standard library: +//! [`Default`], [`Clone`], [`Write`][std::io::Write]. The latter is +//! feature-gated behind `std` feature, which is usually enabled by default +//! by hash implementation crates. + +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![forbid(unsafe_code)] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![warn(missing_docs, rust_2018_idioms)] + +#[cfg(feature = "alloc")] +#[macro_use] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "rand_core")] +#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] +pub use crypto_common::rand_core; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +#[cfg(feature = "dev")] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +pub mod dev; + +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub mod core_api; +mod digest; +#[cfg(feature = "mac")] +mod mac; + +#[cfg(feature = "core-api")] +#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))] +pub use block_buffer; +#[cfg(feature = "oid")] +#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] +pub use const_oid; +pub use crypto_common; + +pub use crate::digest::{Digest, DynDigest, HashMarker}; +pub use crypto_common::{generic_array, typenum, typenum::consts, Output, OutputSizeUser, Reset}; +#[cfg(feature = "mac")] +pub use crypto_common::{InnerInit, InvalidLength, Key, KeyInit}; +#[cfg(feature = "mac")] +pub use mac::{CtOutput, Mac, MacError, MacMarker}; + +use core::fmt; + +/// Types which consume data with byte granularity. +pub trait Update { + /// Update state using the provided data. + fn update(&mut self, data: &[u8]); + + /// Digest input data in a chained manner. + #[must_use] + fn chain(mut self, data: impl AsRef<[u8]>) -> Self + where + Self: Sized, + { + self.update(data.as_ref()); + self + } +} + +/// Trait for hash functions with fixed-size output. +pub trait FixedOutput: Update + OutputSizeUser + Sized { + /// Consume value and write result into provided array. + fn finalize_into(self, out: &mut Output); + + /// Retrieve result and consume the hasher instance. + #[inline] + fn finalize_fixed(self) -> Output { + let mut out = Default::default(); + self.finalize_into(&mut out); + out + } +} + +/// Trait for hash functions with fixed-size output able to reset themselves. +pub trait FixedOutputReset: FixedOutput + Reset { + /// Write result into provided array and reset the hasher state. + fn finalize_into_reset(&mut self, out: &mut Output); + + /// Retrieve result and reset the hasher state. + #[inline] + fn finalize_fixed_reset(&mut self) -> Output { + let mut out = Default::default(); + self.finalize_into_reset(&mut out); + out + } +} + +/// Trait for reader types which are used to extract extendable output +/// from a XOF (extendable-output function) result. +pub trait XofReader { + /// Read output into the `buffer`. Can be called an unlimited number of times. + fn read(&mut self, buffer: &mut [u8]); + + /// Read output into a boxed slice of the specified size. + /// + /// Can be called an unlimited number of times in combination with `read`. + /// + /// `Box<[u8]>` is used instead of `Vec` to save stack space, since + /// they have size of 2 and 3 words respectively. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn read_boxed(&mut self, n: usize) -> Box<[u8]> { + let mut buf = vec![0u8; n].into_boxed_slice(); + self.read(&mut buf); + buf + } +} + +/// Trait for hash functions with extendable-output (XOF). +pub trait ExtendableOutput: Sized + Update { + /// Reader + type Reader: XofReader; + + /// Retrieve XOF reader and consume hasher instance. + fn finalize_xof(self) -> Self::Reader; + + /// Finalize XOF and write result into `out`. + fn finalize_xof_into(self, out: &mut [u8]) { + self.finalize_xof().read(out); + } + + /// Compute hash of `data` and write it into `output`. + fn digest_xof(input: impl AsRef<[u8]>, output: &mut [u8]) + where + Self: Default, + { + let mut hasher = Self::default(); + hasher.update(input.as_ref()); + hasher.finalize_xof().read(output); + } + + /// Retrieve result into a boxed slice of the specified size and consume + /// the hasher. + /// + /// `Box<[u8]>` is used instead of `Vec` to save stack space, since + /// they have size of 2 and 3 words respectively. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn finalize_boxed(self, output_size: usize) -> Box<[u8]> { + let mut buf = vec![0u8; output_size].into_boxed_slice(); + self.finalize_xof().read(&mut buf); + buf + } +} + +/// Trait for hash functions with extendable-output (XOF) able to reset themselves. +pub trait ExtendableOutputReset: ExtendableOutput + Reset { + /// Retrieve XOF reader and reset hasher instance state. + fn finalize_xof_reset(&mut self) -> Self::Reader; + + /// Finalize XOF, write result into `out`, and reset the hasher state. + fn finalize_xof_reset_into(&mut self, out: &mut [u8]) { + self.finalize_xof_reset().read(out); + } + + /// Retrieve result into a boxed slice of the specified size and reset + /// the hasher state. + /// + /// `Box<[u8]>` is used instead of `Vec` to save stack space, since + /// they have size of 2 and 3 words respectively. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn finalize_boxed_reset(&mut self, output_size: usize) -> Box<[u8]> { + let mut buf = vec![0u8; output_size].into_boxed_slice(); + self.finalize_xof_reset().read(&mut buf); + buf + } +} + +/// Trait for hash functions with variable-size output. +pub trait VariableOutput: Sized + Update { + /// Maximum size of output hash. + const MAX_OUTPUT_SIZE: usize; + + /// Create new hasher instance with the given output size. + /// + /// It will return `Err(InvalidOutputSize)` in case if hasher can not return + /// hash of the specified output size. + fn new(output_size: usize) -> Result; + + /// Get output size of the hasher instance provided to the `new` method + fn output_size(&self) -> usize; + + /// Write result into the output buffer. + /// + /// Returns `Err(InvalidOutputSize)` if `out` size is not equal to + /// `self.output_size()`. + fn finalize_variable(self, out: &mut [u8]) -> Result<(), InvalidBufferSize>; + + /// Compute hash of `data` and write it to `output`. + /// + /// Length of the output hash is determined by `output`. If `output` is + /// bigger than `Self::MAX_OUTPUT_SIZE`, this method returns + /// `InvalidOutputSize`. + fn digest_variable( + input: impl AsRef<[u8]>, + output: &mut [u8], + ) -> Result<(), InvalidOutputSize> { + let mut hasher = Self::new(output.len())?; + hasher.update(input.as_ref()); + hasher + .finalize_variable(output) + .map_err(|_| InvalidOutputSize) + } + + /// Retrieve result into a boxed slice and consume hasher. + /// + /// `Box<[u8]>` is used instead of `Vec` to save stack space, since + /// they have size of 2 and 3 words respectively. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn finalize_boxed(self) -> Box<[u8]> { + let n = self.output_size(); + let mut buf = vec![0u8; n].into_boxed_slice(); + self.finalize_variable(&mut buf) + .expect("buf length is equal to output_size"); + buf + } +} + +/// Trait for hash functions with variable-size output able to reset themselves. +pub trait VariableOutputReset: VariableOutput + Reset { + /// Write result into the output buffer and reset the hasher state. + /// + /// Returns `Err(InvalidOutputSize)` if `out` size is not equal to + /// `self.output_size()`. + fn finalize_variable_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>; + + /// Retrieve result into a boxed slice and reset the hasher state. + /// + /// `Box<[u8]>` is used instead of `Vec` to save stack space, since + /// they have size of 2 and 3 words respectively. + #[cfg(feature = "alloc")] + #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] + fn finalize_boxed_reset(&mut self) -> Box<[u8]> { + let n = self.output_size(); + let mut buf = vec![0u8; n].into_boxed_slice(); + self.finalize_variable_reset(&mut buf) + .expect("buf length is equal to output_size"); + buf + } +} + +/// The error type used in variable hash traits. +#[derive(Clone, Copy, Debug, Default)] +pub struct InvalidOutputSize; + +impl fmt::Display for InvalidOutputSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid output size") + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for InvalidOutputSize {} + +/// Buffer length is not equal to hash output size. +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +pub struct InvalidBufferSize; + +impl fmt::Display for InvalidBufferSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid buffer length") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidBufferSize {} diff --git a/anneal/v2/vendor/digest-0.10.7/src/mac.rs b/anneal/v2/vendor/digest-0.10.7/src/mac.rs new file mode 100644 index 0000000000..1c31359ea3 --- /dev/null +++ b/anneal/v2/vendor/digest-0.10.7/src/mac.rs @@ -0,0 +1,305 @@ +use crate::{FixedOutput, FixedOutputReset, Update}; +use crypto_common::{InvalidLength, Key, KeyInit, Output, OutputSizeUser, Reset}; + +#[cfg(feature = "rand_core")] +use crate::rand_core::{CryptoRng, RngCore}; +use core::fmt; +use crypto_common::typenum::Unsigned; +use subtle::{Choice, ConstantTimeEq}; + +/// Marker trait for Message Authentication algorithms. +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +pub trait MacMarker {} + +/// Convenience wrapper trait covering functionality of Message Authentication algorithms. +/// +/// This trait wraps [`KeyInit`], [`Update`], [`FixedOutput`], and [`MacMarker`] +/// traits and provides additional convenience methods. +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +pub trait Mac: OutputSizeUser + Sized { + /// Create new value from fixed size key. + fn new(key: &Key) -> Self + where + Self: KeyInit; + + /// Generate random key using the provided [`CryptoRng`]. + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + fn generate_key(rng: impl CryptoRng + RngCore) -> Key + where + Self: KeyInit; + + /// Create new value from variable size key. + fn new_from_slice(key: &[u8]) -> Result + where + Self: KeyInit; + + /// Update state using the provided data. + fn update(&mut self, data: &[u8]); + + /// Process input data in a chained manner. + #[must_use] + fn chain_update(self, data: impl AsRef<[u8]>) -> Self; + + /// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and consume + /// [`Mac`] instance. + fn finalize(self) -> CtOutput; + + /// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and reset + /// [`Mac`] instance. + fn finalize_reset(&mut self) -> CtOutput + where + Self: FixedOutputReset; + + /// Reset MAC instance to its initial state. + fn reset(&mut self) + where + Self: Reset; + + /// Check if tag/code value is correct for the processed input. + fn verify(self, tag: &Output) -> Result<(), MacError>; + + /// Check if tag/code value is correct for the processed input and reset + /// [`Mac`] instance. + fn verify_reset(&mut self, tag: &Output) -> Result<(), MacError> + where + Self: FixedOutputReset; + + /// Check truncated tag correctness using all bytes + /// of calculated tag. + /// + /// Returns `Error` if `tag` is not valid or not equal in length + /// to MAC's output. + fn verify_slice(self, tag: &[u8]) -> Result<(), MacError>; + + /// Check truncated tag correctness using all bytes + /// of calculated tag and reset [`Mac`] instance. + /// + /// Returns `Error` if `tag` is not valid or not equal in length + /// to MAC's output. + fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError> + where + Self: FixedOutputReset; + + /// Check truncated tag correctness using left side bytes + /// (i.e. `tag[..n]`) of calculated tag. + /// + /// Returns `Error` if `tag` is not valid or empty. + fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError>; + + /// Check truncated tag correctness using right side bytes + /// (i.e. `tag[n..]`) of calculated tag. + /// + /// Returns `Error` if `tag` is not valid or empty. + fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError>; +} + +impl Mac for T { + #[inline(always)] + fn new(key: &Key) -> Self + where + Self: KeyInit, + { + KeyInit::new(key) + } + + #[inline(always)] + fn new_from_slice(key: &[u8]) -> Result + where + Self: KeyInit, + { + KeyInit::new_from_slice(key) + } + + #[inline] + fn update(&mut self, data: &[u8]) { + Update::update(self, data); + } + + #[inline] + fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self { + Update::update(&mut self, data.as_ref()); + self + } + + #[inline] + fn finalize(self) -> CtOutput { + CtOutput::new(self.finalize_fixed()) + } + + #[inline(always)] + fn finalize_reset(&mut self) -> CtOutput + where + Self: FixedOutputReset, + { + CtOutput::new(self.finalize_fixed_reset()) + } + + #[inline] + fn reset(&mut self) + where + Self: Reset, + { + Reset::reset(self) + } + + #[inline] + fn verify(self, tag: &Output) -> Result<(), MacError> { + if self.finalize() == tag.into() { + Ok(()) + } else { + Err(MacError) + } + } + + #[inline] + fn verify_reset(&mut self, tag: &Output) -> Result<(), MacError> + where + Self: FixedOutputReset, + { + if self.finalize_reset() == tag.into() { + Ok(()) + } else { + Err(MacError) + } + } + + #[inline] + fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> { + let n = tag.len(); + if n != Self::OutputSize::USIZE { + return Err(MacError); + } + let choice = self.finalize_fixed().ct_eq(tag); + if choice.into() { + Ok(()) + } else { + Err(MacError) + } + } + + #[inline] + fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError> + where + Self: FixedOutputReset, + { + let n = tag.len(); + if n != Self::OutputSize::USIZE { + return Err(MacError); + } + let choice = self.finalize_fixed_reset().ct_eq(tag); + if choice.into() { + Ok(()) + } else { + Err(MacError) + } + } + + fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> { + let n = tag.len(); + if n == 0 || n > Self::OutputSize::USIZE { + return Err(MacError); + } + let choice = self.finalize_fixed()[..n].ct_eq(tag); + + if choice.into() { + Ok(()) + } else { + Err(MacError) + } + } + + fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError> { + let n = tag.len(); + if n == 0 || n > Self::OutputSize::USIZE { + return Err(MacError); + } + let m = Self::OutputSize::USIZE - n; + let choice = self.finalize_fixed()[m..].ct_eq(tag); + + if choice.into() { + Ok(()) + } else { + Err(MacError) + } + } + + #[cfg(feature = "rand_core")] + #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] + #[inline] + fn generate_key(rng: impl CryptoRng + RngCore) -> Key + where + Self: KeyInit, + { + ::generate_key(rng) + } +} + +/// Fixed size output value which provides a safe [`Eq`] implementation that +/// runs in constant time. +/// +/// It is useful for implementing Message Authentication Codes (MACs). +#[derive(Clone)] +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +pub struct CtOutput { + bytes: Output, +} + +impl CtOutput { + /// Create a new [`CtOutput`] value. + #[inline(always)] + pub fn new(bytes: Output) -> Self { + Self { bytes } + } + + /// Get the inner [`Output`] array this type wraps. + #[inline(always)] + pub fn into_bytes(self) -> Output { + self.bytes + } +} + +impl From> for CtOutput { + #[inline(always)] + fn from(bytes: Output) -> Self { + Self { bytes } + } +} + +impl<'a, T: OutputSizeUser> From<&'a Output> for CtOutput { + #[inline(always)] + fn from(bytes: &'a Output) -> Self { + bytes.clone().into() + } +} + +impl ConstantTimeEq for CtOutput { + #[inline(always)] + fn ct_eq(&self, other: &Self) -> Choice { + self.bytes.ct_eq(&other.bytes) + } +} + +impl PartialEq for CtOutput { + #[inline(always)] + fn eq(&self, x: &CtOutput) -> bool { + self.ct_eq(x).into() + } +} + +impl Eq for CtOutput {} + +/// Error type for when the [`Output`] of a [`Mac`] +/// is not equal to the expected value. +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] +#[cfg_attr(docsrs, doc(cfg(feature = "mac")))] +pub struct MacError; + +impl fmt::Display for MacError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("MAC tag mismatch") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MacError {} diff --git a/anneal/v2/vendor/either/.cargo-checksum.json b/anneal/v2/vendor/either/.cargo-checksum.json new file mode 100644 index 0000000000..9915491767 --- /dev/null +++ b/anneal/v2/vendor/either/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo_vcs_info.json":"3f0041c1992d886f8f19441bd5fd859e3a68cbc9f91d006494ec4bd587653bfc",".github/workflows/ci.yml":"d2da89285c13788a6a355b9ad5fdd84941b3982e395270cb809b64d9be8c9c1f","Cargo.lock":"47e4ddc10d96119e10d5172d19a7eef277f18e93c7a9e7a48e28f0e822b422fa","Cargo.toml":"1f4d971b97901d1420a508ca4c9cc7ec3e2114c782500e5192801509cf043725","Cargo.toml.orig":"f82350f4effc4946b40f8d37e3db28488319cf4def755d00f5687f7cf768621a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README-crates.io.md":"b775991a01ab4a0a8de6169f597775319d9ce8178f5c74ccdc634f13a286b20c","README.rst":"01c248679713f4109b8aedb904bb79edef054e477fce9ab260921b1c0861c70a","src/into_either.rs":"0477f226bbba78ef017de08b87d421d3cd99fbc95b90ba4e6e3e803e3d15254e","src/iterator.rs":"3dd8a1255e1448eeee20b24de849523a13ca0d3c178b81d1d5adc6220ca692c4","src/lib.rs":"481ca250233811a5ccbff9a9fc7c2acb15287aede47d8ec280484fe5209e2ad7","src/serde_untagged.rs":"5f7a4035ca164125a433f42ac0949185d1732e2fcf5b1ac6dfca1e5aede439bb","src/serde_untagged_optional.rs":"ba5d6c2213388b69e127e763b6e394de6388bdd682ffb5d5696b068f1938ec79"},"package":"91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"} \ No newline at end of file diff --git a/anneal/v2/vendor/either/.cargo_vcs_info.json b/anneal/v2/vendor/either/.cargo_vcs_info.json new file mode 100644 index 0000000000..148bd94dd5 --- /dev/null +++ b/anneal/v2/vendor/either/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8f4ecd9964ea909a7f989a3668a2710310a0e62f" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/anneal/v2/vendor/either/.github/workflows/ci.yml b/anneal/v2/vendor/either/.github/workflows/ci.yml new file mode 100644 index 0000000000..1c6dbb0a5e --- /dev/null +++ b/anneal/v2/vendor/either/.github/workflows/ci.yml @@ -0,0 +1,90 @@ +on: + push: + branches: [ main ] + pull_request: + merge_group: + +name: CI + +jobs: + ci: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + rust: + - 1.63.0 # MSRV + - stable + - beta + - nightly + features: + - "" + - "serde" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache the registry + uses: actions/cache@v4 + if: startsWith(matrix.rust, '1') + with: + path: ~/.cargo/registry/index + key: cargo-${{ matrix.rust }}-git-index + + - name: Lock MSRV-compatible dependencies + if: startsWith(matrix.rust, '1') + env: + CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback + # Note that this uses the runner's pre-installed stable cargo + run: cargo generate-lockfile + + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Build (no_std) + run: cargo build --no-default-features --features "${{ matrix.features }}" + + - name: Build + run: cargo build --features "${{ matrix.features }}" + + - name: Test + run: cargo test --features "${{ matrix.features }}" + + - name: Doc + run: cargo doc --features "${{ matrix.features }}" + + clippy: + name: Rustfmt and Clippy + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up nightly Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt, clippy + + - name: Rustfmt + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy # -- -D warnings + + # One job that "summarizes" the success state of this pipeline. This can then be added to branch + # protection, rather than having to add each job separately. + success: + name: Success + runs-on: ubuntu-latest + needs: [ci, clippy] + # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency + # failed" as success. So we have to do some contortions to ensure the job fails if any of its + # dependencies fails. + if: always() # make sure this is never "skipped" + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: check if any dependency failed + run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/anneal/v2/vendor/either/Cargo.lock b/anneal/v2/vendor/either/Cargo.lock new file mode 100644 index 0000000000..3064f8b7e5 --- /dev/null +++ b/anneal/v2/vendor/either/Cargo.lock @@ -0,0 +1,89 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "either" +version = "1.16.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "proc-macro2" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/anneal/v2/vendor/either/Cargo.toml b/anneal/v2/vendor/either/Cargo.toml new file mode 100644 index 0000000000..15de8104b8 --- /dev/null +++ b/anneal/v2/vendor/either/Cargo.toml @@ -0,0 +1,69 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.63.0" +name = "either" +version = "1.16.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +The enum `Either` with variants `Left` and `Right` is a general purpose sum type with two cases. +""" +documentation = "https://docs.rs/either/1/" +readme = "README-crates.io.md" +keywords = [ + "data-structure", + "no_std", +] +categories = [ + "data-structures", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rayon-rs/either" + +[package.metadata.release] +allow-branch = ["main"] +sign-tag = true +tag-name = "{{version}}" + +[package.metadata.docs.rs] +features = ["serde"] + +[package.metadata.playground] +features = ["serde"] + +[features] +default = ["std"] +std = [] +use_std = ["std"] + +[lib] +name = "either" +path = "src/lib.rs" + +[dependencies.serde] +version = "1.0.95" +features = [ + "alloc", + "derive", +] +optional = true +default-features = false + +[dev-dependencies.serde_json] +version = "1.0.0" diff --git a/anneal/v2/vendor/either/Cargo.toml.orig b/anneal/v2/vendor/either/Cargo.toml.orig new file mode 100644 index 0000000000..fc46d174ec --- /dev/null +++ b/anneal/v2/vendor/either/Cargo.toml.orig @@ -0,0 +1,39 @@ +[package] +name = "either" +version = "1.16.0" +edition = "2021" +rust-version = "1.63.0" + +license = "MIT OR Apache-2.0" +repository = "https://github.com/rayon-rs/either" +documentation = "https://docs.rs/either/1/" +readme = "README-crates.io.md" + +description = """ +The enum `Either` with variants `Left` and `Right` is a general purpose sum type with two cases. +""" + +keywords = ["data-structure", "no_std"] +categories = ["data-structures", "no-std"] + +[dependencies] +serde = { version = "1.0.95", optional = true, default-features = false, features = ["alloc", "derive"] } + +[features] +default = ["std"] +std = [] +use_std = ["std"] # deprecated alias + +[dev-dependencies] +serde_json = "1.0.0" + +[package.metadata.release] +allow-branch = ["main"] +sign-tag = true +tag-name = "{{version}}" + +[package.metadata.docs.rs] +features = ["serde"] + +[package.metadata.playground] +features = ["serde"] diff --git a/anneal/v2/vendor/either/LICENSE-APACHE b/anneal/v2/vendor/either/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/anneal/v2/vendor/either/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/anneal/v2/vendor/either/LICENSE-MIT b/anneal/v2/vendor/either/LICENSE-MIT new file mode 100644 index 0000000000..9203baa055 --- /dev/null +++ b/anneal/v2/vendor/either/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2015 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/anneal/v2/vendor/either/README-crates.io.md b/anneal/v2/vendor/either/README-crates.io.md new file mode 100644 index 0000000000..d36890278b --- /dev/null +++ b/anneal/v2/vendor/either/README-crates.io.md @@ -0,0 +1,10 @@ +The enum `Either` with variants `Left` and `Right` is a general purpose +sum type with two cases. + +Either has methods that are similar to Option and Result, and it also implements +traits like `Iterator`. + +Includes macros `try_left!()` and `try_right!()` to use for +short-circuiting logic, similar to how the `?` operator is used with `Result`. +Note that `Either` is general purpose. For describing success or error, use the +regular `Result`. diff --git a/anneal/v2/vendor/either/README.rst b/anneal/v2/vendor/either/README.rst new file mode 100644 index 0000000000..10f392a75b --- /dev/null +++ b/anneal/v2/vendor/either/README.rst @@ -0,0 +1,220 @@ + +Either +====== + +The enum ``Either`` with variants ``Left`` and ``Right`` and trait +implementations including Iterator, Read, Write. + +Either has methods that are similar to Option and Result. + +Includes convenience macros ``try_left!()`` and ``try_right!()`` to use for +short-circuiting logic. + +Please read the `API documentation here`__ + +__ https://docs.rs/either/ + +|build_status|_ |crates|_ + +.. |build_status| image:: https://github.com/rayon-rs/either/workflows/CI/badge.svg?branch=main +.. _build_status: https://github.com/rayon-rs/either/actions + +.. |crates| image:: https://img.shields.io/crates/v/either.svg +.. _crates: https://crates.io/crates/either + +How to use with cargo:: + + [dependencies] + either = "1" + + +Recent Changes +-------------- + +- 1.16.0 + + - Add many new methods dealing with each side, by @A4-Tacks: + + - ``inspect_left`` and ``inspect_right`` (#124) + + - ``left_and`` and ``right_and`` (#125) + + - ``is_left_and`` and ``is_right_and`` (#126) + + - ``map_left_or`` and ``map_right_or`` (#127) + + - Add a version of ``for_both!`` with a single ``ident``, by @A4-Tacks (#128) + + - Add a ``map_both!`` macro, by @JohnScience (#109) and @ronnodas (#137) + +- 1.15.0 + + - Fix ``serde`` support when building without ``std``, by @klkvr (#119) + + - Use a more common ``std`` feature for default enablement, deprecating + the ``use_std`` feature as a mere alias of the new name. + +- 1.14.0 + + - **MSRV**: ``either`` now requires Rust 1.63 or later. + + - Implement ``fmt::Write`` for ``Either``, by @yotamofek (#113) + + - Replace ``Into for Either`` with ``From for Result``, by @cuviper (#118) + +- 1.13.0 + + - Add new methods ``.cloned()`` and ``.copied()``, by @ColonelThirtyTwo (#107) + +- 1.12.0 + + - **MSRV**: ``either`` now requires Rust 1.37 or later. + + - Specialize ``nth_back`` for ``Either`` and ``IterEither``, by @cuviper (#106) + +- 1.11.0 + + - Add new trait ``IntoEither`` that is useful to convert to ``Either`` in method chains, + by @SFM61319 (#101) + +- 1.10.0 + + - Add new methods ``.factor_iter()``, ``.factor_iter_mut()``, and ``.factor_into_iter()`` + that return ``Either`` items, plus ``.iter()`` and ``.iter_mut()`` to convert to direct + reference iterators; by @aj-bagwell and @cuviper (#91) + +- 1.9.0 + + - Add new methods ``.map_either()`` and ``.map_either_with()``, by @nasadorian (#82) + +- 1.8.1 + + - Clarified that the multiple licenses are combined with OR. + +- 1.8.0 + + - **MSRV**: ``either`` now requires Rust 1.36 or later. + + - Add new methods ``.as_pin_ref()`` and ``.as_pin_mut()`` to project a + pinned ``Either`` as inner ``Pin`` variants, by @cuviper (#77) + + - Implement the ``Future`` trait, by @cuviper (#77) + + - Specialize more methods of the ``io`` traits, by @Kixunil and @cuviper (#75) + +- 1.7.0 + + - **MSRV**: ``either`` now requires Rust 1.31 or later. + + - Export the macro ``for_both!``, by @thomaseizinger (#58) + + - Implement the ``io::Seek`` trait, by @Kerollmops (#60) + + - Add new method ``.either_into()`` for ``Into`` conversion, by @TonalidadeHidrica (#63) + + - Add new methods ``.factor_ok()``, ``.factor_err()``, and ``.factor_none()``, + by @zachs18 (#67) + + - Specialize ``source`` in the ``Error`` implementation, by @thomaseizinger (#69) + + - Specialize more iterator methods and implement the ``FusedIterator`` trait, + by @Ten0 (#66) and @cuviper (#71) + + - Specialize ``Clone::clone_from``, by @cuviper (#72) + +- 1.6.1 + + - Add new methods ``.expect_left()``, ``.unwrap_left()``, + and equivalents on the right, by @spenserblack (#51) + +- 1.6.0 + + - Add new modules ``serde_untagged`` and ``serde_untagged_optional`` to customize + how ``Either`` fields are serialized in other types, by @MikailBag (#49) + +- 1.5.3 + + - Add new method ``.map()`` for ``Either`` by @nvzqz (#40). + +- 1.5.2 + + - Add new methods ``.left_or()``, ``.left_or_default()``, ``.left_or_else()``, + and equivalents on the right, by @DCjanus (#36) + +- 1.5.1 + + - Add ``AsRef`` and ``AsMut`` implementations for common unsized types: + ``str``, ``[T]``, ``CStr``, ``OsStr``, and ``Path``, by @mexus (#29) + +- 1.5.0 + + - Add new methods ``.factor_first()``, ``.factor_second()`` and ``.into_inner()`` + by @mathstuf (#19) + +- 1.4.0 + + - Add inherent method ``.into_iter()`` by @cuviper (#12) + +- 1.3.0 + + - Add opt-in serde support by @hcpl + +- 1.2.0 + + - Add method ``.either_with()`` by @Twey (#13) + +- 1.1.0 + + - Add methods ``left_and_then``, ``right_and_then`` by @rampantmonkey + - Include license files in the repository and released crate + +- 1.0.3 + + - Add crate categories + +- 1.0.2 + + - Forward more ``Iterator`` methods + - Implement ``Extend`` for ``Either`` if ``L, R`` do. + +- 1.0.1 + + - Fix ``Iterator`` impl for ``Either`` to forward ``.fold()``. + +- 1.0.0 + + - Add default crate feature ``use_std`` so that you can opt out of linking to + std. + +- 0.1.7 + + - Add methods ``.map_left()``, ``.map_right()`` and ``.either()``. + - Add more documentation + +- 0.1.3 + + - Implement Display, Error + +- 0.1.2 + + - Add macros ``try_left!`` and ``try_right!``. + +- 0.1.1 + + - Implement Deref, DerefMut + +- 0.1.0 + + - Initial release + - Support Iterator, Read, Write + +License +------- + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +https://www.apache.org/licenses/LICENSE-2.0 or the MIT license +https://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. diff --git a/anneal/v2/vendor/either/src/into_either.rs b/anneal/v2/vendor/either/src/into_either.rs new file mode 100644 index 0000000000..73746c80f1 --- /dev/null +++ b/anneal/v2/vendor/either/src/into_either.rs @@ -0,0 +1,64 @@ +//! The trait [`IntoEither`] provides methods for converting a type `Self`, whose +//! size is constant and known at compile-time, into an [`Either`] variant. + +use super::{Either, Left, Right}; + +/// Provides methods for converting a type `Self` into either a [`Left`] or [`Right`] +/// variant of [`Either`](Either). +/// +/// The [`into_either`](IntoEither::into_either) method takes a [`bool`] to determine +/// whether to convert to [`Left`] or [`Right`]. +/// +/// The [`into_either_with`](IntoEither::into_either_with) method takes a +/// [predicate function](FnOnce) to determine whether to convert to [`Left`] or [`Right`]. +pub trait IntoEither: Sized { + /// Converts `self` into a [`Left`] variant of [`Either`](Either) + /// if `into_left` is `true`. + /// Converts `self` into a [`Right`] variant of [`Either`](Either) + /// otherwise. + /// + /// # Examples + /// + /// ``` + /// use either::{IntoEither, Left, Right}; + /// + /// let x = 0; + /// assert_eq!(x.into_either(true), Left(x)); + /// assert_eq!(x.into_either(false), Right(x)); + /// ``` + fn into_either(self, into_left: bool) -> Either { + if into_left { + Left(self) + } else { + Right(self) + } + } + + /// Converts `self` into a [`Left`] variant of [`Either`](Either) + /// if `into_left(&self)` returns `true`. + /// Converts `self` into a [`Right`] variant of [`Either`](Either) + /// otherwise. + /// + /// # Examples + /// + /// ``` + /// use either::{IntoEither, Left, Right}; + /// + /// fn is_even(x: &u8) -> bool { + /// x % 2 == 0 + /// } + /// + /// let x = 0; + /// assert_eq!(x.into_either_with(is_even), Left(x)); + /// assert_eq!(x.into_either_with(|x| !is_even(x)), Right(x)); + /// ``` + fn into_either_with(self, into_left: F) -> Either + where + F: FnOnce(&Self) -> bool, + { + let into_left = into_left(&self); + self.into_either(into_left) + } +} + +impl IntoEither for T {} diff --git a/anneal/v2/vendor/either/src/iterator.rs b/anneal/v2/vendor/either/src/iterator.rs new file mode 100644 index 0000000000..a5535f0530 --- /dev/null +++ b/anneal/v2/vendor/either/src/iterator.rs @@ -0,0 +1,315 @@ +use super::{Either, Left, Right}; +use core::iter; + +macro_rules! wrap_either { + ($value:expr => $( $tail:tt )*) => { + match $value { + Left(inner) => inner.map(Left) $($tail)*, + Right(inner) => inner.map(Right) $($tail)*, + } + }; +} + +/// Iterator that maps left or right iterators to corresponding `Either`-wrapped items. +/// +/// This struct is created by the [`Either::factor_into_iter`], +/// [`factor_iter`][Either::factor_iter], +/// and [`factor_iter_mut`][Either::factor_iter_mut] methods. +#[derive(Clone, Debug)] +pub struct IterEither { + inner: Either, +} + +impl IterEither { + pub(crate) fn new(inner: Either) -> Self { + IterEither { inner } + } +} + +impl Extend for Either +where + L: Extend, + R: Extend, +{ + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + for_both!(self, inner => inner.extend(iter)) + } +} + +/// `Either` is an iterator if both `L` and `R` are iterators. +impl Iterator for Either +where + L: Iterator, + R: Iterator, +{ + type Item = L::Item; + + fn next(&mut self) -> Option { + for_both!(self, inner => inner.next()) + } + + fn size_hint(&self) -> (usize, Option) { + for_both!(self, inner => inner.size_hint()) + } + + fn fold(self, init: Acc, f: G) -> Acc + where + G: FnMut(Acc, Self::Item) -> Acc, + { + for_both!(self, inner => inner.fold(init, f)) + } + + fn for_each(self, f: F) + where + F: FnMut(Self::Item), + { + for_both!(self, inner => inner.for_each(f)) + } + + fn count(self) -> usize { + for_both!(self, inner => inner.count()) + } + + fn last(self) -> Option { + for_both!(self, inner => inner.last()) + } + + fn nth(&mut self, n: usize) -> Option { + for_both!(self, inner => inner.nth(n)) + } + + fn collect(self) -> B + where + B: iter::FromIterator, + { + for_both!(self, inner => inner.collect()) + } + + fn partition(self, f: F) -> (B, B) + where + B: Default + Extend, + F: FnMut(&Self::Item) -> bool, + { + for_both!(self, inner => inner.partition(f)) + } + + fn all(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + for_both!(self, inner => inner.all(f)) + } + + fn any(&mut self, f: F) -> bool + where + F: FnMut(Self::Item) -> bool, + { + for_both!(self, inner => inner.any(f)) + } + + fn find