cxx-1.0.141/.bazelignore000064400000000000000000000000321046102023000130670ustar 00000000000000target/ tools/buck/buck2/ cxx-1.0.141/.bazelrc000064400000000000000000000002561046102023000122200ustar 00000000000000build --enable_platform_specific_config build:linux --@rules_rust//:extra_rustc_flags=-Clink-arg=-fuse-ld=lld build:linux --cxxopt=-std=c++17 build:macos --cxxopt=-std=c++17 cxx-1.0.141/.buckconfig000064400000000000000000000013001046102023000126770ustar 00000000000000[cells] root = . prelude = tools/buck/prelude toolchains = tools/buck/toolchains none = none [external_cells] prelude = bundled [cell_aliases] config = prelude fbcode = none fbsource = none [project] # Hide BUCK files under target/package/ from `buck build ...`. Otherwise: # $ buck build ... # //target/package/cxx-0.3.0/tests:ffi references non-existing file or directory 'target/package/cxx-0.3.0/tests/ffi/lib.rs' # # Also hide some Bazel-managed directories that contain symlinks to the repo root. ignore = \ .git, \ bazel-bin, \ bazel-cxx, \ bazel-out, \ bazel-testlogs, \ target [parser] target_platform_detector_spec = target:root//...->prelude//platforms:default cxx-1.0.141/.buckroot000064400000000000000000000000001046102023000124110ustar 00000000000000cxx-1.0.141/.cargo_vcs_info.json0000644000000001360000000000100120020ustar { "git": { "sha1": "926094db8792e43cc0e3f33b422f6319dbd2cfff" }, "path_in_vcs": "" }cxx-1.0.141/.clang-format000064400000000000000000000001231046102023000131410ustar 00000000000000AlwaysBreakTemplateDeclarations: true MaxEmptyLinesToKeep: 3 ReflowComments: false cxx-1.0.141/.clang-tidy000064400000000000000000000013101046102023000126210ustar 00000000000000Checks: clang-analyzer-*, clang-diagnostic-*, cppcoreguidelines-*, modernize-*, -cppcoreguidelines-avoid-const-or-ref-data-members, -cppcoreguidelines-macro-usage, -cppcoreguidelines-owning-memory, -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-pro-type-const-cast, -cppcoreguidelines-pro-type-member-init, -cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-type-vararg, -cppcoreguidelines-special-member-functions, -modernize-return-braced-init-list, -modernize-use-default-member-init, -modernize-use-equals-default, -modernize-use-trailing-return-type, HeaderFilterRegex: cxx\.h cxx-1.0.141/.devcontainer/Dockerfile000064400000000000000000000000411046102023000153160ustar 00000000000000FROM dtolnay/devcontainer:latest cxx-1.0.141/.devcontainer/README.md000064400000000000000000000002321046102023000146050ustar 00000000000000This directory contains the container setup used when developing CXX inside of GitHub [Codespaces]. [Codespaces]: https://github.com/features/codespaces cxx-1.0.141/.devcontainer/build.Dockerfile000064400000000000000000000015231046102023000164220ustar 00000000000000FROM mcr.microsoft.com/devcontainers/rust:bookworm RUN apt-get update \ && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends clang lld zstd \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && wget -q -O /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 \ && wget -q -O /tmp/buck.zst https://github.com/facebook/buck2/releases/download/latest/buck2-x86_64-unknown-linux-gnu.zst \ && wget -q -O /usr/local/bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier-linux-amd64 \ && unzstd /tmp/buck.zst -o /usr/local/bin/buck \ && chmod +x /usr/local/bin/bazel /usr/local/bin/buck /usr/local/bin/buildifier \ && rm /tmp/buck.zst \ && rustup component add rust-analyzer rust-src cxx-1.0.141/.devcontainer/devcontainer.json000064400000000000000000000010101046102023000166750ustar 00000000000000{ "name": "Rust", "build": { "dockerfile": "Dockerfile" }, "runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"], "settings": { "terminal.integrated.shell.linux": "/bin/bash", "lldb.executable": "/usr/bin/lldb", "files.watcherExclude": { "**/target/**": true } }, "extensions": [ "BazelBuild.vscode-bazel", "ms-vscode.cpptools", "rust-lang.rust-analyzer", "vadimcn.vscode-lldb" ] } cxx-1.0.141/.gitattributes000064400000000000000000000001611046102023000134630ustar 00000000000000MODULE.bazel.lock linguist-generated third-party/BUCK linguist-generated third-party/bazel/** linguist-generated cxx-1.0.141/.github/FUNDING.yml000064400000000000000000000000201046102023000137370ustar 00000000000000github: dtolnay cxx-1.0.141/.github/workflows/buck2.yml000064400000000000000000000012461046102023000157230ustar 00000000000000name: Buck2 on: push: workflow_dispatch: schedule: [cron: "40 1,13 * * *"] permissions: contents: read jobs: buck2: name: Buck2 on ${{matrix.os == 'ubuntu' && 'Linux' || matrix.os == 'macos' && 'macOS' || matrix.os == 'windows' && 'Windows' || '???'}} runs-on: ${{matrix.os}}-latest strategy: fail-fast: false matrix: os: [ubuntu, macos, windows] timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rust-src - uses: dtolnay/install-buck2@latest - run: buck2 run demo - run: buck2 build ... - run: buck2 test ... cxx-1.0.141/.github/workflows/ci.yml000064400000000000000000000163321046102023000153120ustar 00000000000000name: CI on: push: pull_request: workflow_dispatch: schedule: [cron: "40 1 * * *"] permissions: contents: read jobs: pre_ci: uses: dtolnay/.github/.github/workflows/pre_ci.yml@master test: name: ${{matrix.name || format('Rust {0}', matrix.rust)}} needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ${{matrix.os}}-latest strategy: fail-fast: false matrix: rust: [nightly, beta, stable, 1.82.0, 1.77.0, 1.74.0, 1.73.0] os: [ubuntu] flags: [''] include: - name: Cargo on macOS rust: nightly os: macos - name: Cargo on Windows (msvc) rust: nightly-x86_64-pc-windows-msvc os: windows flags: /EHsc - name: C++14 rust: nightly os: ubuntu flags: -std=c++14 - name: C++17 rust: nightly os: ubuntu flags: -std=c++17 - name: C++20 rust: nightly os: ubuntu flags: -std=c++20 env: CXXFLAGS: ${{matrix.flags}} RUSTFLAGS: --cfg deny_warnings -Dwarnings timeout-minutes: 45 steps: - name: Enable symlinks (windows) if: matrix.os == 'windows' run: git config --global core.symlinks true - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} components: rust-src - name: Determine test suite subset # Our Windows and macOS jobs are the longest running, so exclude the # relatively slow compiletest from them to speed up end-to-end CI time, # except during cron builds when no human is presumably waiting on the # build. The extra coverage is not particularly valuable and we can # still ensure the test is kept passing on the basis of the scheduled # builds. run: | echo RUSTFLAGS=$RUSTFLAGS >> $GITHUB_ENV echo exclude=--exclude cxx-test-suite ${{matrix.rust == '1.73.0' && '--exclude cxxbridge-cmd' || ''}} >> $GITHUB_OUTPUT env: RUSTFLAGS: ${{env.RUSTFLAGS}} ${{matrix.os != 'ubuntu' && github.event_name != 'schedule' && '--cfg skip_ui_tests' || ''}} id: testsuite shell: bash - name: Ignore macOS linker warning run: echo RUSTFLAGS=${RUSTFLAGS}\ -Alinker_messages >> $GITHUB_ENV if: matrix.os == 'macos' - run: cargo run --manifest-path demo/Cargo.toml - run: cargo test --workspace ${{steps.testsuite.outputs.exclude}} if: matrix.rust != '1.74.0' && matrix.rust != '1.73.0' - run: cargo check --no-default-features --features alloc env: RUSTFLAGS: --cfg compile_error_if_std ${{env.RUSTFLAGS}} - run: cargo check --no-default-features env: RUSTFLAGS: --cfg compile_error_if_alloc --cfg cxx_experimental_no_alloc ${{env.RUSTFLAGS}} - uses: actions/upload-artifact@v4 if: matrix.os == 'ubuntu' && matrix.rust == 'nightly' && always() with: name: Cargo.lock path: Cargo.lock continue-on-error: true reindeer: name: Reindeer runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rust-src - uses: dtolnay/install@reindeer - run: reindeer buckify working-directory: third-party - name: Check reindeer-generated BUCK file up to date run: git diff --exit-code bazel: name: Bazel on ${{matrix.os == 'ubuntu' && 'Linux' || matrix.os == 'macos' && 'macOS' || matrix.os == 'windows' && 'Windows' || '???'}} runs-on: ${{matrix.os}}-latest if: github.event_name != 'pull_request' strategy: fail-fast: false matrix: os: [ubuntu, macos, windows] timeout-minutes: 45 steps: - uses: actions/checkout@v4 - name: Install lld run: sudo apt-get install lld if: matrix.os == 'ubuntu' - run: bazel --version - run: bazel run demo --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}} continue-on-error: ${{matrix.os == 'windows'}} # https://github.com/bazelbuild/bazel/issues/18592 - run: bazel test ... --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}} continue-on-error: ${{matrix.os == 'windows'}} # https://github.com/bazelbuild/bazel/issues/18592 - name: Check MODULE.bazel.lock up to date run: git diff --exit-code if: matrix.os == 'ubuntu' || matrix.os == 'macos' - run: bazel run //third-party:vendor if: matrix.os == 'ubuntu' || matrix.os == 'macos' - name: Check third-party/bazel up to date run: git diff --exit-code if: matrix.os == 'ubuntu' || matrix.os == 'macos' minimal: name: Minimal versions needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked --workspace doc: name: Documentation needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 env: RUSTDOCFLAGS: -Dwarnings steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly with: components: rust-src - uses: dtolnay/install@cargo-docs-rs - run: cargo docs-rs - run: cargo docs-rs -p cxx-build - run: cargo docs-rs -p cxx-gen - run: cargo docs-rs -p cxxbridge-flags - run: cargo docs-rs -p cxxbridge-macro clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 env: RUSTFLAGS: -Dwarnings steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly with: components: clippy, rust-src - run: cargo clippy --workspace --tests --exclude demo -- -Dclippy::all -Dclippy::pedantic - run: cargo clippy --manifest-path demo/Cargo.toml -- -Dclippy::all clang-tidy: name: Clang Tidy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - name: Install clang-tidy run: sudo apt-get install clang-tidy-18 - name: Run clang-tidy run: clang-tidy-18 src/cxx.cc --warnings-as-errors=* eslint: name: ESLint runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - run: npm install working-directory: book - run: npx eslint working-directory: book outdated: name: Outdated runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 cxx-1.0.141/.github/workflows/install.yml000064400000000000000000000004341046102023000163610ustar 00000000000000name: Install on: workflow_dispatch: schedule: [cron: "40 1 * * *"] push: {tags: ['*']} permissions: {} env: RUSTFLAGS: -Dwarnings jobs: install: name: Install uses: dtolnay/.github/.github/workflows/check_install.yml@master with: crate: cxxbridge-cmd cxx-1.0.141/.github/workflows/site.yml000064400000000000000000000016331046102023000156610ustar 00000000000000name: Deploy on: push: branches: - master paths: - book/** - .github/workflows/site.yml workflow_dispatch: jobs: deploy: name: Deploy runs-on: ubuntu-latest permissions: contents: write timeout-minutes: 30 steps: - uses: actions/checkout@v4 - uses: dtolnay/install@mdbook - run: mdbook --version - name: Build run: book/build.sh - name: Push to gh-pages working-directory: book/build run: | REV=$(git rev-parse --short HEAD) git init git remote add upstream https://x-access-token:${{secrets.GITHUB_TOKEN}}@github.com/dtolnay/cxx git config user.name "CXX" git config user.email "dtolnay+cxx@gmail.com" git add -A . git commit -qm "Website @ ${{github.repository}}@${REV}" git push -q upstream HEAD:refs/heads/gh-pages --force cxx-1.0.141/.gitignore000064400000000000000000000001561046102023000125640ustar 00000000000000/.buckd /bazel-bin /bazel-cxx /bazel-out /bazel-testlogs /buck-out /expand.cc /expand.rs /target/ /Cargo.lock cxx-1.0.141/.vscode/README.md000064400000000000000000000002271046102023000134130ustar 00000000000000VS Code actions and configuration. Applicable when developing CXX inside of GitHub [Codespaces]. [Codespaces]: https://github.com/features/codespaces cxx-1.0.141/.vscode/launch.json000064400000000000000000000013241046102023000143000ustar 00000000000000{ "version": "0.2.0", "configurations": [ { "name": "Run cxx demo", "type": "lldb", "request": "launch", "cargo": { "args": ["build", "--manifest-path", "demo/Cargo.toml"], "filter": { "name": "demo", "kind": "bin" } } }, { "name": "Debug cargo tests", "type": "lldb", "request": "launch", "cargo": { "args": ["test", "--no-run"], "filter": { "name": "test", "kind": "test" } } } ] } cxx-1.0.141/.vscode/settings.json000064400000000000000000000000741046102023000146670ustar 00000000000000{ "search.exclude": { "**/target": true } } cxx-1.0.141/.vscode/tasks.json000064400000000000000000000014051046102023000141530ustar 00000000000000{ "version": "2.0.0", "tasks": [ { "label": "Cargo test", "type": "shell", "command": "cargo test", "group": "test" }, { "label": "Bazel test", "type": "shell", "command": "bazel test ...", "group": "test", "dependsOn": ["Vendor"] }, { "label": "Buck test", "type": "shell", "command": "buck test ...", "group": "test", "dependsOn": ["Vendor"] }, { "label": "Vendor", "type": "shell", "command": "cp third-party/Cargo.lock . && cargo vendor --versioned-dirs --locked third-party/vendor" } ] } cxx-1.0.141/.watchmanconfig000064400000000000000000000000441046102023000135610ustar 00000000000000{ "ignore_dirs": ["buck-out"] } cxx-1.0.141/BUCK000064400000000000000000000041251046102023000112430ustar 00000000000000rust_library( name = "cxx", srcs = glob(["src/**/*.rs"]), doc_deps = [ ":cxx-build", ], edition = "2021", features = [ "alloc", "std", ], visibility = ["PUBLIC"], deps = [ ":core", ":cxxbridge-macro", "//third-party:foldhash", ], ) alias( name = "codegen", actual = ":cxxbridge", visibility = ["PUBLIC"], ) rust_binary( name = "cxxbridge", srcs = glob(["gen/cmd/src/**/*.rs"]) + [ "gen/cmd/src/gen", "gen/cmd/src/syntax", ], edition = "2021", deps = [ "//third-party:clap", "//third-party:codespan-reporting", "//third-party:proc-macro2", "//third-party:quote", "//third-party:syn", ], ) cxx_library( name = "core", srcs = ["src/cxx.cc"], exported_headers = { "cxx.h": "include/cxx.h", }, header_namespace = "rust", preferred_linkage = "static", visibility = ["PUBLIC"], ) rust_library( name = "cxxbridge-macro", srcs = glob(["macro/src/**/*.rs"]) + ["macro/src/syntax"], doctests = False, edition = "2021", proc_macro = True, deps = [ "//third-party:proc-macro2", "//third-party:quote", "//third-party:rustversion", "//third-party:syn", ], ) rust_library( name = "cxx-build", srcs = glob(["gen/build/src/**/*.rs"]) + [ "gen/build/src/gen", "gen/build/src/syntax", ], doctests = False, edition = "2021", deps = [ "//third-party:cc", "//third-party:codespan-reporting", "//third-party:proc-macro2", "//third-party:quote", "//third-party:scratch", "//third-party:syn", ], ) rust_library( name = "cxx-gen", srcs = glob(["gen/lib/src/**/*.rs"]) + [ "gen/lib/src/gen", "gen/lib/src/syntax", ], edition = "2021", visibility = ["PUBLIC"], deps = [ "//third-party:cc", "//third-party:codespan-reporting", "//third-party:proc-macro2", "//third-party:quote", "//third-party:syn", ], ) cxx-1.0.141/BUILD.bazel000064400000000000000000000042621046102023000124540ustar 00000000000000load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro") rust_library( name = "cxx", srcs = glob(["src/**/*.rs"]), crate_features = [ "alloc", "std", ], edition = "2021", proc_macro_deps = [ ":cxxbridge-macro", ], visibility = ["//visibility:public"], deps = [ ":core-lib", "@crates.io//:foldhash", ], ) alias( name = "codegen", actual = ":cxxbridge", visibility = ["//visibility:public"], ) rust_binary( name = "cxxbridge", srcs = glob(["gen/cmd/src/**/*.rs"]), compile_data = ["gen/cmd/src/gen/include/cxx.h"], edition = "2021", deps = [ "@crates.io//:clap", "@crates.io//:codespan-reporting", "@crates.io//:proc-macro2", "@crates.io//:quote", "@crates.io//:syn", ], ) cc_library( name = "core", hdrs = ["include/cxx.h"], include_prefix = "rust", strip_include_prefix = "include", visibility = ["//visibility:public"], ) cc_library( name = "core-lib", srcs = ["src/cxx.cc"], hdrs = ["include/cxx.h"], ) rust_proc_macro( name = "cxxbridge-macro", srcs = glob(["macro/src/**/*.rs"]), edition = "2021", proc_macro_deps = [ "@crates.io//:rustversion", ], deps = [ "@crates.io//:proc-macro2", "@crates.io//:quote", "@crates.io//:syn", ], ) rust_library( name = "cxx-build", srcs = glob(["gen/build/src/**/*.rs"]), compile_data = ["gen/build/src/gen/include/cxx.h"], edition = "2021", deps = [ "@crates.io//:cc", "@crates.io//:codespan-reporting", "@crates.io//:proc-macro2", "@crates.io//:quote", "@crates.io//:scratch", "@crates.io//:syn", ], ) rust_library( name = "cxx-gen", srcs = glob(["gen/lib/src/**/*.rs"]), compile_data = ["gen/lib/src/gen/include/cxx.h"], edition = "2021", visibility = ["//visibility:public"], deps = [ "@crates.io//:cc", "@crates.io//:codespan-reporting", "@crates.io//:proc-macro2", "@crates.io//:quote", "@crates.io//:syn", ], ) cxx-1.0.141/Cargo.lock0000644000000277450000000000100077740ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "cc" version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" dependencies = [ "shlex", ] [[package]] name = "clap" version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" dependencies = [ "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_lex" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "codespan-reporting" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "termcolor", "unicode-width", ] [[package]] name = "cxx" version = "1.0.141" dependencies = [ "cc", "cxx-build", "cxx-gen", "cxx-test-suite", "cxxbridge-cmd", "cxxbridge-flags", "cxxbridge-macro", "foldhash", "link-cplusplus", "rustversion", "trybuild", ] [[package]] name = "cxx-build" version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49d8c1baedad72a7efda12ad8d7ad687b3e7221dfb304a12443fd69e9de8bb30" dependencies = [ "cc", "codespan-reporting", "proc-macro2", "quote", "scratch", "syn", ] [[package]] name = "cxx-gen" version = "0.7.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3343179081b405510bd700a40272ea492d59eaa8d61981c3886242859b3d8ea1" dependencies = [ "codespan-reporting", "proc-macro2", "quote", "syn", ] [[package]] name = "cxx-test-suite" version = "0.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b17bb6fdd4579f6b0ad0becada9b2692ad19dd6f42ec314f0f0411bc226ede" [[package]] name = "cxxbridge-cmd" version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43afb0e3b2ef293492a31ecd796af902112460d53e5f923f7804f348a769f9c" dependencies = [ "clap", "codespan-reporting", "proc-macro2", "quote", "syn", ] [[package]] name = "cxxbridge-flags" version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0257ad2096a2474fe877e9e055ab69603851c3d6b394efcc7e0443899c2492ce" [[package]] name = "cxxbridge-macro" version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b46cbd7358a46b760609f1cb5093683328e58ca50e594a308716f5403fdc03e5" dependencies = [ "proc-macro2", "quote", "rustversion", "syn", ] [[package]] name = "dissimilar" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "foldhash" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "indexmap" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "link-cplusplus" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "scratch" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "serde" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[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.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-triple" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "toml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow", ] [[package]] name = "trybuild" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b812699e0c4f813b872b373a4471717d9eb550da14b311058a4d9cf4173cbca6" dependencies = [ "dissimilar", "glob", "serde", "serde_derive", "serde_json", "target-triple", "termcolor", "toml", ] [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "unicode-width" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "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.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[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.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.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[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.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" dependencies = [ "memchr", ] cxx-1.0.141/Cargo.toml0000644000000056020000000000100100030ustar # 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.73" name = "cxx" version = "1.0.141" authors = ["David Tolnay "] build = "build.rs" links = "cxxbridge1" exclude = [ "/demo", "/gen", "/syntax", "/third-party", "/tools/buck/prelude", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Safe interop between Rust and C++" homepage = "https://cxx.rs" documentation = "https://docs.rs/cxx" readme = "README.md" keywords = [ "ffi", "c++", ] categories = [ "development-tools::ffi", "api-bindings", "no-std", ] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/cxx" [package.metadata.bazel] additive_build_file_content = ''' cc_library( name = "cxx_cc", srcs = ["src/cxx.cc"], hdrs = ["include/cxx.h"], include_prefix = "rust", includes = ["include"], linkstatic = True, strip_include_prefix = "include", visibility = ["//visibility:public"], ) ''' deps = [":cxx_cc"] gen_build_script = false [package.metadata.bazel.extra_aliased_targets] cxx_cc = "cxx_cc" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [features] alloc = [] "c++14" = ["cxxbridge-flags/c++14"] "c++17" = ["cxxbridge-flags/c++17"] "c++20" = ["cxxbridge-flags/c++20"] default = [ "std", "cxxbridge-flags/default", ] std = [ "alloc", "foldhash/std", ] [lib] name = "cxx" path = "src/lib.rs" [[test]] name = "compiletest" path = "tests/compiletest.rs" [[test]] name = "cxx_gen" path = "tests/cxx_gen.rs" [[test]] name = "cxx_string" path = "tests/cxx_string.rs" [[test]] name = "cxx_vector" path = "tests/cxx_vector.rs" [[test]] name = "test" path = "tests/test.rs" [[test]] name = "unique_ptr" path = "tests/unique_ptr.rs" [dependencies.cxxbridge-macro] version = "=1.0.141" [dependencies.foldhash] version = "0.1" default-features = false [dependencies.link-cplusplus] version = "1.0.9" [dev-dependencies.cxx-build] version = "=1.0.141" [dev-dependencies.cxx-gen] version = "0.7" [dev-dependencies.cxx-test-suite] version = "0" [dev-dependencies.rustversion] version = "1.0.13" [dev-dependencies.trybuild] version = "1.0.81" features = ["diff"] [build-dependencies.cc] version = "1.0.83" [build-dependencies.cxxbridge-flags] version = "=1.0.141" default-features = false [target."cfg(any())".build-dependencies.cxxbridge-cmd] version = "=1.0.141" cxx-1.0.141/Cargo.toml.orig000064400000000000000000000041321046102023000134610ustar 00000000000000[package] name = "cxx" version = "1.0.141" authors = ["David Tolnay "] categories = ["development-tools::ffi", "api-bindings", "no-std"] description = "Safe interop between Rust and C++" documentation = "https://docs.rs/cxx" edition = "2021" exclude = ["/demo", "/gen", "/syntax", "/third-party", "/tools/buck/prelude"] homepage = "https://cxx.rs" keywords = ["ffi", "c++"] license = "MIT OR Apache-2.0" links = "cxxbridge1" repository = "https://github.com/dtolnay/cxx" rust-version = "1.73" [features] default = ["std", "cxxbridge-flags/default"] # c++11 "c++14" = ["cxxbridge-flags/c++14"] "c++17" = ["cxxbridge-flags/c++17"] "c++20" = ["cxxbridge-flags/c++20"] alloc = [] std = ["alloc", "foldhash/std"] [dependencies] cxxbridge-macro = { version = "=1.0.141", path = "macro" } foldhash = { version = "0.1", default-features = false } link-cplusplus = "1.0.9" [build-dependencies] cc = "1.0.83" cxxbridge-flags = { version = "=1.0.141", path = "flags", default-features = false } [dev-dependencies] cxx-build = { version = "=1.0.141", path = "gen/build" } cxx-gen = { version = "0.7", path = "gen/lib" } cxx-test-suite = { version = "0", path = "tests/ffi" } rustversion = "1.0.13" trybuild = { version = "1.0.81", features = ["diff"] } # Disallow incompatible cxxbridge-cmd version appearing in the same lockfile. [target.'cfg(any())'.build-dependencies] cxxbridge-cmd = { version = "=1.0.141", path = "gen/cmd" } [workspace] members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"] [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = ["--generate-link-to-definition"] [package.metadata.bazel] additive_build_file_content = """ cc_library( name = "cxx_cc", srcs = ["src/cxx.cc"], hdrs = ["include/cxx.h"], include_prefix = "rust", includes = ["include"], linkstatic = True, strip_include_prefix = "include", visibility = ["//visibility:public"], ) """ deps = [":cxx_cc"] extra_aliased_targets = { cxx_cc = "cxx_cc" } gen_build_script = false [patch.crates-io] cxx = { path = "." } cxx-build = { path = "gen/build" } cxx-1.0.141/LICENSE-APACHE000064400000000000000000000227731046102023000125310ustar 00000000000000 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 cxx-1.0.141/LICENSE-MIT000064400000000000000000000017771046102023000122420ustar 00000000000000Permission 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. cxx-1.0.141/MODULE.bazel000064400000000000000000000007641046102023000126050ustar 00000000000000module(name = "cxx.rs") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "rules_cc", version = "0.0.17") bazel_dep(name = "rules_rust", version = "0.57.1") rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") rust.toolchain( versions = ["1.84.0"], ) use_repo(rust, "rust_toolchains") register_toolchains("@rust_toolchains//:all") crate_repositories = use_extension("//tools/bazel:extension.bzl", "crate_repositories") use_repo(crate_repositories, "crates.io") cxx-1.0.141/MODULE.bazel.lock000064400000000000000000001161671046102023000135410ustar 00000000000000{ "lockFileVersion": 18, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", "https://bcr.bazel.build/modules/apple_support/1.17.1/MODULE.bazel": "655c922ab1209978a94ef6ca7d9d43e940cd97d9c172fb55f94d91ac53f8610b", "https://bcr.bazel.build/modules/apple_support/1.17.1/source.json": "6b2b8c74d14e8d485528a938e44bdb72a5ba17632b9e14ef6e68a5ee96c8347f", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29", "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320", "https://bcr.bazel.build/modules/rules_rust/0.57.1/MODULE.bazel": "2c9a54ba2ca856b97dc24f58089baf66e9b89ea1f5ead0f9fc36f7352e4eef03", "https://bcr.bazel.build/modules/rules_rust/0.57.1/source.json": "deb97fb4b4e7c04adb7d95c21e1b845d5369faa98f3f021c525d20342c3994e0", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", "https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" }, "selectedYankedVersions": {}, "moduleExtensions": { "//tools/bazel:extension.bzl%crate_repositories": { "general": { "bzlTransitiveDigest": "gWxl4t71LETmlnP064/v608/5DKbrcJ3TPs4nQlogkw=", "usagesDigest": "YBItjer1JIu5HatNhG5RFjMV+91FPeCgNI30zNDcWkA=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { "vendor__anstyle-1.0.10": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/anstyle/1.0.10/download" ], "strip_prefix": "anstyle-1.0.10", "build_file": "@@//third-party/bazel:BUILD.anstyle-1.0.10.bazel" } }, "vendor__cc-1.2.14": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/cc/1.2.14/download" ], "strip_prefix": "cc-1.2.14", "build_file": "@@//third-party/bazel:BUILD.cc-1.2.14.bazel" } }, "vendor__clap-4.5.30": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/clap/4.5.30/download" ], "strip_prefix": "clap-4.5.30", "build_file": "@@//third-party/bazel:BUILD.clap-4.5.30.bazel" } }, "vendor__clap_builder-4.5.30": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/clap_builder/4.5.30/download" ], "strip_prefix": "clap_builder-4.5.30", "build_file": "@@//third-party/bazel:BUILD.clap_builder-4.5.30.bazel" } }, "vendor__clap_lex-0.7.4": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/clap_lex/0.7.4/download" ], "strip_prefix": "clap_lex-0.7.4", "build_file": "@@//third-party/bazel:BUILD.clap_lex-0.7.4.bazel" } }, "vendor__codespan-reporting-0.11.1": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/codespan-reporting/0.11.1/download" ], "strip_prefix": "codespan-reporting-0.11.1", "build_file": "@@//third-party/bazel:BUILD.codespan-reporting-0.11.1.bazel" } }, "vendor__foldhash-0.1.4": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/foldhash/0.1.4/download" ], "strip_prefix": "foldhash-0.1.4", "build_file": "@@//third-party/bazel:BUILD.foldhash-0.1.4.bazel" } }, "vendor__proc-macro2-1.0.93": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/proc-macro2/1.0.93/download" ], "strip_prefix": "proc-macro2-1.0.93", "build_file": "@@//third-party/bazel:BUILD.proc-macro2-1.0.93.bazel" } }, "vendor__quote-1.0.38": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/quote/1.0.38/download" ], "strip_prefix": "quote-1.0.38", "build_file": "@@//third-party/bazel:BUILD.quote-1.0.38.bazel" } }, "vendor__rustversion-1.0.19": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/rustversion/1.0.19/download" ], "strip_prefix": "rustversion-1.0.19", "build_file": "@@//third-party/bazel:BUILD.rustversion-1.0.19.bazel" } }, "vendor__scratch-1.0.7": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/scratch/1.0.7/download" ], "strip_prefix": "scratch-1.0.7", "build_file": "@@//third-party/bazel:BUILD.scratch-1.0.7.bazel" } }, "vendor__shlex-1.3.0": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/shlex/1.3.0/download" ], "strip_prefix": "shlex-1.3.0", "build_file": "@@//third-party/bazel:BUILD.shlex-1.3.0.bazel" } }, "vendor__syn-2.0.98": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/syn/2.0.98/download" ], "strip_prefix": "syn-2.0.98", "build_file": "@@//third-party/bazel:BUILD.syn-2.0.98.bazel" } }, "vendor__termcolor-1.4.1": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/termcolor/1.4.1/download" ], "strip_prefix": "termcolor-1.4.1", "build_file": "@@//third-party/bazel:BUILD.termcolor-1.4.1.bazel" } }, "vendor__unicode-ident-1.0.17": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/unicode-ident/1.0.17/download" ], "strip_prefix": "unicode-ident-1.0.17", "build_file": "@@//third-party/bazel:BUILD.unicode-ident-1.0.17.bazel" } }, "vendor__unicode-width-0.1.14": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/unicode-width/0.1.14/download" ], "strip_prefix": "unicode-width-0.1.14", "build_file": "@@//third-party/bazel:BUILD.unicode-width-0.1.14.bazel" } }, "vendor__winapi-util-0.1.9": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/winapi-util/0.1.9/download" ], "strip_prefix": "winapi-util-0.1.9", "build_file": "@@//third-party/bazel:BUILD.winapi-util-0.1.9.bazel" } }, "vendor__windows-sys-0.59.0": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows-sys/0.59.0/download" ], "strip_prefix": "windows-sys-0.59.0", "build_file": "@@//third-party/bazel:BUILD.windows-sys-0.59.0.bazel" } }, "vendor__windows-targets-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows-targets/0.52.6/download" ], "strip_prefix": "windows-targets-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows-targets-0.52.6.bazel" } }, "vendor__windows_aarch64_gnullvm-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_aarch64_gnullvm/0.52.6/download" ], "strip_prefix": "windows_aarch64_gnullvm-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_aarch64_gnullvm-0.52.6.bazel" } }, "vendor__windows_aarch64_msvc-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_aarch64_msvc/0.52.6/download" ], "strip_prefix": "windows_aarch64_msvc-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_aarch64_msvc-0.52.6.bazel" } }, "vendor__windows_i686_gnu-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_i686_gnu/0.52.6/download" ], "strip_prefix": "windows_i686_gnu-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_i686_gnu-0.52.6.bazel" } }, "vendor__windows_i686_gnullvm-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_i686_gnullvm/0.52.6/download" ], "strip_prefix": "windows_i686_gnullvm-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_i686_gnullvm-0.52.6.bazel" } }, "vendor__windows_i686_msvc-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_i686_msvc/0.52.6/download" ], "strip_prefix": "windows_i686_msvc-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_i686_msvc-0.52.6.bazel" } }, "vendor__windows_x86_64_gnu-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_x86_64_gnu/0.52.6/download" ], "strip_prefix": "windows_x86_64_gnu-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_x86_64_gnu-0.52.6.bazel" } }, "vendor__windows_x86_64_gnullvm-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_x86_64_gnullvm/0.52.6/download" ], "strip_prefix": "windows_x86_64_gnullvm-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_x86_64_gnullvm-0.52.6.bazel" } }, "vendor__windows_x86_64_msvc-0.52.6": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec", "type": "tar.gz", "urls": [ "https://static.crates.io/crates/windows_x86_64_msvc/0.52.6/download" ], "strip_prefix": "windows_x86_64_msvc-0.52.6", "build_file": "@@//third-party/bazel:BUILD.windows_x86_64_msvc-0.52.6.bazel" } }, "crates.io": { "repoRuleId": "@@//tools/bazel:extension.bzl%_crates_vendor_remote_repository", "attributes": { "build_file": "@@//third-party/bazel:BUILD.bazel" } } }, "recordedRepoMappingEntries": [ [ "", "bazel_skylib", "bazel_skylib+" ], [ "", "bazel_tools", "bazel_tools" ], [ "", "vendor", "vendor" ] ] } }, "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { "bzlTransitiveDigest": "Ync9nL0AbHC6ondeEY7fBjBjLxojTsiXcJh65ZDTRlA=", "usagesDigest": "3L+PK6aRnliv0iIS8m3kdo+LjmvjJWoFCm3qZcPSg+8=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { "local_config_apple_cc_toolchains": { "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf_toolchains", "attributes": {} }, "local_config_apple_cc": { "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf", "attributes": {} } }, "recordedRepoMappingEntries": [ [ "apple_support+", "bazel_tools", "bazel_tools" ], [ "bazel_tools", "rules_cc", "rules_cc+" ] ] } }, "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": { "general": { "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=", "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { "compatibility_proxy": { "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule", "attributes": {} } }, "recordedRepoMappingEntries": [ [ "rules_java+", "bazel_tools", "bazel_tools" ] ] } }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { "com_github_jetbrains_kotlin_git": { "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", "attributes": { "urls": [ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" ], "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" } }, "com_github_jetbrains_kotlin": { "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", "attributes": { "git_repository_name": "com_github_jetbrains_kotlin_git", "compiler_version": "1.9.23" } }, "com_github_google_ksp": { "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", "attributes": { "urls": [ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" ], "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", "strip_version": "1.9.23-1.0.20" } }, "com_github_pinterest_ktlint": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", "attributes": { "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", "urls": [ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" ], "executable": true } }, "rules_android": { "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", "attributes": { "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", "strip_prefix": "rules_android-0.1.1", "urls": [ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" ] } } }, "recordedRepoMappingEntries": [ [ "rules_kotlin+", "bazel_tools", "bazel_tools" ] ] } } } } cxx-1.0.141/README.md000064400000000000000000000416461046102023000120640ustar 00000000000000CXX — safe FFI between Rust and C++ ========================================= [github](https://github.com/dtolnay/cxx) [crates.io](https://crates.io/crates/cxx) [docs.rs](https://docs.rs/cxx) [build status](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster) This library provides a **safe** mechanism for calling C++ code from Rust and Rust code from C++, not subject to the many ways that things can go wrong when using bindgen or cbindgen to generate unsafe C-style bindings. This doesn't change the fact that 100% of C++ code is unsafe. When auditing a project, you would be on the hook for auditing all the unsafe Rust code and *all* the C++ code. The core safety claim under this new model is that auditing just the C++ side would be sufficient to catch all problems, i.e. the Rust side can be 100% safe. ```toml [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` *Compiler support: requires rustc 1.73+ and c++11 or newer*
*[Release notes](https://github.com/dtolnay/cxx/releases)*
## Guide Please see **** for a tutorial, reference material, and example code.
## Overview The idea is that we define the signatures of both sides of our FFI boundary embedded together in one Rust module (the next section shows an example). From this, CXX receives a complete picture of the boundary to perform static analyses against the types and function signatures to uphold both Rust's and C++'s invariants and requirements. If everything checks out statically, then CXX uses a pair of code generators to emit the relevant `extern "C"` signatures on both sides together with any necessary static assertions for later in the build process to verify correctness. On the Rust side this code generator is simply an attribute procedural macro. On the C++ side it can be a small Cargo build script if your build is managed by Cargo, or for other build systems like Bazel or Buck we provide a command line tool which generates the header and source file and should be easy to integrate. The resulting FFI bridge operates at zero or negligible overhead, i.e. no copying, no serialization, no memory allocation, no runtime checks needed. The FFI signatures are able to use native types from whichever side they please, such as Rust's `String` or C++'s `std::string`, Rust's `Box` or C++'s `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any combination. CXX guarantees an ABI-compatible signature that both sides understand, based on builtin bindings for key standard library types to expose an idiomatic API on those types to the other language. For example when manipulating a C++ string from Rust, its `len()` method becomes a call of the `size()` member function defined by C++; when manipulating a Rust string from C++, its `size()` member function calls Rust's `len()`.
## Example In this example we are writing a Rust application that wishes to take advantage of an existing C++ client for a large-file blobstore service. The blobstore supports a `put` operation for a discontiguous buffer upload. For example we might be uploading snapshots of a circular buffer which would tend to consist of 2 chunks, or fragments of a file spread across memory for some other reason. A runnable version of this example is provided under the *demo* directory of this repo. To try it out, run `cargo run` from that directory. ```rust #[cxx::bridge] mod ffi { // Any shared structs, whose fields will be visible to both languages. struct BlobMetadata { size: usize, tags: Vec, } extern "Rust" { // Zero or more opaque types which both languages can pass around but // only Rust can see the fields. type MultiBuf; // Functions implemented in Rust. fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } unsafe extern "C++" { // One or more headers with the matching C++ declarations. Our code // generators don't read it but it gets #include'd and used in static // assertions to ensure our picture of the FFI boundary is accurate. include!("demo/include/blobstore.h"); // Zero or more opaque types which both languages can pass around but // only C++ can see the fields. type BlobstoreClient; // Functions implemented in C++. fn new_blobstore_client() -> UniquePtr; fn put(&self, parts: &mut MultiBuf) -> u64; fn tag(&self, blobid: u64, tag: &str); fn metadata(&self, blobid: u64) -> BlobMetadata; } } ``` Now we simply provide Rust definitions of all the things in the `extern "Rust"` block and C++ definitions of all the things in the `extern "C++"` block, and get to call back and forth safely. Here are links to the complete set of source files involved in the demo: - [demo/src/main.rs](demo/src/main.rs) - [demo/build.rs](demo/build.rs) - [demo/include/blobstore.h](demo/include/blobstore.h) - [demo/src/blobstore.cc](demo/src/blobstore.cc) To look at the code generated in both languages for the example by the CXX code generators: ```console # run Rust code generator and print to stdout # (requires https://github.com/dtolnay/cargo-expand) $ cargo expand --manifest-path demo/Cargo.toml # run C++ code generator and print to stdout $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs ```
## Details As seen in the example, the language of the FFI boundary involves 3 kinds of items: - **Shared structs** — their fields are made visible to both languages. The definition written within cxx::bridge is the single source of truth. - **Opaque types** — their fields are secret from the other language. These cannot be passed across the FFI by value but only behind an indirection, such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can be a type alias for an arbitrarily complicated generic language-specific type depending on your use case. - **Functions** — implemented in either language, callable from the other language. Within the `extern "Rust"` part of the CXX bridge we list the types and functions for which Rust is the source of truth. These all implicitly refer to the `super` module, the parent module of the CXX bridge. You can think of the two items listed in the example above as being like `use super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The parent module will either contain the definitions directly for simple things, or contain the relevant `use` statements to bring them into scope from elsewhere. Within the `extern "C++"` part, we list types and functions for which C++ is the source of truth, as well as the header(s) that declare those APIs. In the future it's possible that this section could be generated bindgen-style from the headers but for now we need the signatures written out; static assertions will verify that they are accurate. Your function implementations themselves, whether in C++ or Rust, *do not* need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the right shims where necessary to make it all work.
## Comparison vs bindgen and cbindgen Notice that with CXX there is repetition of all the function signatures: they are typed out once where the implementation is defined (in C++ or Rust) and again inside the cxx::bridge module, though compile-time assertions guarantee these are kept in sync. This is different from [bindgen] and [cbindgen] where function signatures are typed by a human once and the tool consumes them in one language and emits them in the other language. [bindgen]: https://github.com/rust-lang/rust-bindgen [cbindgen]: https://github.com/eqrion/cbindgen/ This is because CXX fills a somewhat different role. It is a lower level tool than bindgen or cbindgen in a sense; you can think of it as being a replacement for the concept of `extern "C"` signatures as we know them, rather than a replacement for a bindgen. It would be reasonable to build a higher level bindgen-like tool on top of CXX which consumes a C++ header and/or Rust module (and/or IDL like Thrift) as source of truth and generates the cxx::bridge, eliminating the repetition while leveraging the static analysis safety guarantees of CXX. But note in other ways CXX is higher level than the bindgens, with rich support for common standard library types. Frequently with bindgen when we are dealing with an idiomatic C++ API we would end up manually wrapping that API in C-style raw pointer functions, applying bindgen to get unsafe raw pointer Rust functions, and replicating the API again to expose those idiomatically in Rust. That's a much worse form of repetition because it is unsafe all the way through. By using a CXX bridge as the shared understanding between the languages, rather than `extern "C"` C-style signatures as the shared understanding, common FFI use cases become expressible using 100% safe code. It would also be reasonable to mix and match, using CXX bridge for the 95% of your FFI that is straightforward and doing the remaining few oddball signatures the old fashioned way with bindgen and cbindgen, if for some reason CXX's static restrictions get in the way. Please file an issue if you end up taking this approach so that we know what ways it would be worthwhile to make the tool more expressive.
## Cargo-based setup For builds that are orchestrated by Cargo, you will use a build script that runs CXX's C++ code generator and compiles the resulting C++ code along with any other C++ code for your crate. The canonical build script is as follows. The indicated line returns a [`cc::Build`] instance (from the usual widely used `cc` crate) on which you can set up any additional source files and compiler flags as normal. [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html ```toml # Cargo.toml [build-dependencies] cxx-build = "1.0" ``` ```rust // build.rs fn main() { cxx_build::bridge("src/main.rs") // returns a cc::Build .file("src/demo.cc") .std("c++11") .compile("cxxbridge-demo"); println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/demo.cc"); println!("cargo:rerun-if-changed=include/demo.h"); } ```
## Non-Cargo setup For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate way of invoking the C++ code generator as a standalone command line tool. The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the *gen/cmd* directory of this repo. ```bash $ cargo install cxxbridge-cmd $ cxxbridge src/main.rs --header > path/to/mybridge.h $ cxxbridge src/main.rs > path/to/mybridge.cc ```
## Safety Be aware that the design of this library is intentionally restrictive and opinionated! It isn't a goal to be powerful enough to handle arbitrary signatures in either language. Instead this project is about carving out a reasonably expressive set of functionality about which we can make useful safety guarantees today and maybe extend over time. You may find that it takes some practice to use CXX bridge effectively as it won't work in all the ways that you are used to. Some of the considerations that go into ensuring safety are: - By design, our paired code generators work together to control both sides of the FFI boundary. Ordinarily in Rust writing your own `extern "C"` blocks is unsafe because the Rust compiler has no way to know whether the signatures you've written actually match the signatures implemented in the other language. With CXX we achieve that visibility and know what's on the other side. - Our static analysis detects and prevents passing types by value that shouldn't be passed by value from C++ to Rust, for example because they may contain internal pointers that would be screwed up by Rust's move behavior. - To many people's surprise, it is possible to have a struct in Rust and a struct in C++ with exactly the same layout / fields / alignment / everything, and still not the same ABI when passed by value. This is a longstanding bindgen bug that leads to segfaults in absolutely correct-looking code ([rust-lang/rust-bindgen#778]). CXX knows about this and can insert the necessary zero-cost workaround transparently where needed, so go ahead and pass your structs by value without worries. This is made possible by owning both sides of the boundary rather than just one. - Template instantiations: for example in order to expose a UniquePtr\ type in Rust backed by a real C++ unique\_ptr, we have a way of using a Rust trait to connect the behavior back to the template instantiations performed by the other language. [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
## Builtin types In addition to all the primitive types (i32 <=> int32_t), the following common types may be used in the fields of shared structs and the arguments and returns of functions.
name in Rustname in C++restrictions
Stringrust::String
&strrust::Str
&[T]rust::Slice<const T>cannot hold opaque C++ type
&mut [T]rust::Slice<T>cannot hold opaque C++ type
CxxStringstd::stringcannot be passed by value
Box<T>rust::Box<T>cannot hold opaque C++ type
UniquePtr<T>std::unique_ptr<T>cannot hold opaque Rust type
SharedPtr<T>std::shared_ptr<T>cannot hold opaque Rust type
[T; N]std::array<T, N>cannot hold opaque C++ type
Vec<T>rust::Vec<T>cannot hold opaque C++ type
CxxVector<T>std::vector<T>cannot be passed by value, cannot hold opaque Rust type
*mut T, *const TT*, const T*fn with a raw pointer argument must be declared unsafe to call
fn(T, U) -> Vrust::Fn<V(T, U)>only passing from Rust to C++ is implemented so far
Result<T>throw/catchallowed as return type only
The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in this repo. You will need to include this header in your C++ code when working with those types. The following types are intended to be supported "soon" but are just not implemented yet. I don't expect any of these to be hard to make work but it's a matter of designing a nice API for each in its non-native language.
name in Rustname in C++
BTreeMap<K, V>tbd
HashMap<K, V>tbd
Arc<T>tbd
Option<T>tbd
tbdstd::map<K, V>
tbdstd::unordered_map<K, V>

## Remaining work This is still early days for CXX; I am releasing it as a minimum viable product to collect feedback on the direction and invite collaborators. Please check the open issues. Especially please report issues if you run into trouble building or linking any of this stuff. I'm sure there are ways to make the build aspects friendlier or more robust. Finally, I know more about Rust library design than C++ library design so I would appreciate help making the C++ APIs in this project more idiomatic where anyone has suggestions.
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. cxx-1.0.141/book/.gitignore000064400000000000000000000000371046102023000135140ustar 00000000000000/build/ /mdbook /node_modules/ cxx-1.0.141/book/README.md000064400000000000000000000004071046102023000130040ustar 00000000000000Published automatically to https://cxx.rs from master branch. To build and view locally: - Install [mdBook]: `cargo install mdbook`. - Run `mdbook build` in this directory. - Open the generated *build/index.html*. [mdBook]: https://github.com/rust-lang/mdBook cxx-1.0.141/book/book.toml000064400000000000000000000011161046102023000133520ustar 00000000000000[book] #title = "Rust ♡ C++" authors = ["David Tolnay"] description = "CXX — safe interop between Rust and C++ by David Tolnay. This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++." [rust] edition = "2021" [build] build-dir = "build" create-missing = false [output.html] additional-css = ["css/cxx.css"] cname = "cxx.rs" git-repository-url = "https://github.com/dtolnay/cxx" playground = { copyable = false } print = { enable = false } [output.html.redirect] "binding/index.html" = "../bindings.html" "build/index.html" = "../building.html" cxx-1.0.141/book/build.js000075500000000000000000000104141046102023000131640ustar 00000000000000#!/usr/bin/env node const fs = require('fs'); const cheerio = require('cheerio'); const entities = require('html-entities'); const hljs = require('./build/highlight.js'); const githublink = `\
  • \ \ \ https://github.com/dtolnay/cxx\ \
  • `; const opengraph = `\ \ \ \ \ \ \ `; const themejs = `\ var theme; try { theme = localStorage.getItem('mdbook-theme'); } catch(e) {} if (theme === null || theme === undefined) { theme = default_theme; } const html = document.documentElement; html.classList.remove('light') html.classList.add(theme); html.classList.add("js");`; const themejsReplacement = `\ const html = document.documentElement; html.classList.add('js');`; const dirs = ['build']; while (dirs.length) { const dir = dirs.pop(); fs.readdirSync(dir).forEach((entry) => { const path = dir + '/' + entry; const stat = fs.statSync(path); if (stat.isDirectory()) { dirs.push(path); return; } if (!path.endsWith('.html')) { return; } const index = fs.readFileSync(path, 'utf8'); const $ = cheerio.load(index, { decodeEntities: false, xml: { xmlMode: false }, }); $('head').append(opengraph); $('nav#sidebar ol.chapter').append(githublink); $('head link[href="tomorrow-night.css"]').attr('disabled', true); $('head link[href="ayu-highlight.css"]').attr('disabled', true); $('button#theme-toggle').attr('style', 'display:none'); $('pre code').each(function () { const node = $(this); const langClass = node.attr('class').split(' ', 2)[0]; if (!langClass.startsWith('language-')) { return; } const lang = langClass.replace('language-', ''); const originalLines = node.html().split('\n'); const boring = originalLines.map((line) => line.includes(''), ); const ellipsis = originalLines.map((line) => line.includes('// ...')); const target = entities.decode(node.text()); const highlightedLines = hljs.highlight(lang, target).value.split('\n'); const result = highlightedLines .map(function (line, i) { if (boring[i]) { line = '' + line; } else if (ellipsis[i]) { line = '' + line; } if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) { line = '' + line; } if (i + 1 === highlightedLines.length && (boring[i] || ellipsis[i])) { line = line + ''; } return line; }) .join('\n'); node.text(result); node.removeClass(langClass); if (!node.hasClass('focuscomment')) { node.addClass('hidelines'); node.addClass('hide-boring'); } }); $('code').each(function () { $(this).addClass('hljs'); }); var foundScript = false; $('body script').each(function () { const node = $(this); if (node.text().replace(/\s/g, '') === themejs.replace(/\s/g, '')) { node.text(themejsReplacement); foundScript = true; } }); const pathsWithoutScript = [ 'build/toc.html', 'build/build/index.html', 'build/binding/index.html', ]; if (!foundScript && !pathsWithoutScript.includes(path)) { throw new Error('theme script not found'); } const out = $.html(); fs.writeFileSync(path, out); }); } fs.copyFileSync('build/highlight.css', 'build/tomorrow-night.css'); fs.copyFileSync('build/highlight.css', 'build/ayu-highlight.css'); var bookjs = fs.readFileSync('build/book.js', 'utf8'); bookjs = bookjs .replace('set_theme(theme, false);', '') .replace( 'document.querySelectorAll("code.hljs")', 'document.querySelectorAll("code.hidelines")', ); fs.writeFileSync('build/book.js', bookjs); cxx-1.0.141/book/build.sh000075500000000000000000000002571046102023000131660ustar 00000000000000#!/bin/bash set -e cd "$(dirname "$0")" if [ -f ./mdbook ]; then ./mdbook build else mdbook build fi if [ ! -d node_modules ]; then npm install fi ./build.js cxx-1.0.141/book/css/cxx.css000064400000000000000000000012351046102023000136310ustar 00000000000000:root { --sidebar-width: 310px; } .badges img { margin: 0 7px 7px 0; } .badges { margin: 16px 0 120px; } .boring { opacity: 0.5; } .no-js code:not(.focuscomment) .boring { display: none; } .js code:not(.hide-boring) .ellipsis { display: none; } .focuscomment .hljs-comment { font-weight: bold; color: black; } .focuscomment .boring { opacity: 0.5; } nav.sidebar li.part-title i.fa-github { font-size: 20px; padding-right: 5px; padding-top: 12px; position: relative; top: 1px; } .sidebar .sidebar-scrollbox { padding: 10px 0 10px 10px; } pre > .buttons { visibility: visible; opacity: 0.3; } cxx-1.0.141/book/diagram/.gitignore000064400000000000000000000000711046102023000151160ustar 00000000000000/*.aux /*.fdb_latexmk /*.fls /*.log /*.pdf /*.png /*.svg cxx-1.0.141/book/diagram/Makefile000064400000000000000000000002021046102023000145620ustar 00000000000000overview.svg: overview.pdf pdf2svg $< $@ overview.pdf: overview.tex latexmk $< overview.png: overview.svg svgexport $< $@ 3x cxx-1.0.141/book/diagram/overview.tex000064400000000000000000000035511046102023000155240ustar 00000000000000\documentclass{standalone} \usepackage{makecell} \usepackage{pgfplots} \usepackage{sansmath} \usetikzlibrary{arrows.meta} \pgfplotsset{compat=1.16} \begin{document} \pagecolor{white} \begin{tikzpicture}[ x=1cm, y=-.6cm, every node/.append style={ line width=1.5pt, font=\Large\sansmath\sffamily, }, every path/.append style={ >={Latex[length=10pt,width=8pt]}, line width=1.5pt, }, execute at end node={\vphantom{bg}}, ] \node[draw, rounded corners=5, inner xsep=30pt, inner ysep=2pt] (bridge) at (0, .25) {\makecell{\texttt{\#\hspace{-1pt}[}cxx::bridge\texttt{]} mod\\[-4pt]description of boundary}}; \node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] (rust-bindings) at (-3.5, 6.5) {Rust bindings}; \node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] (cpp-bindings) at (3.5, 6.5) {C\texttt{++} bindings}; \node[inner xsep=4pt, inner ysep=-0pt] (rust-code) at (-9, 6.5) {\makecell[r]{\\[-8pt]Rust\\[-4pt]code}}; \node[inner xsep=4pt, inner ysep=-0pt] (cpp-code) at (9, 6.5) {\makecell[l]{\\[-8pt]C\texttt{++}\\[-4pt]code}}; \draw (bridge) -- (0, 4); \draw[<->] (rust-bindings) |- (0, 4) -| (cpp-bindings); \draw[<->] (rust-code) -- (rust-bindings); \draw[<->, dash pattern=on 8pt off 6pt] (rust-bindings) -- (cpp-bindings); \draw[<->] (cpp-bindings) -- (cpp-code); \draw (-.75, 4) node[anchor=south east] {Macro expansion}; \draw (.75, 4) node[anchor=south west] {Code generation}; \draw (0, 6.5) node[anchor=south, inner ysep=4pt] {Hidden C ABI}; \draw (-6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Safe\\[-4pt]straightforward\\[-4pt]Rust APIs}}; \draw (6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Straightforward\\[-4pt]C\texttt{++} APIs}}; \pgfresetboundingbox\path (-9.5, 0) -- (rust-bindings.south)+(0, .3) -- (9.5, 0) -- (bridge.north); \end{tikzpicture} \end{document} cxx-1.0.141/book/eslint.config.mjs000064400000000000000000000003531046102023000150020ustar 00000000000000import pluginJs from '@eslint/js'; /** @type {import('eslint').Linter.Config[]} */ export default [ { ignores: ['build/*'] }, { files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } }, pluginJs.configs.recommended, ]; cxx-1.0.141/book/package-lock.json000064400000000000000000001365431046102023000147540ustar 00000000000000{ "name": "cxx-book-build", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cxx-book-build", "version": "0.0.0", "dependencies": { "cheerio": "^1.0.0", "html-entities": "^2.5.2" }, "devDependencies": { "@eslint/js": "^9.19.0", "eslint": "^9.19.0" } }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@eslint/js": { "version": "9.19.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { "version": "0.16.6", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/retry": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "license": "ISC" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/cheerio": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "encoding-sniffer": "^0.2.0", "htmlparser2": "^9.1.0", "parse5": "^7.1.2", "parse5-htmlparser2-tree-adapter": "^7.0.0", "parse5-parser-stream": "^7.1.2", "undici": "^6.19.5", "whatwg-mimetype": "^4.0.0" }, "engines": { "node": ">=18.17" }, "funding": { "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, "node_modules/cheerio-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" }, "funding": { "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } ], "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, "engines": { "node": ">= 4" }, "funding": { "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" } }, "node_modules/encoding-sniffer": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", "license": "MIT", "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" }, "funding": { "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { "version": "9.19.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://eslint.org/donate" }, "peerDependencies": { "jiti": "*" }, "peerDependenciesMeta": { "jiti": { "optional": true } } }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, "engines": { "node": ">=0.10" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" }, "engines": { "node": ">=16" } }, "node_modules/flatted": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true, "license": "ISC" }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/html-entities": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/mdevils" }, { "type": "patreon", "url": "https://patreon.com/mdevils" } ], "license": "MIT" }, "node_modules/htmlparser2": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { "type": "github", "url": "https://github.com/sponsors/fb55" } ], "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, "funding": { "url": "https://github.com/fb55/nth-check?sponsor=1" } }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/parse5": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "license": "MIT", "dependencies": { "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "license": "MIT", "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-parser-stream": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", "license": "MIT", "dependencies": { "parse5": "^7.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/undici": { "version": "6.21.1", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", "license": "MIT", "engines": { "node": ">=18.17" } }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" }, "engines": { "node": ">=18" } }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } cxx-1.0.141/book/package.json000064400000000000000000000004311046102023000140100ustar 00000000000000{ "name": "cxx-book-build", "version": "0.0.0", "main": "build.js", "dependencies": { "cheerio": "^1.0.0", "html-entities": "^2.5.2" }, "devDependencies": { "@eslint/js": "^9.19.0", "eslint": "^9.19.0" }, "prettier": { "singleQuote": true } } cxx-1.0.141/book/src/404.md000064400000000000000000000002171046102023000131440ustar 00000000000000### Whoops, this page doesn’t exist :-(
    ferris cxx-1.0.141/book/src/SUMMARY.md000064400000000000000000000025211046102023000137720ustar 00000000000000# Summary - [Rust â¤ï¸ C++](index.md) - [Core concepts](concepts.md) - [Tutorial](tutorial.md) - [Other Rust–C++ interop tools](context.md) - [Multi-language build system options](building.md) - [Cargo](build/cargo.md) - [Bazel or Buck2](build/bazel.md) - [CMake](build/cmake.md) - [More...](build/other.md) - [Reference: the bridge module](reference.md) - [extern "Rust"](extern-rust.md) - [extern "C++"](extern-c++.md) - [Shared types](shared.md) - [Attributes](attributes.md) - [Async functions](async.md) - [Error handling](binding/result.md) - [Reference: built-in bindings](bindings.md) - [String — rust::String](binding/string.md) - [&str — rust::Str](binding/str.md) - [&[T], &mut [T] — rust::Slice\](binding/slice.md) - [CxxString — std::string](binding/cxxstring.md) - [Box\ — rust::Box\](binding/box.md) - [UniquePtr\ — std::unique\_ptr\](binding/uniqueptr.md) - [SharedPtr\ — std::shared\_ptr\](binding/sharedptr.md) - [Vec\ — rust::Vec\](binding/vec.md) - [CxxVector\ — std::vector\](binding/cxxvector.md) - [*mut T, *const T raw pointers](binding/rawptr.md) - [Function pointers](binding/fn.md) - [Result\](binding/result.md) cxx-1.0.141/book/src/async.md000064400000000000000000000035011046102023000137510ustar 00000000000000{{#title Async functions — Rust ♡ C++}} # Async functions Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up) but is not implemented yet in the current release. We are aiming for an implementation that is as easy as: ```rust,noplayground #[cxx::bridge] mod ffi { unsafe extern "C++" { async fn doThing(arg: Arg) -> Ret; } } ``` ```cpp rust::Future doThing(Arg arg) { auto v1 = co_await f(); auto v2 = co_await g(arg); co_return v1 + v2; } ``` ## Workaround For now the recommended approach is to handle the return codepath over a oneshot channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust type on the FFI. [`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html ```rust,noplayground // bridge.rs use futures::channel::oneshot; #[cxx::bridge] mod ffi { extern "Rust" { type DoThingContext; } unsafe extern "C++" { include!("path/to/bridge_shim.h"); fn shim_doThing( arg: Arg, done: fn(Box, ret: Ret), ctx: Box, ); } } struct DoThingContext(oneshot::Sender); pub async fn do_thing(arg: Arg) -> Ret { let (tx, rx) = oneshot::channel(); let context = Box::new(DoThingContext(tx)); ffi::shim_doThing( arg, |context, ret| { let _ = context.0.send(ret); }, context, ); rx.await.unwrap() } ``` ```cpp // bridge_shim.cc #include "path/to/bridge.rs.h" #include "rust/cxx.h" void shim_doThing( Arg arg, rust::Fn ctx, Ret ret)> done, rust::Box ctx) noexcept { doThing(arg) .then([done, ctx(std::move(ctx))](auto &&res) mutable { (*done)(std::move(ctx), std::move(res)); }); } ``` cxx-1.0.141/book/src/attributes.md000064400000000000000000000042301046102023000150220ustar 00000000000000{{#title Attributes — Rust ♡ C++}} # Attributes ## namespace The top-level cxx::bridge attribute macro takes an optional `namespace` argument to control the C++ namespace into which to emit extern Rust items and the namespace in which to expect to find the extern C++ items. ```rust,noplayground #[cxx::bridge(namespace = "path::of::my::company")] mod ffi { extern "Rust" { type MyType; // emitted to path::of::my::company::MyType } extern "C++" { type TheirType; // refers to path::of::my::company::TheirType } } ``` Additionally, a `#[namespace = "..."]` attribute may be used inside the bridge module on any extern block or individual item. An item will inherit the namespace specified on its surrounding extern block if any, otherwise the namespace specified with the top level cxx::bridge attribute if any, otherwise the global namespace. ```rust,noplayground #[cxx::bridge(namespace = "third_priority")] mod ffi { #[namespace = "second_priority"] extern "Rust" { fn f(); #[namespace = "first_priority"] fn g(); } extern "Rust" { fn h(); } } ``` The above would result in functions `::second_priority::f`, `::first_priority::g`, `::third_priority::h`. ## rust\_name, cxx\_name Sometimes you want the Rust name of a function or type to differ from its C++ name. Importantly, this enables binding multiple overloads of the same C++ function name using distinct Rust names. ```rust,noplayground #[cxx::bridge] mod ffi { unsafe extern "C++" { #[rust_name = "i32_overloaded_function"] fn cOverloadedFunction(x: i32) -> String; #[rust_name = "str_overloaded_function"] fn cOverloadedFunction(x: &str) -> String; } } ``` The `#[rust_name = "..."]` attribute replaces the name that Rust should use for this function, and an analogous `#[cxx_name = "..."]` attribute replaces the name that C++ should use. Either of the two attributes may be used on extern "Rust" as well as extern "C++" functions, according to which one you find clearer in context. The same attribute works for renaming functions, opaque types, shared structs and enums, and enum variants. cxx-1.0.141/book/src/binding/box.md000064400000000000000000000051661046102023000150470ustar 00000000000000{{#title rust::Box — Rust ♡ C++}} # rust::Box\ ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...#include ... ...namespace rust { template class Box final { public: using element_type = T; using const_pointer = typename std::add_pointer::type>::type; using pointer = typename std::add_pointer::type; Box(Box &&) noexcept; ~Box() noexcept; explicit Box(const T &); explicit Box(T &&); Box &operator=(Box &&) & noexcept; const T *operator->() const noexcept; const T &operator*() const noexcept; T *operator->() noexcept; T &operator*() noexcept; template static Box in_place(Fields &&...); void swap(Box &) noexcept; // Important: requires that `raw` came from an into_raw call. Do not // pass a pointer from `new` or any other source. static Box from_raw(T *) noexcept; T *into_raw() noexcept; }; ... ...} // namespace rust ``` ### Restrictions: Box\ does not support T being an opaque C++ type. You should use [UniquePtr\](uniqueptr.md) or [SharedPtr\](sharedptr.md) instead for transferring ownership of opaque C++ types on the language boundary. If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size known at compile time. In the future we may introduce support for dynamically sized opaque Rust types. [Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html ## Example This program uses a Box to pass ownership of some opaque piece of Rust state over to C++ and then back to a Rust callback, which is a useful pattern for implementing [async functions over FFI](../async.md). ```rust,noplayground // src/main.rs use std::io::Write; #[cxx::bridge] mod ffi { extern "Rust" { type File; } unsafe extern "C++" { include!("example/include/example.h"); fn f( callback: fn(Box, fst: &str, snd: &str), out: Box, ); } } pub struct File(std::fs::File); fn main() { let out = std::fs::File::create("example.log").unwrap(); ffi::f( |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); }, Box::new(File(out)), ); } ``` ```cpp // include/example.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void f(rust::Fn, rust::Str, rust::Str)> callback, rust::Box out); ``` ```cpp // include/example.cc #include "example/include/example.h" void f(rust::Fn, rust::Str, rust::Str)> callback, rust::Box out) { callback(std::move(out), "fearless", "concurrency"); } ``` cxx-1.0.141/book/src/binding/cxxstring.md000064400000000000000000000077771046102023000163220ustar 00000000000000{{#title std::string — Rust ♡ C++}} # std::string The Rust binding of std::string is called **[`CxxString`]**. See the link for documentation of the Rust API. [`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html ### Restrictions: Rust code can never obtain a CxxString by value. C++'s string requires a move constructor and may hold internal pointers, which is not compatible with Rust's move behavior. Instead in Rust code we will only ever look at a CxxString through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\> or UniquePtr\. In order to construct a CxxString on the stack from Rust, you must use the [`let_cxx_string!`] macro which will pin the string properly. The code below uses this in one place, and the link covers the syntax. [`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html ## Example This example uses C++17's std::variant to build a toy JSON type. JSON can hold various types including strings, and JSON's object type is a map with string keys. The example demonstrates Rust indexing into one of those maps. ```rust,noplayground // src/main.rs use cxx::let_cxx_string; #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/json.h"); #[cxx_name = "json"] type Json; #[cxx_name = "object"] type Object; fn isNull(self: &Json) -> bool; fn isNumber(self: &Json) -> bool; fn isString(self: &Json) -> bool; fn isArray(self: &Json) -> bool; fn isObject(self: &Json) -> bool; fn getNumber(self: &Json) -> f64; fn getString(self: &Json) -> &CxxString; fn getArray(self: &Json) -> &CxxVector; fn getObject(self: &Json) -> &Object; #[cxx_name = "at"] fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; fn load_config() -> UniquePtr; } } fn main() { let config = ffi::load_config(); let_cxx_string!(key = "name"); println!("{}", config.getObject().get(&key).getString()); } ``` ```cpp // include/json.h #pragma once #include #include #include #include #include class json final { public: static const json null; using number = double; using string = std::string; using array = std::vector; using object = std::map; json() noexcept = default; json(const json &) = default; json(json &&) = default; template json(T &&...value) : value(std::forward(value)...) {} bool isNull() const; bool isNumber() const; bool isString() const; bool isArray() const; bool isObject() const; number getNumber() const; const string &getString() const; const array &getArray() const; const object &getObject() const; private: std::variant value; }; using object = json::object; std::unique_ptr load_config(); ``` ```cpp // include/json.cc #include "example/include/json.h" #include #include const json json::null{}; bool json::isNull() const { return std::holds_alternative(value); } bool json::isNumber() const { return std::holds_alternative(value); } bool json::isString() const { return std::holds_alternative(value); } bool json::isArray() const { return std::holds_alternative(value); } bool json::isObject() const { return std::holds_alternative(value); } json::number json::getNumber() const { return std::get(value); } const json::string &json::getString() const { return std::get(value); } const json::array &json::getArray() const { return std::get(value); } const json::object &json::getObject() const { return std::get(value); } std::unique_ptr load_config() { return std::make_unique( std::in_place_type, std::initializer_list>{ {"name", "cxx-example"}, {"edition", 2021.}, {"repository", json::null}}); } ``` cxx-1.0.141/book/src/binding/cxxvector.md000064400000000000000000000025771046102023000163070ustar 00000000000000{{#title std::vector — Rust ♡ C++}} # std::vector\ The Rust binding of std::vector\ is called **[`CxxVector`]**. See the link for documentation of the Rust API. [`CxxVector`]: https://docs.rs/cxx/*/cxx/struct.CxxVector.html ### Restrictions: Rust code can never obtain a CxxVector by value. Instead in Rust code we will only ever look at a vector behind a reference or smart pointer, as in &CxxVector\ or UniquePtr\\>. CxxVector\ does not support T being an opaque Rust type. You should use a Vec\ (C++ rust::Vec\) instead for collections of opaque Rust types on the language boundary. ## Example This program involves Rust code converting a `CxxVector` (i.e. `std::vector`) into a Rust `Vec`. ```rust,noplayground // src/main.rs #![no_main] // main defined in C++ by main.cc use cxx::{CxxString, CxxVector}; #[cxx::bridge] mod ffi { extern "Rust" { fn f(vec: &CxxVector); } } fn f(vec: &CxxVector) { let vec: Vec = vec .iter() .map(|s| s.to_string_lossy().into_owned()) .collect(); g(&vec); } fn g(vec: &[String]) { println!("{:?}", vec); } ``` ```cpp // src/main.cc #include "example/src/main.rs.h" #include #include int main() { std::vector vec{"fearless", "concurrency"}; f(vec); } ``` cxx-1.0.141/book/src/binding/fn.md000064400000000000000000000013471046102023000146570ustar 00000000000000{{#title Function pointers — Rust ♡ C++}} # Function pointers ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...namespace rust { template class Fn; template class Fn final { public: Ret operator()(Args... args) const noexcept; Fn operator*() const noexcept; }; ... ...} // namespace rust ``` ### Restrictions: Function pointers with a Result return type are not implemented yet. Passing a function pointer from C++ to Rust is not implemented yet, only from Rust to an `extern "C++"` function is implemented. ## Example Function pointers are commonly useful for implementing [async functions over FFI](../async.md). See the example code on that page. cxx-1.0.141/book/src/binding/rawptr.md000064400000000000000000000055101046102023000155670ustar 00000000000000{{#title *mut T, *const T — Rust ♡ C++}} # *mut T, *const T Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\] where possible over raw pointers, but raw pointers are available too as an unsafe fallback option. [std::unique_ptr\]: uniqueptr.md ### Restrictions: Extern functions and function pointers taking a raw pointer as an argument must be declared `unsafe fn` i.e. unsafe to call. The same does not apply to functions which only *return* a raw pointer, though presumably doing anything useful with the returned pointer is going to involve unsafe code elsewhere anyway. ## Example This example illustrates making a Rust call to a canonical C-style `main` signature involving `char *argv[]`. ```cpp // include/args.h #pragma once void parseArgs(int argc, char *argv[]); ``` ```cpp // src/args.cc #include "example/include/args.h" #include void parseArgs(int argc, char *argv[]) { std::cout << argc << std::endl; for (int i = 0; i < argc; i++) { std::cout << '"' << argv[i] << '"' << std::endl; } } ``` ```rust,noplayground // src/main.rs use std::env; use std::ffi::CString; use std::os::raw::c_char; use std::os::unix::ffi::OsStrExt; use std::ptr; #[cxx::bridge] mod ffi { extern "C++" { include!("example/include/args.h"); unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char); } } fn main() { // Convert from OsString to nul-terminated CString, truncating each argument // at the first inner nul byte if present. let args: Vec = env::args_os() .map(|os_str| { let bytes = os_str.as_bytes(); CString::new(bytes).unwrap_or_else(|nul_error| { let nul_position = nul_error.nul_position(); let mut bytes = nul_error.into_vec(); bytes.truncate(nul_position); CString::new(bytes).unwrap() }) }) .collect(); // Convert from Vec of owned strings to Vec<*mut c_char> of // borrowed string pointers. // // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467) // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258 // is implemented, and CStr pointers become thin, we can sidestep this step // by accumulating the args as Vec> up front, then simply casting // from *mut [Box] to *mut [*mut CStr] to *mut *mut c_char. let argc = args.len(); let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1); for arg in &args { argv.push(arg.as_ptr() as *mut c_char); } argv.push(ptr::null_mut()); // Nul terminator. unsafe { ffi::parseArgs(argc as i32, argv.as_mut_ptr()); } // The CStrings go out of scope here. C function must not have held on to // the pointers beyond this point. } ``` cxx-1.0.141/book/src/binding/result.md000064400000000000000000000104171046102023000155700ustar 00000000000000{{#title Result — Rust ♡ C++}} # Result\ Result\ is allowed as the return type of an extern function in either direction. Its behavior is to translate to/from C++ exceptions. If your codebase does not use C++ exceptions, or prefers to represent fallibility using something like outcome\, leaf::result\, StatusOr\, etc then you'll need to handle the translation of those to Rust Result\ using your own shims for now. Better support for this is planned. If an exception is thrown from an `extern "C++"` function that is *not* declared by the CXX bridge to return Result, the program calls C++'s `std::terminate`. The behavior is equivalent to the same exception being thrown through a `noexcept` C++ function. If a panic occurs in *any* `extern "Rust"` function, regardless of whether it is declared by the CXX bridge to return Result, a message is logged and the program calls Rust's `std::process::abort`. ## Returning Result from Rust to C++ An `extern "Rust"` function returning a Result turns into a `throw` in C++ if the Rust side produces an error. Note that the return type written inside of cxx::bridge must be written without a second type parameter. Only the Ok type is specified for the purpose of the FFI. The Rust *implementation* (outside of the bridge module) may pick any error type as long as it has a std::fmt::Display impl. ```rust,noplayground # use std::io; # #[cxx::bridge] mod ffi { extern "Rust" { fn fallible1(depth: usize) -> Result; fn fallible2() -> Result<()>; } } fn fallible1(depth: usize) -> anyhow::Result { if depth == 0 { return Err(anyhow::Error::msg("fallible1 requires depth > 0")); } ... } fn fallible2() -> Result<(), io::Error> { ... Ok(()) } ``` The exception that gets thrown by CXX on the C++ side is always of type `rust::Error` and has the following C++ public API. The `what()` member function gives the error message according to the Rust error's std::fmt::Display impl. ```cpp,hidelines=... // rust/cxx.h ... ...namespace rust { class Error final : public std::exception { public: Error(const Error &); Error(Error &&) noexcept; ~Error() noexcept; Error &operator=(const Error &) &; Error &operator=(Error &&) & noexcept; const char *what() const noexcept override; }; ... ...} // namespace rust ``` ## Returning Result from C++ to Rust An `extern "C++"` function returning a Result turns into a `catch` in C++ that converts the exception into an Err for Rust. Note that the return type written inside of cxx::bridge must be written without a second type parameter. Only the Ok type is specified for the purpose of the FFI. The resulting error type created by CXX when an `extern "C++"` function throws will always be of type **[`cxx::Exception`]**. [`cxx::Exception`]: https://docs.rs/cxx/*/cxx/struct.Exception.html ```rust,noplayground # use std::process; # #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/example.h"); fn fallible1(depth: usize) -> Result; fn fallible2() -> Result<()>; } } fn main() { if let Err(err) = ffi::fallible1(99) { eprintln!("Error: {}", err); process::exit(1); } } ``` The specific set of caught exceptions and the conversion to error message are both customizable. The way you do this is by defining a template function `rust::behavior::trycatch` with a suitable signature inside any one of the headers `include!`'d by your cxx::bridge. The template signature is required to be: ```cpp namespace rust { namespace behavior { template static void trycatch(Try &&func, Fail &&fail) noexcept; } // namespace behavior } // namespace rust ``` The default `trycatch` used by CXX if you have not provided your own is the following. You must follow the same pattern: invoke `func` with no arguments, catch whatever exception(s) you want, and invoke `fail` with the error message you'd like for the Rust error to have. ```cpp,hidelines=... ...#include ... ...namespace rust { ...namespace behavior { ... template static void trycatch(Try &&func, Fail &&fail) noexcept try { func(); } catch (const std::exception &e) { fail(e.what()); } ... ...} // namespace behavior ...} // namespace rust ``` cxx-1.0.141/book/src/binding/sharedptr.md000064400000000000000000000033311046102023000162430ustar 00000000000000{{#title std::shared_ptr — Rust ♡ C++}} # std::shared\_ptr\ The Rust binding of std::shared\_ptr\ is called **[`SharedPtr`]**. See the link for documentation of the Rust API. [`SharedPtr`]: https://docs.rs/cxx/*/cxx/struct.SharedPtr.html ### Restrictions: SharedPtr\ does not support T being an opaque Rust type. You should use a Box\ (C++ [rust::Box\](box.md)) instead for transferring ownership of opaque Rust types on the language boundary. ## Example ```rust,noplayground // src/main.rs use std::ops::Deref; use std::ptr; #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/example.h"); type Object; fn create_shared_ptr() -> SharedPtr; } } fn main() { let ptr1 = ffi::create_shared_ptr(); { // Create a second shared_ptr holding shared ownership of the same // object. There is still only one Object but two SharedPtr. // Both pointers point to the same object on the heap. let ptr2 = ptr1.clone(); assert!(ptr::eq(ptr1.deref(), ptr2.deref())); // ptr2 goes out of scope, but Object is not destroyed yet. } println!("say goodbye to Object"); // ptr1 goes out of scope and Object is destroyed. } ``` ```cpp // include/example.h #pragma once #include class Object { public: Object(); ~Object(); }; std::shared_ptr create_shared_ptr(); ``` ```cpp // src/example.cc #include "example/include/example.h" #include Object::Object() { std::cout << "construct Object" << std::endl; } Object::~Object() { std::cout << "~Object" << std::endl; } std::shared_ptr create_shared_ptr() { return std::make_shared(); } ``` cxx-1.0.141/book/src/binding/slice.md000064400000000000000000000112521046102023000153470ustar 00000000000000{{#title rust::Slice — Rust ♡ C++}} # rust::Slice\, rust::Slice\ - Rust `&[T]` is written `rust::Slice` in C++ - Rust `&mut [T]` is written `rust::Slice` in C++ ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...#include ...#include ... ...namespace rust { template class Slice final { public: using value_type = T; Slice() noexcept; Slice(const Slice &) noexcept; Slice(T *, size_t count) noexcept; template explicit Slice(C &c) : Slice(c.data(), c.size()); Slice &operator=(Slice &&) & noexcept; Slice &operator=(const Slice &) & noexcept requires std::is_const_v; T *data() const noexcept; size_t size() const noexcept; size_t length() const noexcept; bool empty() const noexcept; T &operator[](size_t n) const noexcept; T &at(size_t n) const; T &front() const noexcept; T &back() const noexcept; class iterator; iterator begin() const noexcept; iterator end() const noexcept; void swap(Slice &) noexcept; }; ... ...template ...class Slice::iterator final { ...public: ...#if __cplusplus >= 202002L ... using iterator_category = std::contiguous_iterator_tag; ...#else ... using iterator_category = std::random_access_iterator_tag; ...#endif ... using value_type = T; ... using pointer = T *; ... using reference = T &; ... ... T &operator*() const noexcept; ... T *operator->() const noexcept; ... T &operator[](ptrdiff_t) const noexcept; ... ... iterator &operator++() noexcept; ... iterator operator++(int) noexcept; ... iterator &operator--() noexcept; ... iterator operator--(int) noexcept; ... ... iterator &operator+=(ptrdiff_t) noexcept; ... iterator &operator-=(ptrdiff_t) noexcept; ... iterator operator+(ptrdiff_t) const noexcept; ... iterator operator-(ptrdiff_t) const noexcept; ... ptrdiff_t operator-(const iterator &) const noexcept; ... ... bool operator==(const iterator &) const noexcept; ... bool operator!=(const iterator &) const noexcept; ... bool operator<(const iterator &) const noexcept; ... bool operator>(const iterator &) const noexcept; ... bool operator<=(const iterator &) const noexcept; ... bool operator>=(const iterator &) const noexcept; ...}; ... ...} // namespace rust ``` ### Restrictions: T must not be an opaque Rust type or opaque C++ type. Support for opaque Rust types in slices is coming. Allowed as function argument or return value. Not supported in shared structs. Only rust::Slice\ is copy-assignable, not rust::Slice\. (Both are move-assignable.) You'll need to write std::move occasionally as a reminder that accidentally exposing overlapping &mut \[T\] to Rust is UB. ## Example This example is a C++ program that constructs a slice containing JSON data (by reading from stdin, but it could be from anywhere), then calls into Rust to pretty-print that JSON data into a std::string via the [serde_json] and [serde_transcode] crates. [serde_json]: https://github.com/serde-rs/json [serde_transcode]: https://github.com/sfackler/serde-transcode ```rust,noplayground // src/main.rs #![no_main] // main defined in C++ by main.cc use cxx::CxxString; use std::io::{self, Write}; use std::pin::Pin; #[cxx::bridge] mod ffi { extern "Rust" { fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>; } } struct WriteToCxxString<'a>(Pin<&'a mut CxxString>); impl<'a> Write for WriteToCxxString<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.as_mut().push_bytes(buf); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> { let writer = WriteToCxxString(output); let mut deserializer = serde_json::Deserializer::from_slice(input); let mut serializer = serde_json::Serializer::pretty(writer); serde_transcode::transcode(&mut deserializer, &mut serializer) } ``` ```cpp // src/main.cc #include "example/src/main.rs.h" #include #include #include #include int main() { // Read json from stdin. std::istreambuf_iterator begin{std::cin}, end; std::vector input{begin, end}; rust::Slice slice{input.data(), input.size()}; // Prettify using serde_json and serde_transcode. std::string output; prettify_json(slice, output); // Write to stdout. std::cout << output << std::endl; } ``` Testing the example: ```console $ echo '{"fearless":"concurrency"}' | cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/example` { "fearless": "concurrency" } ``` cxx-1.0.141/book/src/binding/str.md000064400000000000000000000046421046102023000150650ustar 00000000000000{{#title rust::Str — Rust ♡ C++}} # rust::Str ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...#include ...#include ... ...namespace rust { class Str final { public: Str() noexcept; Str(const Str &) noexcept; Str(const String &) noexcept; // Throws std::invalid_argument if not utf-8. Str(const std::string &); Str(const char *); Str(const char *, size_t); Str &operator=(const Str &) & noexcept; explicit operator std::string() const; // Note: no null terminator. const char *data() const noexcept; size_t size() const noexcept; size_t length() const noexcept; bool empty() const noexcept; using iterator = const char *; using const_iterator = const char *; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; bool operator==(const Str &) const noexcept; bool operator!=(const Str &) const noexcept; bool operator<(const Str &) const noexcept; bool operator<=(const Str &) const noexcept; bool operator>(const Str &) const noexcept; bool operator>=(const Str &) const noexcept; void swap(Str &) noexcept; }; std::ostream &operator<<(std::ostream &, const Str &); ... ...} // namespace rust ``` ### Notes: **Be aware that rust::Str behaves like &str i.e. it is a borrow!** C++ needs to be mindful of the lifetimes at play. Just to reiterate: &str is rust::Str. Do not try to write &str as `const rust::Str &`. A language-level C++ reference is not able to capture the fat pointer nature of &str. ### Restrictions: Allowed as function argument or return value. Not supported in shared structs yet. `&mut str` is not supported yet, but is also extremely obscure so this is fine. ## Example ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { extern "Rust" { fn r(greeting: &str); } unsafe extern "C++" { include!("example/include/greeting.h"); fn c(greeting: &str); } } fn r(greeting: &str) { println!("{}", greeting); } fn main() { ffi::c("hello from Rust"); } ``` ```cpp // include/greeting.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void c(rust::Str greeting); ``` ```cpp // src/greeting.cc #include "example/include/greeting.h" #include void c(rust::Str greeting) { std::cout << greeting << std::endl; r("hello from C++"); } ``` cxx-1.0.141/book/src/binding/string.md000064400000000000000000000062321046102023000155600ustar 00000000000000{{#title rust::String — Rust ♡ C++}} # rust::String ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...#include ...#include ... ...namespace rust { class String final { public: String() noexcept; String(const String &) noexcept; String(String &&) noexcept; ~String() noexcept; // Throws std::invalid_argument if not UTF-8. String(const std::string &); String(const char *); String(const char *, size_t); String(const char8_t *); String(const char8_t *, size_t); // Replaces invalid UTF-8 data with the replacement character (U+FFFD). static String lossy(const std::string &) noexcept; static String lossy(const char *) noexcept; static String lossy(const char *, size_t) noexcept; // Throws std::invalid_argument if not UTF-16. String(const char16_t *); String(const char16_t *, size_t); // Replaces invalid UTF-16 data with the replacement character (U+FFFD). static String lossy(const char16_t *) noexcept; static String lossy(const char16_t *, size_t) noexcept; String &operator=(const String &) & noexcept; String &operator=(String &&) & noexcept; explicit operator std::string() const; // Note: no null terminator. const char *data() const noexcept; size_t size() const noexcept; size_t length() const noexcept; bool empty() const noexcept; const char *c_str() noexcept; size_t capacity() const noexcept; void reserve(size_t new_cap) noexcept; using iterator = char *; iterator begin() noexcept; iterator end() noexcept; using const_iterator = const char *; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; bool operator==(const String &) const noexcept; bool operator!=(const String &) const noexcept; bool operator<(const String &) const noexcept; bool operator<=(const String &) const noexcept; bool operator>(const String &) const noexcept; bool operator>=(const String &) const noexcept; void swap(String &) noexcept; }; std::ostream &operator<<(std::ostream &, const String &); ... ...} // namespace rust ``` ### Restrictions: None. Strings may be used as function arguments and function return values, by value or by reference, as well as fields of shared structs. ## Example ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { struct ConcatRequest { fst: String, snd: String, } unsafe extern "C++" { include!("example/include/concat.h"); fn concat(r: ConcatRequest) -> String; } } fn main() { let concatenated = ffi::concat(ffi::ConcatRequest { fst: "fearless".to_owned(), snd: "concurrency".to_owned(), }); println!("concatenated: {:?}", concatenated); } ``` ```cpp // include/concat.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" rust::String concat(ConcatRequest r); ``` ```cpp // src/concat.cc #include "example/include/concat.h" rust::String concat(ConcatRequest r) { // The full suite of operator overloads hasn't been added // yet on rust::String, but we can get it done like this: return std::string(r.fst) + std::string(r.snd); } ``` cxx-1.0.141/book/src/binding/uniqueptr.md000064400000000000000000000026201046102023000163030ustar 00000000000000{{#title std::unique_ptr — Rust ♡ C++}} # std::unique\_ptr\ The Rust binding of std::unique\_ptr\ is called **[`UniquePtr`]**. See the link for documentation of the Rust API. [`UniquePtr`]: https://docs.rs/cxx/*/cxx/struct.UniquePtr.html ### Restrictions: Only `std::unique_ptr>` is currently supported. Custom deleters may be supported in the future. UniquePtr\ does not support T being an opaque Rust type. You should use a Box\ (C++ [rust::Box\](box.md)) instead for transferring ownership of opaque Rust types on the language boundary. ## Example UniquePtr is commonly useful for returning opaque C++ objects to Rust. This use case was featured in the [*blobstore tutorial*](../tutorial.md). ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; // ... } } fn main() { let client = ffi::new_blobstore_client(); // ... } ``` ```cpp // include/blobstore.h #pragma once #include class BlobstoreClient; std::unique_ptr new_blobstore_client(); ``` ```cpp // src/blobstore.cc #include "example/include/blobstore.h" std::unique_ptr new_blobstore_client() { return std::make_unique(); } ``` cxx-1.0.141/book/src/binding/vec.md000064400000000000000000000117551046102023000150350ustar 00000000000000{{#title rust::Vec — Rust ♡ C++}} # rust::Vec\ ### Public API: ```cpp,hidelines=... // rust/cxx.h ... ...#include ...#include ...#include ... ...namespace rust { template class Vec final { public: using value_type = T; Vec() noexcept; Vec(std::initializer_list); Vec(const Vec &); Vec(Vec &&) noexcept; ~Vec() noexcept; Vec &operator=(Vec &&) & noexcept; Vec &operator=(const Vec &) &; size_t size() const noexcept; bool empty() const noexcept; const T *data() const noexcept; T *data() noexcept; size_t capacity() const noexcept; const T &operator[](size_t n) const noexcept; const T &at(size_t n) const; const T &front() const; const T &back() const; T &operator[](size_t n) noexcept; T &at(size_t n); T &front(); T &back(); void reserve(size_t new_cap); void push_back(const T &value); void push_back(T &&value); template void emplace_back(Args &&...args); void truncate(size_t len); void clear(); class iterator; iterator begin() noexcept; iterator end() noexcept; class const_iterator; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; void swap(Vec &) noexcept; }; ... ...template ...class Vec::iterator final { ...public: ...#if __cplusplus >= 202002L ... using iterator_category = std::contiguous_iterator_tag; ...#else ... using iterator_category = std::random_access_iterator_tag; ...#endif ... using value_type = T; ... using pointer = T *; ... using reference = T &; ... ... T &operator*() const noexcept; ... T *operator->() const noexcept; ... T &operator[](ptrdiff_t) const noexcept; ... ... iterator &operator++() noexcept; ... iterator operator++(int) noexcept; ... iterator &operator--() noexcept; ... iterator operator--(int) noexcept; ... ... iterator &operator+=(ptrdiff_t) noexcept; ... iterator &operator-=(ptrdiff_t) noexcept; ... iterator operator+(ptrdiff_t) const noexcept; ... iterator operator-(ptrdiff_t) const noexcept; ... ptrdiff_t operator-(const iterator &) const noexcept; ... ... bool operator==(const iterator &) const noexcept; ... bool operator!=(const iterator &) const noexcept; ... bool operator<(const iterator &) const noexcept; ... bool operator<=(const iterator &) const noexcept; ... bool operator>(const iterator &) const noexcept; ... bool operator>=(const iterator &) const noexcept; ...}; ... ...template ...class Vec::const_iterator final { ...public: ...#if __cplusplus >= 202002L ... using iterator_category = std::contiguous_iterator_tag; ...#else ... using iterator_category = std::random_access_iterator_tag; ...#endif ... using value_type = const T; ... using pointer = const T *; ... using reference = const T &; ... ... const T &operator*() const noexcept; ... const T *operator->() const noexcept; ... const T &operator[](ptrdiff_t) const noexcept; ... ... const_iterator &operator++() noexcept; ... const_iterator operator++(int) noexcept; ... const_iterator &operator--() noexcept; ... const_iterator operator--(int) noexcept; ... ... const_iterator &operator+=(ptrdiff_t) noexcept; ... const_iterator &operator-=(ptrdiff_t) noexcept; ... const_iterator operator+(ptrdiff_t) const noexcept; ... const_iterator operator-(ptrdiff_t) const noexcept; ... ptrdiff_t operator-(const const_iterator &) const noexcept; ... ... bool operator==(const const_iterator &) const noexcept; ... bool operator!=(const const_iterator &) const noexcept; ... bool operator<(const const_iterator &) const noexcept; ... bool operator<=(const const_iterator &) const noexcept; ... bool operator>(const const_iterator &) const noexcept; ... bool operator>=(const const_iterator &) const noexcept; ...}; ... ...} // namespace rust ``` ### Restrictions: Vec\ does not support T being an opaque C++ type. You should use CxxVector\ (C++ std::vector\) instead for collections of opaque C++ types on the language boundary. ## Example ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { struct Shared { v: u32, } unsafe extern "C++" { include!("example/include/example.h"); fn f(elements: Vec); } } fn main() { let shared = |v| ffi::Shared { v }; let elements = vec![shared(3), shared(2), shared(1)]; ffi::f(elements); } ``` ```cpp // include/example.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void f(rust::Vec elements); ``` ```cpp // src/example.cc #include "example/include/example.h" #include #include #include #include #include void f(rust::Vec v) { for (auto shared : v) { std::cout << shared.v << std::endl; } // Copy the elements to a C++ std::vector using STL algorithm. std::vector stdv; std::copy(v.begin(), v.end(), std::back_inserter(stdv)); assert(v.size() == stdv.size()); } ``` cxx-1.0.141/book/src/bindings.md000064400000000000000000000111701046102023000144320ustar 00000000000000{{#title Built-in bindings — Rust ♡ C++}} # Built-in bindings reference In addition to all the primitive types (i32 <=> int32_t), the following common types may be used in the fields of shared structs and the arguments and returns of extern functions.
    name in Rustname in C++restrictions
    Stringrust::String
    &strrust::Str
    &[T]rust::Slice<const T>cannot hold opaque C++ type
    &mut [T]rust::Slice<T>cannot hold opaque C++ type
    CxxStringstd::stringcannot be passed by value
    Box<T>rust::Box<T>cannot hold opaque C++ type
    UniquePtr<T>std::unique_ptr<T>cannot hold opaque Rust type
    SharedPtr<T>std::shared_ptr<T>cannot hold opaque Rust type
    [T; N]std::array<T, N>cannot hold opaque C++ type
    Vec<T>rust::Vec<T>cannot hold opaque C++ type
    CxxVector<T>std::vector<T>cannot be passed by value, cannot hold opaque Rust type
    *mut T, *const TT*, const T*fn with a raw pointer argument must be declared unsafe to call
    fn(T, U) -> Vrust::Fn<V(T, U)>only passing from Rust to C++ is implemented so far
    Result<T>throw/catchallowed as return type only

    The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in the CXX GitHub repo. You will need to include this header in your C++ code when working with those types. **When using Cargo and the cxx-build crate, the header is made available to you at `#include "rust/cxx.h"`.** The `rust` namespace additionally provides lowercase type aliases of all the types mentioned in the table, for use in codebases preferring that style. For example `rust::String`, `rust::Vec` may alternatively be written `rust::string`, `rust::vec` etc. ## Pending bindings The following types are intended to be supported "soon" but are just not implemented yet. I don't expect any of these to be hard to make work but it's a matter of designing a nice API for each in its non-native language.
    name in Rustname in C++
    BTreeMap<K, V>tbd
    HashMap<K, V>tbd
    Arc<T>tbd
    Option<T>tbd
    tbdstd::map<K, V>
    tbdstd::unordered_map<K, V>
    cxx-1.0.141/book/src/build/bazel.md000064400000000000000000000050131046102023000150300ustar 00000000000000{{#title Bazel, Buck2 — Rust ♡ C++}} ## Bazel, Buck2, potentially other similar environments Starlark-based build systems with the ability to compile a code generator and invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge` command line interface. The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the *gen/cmd/* directory of the CXX GitHub repo. ```console $ cargo install cxxbridge-cmd $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc ``` The CXX repo maintains working [Bazel] `BUILD.bazel` and [Buck2] `BUCK` targets for the complete blobstore tutorial (chapter 3) for your reference, tested in CI. These aren't meant to be directly what you use in your codebase, but serve as an illustration of one possible working pattern. [Bazel]: https://bazel.build [Buck2]: https://buck2.build ```python # tools/bazel/rust_cxx_bridge.bzl load("@bazel_skylib//rules:run_binary.bzl", "run_binary") load("@rules_cc//cc:defs.bzl", "cc_library") def rust_cxx_bridge(name, src, deps = []): native.alias( name = "%s/header" % name, actual = src + ".h", ) native.alias( name = "%s/source" % name, actual = src + ".cc", ) run_binary( name = "%s/generated" % name, srcs = [src], outs = [ src + ".h", src + ".cc", ], args = [ "$(location %s)" % src, "-o", "$(location %s.h)" % src, "-o", "$(location %s.cc)" % src, ], tool = "//:codegen", ) cc_library( name = name, srcs = [src + ".cc"], deps = deps + [":%s/include" % name], ) cc_library( name = "%s/include" % name, hdrs = [src + ".h"], ) ``` ```python # demo/BUILD.bazel load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_rust//rust:defs.bzl", "rust_binary") load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") rust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), deps = [ ":blobstore-sys", ":bridge", "//:cxx", ], ) rust_cxx_bridge( name = "bridge", src = "src/main.rs", deps = [":blobstore-include"], ) cc_library( name = "blobstore-sys", srcs = ["src/blobstore.cc"], deps = [ ":blobstore-include", ":bridge/include", ], ) cc_library( name = "blobstore-include", hdrs = ["include/blobstore.h"], deps = ["//:core"], ) ``` cxx-1.0.141/book/src/build/cargo.md000064400000000000000000000241421046102023000150320ustar 00000000000000{{#title Cargo-based setup — Rust ♡ C++}} # Cargo-based builds As one aspect of delivering a good Rust–C++ interop experience, CXX turns Cargo into a quite usable build system for C++ projects published as a collection of crates.io packages, including a consistent and frictionless experience `#include`-ing C++ headers across dependencies. ## Canonical setup CXX's integration with Cargo is handled through the [cxx-build] crate. [cxx-build]: https://docs.rs/cxx-build ```toml,hidelines=... # Cargo.toml ...[package] ...name = "..." ...version = "..." ...edition = "2021" [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` The canonical build script is as follows. The indicated line returns a [`cc::Build`] instance (from the usual widely used `cc` crate) on which you can set up any additional source files and compiler flags as normal. [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html ```rust,noplayground // build.rs fn main() { cxx_build::bridge("src/main.rs") // returns a cc::Build .file("src/demo.cc") .std("c++11") .compile("cxxbridge-demo"); println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/demo.cc"); println!("cargo:rerun-if-changed=include/demo.h"); } ``` The `rerun-if-changed` lines are optional but make it so that Cargo does not spend time recompiling your C++ code when only non-C++ code has changed since the previous Cargo build. By default without any `rerun-if-changed`, Cargo will re-execute the build script after *any* file changed in the project. If stuck, try comparing what you have against the *demo/* directory of the CXX GitHub repo, which maintains a working Cargo-based setup for the blobstore tutorial (chapter 3). ## Header include paths With cxx-build, by default your include paths always start with the crate name. This applies to both `#include` within your C++ code, and `include!` in the `extern "C++"` section of your Rust cxx::bridge. Your crate name is determined by the `name` entry in Cargo.toml. For example if your crate is named `yourcratename` and contains a C++ header file `path/to/header.h` relative to Cargo.toml, that file will be includable as: ```cpp #include "yourcratename/path/to/header.h" ``` A crate can choose a prefix for its headers that is different from the crate name by modifying **[`CFG.include_prefix`][CFG]** from build.rs: [CFG]: https://docs.rs/cxx-build/*/cxx_build/static.CFG.html ```rust,noplayground // build.rs use cxx_build::CFG; fn main() { CFG.include_prefix = "my/project"; cxx_build::bridge(...)... } ``` Subsequently the header located at `path/to/header.h` would now be includable as: ```cpp #include "my/project/path/to/header.h" ``` The empty string `""` is a valid include prefix and will make it possible to have `#include "path/to/header.h"`. However, if your crate is a library, be considerate of possible name collisions that may occur in downstream crates. If using an empty include prefix, you'll want to make sure your headers' local path within the crate is sufficiently namespaced or unique. ## Including generated code If your `#[cxx::bridge]` module contains an `extern "Rust"` block i.e. types or functions exposed from Rust to C++, or any shared data structures, the CXX-generated C++ header declaring those things is available using a `.rs.h` extension on the Rust source file's name. ```cpp // the header generated from path/to/lib.rs #include "yourcratename/path/to/lib.rs.h" ``` For giggles, it's also available using just a plain `.rs` extension as if you were including the Rust file directly. Use whichever you find more palatable. ```cpp #include "yourcratename/path/to/lib.rs" ``` ## Including headers from dependencies You get to include headers from your dependencies, both handwritten ones contained as `.h` files in their Cargo package, as well as CXX-generated ones. It works the same as an include of a local header: use the crate name (or their include\_prefix if their crate changed it) followed by the relative path of the header within the crate. ```cpp #include "dependencycratename/path/to/their/header.h` ``` Note that cross-crate imports are only made available between **direct dependencies**. You must directly depend on the other crate in order to #include its headers; a transitive dependency is not sufficient. Additionally, headers from a direct dependency are only importable if the dependency's Cargo.toml manifest contains a `links` key. If not, its headers will not be importable from outside of the same crate. See *[the `links` manifest key][links]* in the Cargo reference. [links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key


    # Advanced features The following CFG settings are only relevant to you if you are writing a library that needs to support downstream crates `#include`-ing its C++ public headers. ## Publicly exporting header directories **[`CFG.exported_header_dirs`][CFG]** (vector of absolute paths) defines a set of additional directories from which the current crate, directly dependent crates, and further crates to which this crate's headers are exported (more below) will be able to `#include` headers. Adding a directory to `exported_header_dirs` is similar to adding it to the current build via the `cc` crate's [`Build::include`], but *also* makes the directory available to downstream crates that want to `#include` one of the headers from your crate. If the dir were added only using `Build::include`, the downstream crate including your header would need to manually add the same directory to their own build as well. [`Build::include`]: https://docs.rs/cc/1/cc/struct.Build.html#method.include When using `exported_header_dirs`, your crate must also set a `links` key for itself in Cargo.toml. See [*the `links` manifest key*][links]. The reason is that Cargo imposes no ordering on the execution of build scripts without a `links` key, which means the downstream crate's build script might otherwise execute before yours decides what to put into `exported_header_dirs`. ### Example One of your crate's headers wants to include a system library, such as `#include "Python.h"`. ```rust,noplayground // build.rs use cxx_build::CFG; use std::path::PathBuf; fn main() { let python3 = pkg_config::probe_library("python3").unwrap(); let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path); CFG.exported_header_dirs.extend(python_include_paths); cxx_build::bridge("src/bridge.rs").compile("demo"); } ``` ### Example Your crate wants to rearrange the headers that it exports vs how they're laid out locally inside the crate's source directory. Suppose the crate as published contains a file at `./include/myheader.h` but wants it available to downstream crates as `#include "foo/v1/public.h"`. ```rust,noplayground // build.rs use cxx_build::CFG; use std::path::Path; use std::{env, fs}; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let headers = Path::new(&out_dir).join("headers"); CFG.exported_header_dirs.push(&headers); // We contain `include/myheader.h` locally, but // downstream will use `#include "foo/v1/public.h"` let foo = headers.join("foo").join("v1"); fs::create_dir_all(&foo).unwrap(); fs::copy("include/myheader.h", foo.join("public.h")).unwrap(); cxx_build::bridge("src/bridge.rs").compile("demo"); } ``` ## Publicly exporting dependencies **[`CFG.exported_header_prefixes`][CFG]** (vector of strings) each refer to the `include_prefix` of one of your direct dependencies, or a prefix thereof. They describe which of your dependencies participate in your crate's C++ public API, as opposed to private use by your crate's implementation. As a general rule, if one of your headers `#include`s something from one of your dependencies, you need to put that dependency's `include_prefix` into `CFG.exported_header_prefixes` (*or* their `links` key into `CFG.exported_header_links`; see below). On the other hand if only your C++ implementation files and *not* your headers are importing from the dependency, you do not export that dependency. The significance of exported headers is that if downstream code (crate **ð’œ**) contains an `#include` of a header from your crate (**ℬ**) and your header contains an `#include` of something from your dependency (**ð’ž**), the exported dependency **ð’ž** becomes available during the downstream crate **ð’œ**'s build. Otherwise the downstream crate **ð’œ** doesn't know about **ð’ž** and wouldn't be able to find what header your header is referring to, and would fail to build. When using `exported_header_prefixes`, your crate must also set a `links` key for itself in Cargo.toml. ### Example Suppose you have a crate with 5 direct dependencies and the `include_prefix` for each one are: - "crate0" - "group/api/crate1" - "group/api/crate2" - "group/api/contrib/crate3" - "detail/crate4" Your header involves types from the first four so we re-export those as part of your public API, while crate4 is only used internally by your cc file not your header, so we do not export: ```rust,noplayground // build.rs use cxx_build::CFG; fn main() { CFG.exported_header_prefixes = vec!["crate0", "group/api"]; cxx_build::bridge("src/bridge.rs") .file("src/impl.cc") .compile("demo"); } ```
    For more fine grained control, there is **[`CFG.exported_header_links`][CFG]** (vector of strings) which each refer to the `links` attribute ([*the `links` manifest key*][links]) of one of your crate's direct dependencies. This achieves an equivalent result to `CFG.exported_header_prefixes` by re-exporting a C++ dependency as part of your crate's public API, except with finer control for cases when multiple crates might be sharing the same `include_prefix` and you'd like to export some but not others. Links attributes are guaranteed to be unique identifiers by Cargo. When using `exported_header_links`, your crate must also set a `links` key for itself in Cargo.toml. ### Example ```rust,noplayground // build.rs use cxx_build::CFG; fn main() { CFG.exported_header_links.push("git2"); cxx_build::bridge("src/bridge.rs").compile("demo"); } ``` cxx-1.0.141/book/src/build/cmake.md000064400000000000000000000023251046102023000150160ustar 00000000000000{{#title CMake — Rust ♡ C++}} # CMake There is not an officially endorsed CMake setup for CXX, but a few developers have shared one that they got working. You can try one of these as a starting point. If you feel that you have arrived at a CMake setup that is superior to what is available in these links, feel free to make a PR adding it to this list.
    --- - **** - Supports cross-language link time optimization (LTO) --- - **** - Includes a cbindgen component - Tested on Windows 10 with MSVC, and on Linux --- - **** - Alias target that can be linked into a C++ project - Tested on Windows 10 with GNU target, and on Linux --- - **** - Improved rusty_cmake CMake file to use modern C++ - Rich examples of using different primitive types and Rust's Result return to C++ - MacOS and Linux only --- - **** - Same blobstore example as the official demo, but inverted languages - Minimal CMake configuration - Tested on Linux, macOS, and Windows --- cxx-1.0.141/book/src/build/other.md000064400000000000000000000070741046102023000150650ustar 00000000000000{{#title Other build systems — Rust ♡ C++}} # Some other build system You will need to achieve at least these three things: - Produce the CXX-generated C++ bindings code. - Compile the generated C++ code. - Link the resulting objects together with your other C++ and Rust objects. *Not all build systems are created equal. If you're hoping to use a build system from the '90s, especially if you're hoping to overlaying the limitations of 2 or more build systems (like automake+cargo) and expect to solve them simultaneously, then be mindful that your expectations are set accordingly and seek sympathy from those who have imposed the same approach on themselves.* ### Producing the generated code CXX's Rust code generation automatically happens when the `#[cxx::bridge]` procedural macro is expanded during the normal Rust compilation process, so no special build steps are required there. But the C++ side of the bindings needs to be generated. Your options are: - Use the `cxxbridge` command, which is a standalone command line interface to the CXX C++ code generator. Wire up your build system to compile and invoke this tool. ```console $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc ``` It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the *gen/cmd/* directory of the CXX GitHub repo. - Or, build your own code generator frontend on top of the [cxx-gen] crate. This is currently unofficial and unsupported. [cxx-gen]: https://docs.rs/cxx-gen ### Compiling C++ However you like. We can provide no guidance. ### Linking the C++ and Rust together When linking a binary which contains mixed Rust and C++ code, you will have to choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you may already have extensively tuned. The generated C++ code and the Rust code generated by the procedural macro both depend on each other. Simple examples may only require one or the other, but in general your linking will need to handle both directions. For some linkers, such as llvm-ld, this is not a problem at all. For others, such as GNU ld, flags like `--start-lib`/`--end-lib` may help. Rust does not generate simple standalone `.o` files, so you can't just throw the Rust-generated code into your existing C++ toolchain linker. Instead you need to choose one of these options: * Use `rustc` as the final linker. Pass any non-Rust libraries using `-L ` and `-l` rustc arguments, and/or `#[link]` directives in your Rust code. If you need to link against C/C++ `.o` files you can use `-Clink-arg=file.o`. * Use your C++ linker. In this case, you first need to use `rustc` and/or `cargo` to generate a _single_ Rust `staticlib` target and pass that into your foreign linker invocation. * If you need to link multiple Rust subsystems, you will need to generate a _single_ `staticlib` perhaps using lots of `extern crate` statements to include multiple Rust `rlib`s. Multiple Rust `staticlib` files are likely to conflict. Passing Rust `rlib`s directly into your non-Rust linker is not supported (but apparently sometimes works). See the [Rust reference's *Linkage*][linkage] page for some general information here. [linkage]: https://doc.rust-lang.org/reference/linkage.html The following open rust-lang issues might hold more recent guidance or inspiration: [rust-lang/rust#73632], [rust-lang/rust#73295]. [rust-lang/rust#73632]: https://github.com/rust-lang/rust/issues/73632 [rust-lang/rust#73295]: https://github.com/rust-lang/rust/issues/73295 cxx-1.0.141/book/src/building.md000064400000000000000000000016711046102023000144370ustar 00000000000000{{#title Multi-language build system options — Rust ♡ C++}} # Multi-language build system options CXX is designed to be convenient to integrate into a variety of build systems. If you are working in a project that does not already have a preferred build system for its C++ code *or* which will be relying heavily on open source libraries from the Rust package registry, you're likely to have the easiest experience with Cargo which is the build system commonly used by open source Rust projects. Refer to the ***[Cargo](build/cargo.md)*** chapter about CXX's Cargo support. Among build systems designed for first class multi-language support, Bazel is a solid choice. Refer to the ***[Bazel](build/bazel.md)*** chapter. If your codebase is already invested in CMake, refer to the ***[CMake](build/cmake.md)*** chapter. If you have some other build system that you'd like to try to make work with CXX, see [this page](build/other.md) for notes. cxx-1.0.141/book/src/concepts.md000064400000000000000000000071131046102023000144550ustar 00000000000000{{#title Core concepts — Rust ♡ C++}} # Core concepts This page is a brief overview of the major concepts of CXX, enough so that you recognize the shape of things as you read the tutorial and following chapters. In CXX, the language of the FFI boundary involves 3 kinds of items: - **Shared structs** — data structures whose fields are made visible to both languages. The definition written within cxx::bridge in Rust is usually the single source of truth, though there are ways to do sharing based on a bindgen-generated definition with C++ as source of truth. - **Opaque types** — their fields are secret from the other language. These cannot be passed across the FFI by value but only behind an indirection, such as a reference `&`, a Rust `Box`, or a C++ `unique_ptr`. Can be a type alias for an arbitrarily complicated generic language-specific type depending on your use case. - **Functions** — implemented in either language, callable from the other language. ```rust,noplayground,focuscomment # #[cxx::bridge] # mod ffi { // Any shared structs, whose fields will be visible to both languages. # struct BlobMetadata { # size: usize, # tags: Vec, # } # # extern "Rust" { // Zero or more opaque types which both languages can pass around // but only Rust can see the fields. # type MultiBuf; # // Functions implemented in Rust. # fn next_chunk(buf: &mut MultiBuf) -> &[u8]; # } # # unsafe extern "C++" { // One or more headers with the matching C++ declarations for the // enclosing extern "C++" block. Our code generators don't read it // but it gets #include'd and used in static assertions to ensure // our picture of the FFI boundary is accurate. # include!("demo/include/blobstore.h"); # // Zero or more opaque types which both languages can pass around // but only C++ can see the fields. # type BlobstoreClient; # // Functions implemented in C++. # fn new_blobstore_client() -> UniquePtr; # fn put(&self, parts: &mut MultiBuf) -> u64; # fn tag(&self, blobid: u64, tag: &str); # fn metadata(&self, blobid: u64) -> BlobMetadata; # } # } ``` Within the `extern "Rust"` part of the CXX bridge we list the types and functions for which Rust is the source of truth. These all implicitly refer to the `super` module, the parent module of the CXX bridge. You can think of the two items listed in the example above as being like `use super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The parent module will either contain the definitions directly for simple things, or contain the relevant `use` statements to bring them into scope from elsewhere. Within the `extern "C++"` part, we list types and functions for which C++ is the source of truth, as well as the header(s) that declare those APIs. In the future it's possible that this section could be generated bindgen-style from the headers but for now we need the signatures written out; static assertions verify that they are accurate.

    Be aware that the design of this library is intentionally restrictive and opinionated! It isn't a goal to be flexible enough to handle an arbitrary signature in either language. Instead this project is about carving out a highly expressive set of functionality about which we can make powerful safety guarantees today and extend over time. You may find that it takes some practice to use CXX bridge effectively as it won't work in all the ways that you may be used to.
    cxx-1.0.141/book/src/context.md000064400000000000000000000143471046102023000143320ustar 00000000000000{{#title Other Rust–C++ interop tools — Rust ♡ C++}} # Context: other Rust–C++ interop tools When it comes to interacting with an idiomatic Rust API or idiomatic C++ API from the other language, the generally applicable approaches outside of the CXX crate are: - Build a C-compatible wrapper around the code (expressed using `extern "C"` signatures, primitives, C-compatible structs, raw pointers). Translate that manually to equivalent `extern "C"` declarations in the other language and keep them in sync. Preferably, build a safe/idiomatic wrapper around the translated `extern "C"` signatures for callers to use. - Build a C wrapper around the C++ code and use **[bindgen]** to translate that programmatically to `extern "C"` Rust signatures. Preferably, build a safe/idiomatic Rust wrapper on top. - Build a C-compatible Rust wrapper around the Rust code and use **[cbindgen]** to translate that programmatically to an `extern "C"` C++ header. Preferably, build an idiomatic C++ wrapper. **If the code you are binding is already *"effectively C"*, the above has you covered.** You should use bindgen or cbindgen, or manually translated C signatures if there aren't too many and they seldom change. [bindgen]: https://github.com/rust-lang/rust-bindgen [cbindgen]: https://github.com/eqrion/cbindgen ## C++ vs C Bindgen has some basic support for C++. It can reason about classes, member functions, and the layout of templated types. However, everything it does related to C++ is best-effort only. Bindgen starts from a point of wanting to generate declarations for everything, so any C++ detail that it hasn't implemented will cause a crash if you are lucky ([bindgen#388]) or more likely silently emit an incompatible signature ([bindgen#380], [bindgen#607], [bindgen#652], [bindgen#778], [bindgen#1194]) which will do arbitrary memory-unsafe things at runtime whenever called. [bindgen#388]: https://github.com/rust-lang/rust-bindgen/issues/388 [bindgen#380]: https://github.com/rust-lang/rust-bindgen/issues/380 [bindgen#607]: https://github.com/rust-lang/rust-bindgen/issues/607 [bindgen#652]: https://github.com/rust-lang/rust-bindgen/issues/652 [bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778 [bindgen#1194]: https://github.com/rust-lang/rust-bindgen/issues/1194 Thus using bindgen correctly requires not just juggling all your pointers correctly at the language boundary, but also understanding ABI details and their workarounds and reliably applying them. For example, the programmer will discover that their program sometimes segfaults if they call a function that returns std::unique\_ptr\ through bindgen. Why? Because unique\_ptr, despite being "just a pointer", has a different ABI than a pointer or a C struct containing a pointer ([bindgen#778]) and is not directly expressible in Rust. Bindgen emitted something that *looks* reasonable and you will have a hell of a time in gdb working out what went wrong. Eventually people learn to avoid anything involving a non-trivial copy constructor, destructor, or inheritance, and instead stick to raw pointers and primitives and trivial structs only — in other words C. ## Geometric intuition for why there is so much opportunity for improvement The CXX project attempts a different approach to C++ FFI. Imagine Rust and C and C++ as three vertices of a scalene triangle, with length of the edges being related to similarity of the languages when it comes to library design. The most similar pair (the shortest edge) is Rust–C++. These languages have largely compatible concepts of things like ownership, vectors, strings, fallibility, etc that translate clearly from signatures in either language to signatures in the other language. When we make a binding for an idiomatic C++ API using bindgen, and we fall down to raw pointers and primitives and trivial structs as described above, what we are really doing is coding the two longest edges of the triangle: getting from C++ down to C, and C back up to Rust. The Rust–C edge always involves a great deal of `unsafe` code, and the C++–C edge similarly requires care just for basic memory safety. Something as basic as "how do I pass ownership of a string to the other language?" becomes a strap-yourself-in moment, particularly for someone not already an expert in one or both sides. You should think of the `cxx` crate as being the midpoint of the Rust–C++ edge. Rather than coding the two long edges, you will code half the short edge in Rust and half the short edge in C++, in both cases with the library playing to the strengths of the Rust type system *and* the C++ type system to help assure correctness. If you've already been through the tutorial in the previous chapter, take a moment to appreciate that the C++ side *really* looks like we are just writing C++ and the Rust side *really* looks like we are just writing Rust. Anything you could do wrong in Rust, and almost anything you could reasonably do wrong in C++, will be caught by the compiler. This highlights that we are on the "short edge of the triangle". But it all still boils down to the same things: it's still FFI from one piece of native code to another, nothing is getting serialized or allocated or runtime-checked in between. ## Role of CXX The role of CXX is to capture the language boundary with more fidelity than what `extern "C"` is able to represent. You can think of CXX as being a replacement for `extern "C"` in a sense. From this perspective, CXX is a lower level tool than the bindgens. Just as bindgen and cbindgen are built on top of `extern "C"`, it makes sense to think about higher level tools built on top of CXX. Such a tool might consume a C++ header and/or Rust module (and/or IDL like Thrift) and emit the corresponding safe cxx::bridge language boundary, leveraging CXX's static analysis and underlying implementation of that boundary. We are beginning to see this space explored by the [autocxx] tool, though nothing yet ready for broad use in the way that CXX on its own is. [autocxx]: https://github.com/google/autocxx But note in other ways CXX is higher level than the bindgens, with rich support for common standard library types. CXX's types serve as an intuitive vocabulary for designing a good boundary between components in different languages. cxx-1.0.141/book/src/cxx.png000064400000000000000000002140141046102023000136250ustar 00000000000000‰PNG  IHDRx9Ð<wsRGB®Îé IDATxœìÝ{Œ+g}øÿÏž„¨ihf¡ˆ{¶‚–xLi©ZǪ¾Š¸Ú …‚¸x\µRoêz«^„Új½T UH¬·UÿBªg[PKI´³\«”âY èÎA$•*ÏФ@ØYQ’B”ãßç7ƒçb{Æk{ìÝ÷K²z<žñ|æ™ç™mx>~>kƒÁàq¹Y€ ìcû˜|îsŸ“~¿/ßøÆ7äᇖ«W¯æ€žýìgË]wݼî¾ûnÙØØg<ãy‡ÌÌ ¸ˆþïÿþO>üáË}÷Ý'÷ß¿<ñÄy‡`Æ^þò—Ëk_ûZyÛÛÞ&wÜqGÞágB‚.”Á` ûûûòñòðÃ瀸ùæ›åÿðåï|§ÜrË-y‡L…\GGGòû¿ÿûòÕ¯~5ïPäàYÏz–ìììÈoýÖoÉ 7Üw8@&$xàBø“?ùyï{ß›w–@¥R‘ÃÃCQ%ïP€ÔHðÀ¹öƒü@Þþö·Ë‡?üá¼C°D~æg~F>õ©OÉwÞ™w(@*$xàÜúÞ÷¾'¯|å+峟ýìÄ}o½õVyík_+¯ýë¥X,Êm·Ý&·Ýv›<ýéO_@¤Îâ¿ÿû¿å±Ç“G}T>ùÉOÊÁÁ¸®;ñ¸;î¸Cþõ_ÿU~ögvQgC‚έ{î¹Gî¿ÿþ±û¼ð…/”w¿ûݲ±±± ¨,¿øEù«¿ú+¹ï¾ûÆîwûí·Ë—¾ô%yÎsž³ È€é\Ê;`677Ç&w ùçþgyðÁIîΡ_ø…_{ï½W¾øÅ/ÊË_þò‘û=úè£òêW¿Zžxâ‰FdÇ 8wºÝ®üÆoüÆÈÏ_ö²—É'?ùI¹|ùò£—k×®ÉoÿöoËûßÿþ‘û¼îu¯˲dmmm‘é‘à€såêÕ«òS?õSòä“O&~þú׿^þñÿQnºé¦G o»»»òGôGríÚµÄÏMÓ”F£±à¨€tHðÀ¹òÆ7¾Qî½÷ÞÄÏþßÿûò/ÿò/ré• €‹ê¯ÿú¯ess3ñ³ç<ç9òµ¯}M~ìÇ~lÁQ“ñ¿làÜøüç??2¹ã…/|¡Ü\pð ¿ù›¿™øÙ7¿ùMyï{ß»àˆ€tXÁçÆK^ò9>>Žmæ3Ÿ)ÇÇÇrçwæ€eóÔSOI¥R‘Ï~ö³±Ïn¹åy衇äYÏzV‘£ñóEœ Ÿÿüç“;DDÞ÷¾÷‘Ü pà 7È?øA¹ñÆcŸ}ÿûß—÷¿ÿý9DŒG‚Î…|ä#‰ÛŸûÜçÊ[ßúÖG`Ù yÇ;Þ‘øÙ¨ÿ¾òD‚Î…ÃÃÃÄí¿÷{¿'—.ñÿöˆûßùÄíÿþïÿ.ßùÎw 0ÿK7Vžëºòàƒ&~öæ7¿yÁÑX/}éKåŽ;îHüì¾ûî[p4Àx$x`å}þóŸOÜ~÷ÝwËsŸûÜG`•üú¯ÿzâö/~ñ‹ ެ¼‡~8qûÞð†G`ÕŒúï†o~ó› Ž¬¼QÿÃk¹\^p$Vͨÿn ÁËæÆ¼ÎjÔÿðzë­·.8`õ¸®+ûûûâ8Žxž—ê]×essSTUstX„V«%W®\ Þ7 1 #Lj–m%Òétäðð0õþº®K­VMÓæ–‘iš²¿¿¼/•JÒétrŒí–[n‘K—.ɵk×BÛIðÀ²!Á+oÔÿðª(Ê‚#VO«ÕÊ4Y+"bÛ¶œœœ0QwN8Ž#GGGÁûJ¥’c4é½ãï¯ýë¡m–eÍ5ñhUÛjV:Žlmme:ƶm1MSúýþœ¢Â²r]WlÛÞƒ£&SENNNBÛ¾ûÝïÊ“O>)O{ÚÓrŠ #Á+ïÿ÷·ßtÓM ŽX=iWí˜ÕqÀ¬|á _ÿú¯ÿ mûÁ~S4ÇuݼC€‰n¹å–X‚‡ˆÈc=&·ß~{q$xiV$Ð4MÚíö¢°LZ­–ˆ\_)eÇqäôôtÞ!p¡à /§Q­V+HôG×õP9pv—òð#¦iJ¹\–±ePüýšÍ&åR€ €<`‰´Z-9==Çq¤R©$þRÞ󚦅öI«V«…¾GQ” Íz½^b,Ó\·ªª¡ï)•J#÷O:ïöövêómooÇŽïõz©Žöÿ¼ý~`Fì:¢/UUÝnwª8£1v»ÝA±XLu-ïyÏ{BûüÒ/ýRª|½^oâµù÷¿ßïm«,çLº¾áW±Xôz½A¯×›Øþ“ôûý®ë©Æœ®ëÁuμŸ-g‘4Þ|ÇÇÇ©ÚLÓ´Ägm§ÓIÕ¯ÚíöÔñ§ÑµZ­©ž•Ãúýþ@Ó´TýȯÑñ^©TÎ0owÞygb¿~ä‘Gò P¢(ºJÃxž'Ífsªû<üÕjUšÍfl%‚yèt:R­VS•³0MSÊå²ìíí霦iJµZx}®ëJµZ•jµ:±ýÇ}—?†Òö;Û¶¥\._èÒIþ½NÓfŽã„î§çy²±±!­V+U¿j·Û™Ÿ_~ŒÕj5Óó¤ÓéÈúúúÔ÷6Kß°m[ªÕªlmmQ.æ€-°@µZ-–`0KŠ¢ˆasûþ´üÉÏ蟢(R¯×cËø;Ž#¶m‡Ê£”J¥Ð>š¦‰iš²±±l³,KÚívªäÛ¶ceoºÝn¬4…aA_³ÙMÓ‚DqZ­V¨ ‰¢(bYÖ\J}ÌÃÞÞ^辕J%)‹¢iš8Ž#ŽãÄÊÁˆˆìììH±XÌÜÿüäŽE%˜¦)[[[‰Ÿ)Š"º®‹¦iAi+W®ˆçyÒjµÎtÎèd~¥R‘z½œ+ÚçD~T¦GÓ´Lý'é|"×Kâèº.Åb1ñœ~’ÂñññÊô×Y‰¶Y¥R Æ»ßï£å›<Ï“v»$]ø}xT?J:§O¦‰q8Vÿ|~¼–e…Îé³^¯—ê9æsG666F&køçö%»,÷(©ï*iÓëõŠ¢„öÍRrɿƤò@£îK¿ß]ߤ±‘ƪ•hIÓVIãLDõz=ÔvIω¤v‘A­VKóÁÁAâ±ãÆ[Rß4F‡œœ$–ReÐívG^g´ Öð¸–%Z° HðÀÊ#ÁçAÚÉÐáý …ÂÂΛEÒä^ÖIêÝÝÝ‘“àƒÁ`Ðh4b“–ãÎä,•Jc899‰§iÚÈý“&ÖÓ&iœœœÄ’uÒNÂ×'U§MöIJðH3ÁŸÔ>“ŽNG'Ç%•DM“à1êZ'µÕÉÉIâ±iîo´¯N:fww÷LÉI}=ÍõEËÒÿ’¬b‚‡¢(ÛjT’Gš{urr’˜•æþdMP>6ËslÒµŽK€¶¹¹I‚V X—;×uƒ …‘û —þˆ–9Y¶mÇJÐt»ÝL%D®—9WêÃ4M©T*Á{Ïó¤Ùl&–0 #Tª P(ˆmÛcPUU,ËEQ‚mŽã$–HH:£ÑHU:Æ?—®ë¡W–û[,cÇO[b£R©ˆiš©b¶m;Ö_÷÷÷G–sˆî÷FCÇI]®"+˲BãGäG×:©­ü¾0nlŽ“J½´Z­Ðy²´§i𡾮(ŠØ¶úú¢ßuÑt:‰mÕjµBÏŸ¢(Ë’¨ªšøL˜Tž¨Õj…ú@Ú1êŸÓ¶íØslÒñžçÅJZùý)ͳ©ÓéH­VK# =<` \½z5øwÚ‰ýi'ðç):ÁY©TÆ&jœ…eYR*•‚÷IɦiÊþþ~ð^Q±,+uÛ‹ÅX2ˆiš±ÉQÃ0B“´¥Riâdï²Ê’`¡ªjâDqÖä€,ÖÓŠ~¿¢(™Î©ªjæ¤*Û¶cóiú^ô¤IH‰¿4 ¾b±(F#xML9ï …Bªg•ªª‰ k†aLuo'q]7ô É>¾TUõhòFTÒ9²<;E$sb`2< g눌NðˆNò.Ûä™ëº™W+8 ?¹`ø—é–e¿wG¶¶¶Bǘ¦™¹Ý4M“n·ÚÖl6ƒ„ŽN§ºî´«&œº®ÇV¶ˆ®1ŽŸt3OžçÅú¦as_'ºòFÚÉýh\“Vxð÷‰®T“5¹jxÇqR¯rÔëõÔû&õ›´mt츞hbF­V›ªß†§®ëŽwÑR©4·Õué‘à9K›àµl ÑIJEQ2MšNCÓ´ØywvvÄ4MÙØØMPoooOa²½½ÚV­VÅ4ÍXÉEJîðE'·£¥PÆiµZso¯¤‰y­,3é¼óÓôõhòÓ"ãÏ[–į¤gô¼îfq_}YV†NYÌxLvcÞÀEw^Vðˆþ|Qñù+l —g‰–ji4ÁÊÓj·Û¡r žçÅÎÓív—î¾,‚®ë±’Žã¤j‹y'‰$'-â>%µË4Ò$ÀD¯ñèèHªÕê™Îë8Î…Yµá,«¹ —Šš%Ïób‰g¹º®‡Ê½&–’JJü¸(ý– ³iWðX6Ó–£˜Ã0ÄqÙÛÛ‹}V*•'1§Ñétb¥0|›››öWîI}6MyB¡°D‹h,‹J‰¶Ë¸†EWÎHoôg±úÆE*ÑróZ&éžåïCôØèßžqÛ/bâ,#J´@Φ]ÁcÙ~Qw9‡N§#F#´MQ”™–LQUUlÛEQBÛkµÚÌ’HVÑ´“΋JfÊ«o‹E) Áû£££‘“ê>ÏóB%nEI5Öó8?&õQ@~XÁ¨ÓéÈÎÎÎØ_Ư¯¯§ú®µµµØ6]×åàà`n¿(çôôtáçœäòåËsùÞõõõЄú¼Î³Ê.RyqZ­–lmmï·¶¶äàà`äþN'ô|hµZ©Î½^/c¤q«ºšÐy‘vÅ—³p]wâ}Îãï  °@ýó`Û¶˜¦™zRx– …‚\½zuáçõu:Ùßßms]WªÕªôz½™MRÖëõØj ¦iJ¡Pv»=“sœ”t¸®ÕjI§Ó ƆeYÒl6eww7Ö'wvvdgg'x¯(Jê±\©TB+ˆ,ß*?ÈF×õP˜‡4I<”ê€åA‰X hiyÈëW÷Ñó.rRжíPòL©T þí8ÎÌkZ­Vh½R©ÿÞÙÙÓ4gržU³ìåAòN6‰®ðb𦬝¯K³Ù”i6›rùòåX‚eY¬ž€³”OI{lÞã0+xÀÙ¶-N'˜hó. qÖ2óÖjµbå0LÓ”r¹<²,†eY²µµ%—/_M‚G÷M*™²½½jÅÓ4CÉ1ã&!ýx¢Û&•Ɖ–„¹>©?)YÃu]i·Û¡WÖèñÓ&xˆüè~%Åà'Ç$­‚’ö^ä%)ùÄOhHZmÀ¶mÙØØˆ­R’Åpb‘eYrùòeY__—jµ:öµµµ%{{{™Ë\†‘8þF]£Èõþ···'ëëësOBÁtLÓ %‰\¶T«ÕØ}õç8ÎȉÛF£‘ú^äEÓ4év»±û뺮ÔëuQU5¸GÑk­T*ây^¬ÔÅ$­V+6ïºîÄœáäšb±(ív;–¸1ʨñç—Ý^½aÜ=ug%úìE išØ¶-º®Ëééi°Ý¶í ¯ø h£îg©TÊ”8æ?3£çô>žº‹LN,ñU*• ÿLólL¶6 ‘›ó˜V©T’¯|å+±í<ð€¼èE/Ê!" ÏóRM†¥Ý/ ]×åèè(x? fúýÃ<Ï˲‚¥ü]× Êhš&š¦œTŽ–.¥1m,ÑDžñŒgÈw¿ûÝжáò$ÓH*Å¡iZì>&Å“åÜiÏ“$Z¢#z^ÿÿúm¯ëzêUgFÅy–ûøõ¯]zè¡à½¢(¡ò;iù+øí ëº‹Åàÿ›ÔVÃ\×­¸Q(Ä0Œ‰÷f¸½¯^½û|šS&?]×gú|Yä³%«¤ñ–v¼ˆœ½GŸggyÎ8Žô…ÿYê—š%×uÅ4Í  üséºkƒYŽw`îºë.yøá‡cÛyä¹ýöÛsˆˆ#Á+`zÑIØv»=ñ˜áE$«×ërxx¼¯Õjbšfæ wÛ¶Å0ŒX¢G¿ßÏe• ÇqB×5ŠŸà[¦HB‚VÁyXi¾T*I·Û×uIîà‚c€9Óu]t]Vïp]WlÛ‘ë+zxž'ÅbQD®¯üá—„dÆ IDAToñ·à° ªªŠay‡V%Z– KŽ-9rGNOOŶmÑu]EMÓrŽ ,<\HŽãÈÖÖVh[¯×Ë)çy²³³#¦iŠçy#÷ 3?·®ë²¶¶¼ßÝÝ%™ä‚2MSö÷÷ƒ÷¥RI:NŽÆ!ÁÀ…äy^ðky,Ÿ×½îuòÑ~4´íèèH^ñŠWäÑb|ðƒ”·½ím¡m¿û»¿+û·›SD˜Û¶eccclbÇ<…Þçòçºnèoá<гs)ï. ˲¤Z­’T2c€p]WšÍfh[£Ñz½.º®‹ªª"r}…ÇqXe„à°ív;´rG·ÛÃ0bûéº.º®K«ÕZdx`ÉQ¢`Î\וýýýà}¥RILî…<Kç#ùHÞ!äâ­o}«¼õ­oÍ; ÌeY¡÷õz=§HÀª"Á€3Òu]ÖÖÖ‚÷½^/Çh°ŒlÛ½×4-§HÀª"Á€3:::Ê;,9Ïóò¬¸Ky€ñHðXr$x,9<–ÜyççyråÊñVØÝwß=‘ØëÈ;4,Èñññ@Ó´Ä~}†1899ôz½ØgYôûý®ë©Î)"ƒV«5ók‰¾Æ\b÷_Åbqppp0ò{···CûoooŸœœ Úívâ÷öz½ØwÝwß}¡}._¾œêÚF}w·Û‹ÅT×ÙétÆž£R©LuÒöµo¼1´ïý÷ߟêÚ}Ýnw ªjêXt]ôûýL父ßÎ'''©ûVÚ11O'''Ã02Ý»v»=899™øÝÓöáq3/£ÆÉîînêqÒívÏÃ4ýôøø8Ó9¢ý´R©¤>6éoDÒ³jÒ9ýc²ö¬ü6m6›¡•ÆiµZÒjµæÙìyž'†aH³Ù»"K”mÛS÷‰aŽãÈúúzêïét:¹¶³¯iš™Žk·ÛR­V3µñ²óŸ [[[©ÇI³ÙœzLOÛO«Õjæûµ LÓÌ4ÆÚí¶t:ÌçØØØHÕ¦žçI»Ý–r¹Z!#-Û¶3=S‡Ï;‹{˜¶=£«µN5n£«­ VïJ´XY~â@Ò„M¡Pz½.š¦‰ªªâ8ŽØ¶-GGGây^æÉ³IçôË‘øËÇÛ¶,]ï³,KZ­ÖÈs·ÛíÐ÷*Š"­V+¸Žáü—išrzz*"2qYÿQ±—J¥PìÃûû%M†÷ÍbÜ=¹¾Ìý¬J$i6›Á¿E‘z½,ÑﺮX–´ß°½½=Ñ4-±œCR;GKmT*•³†ž™®ë±ÉÚB¡ ­VK4M]×ÅuÝà¾îííûù¯Ýn7u ‹aŽãÈÎÎNpŸ†hš&š¦e>’ÚzooOZ­ÖÌK'¥‰wÔ8öûÈpì¦i†î±|¯×Ù£}ÀqœÐõ …Äë^t[ˆˆlmmÿöŸÅbQŠÅbð¬IJŠÛÙÙMÓ¤^¯§>—a±ÒIýÔï3ÃÏ8Ïó‚1=M?̓ã8¡öM;6vvvÄ0ŒTÏG˲BϺa¥R)øây^П¯^½ÜÛ³òûŒ_Æçy^ðwoøú¶¶¶‚6ÈÊ4͑ת(Jè;[­V¨\–OÖ¾3ü¬ô¿r3 D V%Z.®R©»ïŠ¢Œ-ÐëõŠ¢Œ]Ö}”“““Xù”B¡0¶l@Òù’ÊaôûýØu¤-Gppp0¨T*c—Œï÷û±%æE[reøXÿqKÜG—úßÜÜŒµ—¢(ƒÍÍ͉×6«-þk{{{dYhÜþKUÕT¥8’Î{Ó”hi4±vwwÇÓï÷c%TUMÕïF•©×oONNÛÜÜœx¾Y:99‰•–(•J¯;i,뺞ú¼Ñk_D)–QF“q}¦×ë%>s³Œ“¤±6©Ÿžœœ jµZì¸iúi%ZÒü­è÷û‰m;©mƒäò!~Ÿo·ÛMŒ3MœœçHSªçøøxª±“4f’ÚµÛíŽ,3}6jš6ñ¼ÑØ£çÌZÒ «ƒ-X$x`å‘àq1%MN•J¥Tý~?1Éc’ÍÍÍØdvš‰žèDaR’ÄÁÁÁ\'½£eYH|ÇÇÇcBF%Jø¯Z­–z"x– i&e“& ³LÂgíKãdMðˆö´×ì‹Nž§™5‰=é¼'''ƒB¡p¦ ׳Š^oÚçÆ`ÜOÒö‘eNðHû<899ILDHs-I i’|щúb±8ñ˜eJð˜Ô¾'''±¾•&ޤ䮴ÏÚ¤kLÛFYûoÒßìIm2ª-ýWš˜iï£/Ú¾µZ-õ±X=$x`\XAív;ô^Q1M3ÕröÅbQLÓÌt>Ïóbe,ËJUNA×ui4Áûè÷ˆHl™üY–-ñKÓ ³,+óòøYK1 k4bYÖ\˱$ÙÝÝ]×'î§iZbŸHºWË&Z. í5ûLÓ”B¡¼÷KÿdÕh4&žWUÕXšE‰ˆ´¢¥F²<7D®÷˲BÛöööF– Zív;Õó@UU±m[E m–°uŽaÛÛÛ™Jet:P‰(¿ÔÈ*ØÜܜؾIc#Zr)*éïR©TJݧu]—ÍÍ͉û%‰ÞÏI ÈõÛ¶§:·ˆH¯×KU*E×õXi±,ý&ZšhUJ8¿Hð°rlÛ–«W¯†¶µZ­L Y :Nh·R©dšDN†E'‰£f9a=wÖØÏªV«å6›¥OÔëu©Õj¡m®ëN¼Wy2M34 …BªIÏaªªÆúÈÎÎNæXÒ&ÿ,²ïEu:Ð{Ã02':éº.•J%xïy^ì{WMÖggôz=Ï;N¢IfŠ¢LÕO£ÇLÓOóöZ£ ƒ“þ$=W;N¦¿o‹Lº‹ö³iŸ­Ýn7Ós$Úþûûû©þÆš¦Ú¯P(Lä³B‚€•R%ó¯‰Ïzάç+‹¡_G¹ØÛßߟÉÊ®ëÆVïÈ:±zŠ¢¬ÔäwÒ}=˯Ìç-Ú/§ýuyô×õ®ëfºnEQRO|&M(/¢“V;˜v,$M_$YWcˆ&"†1Uba¡Õf–=KäzR@š•žD²'?E¯½T*åš@5IÖdª$•J%ós®^¯Çúkš¤Ãhû’Ü`à`åD'ç=éâºnh©üB¡0Õ$Úð1Ñäè5xž'Õj5õ/G‰¶U–‰øY0 #õäæ2Ð4-¶œÿ"Kˆd-p–{íÓY’.f1q;oÑëÉ2ñm+×uÅuÝ©c[EÑ67Nf9Q~–~š‡yŽhòÞ²—™Åj!Ó$sªªk›Ie…<Ï‹=_™ £à`å '[ˆÌ¿äCtâöêÕ«²¶¶–ù5nBIUUÙÜÜ mó—yõŽYPeêkŒ&gLZ¥(ºÂG¥RY©dEç VJÒ¯äç=é2_ˆ'MJ¶ÛíØê>ÇqÄ4MiµZR.—e}}]šÍæÄU¢Ÿ/zp'W%æh¢Ï¨¾“Vt":šH•åØe ³~nœe¥U”öžÏº]¢÷m™WØY´e‡~‰0ÿ•å™’ä,Ïæb±(µZ-´m\™–hÙ¥e_ÀÅA‚€•ržË ¨ª*¶mÇ&¡’¸®+¦iÊúúúØ•AòœtV%·sŸEÒjË8y鬫hD_Æk^fçùÙ”VRD· …E…s®-[b‹ëº²¿¿/R.—emmMÖ××E×õàuÖUnΚÀMÒUÍuÝPû.º´ŒC‚d´½½-ƒÁà̯$ªªŠeYÒívSO„¶Z-i6›‰Ÿå9I¿l¿&æ‰äçMR‰+œÝ²$`™¦)ÕjUÖ××Å0 ±,ké’O|õz=öw5ih"J½^_‰2T.<` †!®ëJ¿ß—ÝÝ]i4c>LÓ”N§Û>ïò5çQÒÄé*LîµüÁ²NÊ®ŠU)í3OII]$zÍGÞýÍq)—ËÒl6G–1«T*R©Td{{[¶··¥R©,8ʸV«z-Å""±U±¢Ç@žHð°Rò˜ÔŠžsÔdÖ<‹EiµZb𦏮+'''Òív'Êvvv&þª›IüÉV¥¢çžçéWýÑcK¥ÒÔßµ ÎzŸ/úŠiÛ/)9ê,m}þ®j)¨yXÔªþªÑ>P©T¤ÛíÊññ± ±m[lÛ–v»-ív;÷¤‘x™ÇqBý1ú¾T*‘¤`©à`åD'ôæp]ãèèh®çGUU1 ClÛ–n·úÌó¼Ä¥å‡åûªˆö§eøÕy’¤IdzŒ…è±çmRs–cÁuÝX©‘óÖ^“D'÷G%ͺŸFÏ» IyHZiɇŽãÈÖÖV(™¤R©Èññ±Ø¶-†a,õXPUUFhÛðßÍhFB o$xX9‹^Q£X,Æ&/£‰y0 C¶··CÛ&M~zž·ÐHV뺱‰ÿe@.‹±²=ÓöKÏóV溧5˱t\4伋¶Á¨þ¢ªjìù9m»_„~šVÒø_ij½Ýn‡’;J¥’ض½ÔIQãÊ´DK¶à`Ùà`åD'ôŽŽŽæ^.!:y»··7×ó¥m‹h‚‡¦i±I@Ó4çתJj›ež¸ŒN>îïïOU¦¡Óé„Þ+Šrî’ÆBôºÓj·Û¡÷µZmê¸V‘iš±LÆ%Z$õÓižÙ¦iÆú÷¼úé¢ÊœE´Í§ÿYD“HVñi¡•™ü²,žç…þ†6ÄC'<¬œ¤_Ônmmeúެ+´Z­PiÛ¶Wfb+:½¿¿aVñÈ2‰ì8Žììì„¶ …©&59œ4šÍf¦ïp]7–°ÔjµÎåÄft,f N'–Ü]`Õd'žçe'†aÄJke}f'·Ñh$–*™…eX¥i’èø÷KûGóm;Û¶cmqÞ’Üœ$xX9ªªÆ~1oYVê‰-Û¶3¯À¡ªjlwkk+ó„•çyÒl6cI¶mËÎÎNæÄ€4e È­\°µµ•ù\ŽãH¹\^©ä´÷Ù¿/QÑ„€´5‘Y,cez²ŒÏódcc#ÔEYù„…Q’ÆÂÆÆFêûå8N,1¡Ñh¬|™,ÏÃV«K™4N’žŸ–e¥^AÅó<©V«±~:é¼Ó&¸®+Õ±Œt]O|¶§íÏN'Vò&«´’Êëä)štMð˜6¹æ+)ib°ÙlNœ¨´,K666¦:g»Ý–R©¼÷'ÓþÒÛ4M)—Ëbšflζmi·ÛR.—S/³ï8NìzGM4GctGªÕjªÉ9×u¥ÙlJ¹\^ª_`§á8ÎÄ-lÛN¼¶R©”¸BF’´epü„ŠY¶c´_Š\ ÑÕ¢\וjµ‹Å4Ís¹z‡Ï²¬ÐÄ®?Ž'…N§#år9´­P(L]æe™øãdÜsÇï»Ñć´ã¤Ýn‡Êbˆ\OF˜tÞQý´ÓéLLàˆ~~åÊ•‰qú×¹*’ú_ÚþœuI|ÖLzž%%è,ƒá¤£+W®„®#í³+)iå‘ë6Õj5–$aÛ¶4›ÍØjYÙ¶›ÞØØH<§ÿ‹å­­-Y__—f³üò=ƒ¿Ýu]1 C._¾,²··'GGGÁÄ“ëºrxx$\ O©T™à¡išt»ÝÐ6?ÉcccCƒsض-GGG²³³#ÕjUÖ××C YÊ9,Ó4e}}=v,Ë’f³)Õj5vMŠ¢d*u iZèýþþ¾ìììˆëº±~`YÖÌWA‰&-ˆ\ŸP___úçyâ8NÐÖ××c³›››çþW뚦Å&Åý hû+ ø«ýT«ÕØd¸¢(bYÖ¹I†ñТãÄ_µÄï»Ã²Ž˲b þy·¶¶‚~:üœKê§F#Õ|4ÁÃ_©gÔßÿY±J‰lõz=¶¢•ߟýgûðöÃÃÃÄþœVRY˜jµ*;;;±:ü¿»ËÚ¦Ã×â8N(ˆKk0<>VØÝwß=‘ØëÈ;4,@£ÑH¼ÿã^…Ba°»»ÛžV¿ß”J¥Ìç~„¾³R©œéûDdp||<1ön·{¦s(Š‹Ý·½½Ú·R©¤nÓ¨ûî»/ô]—/_Nu\4Þiî“¢(©ÚrXÖv­Õj#¿ëÆo í{ÿý÷§ŠáøøøLýrww7õõFûëöövêc{½^ìܽ^/õñ³ÒívŠ¢L=²ö‘³´Ù¬E¯gšçÏ4m0 '''gê§›››™Î5êëºzE?OÓiúé¬ÇFÚ뜦M+•Ê`ss3¶mÒ¹¦7IçŸW[¦U«Õ2Ç…óëÎ;ïLì«<òHÞ¡Vð°ÒLÓ”F£‘zÿZ­&ŽãÄV\È¢X,ŠmÛ™Îë«T*Òï÷c«$$•/HKQ9>>NuM†aH¯×‹•IÃo»UZá¡ÓéH·Û­n1J¡PÛ¶3÷z½žºME9SÿEÓ4±m[6773W(äàà T®à"0 ClÛÎ<îfñ Y6ív[æ>NDDTU=S?ÍRGUÕ‘ûÛ¶zù*•Š¯Ô ~›FWGgssSlÛμ®,E‘íííÄU·ò–ôÜ[¥{àâ!ÁÀÊ3MSÆNnÕj5éõz3+© ªª˜¦)½^OÆØ‰QEQ¤ÑhÈññ±Ø¶+ "¢ëºØ¶-ý~_vwwSMÔù“f®ëfšhÕu]\וn·;ñ<Š¢Èææ¦ôû}±,+1öeg†¸®+ÛÛÛ#“0ü¶œvâ^UU±,kl’G­V“n·+žçI»ÝÎ|Ž´qt:9>>žØ/K¥’ìîîŠëº+•´3K~RL·Û•¹ˆ~†¬â8˜¤^¯ãdT¿9ë8ñùý´ßï§î§Ó&—†1öšD~ôŒîõzS'®äMUUqgâýk4Òï÷3%ÊDiš&ÇÇÇ“Úügžëºs{æ•®ë¡ëP…Kmm0<."7ç0­R©$_ùÊWbÛxàyÑ‹^”CDÈ“ã8â8ޏ®+ªªŠ¦i¢ëúBÎmÛ¶¸®+®ëŠÈõI°b±x¦ÉÂèwŠ\Ÿò¯müïwG<Ï ÎQ,Wn"{mm-ô¾×ëÅî¿ß?Ç ®q–}IJ,qGD$øÞEõÁ$¶m‹çyâ8NÐoVñÞ.‚ßNþXðÛIÓ´™$†­’ágé<ÆIÔ"úitµŽY<£—Õðµú×8ët'¸wþ}›åß§EX__þÆnnnž)ù«í®»î’‡~8¶ý‘G‘Ûo¿=‡ˆ€8<°òHðàK“à€Èõ„¼à}Úrg8ŸHðÀ* D € Ç4ÍàߥR‰äKŠçyrxx¼oµZ9FéààB^½CD¤^¯ç ¤G‚€ eoo/øw£ÑUUsŒÒ!ÁÀ…a𦏮¼o·Û9Fé‘àà\q]WÅó¼ÐvÇqdkk+x_«Õ¤X,.:<˜Êy³äº®ÔëuÑ4-(ÁbÛv°¢(Òétr‰¦A‚VÞ7&ÿ¿µ×®][p$Xº®ÿv'qŸN§ÃêŒúo‡n¸aÁ‘£Q¢+ï¶ÛnKÜþï|gÁ‘`t»]1 #ï0°D¾ýíoǶ­­­É3ŸùÌ¢’±‚VÞ³ŸýìÄíÿó?ÿ³àHäm0ä`Iôz=qG<Ï ¶©ª*õz•;òÝï~Wž|òÉØög=ëY²¶¶–CD@2<°òF%x|ë[ßZp$Xº®‡Jµ£<ú裉Ûo¿ýöGŒG‰¬¼Q _þò— €U3ê¿Fýw<°òÊårâöüã”k0Öááaâö—¼ä% Žom0<."7ç0­§žzJE‘ïÿû±ÏŽŽŽä¯xEQXv?üáEUUyâ‰'bŸ}æ3Ÿ‘_ù•_É!* +x`åÝpà rÏ=÷$~ö7ó7 ŽÀªø»¿û»ÄäEQä—ù—sˆœ ¯yÍk·ß{ï½ò¥/}iÁÑXvßÿþ÷e{{;ñ³×¼æ5²¶¶¶àˆ€ñHðÀ¹ð¦7½In»í¶Ä϶¶¶ €e÷¾÷½O¾õ­o%~Öjµ 0 8n¹åù³?û³ÄÏ>ó™ÏH§ÓYpD–Õ—¾ô%y÷»ßøÙ«_ýjyéK_ºàˆ€ÉÖƒÁã"rsÞgõÃþP^ð‚È7¾ñØg—.]’O|ârÏ=÷ä€eñè£Ê‹_übùÎw¾“øùW¾òyñ‹_¼à¨€ÉXÁçÆM7Ý4²†öµk×ä oxƒ|á _XpT–Åc=&÷ÜsÏÈ䎷¼å-$w`i±‚Εk×®É=÷Ü#ŸúÔ§?¿é¦›äø€¼ño\pdòôÕ¯~U^õªW%®ø'"rÇwÈ•+Wä'ò'+xà\¹té’Ü{ï½òüç??ñóþð‡ò¦7½IþüÏÿ\ƒÁ‚£‡O|âò²—½ldrÇÓžö4ùøÇ?Nr– 8wE‘}ìcòô§?}ä>ï~÷»åçþçåcûØ#°H>ø ¼þõ¯—×¼æ5òøãÜïýï¿”ËåFdG‰œ[‡‡‡R¯×'îW.—åÍo~³üÚ¯ýš<ïyÏ[@dæåääD>úÑʇ>ô!ùÄ'>1qÿV«%»»» ˆ 8<p®}úÓŸ–z½.ßûÞ÷Ríÿâ¿XŠÅ¢ÜvÛmrÛm·]@þž|òIùö·¿-=ö˜<úè£ò¹Ï}.õ±ïyÏ{äï|ç£f‡œ{_ûÚ×䕯|¥|ík_Ë;KàÇüÇåÃþ°¼êU¯Ê; µKyÌÛ ^ðùò—¿,•J%ïPäì®»î’/|á $w`åà€ áÖ[o•OúÓòÁ~P~ú§:ïp@ƒ°e IDAT,˜ªªò®w½K|ðAù¹Ÿû¹¼Ã2£D .œ§žzJ>ðÈ»Þõ.y衇òÀýÄOü„lnnÊÿñË­·Þšw8ÀÔHðÀ…uíÚ5ùÿøù·û7ùÔ§>%Ÿýìgå‰'žÈ;,gpéÒ%)—Ëò«¿ú«ò«¿ú«òò—¿\n¾™ÿ «`ÈÃ?zyž—wH€3úÖ·¾%>ø`lû³Ÿýlyá _˜CD€Yºùæ›åÎ;ï ^Ïþóó ˜ <À¹öOÿôOò–·¼%¶ýío»üýßÿ}dw)ï0 KŽ€%G‚À’#Á`É‘à°äHðXr$x,9<– KŽ€%G‚À’#Á`É‘à°äHðXr$x,9<– KŽ€%G‚À’#Á`É‘à°äHðXr$x,9<– KŽ€%G‚À’#Á`É‘à°äHðXr$x,9<– KŽüìÝ¿o#á™àw W‘Ni A€\‘Û$wÍqÔg¤· CTs­(¸DõDå×W8Ía©ÆÉÁ4*SirMÍr•f·L± #I‰¤(‘Ò>@`gv~|óûÓ|ï¼°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ã~ºí¼EƒÁ ¾~ý:3¾Z­ÆÑÑѳ®;MÓ¸¾¾žû'''Ϻn€mȲ,®¯¯c8F–eQÅÌ4õz}òK’$Z­VÔëõ-”öe”넵Z-:ÎKÀS ðxƒÁ`aE«ÕŠf³ùlë>>>Ž,ËæþŸà¥üö·¿ÿý¿ÿ÷Ô¸¿ù›¿‰Ÿÿüç[*ð ‡Ã8==]X÷¹/ÏóÈó<"¾×Õ""šÍft:ØßßsÁišÆéééd¸Õj ð€-û»¿û»øÿãLû÷ÿþßÇ?ÿçÿ|K%àµàðƒAôûýgYvžçK5p<·ßþö·ñßþÛ›÷oÿí¿àlD–eq||iš>y9Ýn7Æ› ðvÏßýÝßÅï~÷»©qÿú_ÿk,M€À »¼¼|¶çZ.À® qxx¸ðÿ[­VT«Õ©ŒiY–E–es»Ð‹Á¼ <^Xžç1£Ýno|Ù———_&À®8<<œt¯r_­V‹N§Ýn7ªÕêÂùÇõ°~¿? ö¨T*<x~²íüjµÚÔðp8Üø:†Ãá¤_ùˆˆýýý¯`[wEžçÑëõ îˆøž©£ÛíFžçqqqµZm*Óì2<^@½^jµ_¾|‰ˆˆOŸ>E¿ß´bå ‘v»-£°5ÿñ?þǸ»»›÷/þÅ¿ØRi€×®ßïÏwT*•è÷ûÑétÖZf§Ó‰v»= ðœþÃøñ7ó7SãþÕ¿úW[* ¯‘€’$É$À#â{@ƺ eEQħOŸ&õZMªq`«ƶ‹¼išÆñññÌø§wŒU«U<€åy>ó·Öº÷ž?ÿó??ÿó?ßTÑøé¢à…”_žŸŸolÙåìÝnwcËØ–¢(âððpfüÙÙÙÆe2îjü›×U¼/¤ÙlF­V› gY¶±”àå`‘v»½‘ålS¿ßŸ©/µZ-Á¬üx¼ ràÅ&¾þÊó<²,› 7 ݳ¯^Qs3žõz½-”¶O€À *§¿ß—óºÊA"Ò•oÁ`0ˆ¢(¦ÆD’$[*l—€Ôl6£ÑhL†ó<4MŸ´ÌrˆîY€·`^ö¬üÈx¼°rÃÄSºiIÓtª_úV«¥{àÕ˲lªŽQ«Õdïà‡öÓmàGÓn·ãøøx2|yyEQDµZ]yY/Ñ=K–eqyyY–EQ“Œ#Õj5šÍf4›Í888ˆf³¹±uæy———1#"¦²œŒ×™$Iìïï/µßz½^¼{÷n2|rr2wº4Mãúú:òÕøøŒS«Õjµh·Û“c6N·\žoÞq­V«1#I’I÷*Y–ÅñññÒÛ˜$ÉÔqh43Ý=äëׯñáÇÉùq»æËciš.]Îò²ÇåwÕ1>ÿÒ4OŸ>MMwxx8éJdóŽÛý®kæ]EQÄÇãöööÁeƒ™ò–χ±4MgºÑß6­ÓéÌ”+"fº ™w®Æ×¯_vÅô˜,ËbooorNÞO³>¯[¢ñ<½^oétþÀãæÝÓ×éÎn“Ê÷‡±Z­6é¢+â{Ù‡ÃáÔýr<ïÅÅÅJÝ™Œïkåg÷ýu×{ÿÝív×Þ_ÏQ_xNišÆÇ–µ(Ї“:ÁýûûýgxÙ¸;°²EçÁýz`y÷绹¹YyËuåEÇý¾ÓÓÓH’dégõ¢úøýíw›r»Æu¶u궋εeæ+»ÌÇ¿,Ëb0LíŸ~¿µZ-ºÝîÊåݶEõ£òß åk3âû=!˲µÿY§~”çyt»Ý•êõ,a$ƒÀÆ=–Ác4šM=~vv¶ôòooo§æ­T*3Ó<%ƒÇxúF£ñè×ðó2Y”³‰¬:¥Ryt½Ÿ?žÚÏ}V^þÍÍÍܯÌö÷÷Gggg£«««…_ Îûbpaêã»»»¹–ýÚq“ÊÝ©T*•…çÝÍÍÍÌôI’,\ö¼óm™sºüÅf¥Ryôë߇¾\ÜßߟùÒóöövtrr2ªT*sçY&ãÃøz­T*£“““G¿ê×uͲ_0–ï÷¿¤=::šYÎÝÝÝèììlîö=¶måì+Ë\»Ÿ?žì‡–¿ny×˼í»½½Û•ò÷Ôò|ãý½è>´h}݇Ø.<^—yÏéuºÙt™Ê™ jµÚƒ]>\\\ÌÜ›Wý¢½üL¸¿ž÷¼¼ººšy­ºŸ³¾°ió²€-Ê\Q®Ã­òl~h}•JåÁnDÊçÀc™5Êõœûëk4s×õùóç¹ø–Í8¯×h4¬—·ë±.”æeð˜w~×jµÑÑÑÑèóçÏ“,f‹–U©TFGGGvArww7÷šxhž«««©_ù܇E¿‡ê²ëfð˜—åä¡¿AÕW–ÍìRžï~æ¢y÷ƒÛÛÛ…™X¶Ý}À[#Àà,àñùóç™—fË*¿d<::š™æ)Ëv¶Íå¥jµ:÷üœ÷%ôSò—wÞ þe^<¯sœÊû¢Ùl.5ß¼eæeÿX¤üÂÙ”e­à1ï«èU&Êû|™¯ÈçÝ–Ùwww3ó­ÚPÈËàñºìZ€Gù¹³j0êÍÍÍÊÙF£ÙºÕ2Á÷-[{Éú¦”Ÿ—r=à¡çdYù¼\åx”ç}èù¶(Àc™u­Ó˜_^ß*õñrÝö¡u=”mÕkjóÖ¿¬mxÌ ÀYµÎVÞöe>,˜wœ–½®Ë÷®e3ɰœŸ[s¿¯äˆï}B?&˲©~ékµÚJ}¹?—ò¶<Ö—v–eq}}=5®ßï¿hŸíÑét–šv0Lõ7^«ÕVîOºÛíF«Õš E±Ô1ªò:ö÷÷gŽ×"õz}j]^^>8ý`0˜ÙÆÃÃé¾Òç;88XúX”µZ­¥ç­V«1gÆÏëϼ<ߪæ]÷¯ÝU,»}I’L Ïë£~lݲ<—~¿?UÞUŽëýeT*•Ép𦑦éJ˨T*Ñív®Z­Nëß÷€×§(Š8??Ÿ·j}¥ÙlÎ<‹OOOœg0Ä·oߦÆõz½•ê|ågÂc^²¾° Y–M=7ö÷÷=.Õjuj¿E±ôs¢×ëM w»Ý¥G’$SÏŒUëûûûK­kÞñzèy?ïü KŸßÝnwê¹;¯Žõ˜F£iš>ûßóöͪu„m SǰÑhÌœ‹éõzQ«Õ&Ãyž¯|Ž—³ŒU꣬N€À•—y^~ù¾LCäK¨×ëSÃåà²òv4¥6a¥ÆãòKÐuƒÊÇ«üRý9”˾êKáûe.ŠâÑFìápFc2œeYN†;ÎÔ2ÆZ/™×Und—qÓåk"bý Šu<R.ßcA.Ï­|OXõ<øÞpW¾ÆV ¢J’déF¦yÇxº]º¶ƒÁTãd£ÑX9p"â{ãr9í¡çi¹¡¼V«={ï¥ë OU~¦.lQžn™r–“— ¼ïþ³ü±zrÙ²uäyϯ‡êÃáp&¸rÕóû)Û5.ÃKxÏ;?v-ØužMýíW¾žWý¤Ñh,}oÞ…Þ2[Ôl6§¾¦*ŠâÑ/ßÊA /ñUcÊÛ¹nÀĺViô-Šbæ…õºå-7ð|˜Œ+§£¯T*/öÕfÙ¼k,˲|yý\×x³ÙŒV«5s.‡Ãh·Û‘$ÉdšçV>OŸr?70ÞoIÓtécû’÷"`±òu\Eäyþâõžr`íSîI’LeKZ”í`^=鹟OÛª/<Ŧ΅e–S® ^__¯µî[%øð¹ÎûòvŸŸ¯œÑ«¼Y–-]¯Ý•L„»ª||Z­ÖÚõæjµFc*X.MÓ¥ƒzvåoNxl]»Ýž 𸼼\Ø€Q~ù¾‹Ñ˘÷µØK¦ò]u¿•¿F|ê Î$I¦už3ƒEù¥{žçOþZqÙò6›Í¸¸¸˜êžå¾Á`°ÕÎåà†]í‡ý9_¨÷ûýH’d¦Anè1Öl6#I’888x–cV¾ÆžºŽz½>Õ0¼«Á;ÀbÍfsæËõ,Ë^´‘qÞsá)÷§rÙe;˜×ðÿÜÁgÛ¬/¬kÙýY¶N½î9öÏ.<›æ]cOµlàJ¥RÑ•Ç#6]®²Ê9,À`wè¢`ËêõúÌòóRZE1õi¥RyñnM²,‹óóó8>>޽½½ØÛÛ‹ŸýìgñîÝ»•¾b|î>Ù³êËämtY±)ÛÞ×N'NNNfÆŸœœl½QcòÅééi|üø1öööâÇñîÝ»x÷îݶ‹÷¨f³ý~ª;y²,‹~¿>|ˆ½½½Oi¼~óv5oÓ¶ñìÞv}aI’L=¿®¯¯—ª³Ýî\¶K°×¸³íúíswäy———¯¶^VV®o=5Ы¼Ïßây ð#Á`t:©—ÍŸ>}šIY\î§ý¥ÇÓ4óóóHÓôÙ^¿DOQ~ù¹.E6e}¯:»Ýžéže‚;Ê™T–•çyœžžFš¦o"СÓéD’$3÷¡EÆ]ï\]]m¬qæ¹÷£ x}ÊÎ"¾g9ë÷û[*ÑóHÓt¦ÑvÛ ïÛ©/¬£ÓéÄùùyD|ßoý~?z½ÞÂé{½ÞÔþ]¶>RÎt5/xuUÛî¬ül¬Õj éLã`Ûápèyÿˆòß0»p¯`u<v@»ÝŽn·;yyœeÙL7-åþ°Ÿ;{Çp8ŒãããiÀ^§‘ý%Õëõ©2¾æ—¡ãÆü—RE|üøqfüÞÞ^ÜÞÞn5XfÕ/Á³,‹ÓÓÓ¹v^»z½išF–e1 "MÓ©>ÚËŠ¢ˆ>ÄÍÍÍF‚<Ê]ªlš´âðúÔëõh4S÷¢<Ïc0¼x³ç´«÷§—®/¬«×ëÅ`0˜Ô¡OOO£^¯Ï=GƒÁTÀi¥Ry0ä¾Z­6õœêt:;{ì–U>¾_¿~]zì‚¢(âøøx&þ-Ûõn“xºhØÕjuæ ÂûÈyžO}‘V«Õží¥{Qqxx?~œy‰X«Õâàà ...âêê*îîîb4Åh4Š«««¥×ñÚúÛÞô ü—ÌúP>O^úÅn’$“í­T*“TêEQÄÞÞÞNËïÙ³ÀŠm×ÖU­Vãýû÷SããÇqzz:éFmoooæ™Õï÷—®ã•§{ ¼^³4Mãýû÷sƒ;Z­Vœœœ¼‰zY٦ϻ×ö7ß ðØå/ ï7`”•ŸóËÕN§3ó²t?nnn¦¾œM’díFÓy/Ów9¥ry;Ÿšq¤Ühòœ/WËeÉýÜét¦¾¼î÷ûSçV–e3é÷_Rù8.jä qxx84P«Õâââ"Š¢ˆápÝn7’$yõ_ó–%I½^/†ÃaÜÞÞÎzdY¶‘Œ&åýö”k¬(Š™ì#oí¸À¢ÓéD­V›—¦é‹eRšwïxJàCyÞò¶=也ßåúÂk ` s÷M–eÑÁ IDATëõ¢ÓéD¯×›Ù÷+Õ§ËçÂ.×[WÑh4¦†_C`O–e3A•J%...âîî.Ò4^¯÷&êe󲬯ƒ€R~Ù<g^äíïï?Û×VåÌGGGK¿_µ¡¥üröüü|¥ù_R½^Ÿi0X÷ø¼TÒóH6¥\ö¢(ž½¯ò4M§Ò 7è÷û“á~¿?Õ`vzzúâý§ß/ÏØ¼ ¦4M§ÎíF£ñCõõ>O¹Ë„M|Å<¯aÞ1ZFùø4 _¨Â+ÖétfËæß=—òýéòòr­à’,Ëf² =ôü/–˲øøñãÔ¸Á`0óâ}8N½°><<\;P Ü`ö˜4Mg2™Ìm(7Þ¬Ò(´Ë $Oñ(ÕjuæZ8??_yfY6ÓZH^ŸÁ`0·‘ó~0áS-ºß”ï!EQ¬€V~×jµëYåzRš¦+gXõú’õ…MX´?’$‰~¿?ÙgišF¿ßRzÞsj›ÝÌmJ»Ýž ìY7Àò%”ëŠÍfóÍwŒ•ïççç+åyþb!x~<vH½^ŸúJ5˲©—וJåY_Æ•_â¯òòpÕI’Ì|‘{xx¸öW±ÏÒétf²x¬ZÞN§3Ó_øK¼D/—ý)_>?ôÕ`Q3ûäììlî×õz}fY{{{k} [ÅÒ^ã2–-{]­R¾]XŠX?ÍwùœßTÃJ¹aqѱz¨\åà¢Z­¦Þ€yÏŒˆÍyœŸŸ/lü¯×ë3 û§§§+Ý?ƒÁLðÙcݓͻw­Ò5M–e+gG{©úÂsX5Øsåc6×ÞÎ]ÊŽ2/°gÝúÁK‡”»=|È&2Ž­³Þ§êõz3nåúÎcÊ÷·J¥"àà°cÊ/ôï7¬Ô`1{.mªÿöz½>u>D|o<[æ<]tlw© xšv»3ãƒÁÚõ€4MãÇ6t–ë+߃—Yç¼çm£Ñx4ø¬Z­ÆÑÑÑÔ¸,Ë–ºgÏ˦µ¬—¨/lÊýçϪAë˜÷œ:<<\éY3~ö>wYWÑétbjܲç÷Øp8Œ><{pkùo•<Ï—Úÿ›>?ò<ðüÞdý£Z­Îጯñeë¾å¨~¿ÿæ3Ÿ¼i£Ñè#6ªÕj"bòkµZKÏ{ww7ªT*Só777K/çêêjfþÇ\\\ÌÌÓl6GWWWs§¿½½õz½¹e]f}‹ÖY­VGý~tww·pÛºÝî¨Z­.µËË_´=Ë899™[ÞÁ`0·¼Ÿ?Õëõ™yö÷÷×.ÃºŽŽŽfÊ‘$ɃûãææfÔétÝåe×jµ…ǯ¬|½$IòàôóŽADŒêõúÂm9;;›:_Æ¿J¥2º½½]¸®ÛÛÛ…Ç{‘‹‹‹¹ëZöÜ+ï“““Gç[åº/ïÇN§3‡ Ûííí(I’™å/šþoÿöo§¦ûùϾÔ6ìïïÏ=¶ÃápfÚ»»»Ñ`0˜»¿—ÝoO¹?”÷á*÷z^Öï~÷»¹×ä¯~õ«mÍ«7Œív{î½â¾›››Q¿ß5›Í•ê-777s×Ùívç>GnnnFív{îsgÙçã¢:áCu³‡žAËÞ£ž³¾°iFcæy‘$ÉÂ_§Óõz½Q¿ß¥iºÖ:ËÏéñ¹÷P}âóçÏ3ÏÐEæÕsV±ÎóðîînT«Õfæíõz Ï×ñ3øþv=tŽmê™9ïšx¨œs¯÷Uê wwwsyÙÕÕÕd,*ÏßÿýßO-çOþäO–*ÃÁÁÁÜúÑ¢:éÅÅÅÜ¿AŽŽŽ–ZŸúÀîúi°SªÕj´Û홌FcnW›Ôn·£ÛíÆ·oß&ãÆY*šÍfÔëõh6›“®6‘5cüëý¯êŠ¢ˆn·Ýnw&;ÀªýÏoZ¯×›éǺ(ŠÉvÜ/o–es¿¬ÛßßßJf~¿EQL•}Ü7ýøØ6›Í(Šbr|—ÍàRN?—þ2p8F½^ŸœwišÆáááÜ/µç©T*ñíÛ·Èó|r®&IÕj5Ò4}p;úý~Ôëõ…Ë®×뱿¿?•}e|¼{½^ÔëõH’d²Ï¶}~®¢|ýƒÉyYîÓ~Ñ—ª'''ÿt0D»ÝŽëëë©õ·Ûí¨V«S÷ÁEûûèèèÑî€×©ÓéD³ÙŒv»=ÓMÂp8œd(ß/Æ÷éEÊ:ÊšÍf|þü9:ÎT=©ßïG¿ßŸºo.ºgV*•HÓtéûfµZáp{{{SãÇu³ûÏî4M§Ö[©T¢^¯¯ÕuÉsÕžC·ÛªC>–Yažv»GGGKg¤‡‘$ÉÔ¾Ÿ{ã}S¯×­äyþ`ä%ϵòuÕëõ¢×ëE’$Q¯×£^¯Oöñ¼íºÿì~.Ýnw&KZ¯×›\‡ãkñ±:à*ªÕjÔjµ©}3ãýû÷“cX^Wš¦;8®£Ý¿.óOV:®ÀëV­V'ϳ£££¥îÑeãûõ`0X:«F³ÙŒ,ËâäädéçÂÅÅÅJ™;Ê:NÜÜÜO·Û]jãõ=×5ÐëõVªµZ­WQ/`yïF£Ñ#â϶]€·¤œ¢·œ&ü%ÌKE¾ÊËä<Ï'Ý‘ÜO!=NÍ$É£©Ï×}y]Å$ÕuQ3ëO’d’*zå r÷O•çùTZøûåm·ÛÑn·w&wÙCeïçEÇq^ô§îÛò±šwíôz½©ÔÜ­Vkj¾ò6EÕj5êõzt»Ýµ¯Å¢(b0Äp8œÚOã2ÎÛWëœ{åûÇ8%ú²e\÷:§‘ϲlr\Ë×^»Ýžtó˜üÇŒø‡˜ ÿéŸþiüå_þåRe)[tLÇ]Z»oYÇSîåk`÷z–óŸÿóŽ÷ïþÝÌø_ýêWñÛßþv %â9 ‡ÃG»Ë×_–½—-³Îñsa|oŠø~/w'³IÃá0ƒÁTýh\7*ß 7yzJ}á9Eïß¿Ÿz^V*•¥ê\ãý²¨;‘“““•ó,‹Á`0y÷ÏxŸ·Ûí¥÷ý¼úÕ*û¶|þ¯R(+Ÿß1©S·kÙeoú™9þ{a|=Œ—y¿^V~¦?¥Ž5^g¿ß4Mg®÷ñ5ðØ}åîînª{ŸŸüä'ñWõWK—á¾<Ï'ç]ùo¦§þ ¢~°»x¯Êce<àmét:ñéÓ§Ép£ÑX9Kʸ±¾ßïÇ·oß&ã«ÕjÜÞÞn4`StѼ EQLwD|Ï4±j@FµZ^¯7$:/À®à¼ åà‹V«õ¤®ðšÍf<¸€]!ÀxŠ¢˜~JpÇ¢e”×°+x¯B¹+–ëëë'/³¼ŒM<À«$IÔjµÉpžçqxx¸öòƒA¤i:®T*Ñn·ŸTF€ç"Àx5úýþÔð`0ˆ½½½Èó|éeäy?~œ éõz3YBvÅO·]€eµÛí¸¸¸˜ ÎHÓ4Þ¿Íf3Úíö$ÓǸ»•<Ïãëׯ‘eY¤iÃápf¹Ñív_l;V%ÀxU:NÔëõh·ÛñíÛ·Éø,Ë"˲•–U©T¢ßïG§ÓÙt16J-À«“$Iäy'''Q«ÕVž¿R©ÄÑÑQäy.¸xdð^•$I¦†Ç©×€OµZ^¯½^/²,‹ápišF–eS™="¾t4›Íh6›‘$I´Ûí-•`=<€W%I’™ €qðÀ[¥‹€'À`Ç ðØq?Ýv€[žçñõë׈ˆh4Q­V·\"€Ý#ÀxQišÆååe ‡ÃÈó|î4Õj5’$‰$Ib?êõú —rs²,‹ËËË™ñI’h–&ÀxišÆééi¤iúè´EQÄp8ŒápÝn7ÚívE’$/PÒÍ qzzº0ˆ%"âää$z½Þ – x­~²íoßééiìíí-Ü1Ïp8Œ½½½ØÛÛ‹¢(6\ºÍ*Š">~ü‡‡‡w¬BàYÆ`0˜ûûûûÑl6§Æ¥iyžÇׯ_g¦OÓtç»4I’$¾|ù23¾ÑhDDÌý?€ÇðžM·Û î¨T*Ñï÷£Ýn?¬‘eYôûýøôéÓd\«Õz¶²nB·Û à¨ÕjÑëõ¢ÓéLM7î‚f׃U€Ý!ÀxišÆùùùÔ¸F£±tŽf³ƒÁ` q}}=“íc—äy>µ½mkµZ úxÈO¶]àm:==®Õjku±R¯×#MÓ8::Šz½¾É"nT¿ßŸîõz2t#ƒ°qY–Eš¦SãƒÁ“Ê»¦¼½ív{K%øqÜÝÝMu‹üÏÿù?çŽÿ¿ÿ÷ÿÎÔå`žúOÿiü³ö϶] ~pïF£Ñ#â϶]àíèv»SÝ•ÔjµÈó|‹%z~ïÞ½›F[* ÀãøCüâ¿Øv1€À¯ýëøÍo~³íbðƒÓE °qY–M 'I²¥’¼Œ¢(¶]àà<»z½¾í"<«r@ /£œ= Þ2À³Ó§5ÏAwXüHxÏîË—/º1x‚Ÿn»ÀÛ“$I\__O†‹¢ˆÁ`Ýnw‹¥à­YÔEË?ù'ÿ$þå¿ü—/\à-ø?ÿçÿÄÿú_ÿkÛÅ€¹x×n·ãôôtjÜññq$IÍfs+eÊó<¾|ùY–Mo6›Ñjµ¢Z­n¥\)Š"¾|ù2ÕÅM½^V«õz}‹%Ø ‹ºhù7ÿæßÄïÿû. 𜟟ûH €%ÀظqÐÄý,{{{qqqívûEÊ‘çyœŸŸÇp8Œ<Ïœ¶ÓéÄÉÉÉRY–Åñññdx^÷3{{{sç=;;{4È%Ïó8==áp¸°k›$Iâää$’$y´¼Àë'Àx½^o&È¡(Šøøñc$IN'ö÷÷Ÿ%sÆ8@b0,=Ï`0ˆápgggÑétœ¶(Š©¬ó,úÿEcý~?NOO.MÓHÓ4ºÝnœ=8-ðúýdÛÞ¦$Iâèèhîÿ¥iN'~ö³ŸÅ‡âøø8.//7¶îáp¸0¸£R©D«ÕŠV«µZmêÿŠ¢ˆÃÃÕC6©ÓéÄñññ£Á÷õûý8<<|ÆR»@àÙôûýˆøÞwé"Y–E–e“i“$‰v»kg÷(wrppív;’$™Yfš¦Ñn·ãÛ·o“qÇÇÇ‘$ÉÂîZªÕj´Z­ÉpQñåË—©iîÿyÞyºÝn|úôij\£Ñˆ^¯7Õ¥Íx_ÝŸv0D£ÑÐ?,¼aïF£Ñ#â϶]àí ke™èt:qvv¶r G𦱷·GGGÑívjŒeYI’Ly,Éc¼¾ûF£ÑÊå½ï±õ‡Ãèt:“2W«Õ¸»»[zoÁþð‡øÅ/~13þ—¿üeüþ÷¿ßB‰€×îüü|îG4¿þõ¯ã7¿ùÍJÿŸ.Z€g×étâöö6ö÷÷Wšo0Äû÷ïWî2¥Z­ÆÕÕUôûýGƒ;"¾gü(ÿáþéÓ§Èó|¥õ®«ÓéL /\Òn·'YO"¾gÙV×2Àó༈z½Ãá0nooãìì,ÆRóE‡‡‡+/4›ÍH’d¥òÍû2#MÓ•–±ŽÁ`_¿~ ×jµ©À‡t:©®`ê xÝx/ª^¯G·Û,Ëâîî.>þGGG|¬䱪jµ:S†—ÈàÑëõf†Wé’æ~ö,Ë¢(Š• Ø<€­©V«“®F²,‹ÛÛÛ¸¸¸ˆZ­6wúãããg º(VdYölëŠø@RÎÞQî®å1ív{jø%²Ž/ï§Û.ÀX½^N§N'úý~OýQÑëõž5“Gy}Ïi8N ¿ÿ>®¯¯W^N½^Ÿ¾dY6ô¼~<€Ôív£Z­ÆáááÔøOŸ>E¯×‹z½¾¥’mN9Iš¦‘$É“–©‹x›x;«ÓéDžçqzz:5~0D¯×{Ò²Ó4wïÞMuir¿»”—ð]ÀMÆ]__/5ožçq~~ƒÁàUt]Òï÷ŸÜE ð6 ðv^½^_yž~¿ÇÇÇsÿ¯R©D³ÙŒf³Õj5ªÕj4›Íèv»ñåË—§wiOÍÖü8x;oÕN§3•ñ#"¢V«E»ÝŽN§³°“—¸h6›qyy9NÓT`.ÀÎËó|éiûýþLpÇÉÉIt»Ý˘Q4IÓtK%vÝO¶]€ÇdY65ÜjµNÛëõ¦†ÏÎ΢×ëí\pGDÌd븾¾^)˜øqð6n8nlYEQÄõõõÔ¸v»=wÚ<ÏãÛ·oSã:ÎÆÊ²iÕj5¦Æ•T"xÏàôô4>|ø°‘l½^/Š¢˜÷P€Ç}Õju¥Ìåõ¼„r@ǧOŸÖîªeå^†`ã²,‹,ËâÇñéÓ§µ—3 âüü|jÜÁÁAÔëõ¹Ó—ÇE±t6‘4MãË—/ëô êõúL?ÎtKó˜4Mãýû÷›,°Cxu?0¡(Šèt:ñþýû•=ÎÏÏãððpj\¥R‰~¿¿pžz½µZmjÜááá£ÁÃá0>~ü¸Rù6©ßïO•»(ŠØÛÛ[*8%˲øøñcìííEQ+†¯ÃO·]àm™`çyt:èt:Ñn·£ÝnG½^V«53Ýååeôûý¹Ý»¤iúh—+N'NOO'ÃEQć&ë®V«Q©TâÛ·o‘eY ƒ­ET«Õ‡‘$I|ûömRî?F³ÙŒN§ÍfsRîˆïûb8Δ]7-ð6 ð6ªÝnG–e3]«Œ ‡Ã¥»Mgîh6›NÛív£ßïO!ƃA ƒç­Õjñõëוʶ)Íf3Ò4v»=U†,Ë¢Ûí.µŒF£±°ûàuÓE °QÕj5úý~ÜÞÞÆÁÁÁ“—W«Õ"MÓèt:K¯?MÓ¨T*K¯£ÕjÅÍÍÍÒëx.Íf3²,‹£££•æ«T*qvvY– ð€7J€ð,êõz ƒ¸½½³³³h4+Í_©Tâää$ò<_*sÇ}ãlå.`îkµZqtt···‘¦i4›ÍI·1ãß²ë­V«Só=´Þe–59::ŠZ­6wºJ¥ûûûqqqEQ,åxÞF£?FÄŸm» ÀÛ—çy¤iY–E–eq}}ß»©V«Ñl6#I’h·Ûžç“áñ:^“¢(&û+â{ðŒLøÃâ¿øÅÌø_þò—ñûßÿ~ %^»óóó¹Òüú׿Žßüæ7[(ü?Ýv€G½^ñnPÞB0DµZ$I¶] `‹tѰãxì8;N€ÀŽà°ãxì8;N€ÀŽà°ãxì8;N€ÀŽûé¶ Àë’çy|ýú5ò<<Ï£Z­F³ÙŒˆˆF£ÕjuË%€·G€ð"²,‹oß¾M†kµZÔëõ-–h³²,‹ËËËHÓtjüøšƒƒƒ7µ½¼¬¢(âË—/SãZ­Ö–JÀ*Ïó8??ápyž?8m½^$Iâàà ’$y¡² išÆ»wï&Ão-À'MÓ¸¼¼Œ,˦Æ×ëõÉûÿ·´½¼¬q°ÜX¥R™ËÁ<<à•˲,†ÃáÔ¸¿ø‹¿ˆ¿þë¿ÞR‰æëv»q}}=>99‰^¯·ÅmFžçqxx8Øqßp8ŒÑhô&¶—íȲ,ööö¦ÆF£-•€MQq||ƒÁ`éyò<Á`ƒÁ êõzôz½888xÆR¾=ÿå¿ü—øïÿý¿Oûøñc4-•h¾ò»Ë«««7Ô“¦iÏv”57±½lÇ`0ˆÓÓÓÉp«Õz°Í xÀ+—eÙÔ?"âèèhç<Þ¢4MããÇQŶ‹ð,²,‹ÃÃÃG¹’çyt:¸¸¸Ðp¹‚ÿú_ÿkü§ÿôŸ¦Æ½ÿ~ç<Þ¢Á`‡‡‡Û.À k˜—Q!â{de³ÙŒ<Ï£(Š™®i^‹ñ{Ðy¹íïïG’$S] Œß‰¦i:•Ñ^“yÁãn3î¿ÿwŽÛ À` ív{jøää$ºÝîÜ~ö²,“åxUŠ¢˜›Áx?úý~Ôëõ¹óߎ»hé÷û“àtcÁ®Ëó<Ž'ÕJ%z½^t»Ý¹Ó§iºðZx?Ùv^›Á`_¿~ ŸœœD¯×›ÜÑl6ýá¼*½^/ò<ŸwqqÃáp©íz½½^/²,‹ýýýˆˆ©l°‹z½ÞTPÓ`0XÜñ=hI€ð’dð€W®ÙlÆÉÉÉÔ¸¿ø‹¿ØRi~ ý~jø¡ÊÀk“çyœŸŸO;99‰N§³ò²êõz ‡Ãèõz}ú4ùw­V›Éæ °m?—iÏÚEãs7˲™î¢Æ××:÷¥çj˲,¾|ù²Ò5KFÁ3»¹¹%I2Šˆ¥~ÕjuÔívG777SËiµZK/cÑï!M{uu5j·ÛSÓ´Z­…Ë»ººu:QµZ]j›{½Þèîînåý[^ÖÕÕÕJóßÞÞŽ:β5›ÍÑçÏŸG£Ñhtww7ü?öî?Æu´ºÿ¹U ýabiní)°‚¶O¥þ.µ£…²Ðn㨅jP‹ÚÒq@¥[)N"¡g©D ‚8ZÑR¤Ôb©â©P«þ€ñQ`a;¾ ,°,ä¹»êÂ?(ß?î×!~ì$vÇNò~I£Ý›™ÄO'y|žãs\7±¢Ÿv»º þµ›þ»EÛ'¢±iš ÷Íp8\ùøàÇßn· 9Ö"Yß²,]×Íô˜³ö9oÖ~ÇãÁ`¸=ϱyzzš8†òà_KAfþݬc1í=¶ê>äß[Ñ>äßã‹,zÝeYŽ}¤Û0ô£M}½ð…/,{h°¥ÇI=Ïxýë__öÐ6N’¤Ô›ã8…loÕØî¢Xý¢¿íõzcEQ2Å»Çã1Ô¬±Éeâ»ãñ8"ÿXŒ±\1çÆ"5M›¬Å\^^ŽÇ™ù÷Ñ:ÿ»é8ê¢n´´È*±úYñÝeלækü¾ç©Y¯AÞuEñâyëY|ü^–å\Û6 #vÿ“““\÷ç·?kžžžfÚD7Ö 6¹ç cY–~DñþØÎz|ÁþB‚®×ë-ýe[«ÕbUV‚Çh4š9™õA»ìXEÉä±h’2Ož×GÓ´…É*Y÷G41æ¿Èçýˆ¢8¾¼¼œù\¶-Áãää$÷cjš–ùø˜—à1oÛAb·÷z½LÛÇãF£‘xÜ<Ç5?>Ã0b¿¿¼¼Ì•46ý“%Y(2/Á#Ë>L“瘊N˜‘à °nHðøž´‹À¢Y–Ç–e}ß_ÛöVí.›à1/Ö˜–౩Øäx¼z‚‡eY™Ç–%YeV ÿwQ5O |ÑÚÈ6%xÌ[SZ×ñÁß7˶£q§Wü×óðëDyDøõƒÓÓÓØï‡Ãá܉y?yÐVÙ‡iF£Ñ‹™§DQ$x@nhÑ…ò}ŸšÍfâö¨(Š“rJ|+"ªD©· èøø8ÑRf‘¨Uô¨ì[Ôzƒ1Fžçѵk×bÛ«×ë4 oKâºnâõ™.M•L‹ðå刈$Iš”“âÿ~Ó4©ßïgþ{ÆÓÅÅEæûTcŒšÍ&yž—øÝôþäËÝx ŽŽŽh0,õþ`ŒQ½^O”1K£iZ¬ £ïû™J1Æå‰ˆ<ÏË\ºŒÿ¤õüœw³^ÏóR“;¢ñëºûŒp]—ljõèØ$×uI–å…-yž7Iey’’'Ùƒ³ò±XI’æÆóò.’ÎZ —$‰t]'QqI~;ј6›Ì*ÚFDr'±M×uɲ¬XJÚ:A^Ngãm4ä8NlÿDë@|œ¼Ûíμà--®ïºn,IÁ0Œ¹ÇÁ¢5'~=aÖ17ki1øyñë0 ɶíØñ—y/tÖ ²®géºNÝnwòoÏó2½îÓ‰@ÓI"YDø$¡é$¢ÿ³m{òžä…aHº®Çbö­VkòœóXeMpVrG4~MÓb÷zžG¶mÓµk×ÿ‡üÆhÑáK< ‚«ôX¯×ËTŠf”PZÿX|o/I’2·©¨Õjã“““ÌÏ9­TÙ¼v$óÆ¥E _BnÞóF‰vYÇ™Uê¬Ñh̽_Z ™E÷™Æ—¶š×31‹U[eðãafßÂi———ãZ­»¯¦isïÃïs¾4˜ ‰ÒgÓF£ÑReÚ¦ûïMÿ¿(Š ï;'ÛöÌz½AÈõzòûC–å…ïOþ>ügB4†E3RÛ5…÷åû®ã³`W E ¬Z´¤ëõz‰q–MÓrÇ’#óÚª¬úXŠ¢$âuªªfn¾ŽØdË´hF‰öóâºü6²Æq§ÍzýONNæÞ/-ö¹Ê~ÍÓ¾>ͪ­2øÖ#’$eŠ©_\\$Þ_‹ö¿ßò®g¥µ`ʲž5½éç›u_ñ¯yÚó‡cI’2­ŒÇékXº®/¼ßªû0’ö>Ír,F£Ôv÷hÑ‹ Á ÃO˜ Ã(d;ë\ôœ75 #W‚JÞIkÚPÖ‰ ?ÖE“þ˦V«-ÜŸh±hrÁKKðÈšôÃß7ϳJ ———‰ûf ŒÇù‘yýUUÍ´ïù¤’,¯ûôÉ?IÌ2Á^Ô/’÷=–6ÉZ´ÿçíÃZ­¶RWžÏÄ´@‚¬<fFcÃ0–JôÈzáä´"<ò.Äò6›œu¿E |,?K’?æ}½fÅ I‹yçy«”àÁïwA2%wDÒ^ëyÏgÞñœu=‹ß÷‹ŽI~ƒÿgÙ&Ÿ|”öG£Q®õ¸ñ8yáh–ñ¬cŽÇéëYßC£Ñ(±ƒXä1P¾ÌÒ2ýª"jI’ç9ä-ý”Vî-k?»¼ø^zYJÁñcËÚ®c˲2íS~Ûyú!V ß²È0ŒÔ³ˆ¢˜xí¦[ÝdU«ÕÈ÷ýLûž?6ø’y¼ båÄt]'A&ÿNëãÈ[Ô/’÷=¦( ÕjµØmYÆ“&Ï>dŒ%J³Õjµ\mŽŠ,×…(Šäº.1ƨ×ë‘a$IR¦û6›Í•Û~¥×ë%b·‹”›\d™ø?ÿ7ëX›È²OÓÖE¦ÛÅlþù:Ž“«E‘¢(‰6E‹Z#¥É³žÅ·½YtLNªª&žß¢ûóëQûxž(й×ÓŽóeßcyöa†‰u“F£‘9¦?«À± Oü^Q’e91Þ¬÷OÛþ*ø5,¢åÞc’$åÚ‡i±~Äÿ¡hHð€Âð_ÊaR³Ù,i4ËÛäqÕÖ9ÑZuᾨê&Eá'.ªª.ýüWɦÎZ5%¢(JbR4o{Ó‰\Ññ<=‘Ï“ ÂßwÖ‘,’wòûK’¤µ?/€²È²Æ¾Å?ù𲉠iÕò$佨”ßV†s_ûéè5ž~­]èµz÷²ÖñË{Á7ÿÚ7½×a!Á “VrÌu]:<<¤N§SXuŠuÚôBlÕÛØð¥ÑVIH©ús]7þK~•㊿ožê8–eåÞ?Éš•eÏ‹MþÒ&xóîO”Ì®bk’¼ûp¯=@ÕéºN¾ïS¯×KüŽ1V™«Û ÃÀBì ó*±dQõ‹Y×­ÈøÖµ´Z­–{»¢(&’±f]àÉWªN‹ÿókÓÒ~WµXyÞ5AÆX¢Ú Ú­À& Á •6Q ÃlÛ&MÓèÊ•+tttDÍf“úý~¥2w‰v÷ƒ˜Ÿ´fÝïë,Vµ/î¢ñI«<ÿ´Éq–*Fc©Äš¬ÊYÕ74MËT¦-­ÿ^ÕNjµZî}¸LID€mgšfj’G·Û-a4I»§ãì³´©àÿ¦jqÙ*cŒ%bÀ«ì¿e+©/{´hÐ4Â0¤^¯—©òCT¯×+1ZE†Ôl6éðð,˪DrGIJ¬Éÿ3ƨ^¯ÏLDp]76—$ ¼6ñ…^ô6µi™Î’%JNÎøóï…eûïù¾OõzÉqœÊ}f`2ûN–eªÕj±ÛªÇ[5vWÕØ¤,˱u˜hb–f³[¨6 UˆKTÆ:Ò¢6-‹ªoðÿ柃çy±õƒZ­–és]—©^¯“뺫‚“Þ'P$xÀF™¦IžçÑx<¦ápH§§§dI’”ø[ÆØÜIGÕ¹®KGGG©ýÆjµœœÐéé) ‡C‡tyyIÃápcã›Nð º1¡>::¢n·Kçççt~~NgggT¯×¯Ã¬lݺ«z=‘à'x|BÇô1!B"ÓUÅØIߦe™þ{¶mS½^OðªªJív›z½Þä=6¨ÝnÏ}Ìu+» @ìÚ…P–eU:6ÉÇÿ£…ò~¿?‰ÿ÷û}:<<Œ­a‚¨æ ù­;Ù§è–9|üŸ¿Àsú8çÛ³§ÝŸ÷çm]”Ì'Ý8FµÛm “÷Øx<&UUç>î&l¢¢;Z´@i4M‹}ˆû¾O–eÅzdA@¾ïo]¿7Û¶%Í$I"˲È4Í™“ÙMfÚ¶º}~â7-šÜaÑ:?A&-qˆ’%ÎòH;i(úIERU56±ó³&/üíÓY¼üoÞ$oDDtzz:9>«ð›Æg W©UÀ&T¥}ɪÇIÄ2«›Œ.œ%º›ÌRÕ@UU ‚w.‰_×Z%ÌßwºÝN‘fUáà«yg‰ÿ3Æ&Ï#J‰¤UŸfšfìóB‡äºn¥’;ˆÒ+xïÊgT< RDQLT–¨ZO­EøòeFƒ\×­ÄÄ.âûþä Ù4Mr]—.//éää$6‘$‰õz½•2N!½ÅɲÇ6Ÿô´©lÐYI*ü„sÖ$+ÊŽD÷ã'ˆ‹úïñÏÿôôtn噲ñï›]¹R «éÊÝDó/ðª²mˆMN_XgYù¾OÃá à I’&¿‹.þ‡äû~ámÀw£ï÷ûKµê`Œ%ˆ6ÿç·Åï§§y›Îº@4ëúQúó¯z•>Š?@à•³íI|v^žŠ›êÍ•–A(Ë29ŽCAÐx<¦ñxLaÆÚpÀòøä¢ô69‹¸®K×®]‹Ý¶©×G–åØ @†±L\¢É󒙦'byDøûeýû²ñãcŒm]e"Ø/­Vkmñj×uUõ˜Þ,Û¨2obµš¦‘뺆a,þïºn¥Ï·Ÿä³l ˜¿€X„Åÿùc9:֧דæïüúÁ2 üÚÕ¦ª—¯"-±U¼¡hHð€B-3\µbGÕ*~äÙe|èo*©¤*Êz¾iÕiúý~,ûuƵZ­Ømªªnt¾h²²è„fú÷Œ±X¹À¬ÁËóšæÙßë¢iZlbK”ÿy™d €e0ÆÈqª×ë+·`Œ%Zš«ªºTµˆ*VÆ­zl²jë%E+ëùʲL†aÄnët:¹ÆAâ½bYÖÆªÃ‹¢«FµVÉÒž=2ÛîÇ¿oó¬g\¿~=óß2ÆJùŒHKÀá×qæaŒ%ZÒ,‚(Œïûtxx˜ûƒ‰ÏjÌ›7/Ib_îü—mÖrLAlìC|zŒý~¯&y‹¾à‹ìfYV¢_³ÙÌ´MÆÕëõØ ƒ ‰ŒÞ¢¥µš™ÎZ_”œÁOÞ‚ ˆ½&Y2rùJ(ÝnwîßG<ÏKdØo Ÿ ‘özÎbšf%O^`7EñÊ ¨^¯S§ÓYºÝD½^OÄŸ³^Ì”¶°=/–]dl7ÂÇ&³ViØdlr:y¦ÛíîÕEžóÖ‡c…î Û¶cÇGtüg9.£÷Ú4I’6Þþ‡ï{žÛgyãÿžçÅÞ³Fcn ÿ»<•PʺHRÅDrOÔl6Þ—1FÍfs¯Öè`=[ö`wA@Œ12M“lÛ&˲¨ÑhÌÌÌeŒQ·ÛM$9,*?U«Õb£n·Kº®Ç¾¢ 8Û¶i0Zñ@×õØb¬çyÔl6éôôtæ—ëºk-y·ÈôógŒÑÑÑ™¦¹04j3Rõ’XÓøã-ª‘–hÐl6I’¤B3©£’wQæi´ÿmÛ¦“““Ô×ÀuÝÔl_Çq6þZDÇ@4~ß÷'Çm–ä Y–cïY~‚˜å½©ëzìsÂu]’eyæþ‹ÞÿeöÂ4M“lj}VE“öÓÓÓÔçUlAö.ìÓ4m¨æF©·ÿÇüGâ¤x‘ÓÓÓ­ú~€lt]Ïuð—¿üåÔÛ?ðÐ'>ñ‰\Û »ò`¦ÉcdÛ69ŽC–e‘a™ªoø¾O­V+±¸mFæø|Úyz«Õ¢Á`»-Z[°m›F£Q¡ï;>6Ùívéàà R±IMÓ&c ‚€ŽŽŽk&È=Ï#]×'Ï? Ã|ßßxvž¢(¤ªêdâ•ÜËC×uÒu}æ—jU¤?õzLÓ$Y–‰1F¾ïDzҋOt,L#¶m“mÛ¤ëúdÌóŽ“““õÞãMŸÄä)Ï6ýwÑ{–¯p“¥=‹iš‰¤‡è$3JTš~ñI$eá“{ˆ¾—ä¡(Êäó!*}7=î餀]¦ëzì$xYßúÖ·rµ=SUu«‚¦i¹J¥Ïò¥/}‰¾ô¥/eþûY‹½Û -%zضM²,Oâ˜ÑÂe´(yž—z^^«Õr/ÂòxzžGõz}‹ä[H{žWhÜtb“º®“eY“xb†¹âÿ¢(Nbÿ›l¾ >žU͈^ >Æ~vvVh¥]ש×ëŪ70ÆÈ²¬Iü?zÏÌ;>z½^)±*Y–c yªwGÆ$îÏ¿W²Æÿ§[ÕL_H½®Ñk}Þ”MEr'QµÃó¼ÉzPôyÅÿ§? ÿ‡ÜÆãñ£c€†1&¢¥jµÚx4-ÜÎp8Ìõ¸ªªÎ|,þo‡ÃáRϽÝn/õœUUMÜ–Å2ã +½>Ñ,Ëã‹‹‹…ÛãŸ[»ÝÎôÜÆãô×8ÏkS«Õr=§y6–e\\\ŒAXjŸ÷z½LÛXeŸÏÓëõRÇ5 2ÝÞ{6«F£‘{¿ ‚8æ}ŒÇë߇y?¯ˆh|rr²¶ã`¤}ýsyyYöÓ€I’´Ñs A2Å5ª¬Ýn/¿LûQUu©÷Åééi®í†‘ú8댯m*69߈#óÅ[x¿e×(øMÓ2ÅMøû剣¦5«Ñh”û8Í3–,¯Qš^¯·ÔûG„Lë-ãñúÖ³x'''©cË?›õž­Õj™î?–úÞ–$)q¿EÇáº÷ᬵ“y?½^omÇìÇ@A\×¥áp˜©l¯Ñhïû™²Ü5MËTEBj·ÛÉæ³m;We‹F£Aë–µÿWQ‰±2Ë_-’5;¹ÑhÐp8ÜHV²¢(†!µÛíÌ÷QU•.//K«Ü™•e›5ƒ7jóÂËóYáº.©ªšéoA Ã0(‚Ìc,ЦitqqA’$-ü[I’h0ä®®°í6ý}Òn·3•–€íµéó ÇqP½¶žmÛ“øeZ,/v»9Þϳ,‹jµÚ¿“$‰NOO7K«zlÒu]êv»ky,ß÷éè訲m$¢Ê Y†A———èÓ4)‚\ëD†aP†¥W™M[¨Õj™ãg«®ˆ¢HžçeŠ¡Ýxï·Ûm ‚ ôŸiš4 2}fªªJ¥¯÷ÀvB‹(”¦i¤i1Æ&eÙÂ0ŒµuˆÔj5Ò4LÓÌýæº.ɲLŽãÄÊE©iZ¦/~±}•/×uI×ur'ñ|kµ)Š2W4±Í»à¿Ì¸£6¼,RÆX¬$×ôí­V‹4M›¹mÓ4c‰y’(dY^éµÑ4†Ã!Ù¶{-AˆY3m,ËEqRV,*ÕAìŽÚ,ó¾XeŸ/w¯×‹•jÌû^q'Qê1ÏøDQ$ß÷Éqr'Ö“è{û-Úw³¶±hÜEìèD£çyäºn옔$irLN{Ç@ÕEÇût)Æ¢‚°Ñ¸PMÓb%㋤ª ±iS IDAT*k`gDñKÛ¶'mÈ}ßÏÔJ@„I;óU]}ß'˲íTUÄÒÅíÖ×ÝDl’ˆèGôGã¾é¦›fþ½çy‰‹;AÈ[Ã0ñ\ˆnÄÿç&GðcÌG]5æµí°,+6þéXëô:Lž±¬rìʲL®ë’eYäû>yž—X+RU•t]ϼ>1mëYÓEI>žûøPŽ+ãñøQ"z\Ù€ÍÐ4ÎÏÏ'ÿE‘z½^®Å.Æ5›ÍDápˆI¬,ËkëóÚëõО`Ï1Æèàà`mwyy‰(cŒdY¦ëׯOnS…z½^®v-AP³ÙŒ]*A€Ï:€ @€=ãyÕjµÉ¿£LÜÃÃCêv»±äiaÒÙÙ5›M:88H$wôz=$w@!Ö•!I’;€DQ$Ã0ÖòXªªbÁ*AEò}?Ö†*:::¢z½NÝnwfEï ¨ßïS½^§£££Äßyž‡Ï:€Š@€=Ä#Ó4éììlîß)ŠBaÎ-ã&9Žƒ3(̺®®k·ÛkoùÛ)Zô\ª@ÕA@¦iÒÕ«Wçþ¢( [¸K’DžçåªÅB‚Àó<Ç™YµcÃ0ȶmdî@áLÓ¤~¿¿ÒcŒF#EqM#€mÇ·2ÎK’$ Ãp#X×uɶí¥ÚÞ ‚@–e‘eYˆ¥T <€‚ ÏóÈ÷ý¹'µ’$‘¢(¤ë:麎‰l̪W׆A®ë®qD°í\×¥f³¹ôýQ%¶çyäyA0·ªG­V‹Åÿ šà©|ßý[Q$t@©V¹ºîââåD A–奮n'B•@ØNA$Ú²kšVÒh ¯Ç–=¨&Lè jLÓ\*ÁCUU$w@*Ó4©Óé侟aH„ ÀvCØË\]×ëõÈ4Í‚F°º0 éüüœÂ0œYMQ–åIÙl¨¾o~ó›ôÝï~7vÛ“žô¤’Fó„aH‡‡‡¹ï‡*P$xÀÖ°m;×Õu‚ $ÊŽ@u¤µ^‡k«&·ìãå+_¡/|á ±Û$IZjñ'+ß÷©^¯ÇnÇ…m(ù™ªªj"¹ŠÃ£~¿OŽãP†™ï'Š"išFº®S£Ñ¨ìÕ㺮ÓÙÙYì6EQèââbíÛºråÊJ÷W…4M#MÓHUÕµìÓ[o½5ñ9òàƒÒÍ7ß¼òcÀú¥}fÍS«Õ(‚G-ZÖ( Cê÷ûKß_Ó4Ùÿ;,mQÒ0 ’ey­Ûñ}©6‘u‹ïxÇ;h4ÅnûÓ?ýSzÜã_ùä-ŸŒÊ°ŒÁ`@¯}íkc·Ýyçôæ7¿¹¤Á®ét:ä8ÎRIˆŒ1ò<<Ï#¢j^AÎK]( ‚€Â0\ûùϪ‚   ÈqE‘t]§v»]¹q@qLÓÌ•àaYV£€]͉|ߟÌ7ÒDÛ¦N¡:ö5¦ÿ®w½‹¾öµ¯Ånû“?ù“Ê&˜ì$x¬Q†dÛöZKÓ42M³ÒWdA>žç¥ãñxmÇMÄ÷ý¥úÇòdY&MÓÈ0Œ•®¤½ë®»è‹_übì¶?ú£?B‚ä&Ë2©ªšù„ P%AP³Ù\xÕ· DDtýúõ…Yµä"š$Ÿ¤q‡ÇÙàhòaŒ‘ëºäº.Ù¶Mív»ì!ÀèºN’$en©ëzÁ#€m†!u:r]7ÓßGsèš^”pºjLVAjì~4­}N»®˜þºŽŸ¿ýÛ¿¥O~ò“±Û^ñŠW`½  Sö ïûdš&R§ÓAyù0+ȹJÕ—¢…aH®ëR½^§z½Žò£P Y“6jµZ%½`?Eóê´9u­V£^¯G4‰1FŒ1Ç4h8R»Ý&I’b÷ãÿ]Ýnwæïò\!¿,UUi<Ïü¹¸¸ ápHƒÁ€Úí6ÕjµÔDZm›ŽŽŽp>°'²&m†Å-HÅ£N§C‡‡‡™“;f=N”l 嚕ı‰9í²¢ã1}€Ý… “$)s©® Wh1ÆÈ¶mr]—ƒª¶TÔ_;M†Aá¯m­VË€Ã0õŠ•¨/üéé)®ˆ€RéºNÍfsáßá³ ªÂuÝÔï®Z­FŽã̽²nº\·mÛäy9ŽCççç•‘ã8trrRÄ Hð(˜iš¹2mƒ ß÷ÉqœØ"{†tttD½^ V[ˆ¯Þ!B,™Çqœ•²º³X8ž]]×`0ƨÙlc ýf 4¢(’a + !ð ËzêSŸšè{}xxXÒh`Ûyž—šÜa9Ž“;i@×uÒu\×­de þ¼Æu]R%vþãºnåÊ˲<¹RV×õX€^õ9mZû1¬-l7$xl ”šßNÓ%Š§Û³Døà@•/Æ‹Hð€2¥OªP€ý‘6§—$i§¿ŸcsÛ³D¶éü‡1–Öó­S`w©ªûw­VÃUù@DÉyO¤ªÉ¼¶m“çyäûþÆ’-cÔl6É÷}r]wëªELϧ۳DÒæ´U‘óßaUo•ó!Á`K¤eTâIJÚ<Ï‹+Ó®ô@™b€Õð‹eF£¤‘Ìæû>ŸŸÓùùùÆÓÛÜÄzèît:“Ÿn·[ø¶§Ÿçùùy¡ÛÊ*-€½ëW}óÏ9­ 4Qú~p§1­ªÕj%ßU]¸€õã?¯v9IòIkÅ×h4*{æôùǦÎEøíT=ùaŸ€œ6M›ë"¦›„€-‘6 ÂÉeµe rnc™âk×®Åþ]Փؼ@¾ýío“¦i±ŸÏþó¹# Cj6›tåʪ×ë“Ç9::¢ƒƒ:>>^{YÜèª<~›‡‡‡txxHÍfsí Ñó<88 ]×ɶíÉeYtxxHGGG¹®Úó}Ÿ®\¹2ùá?Ûg=OMÓèÊ•+Ôl6K "§½®»žàÁ·šœõ|ÓÎÒ®€-StÅ)¤ïõz8÷Ø#üwÎ3 ’6¯•Ü Û‡O>N›×¦µi©Úœ–wýúõ²‡kôز‹1Æ=œÓÚ}ð‚ ˆ}qK’”9 Å£«W¯ÆnãËSλïÙÙyž—ÈxE‘E!Y–IÓ4RU5uLüØÓÌ»BO„R{#ó¥úæ½^º®Ç’:Â0¤ *ÙÛ9 ÃÄ¢À&Ɔa옚Β—e™dY&EQ&ǪÛìUU'ß ¼À:|÷»ßMÌ5yä‘Ì÷w‡:Î̲·Œ1ò<<Ï#MÓèôôt¥ñY–•XdŸ†!¹®K®ë’¦i4 VÞ¦mÛÔív–÷ ‚€ŽÉ4MêõzKo/:/ZTñ!*}zzZJ°=í@6Hð¨°((É—}k4•¼z(o`9âû>I’TÉÉϲø×lQ‚ÇôU!D7Ú´T-Á#‚D%™YXÖ!oú~®ëR£ÑÀd`OèºNNg§¾GöY«ÕZÛ•;|Eº¢yž73¹Ã0 ÒudY&Q'5<Ï£ëׯçja2ͶíÔ9xtµ™iš“ý]UÖï÷c‰×yY–•ئªªdYVì³8 ÃÄø\×¥Z­F–eeÞÞõë×cóBÃ0È4M’eyr˜çy©LZ­ ‡Ã\Ïois×]¿?«¦ÿ¬»¤õÕ«W,¤™õ,Ë"˲vþõ€Ù¢]®Âù¤Íð±;ø„„yq¦¨MËt;ó³³3bŒUjþÈKœ'U1¦Otcÿ«ªŠ˜>@Hð¨ èK×qœÄ`µZ­´+›æI ,K’ (GÏÅ÷ýD –]êe•‹‚û*¶¨lwU+£d#^‘I(š¦%e¢¤é`>clrÕÝ´]:¦`¾¨|2‚*»a™@PÌš/©ªJ®ë&æ&QË È4Í¥’Q|ßO$àݘ3¹®›,*Š2IúÐu}©>̾ï'„'''©óBY–Éu]²,‹4M›l¯ÓéÄΙ>&øVÑ~Õ4LÓŒm'o†¥Î wy^Ê·äÌÒJ”¨øóŸe˜éºNº®W*0åˆÎ/ª›€ò¥UkÃbônà[®gi½Ã·i‰æ´U¹87J¶X¦:ü²t]OœÓ«ªJš¦!¦°FHð(صk×¶‰ÊQEA¨YAíZ­F¾ïW.Д–zzzºðª<ÏóÈq:??O,ÊñÉ-A$®†œw%^™û(OõŽé¿ádª’à1«u‘åÒ\×-r‚@¾ïÏÝ^4¶m›®]»†“+€=£i< T–e%g†a,LÎVe2Ï™¾ú+‹´À\–¶Œš¦‘ïû‰dˆ,øù©a “~E!×uéøø˜ˆ¾Wq-O¢óÏyÁREQÈqœD¢ïû¥Yw9HÉ¿öYÏ_fµ©,ûüçì쌮_¿Nׯ_§F£±Ó¯,¦( Õj5Ä`b«µí‹ebú³Ú´T!Á#:>>Né?ó}?¶&yž7w{|L±=€làP0×u×Rq#K ¶,¾ïÇ‚ÙQyæE¢+£ÒŸ÷j™]:¦Vqß}÷Ñ`0 O}êStï½÷Òƒ>Hßüæ7éá‡.{hÓžô$:88 '<á ¤i½â¯ g=ëYe«0Žã¬í»\Ó´…ÕôÖ!-É¡èù¿MA ß&¿È•wÑ˲¬ÉëA®Åü<-3¦Iª`W“=Ï‹%úgmÏ)òü'ªŒ“•ïûäyyž ÐGl8ŽC'''+k×=ðÀt÷ÝwÓ‡?üaúÆ7¾A£ÑˆF£}ç;ß){h{íG~äGèàà€žøÄ'R½^§f³I‡‡‡ekg ‚Çö Ã0ÏÓO«â‘·Zá,ëŠéÜA´ú:QÙÕü¶ <*ª×ë¡ïïâíy&%iÎ~¿¿¶UûÙG‹›(1Ç—7Oëo é¾óïÐÛßþvú»¿û;úÌg>Söp` |ðAzðÁ‰ˆèßÿýßé­o}+=ûÙϦf³I¿ÿû¿O?ð?Pò¿Ò¨V«žpšVB¸È¤p¾Ò$I¹ç…üÜØ÷ýÌóe$ðVÏ*ç>Ñßóç?Ýn·”’ÖQ«7ÇqÈuÝI‰èˆeYõz½mÜ}÷ÝôÞ÷¾wg“™¶Ý׿þuúú׿NDDÿøÇéMozýÜÏý½ò•¯¤?øƒ?(ytÛ¯Œ¸e†t||¼T¼÷Ê•+ ÿF–e ‰ä]Çq¨Óéä~ÎN'Så@˲èôô4×c¯nÕh42ß7­MKÞj…ólSL6ç1e`×µÛmÇs†Ãaâ~ë*M[¾Lï>áŸ{ÞAb·ù¾_zIiI’¨ÝnS†›òÇ>…ٜѳžõ,ºóÎ;‘ܰã>ýéOÓë^÷:úñÿq²m›¾õ­o•=¤½¶ìÕ^Ë Ã0ÑzfÓ %GGGt~~žûg:Hœ'XY劆ÓÒ^¾È.`Œ-Ýž%’vþAéç?¦iRdFìv×uíöÝ;ßùNzÚÓžF¿÷{¿‡s6€-óŸÿùŸôš×¼†žüä'ÓÛÞö6zä‘GÊäàyÞÊ ÿó„a˜ZíÁ¶íBZÇ)e.¸L{–HÔ¦e_å» eÄôyh¹PTð¨MÓ¨ÑhÄdN‡LÓÜŠ$MÓb¸AÐññ1õz½­ÿºxž›€æiÏ™U¦x¿YûÙ‹¢HŠ¢(Š…_ :‹¢(±²ÚN‡Py†ï|ç;d}à({(°aßúÖ·¨ÓéÐ]wÝEþð‡éçþçËÒÞ ‚`ãÉiAÏM$•L‹ÚY¬"Opx›*xð}¸Ã0,µwø×^Eº~ýzîÖ8GGG‰Ä€¨‚F™DQœT(™>?s]—ÆÞ—¾ÿþûéùÏ>Ý{ï½eVôµ¯}þìÏþŒîºë.úЇ>DÏyÎsÊR¥¥µ€,£‚Ç&bîisWY–éêÕ«…nwÓë i ÆËÄôù$‘¨Íߪ$IÊt1Ó×4-wËóuÐu=öþèv»tpp@ív{ãcØuHð¨ÇqÈ÷ýIp˜1F–e¥öó®MÓ¨V«Å&wžç‘ïû“R·Š¢ªª%޲xie²óšU¦x ëìg_4˲“b˲ÈqÒuE¡Z­VÊDµj|ðAºýöÛéââ¢ì¡@‰F£ýÂ/üýýßÿ=½ô¥/-{8{¥Œ€nÚ•òEB‹¸­ì«ÚŠ¢iZbNïûþN•EæçꌱµkôûýÒ<"®ëR±sÝf³¹× ŸøÄ'èöÛo§‡z¨ì¡À}å+_¡_üÅ_¤~ðƒô‚¼ ìáTVÚœ;OÛÁu‰æ•Yª]¸®K>βØ.Šbj<Ú÷ýLI aÆæÃªªfš+–Ѳž_i4¹ÇÖ¦åììl- ¦iVfn¼ˆ®ëdÛvìÛ¶ÉuÝÉ:bú뀊e™,ËŠUÂè÷ûdšæV,Ê;ŽCõz=vc,qeŸ¢(¤i†±S_äi%Н_¿ž©·à"aR;µ¿‘e™Úívbÿ¥•Ôu}Rg—®ŠÌâ¾ûî£ç>÷¹ôÕ¯~µì¡@E¼ìe/£x€^÷º×•=”½¶ ó÷Ue­7Ï®Îow=Á#:?)úñ«r|ضMÇÇÇ“3ÆÈuÝy=óøÈG>B/|á ËäÑG¥Ûo¿ÞûÞ÷¢-Ù ióü¼ÌÖ%ë\Ä÷ýX‚Ç*É¢(fº¿ïû±ù°¦i•MRàçíëŒé{ž·W‰Áik\D7ö…뺱dMÓH×õ½Œé¬<*$ªØ1=ájµZ[qe¾¦iÔëõȲ¬D‰êiQÿ¹¨ÃéééN|{ž—¸zse«#ë*é¶MlÛNd{§‰ö³mÛdYÖÞ”|{øá‡é…/|a¦äŽÛn»~ý×î¸ãz⟸W­“¶Ý·¿ýmzàè {ÎÎÎèSŸúÔÜû¼þõ¯§§>õ©ôÛ¿ýÛ%ì£mª·iº®'Eúý>9޳ó°MôÒv§2Õ,u]'Abç¹»Z}fžOúÓô’—¼dáßÝrË-ô⿘^ô¢Ñ-·ÜBO~ò“I„ ŒÒ<úè£ô•¯|…¾üå/Ó=÷ÜCüàéóŸÿüÜû¼ò•¯¤[n¹…ž÷¼çmh”ÛCQ”Ôycl'æyû&-¦ïû~jÅÄeŸ<ˆnÄôc‰Š&¼h?[–5‰éã=ÝcÊ|(ЉEü(b˜¦I¾ïgnÅâyíDp¬è ç¢$‡]åº. ’$iáß2ÆÈ¶m:::*¥Tú¦½ä%/¡/|á sÿæôô”yäúØÇ>F­V‹žþô§c¢ °e÷¸ÇÑÓžö4zîsŸKù—IW¯^¥üãT«ÕæÞï¥/}éṈ¶Õº‚UÂÏ!öa¾µ,QÉ0ŒÄíUIXX¬íõz4—þ¹¼¼Llƒ¯ŽX6¾šÈ¾}¾>ôÐCô¢½ˆþïÿþoæßÜrË-ô¾÷½î¿ÿ~:==¥ç?ÿùôÌg>É˺†á IDAT%{üãOÏxÆ3¨^¯Ó_ýÕ_Ñç>÷9úØÇ>FÏ|æ3çÞïÅ/~1Ý{ï½åvI[°ßD,¬_ѯ[Õæ´›â8Næ˜~ô÷õzç˜9 Á bt]O$Ht:­ùrS…|ß§‹‹ :99Y¸øÀ£z½¾Õ²0 “5UUWúáƒ`Q»›}¤ë:…aHƒÁ€ ÃX81 ‚ Ñ.h×¼ýío§{î¹gæïŽŽèÞ{ï%˲èð782Ø„_þå_¦ èïxÇÜ¿Ër¥5¬®ŒäÉ´ÊEŸ/ð Ü»˜Ä²Ni%³»ÝîÖœ×ÍA¬×» +_•(Ërâ¼qŸÏªè5¯y }ùË_žùû×½îutï½÷ÒïüÎïlpT°¬Ûn»>ûÙÏÒ›ßüæ™óðÃÓïþîïnpTÛ#mZTc,qQåª1}>nµöÛGËÆô·ý| `SТ ‚Ç¡£££É¿c“ö-ÛBQ”Xåß÷)ò}?‘ Á£V«EÃápÓÃ\ >ðX«ÕVx;ŽC­V+±}+é6M×õÉógŒMŽ'ÏóèêÕ«±¿ ‚€lÛ®loÇU<ôÐCsŸ×ßøFzË[Þ²Á@Yþøÿ˜~åW~…Ýÿý‰ßßwß}tzzš˜SÀzñ‰D7æ¾E¶/Ikqèû~¡sEþy–Õk|[hšFªªÆöS†dÛöÖThLß“꺾–$'˲mm\×­Äùc,q¼ïS{¢óósúÇüÇÔß=þñ§÷¿ÿýtÇwlxT°wÞy'ýê¯þ*½ä%/¡|0ñûÿþïÿ¦÷½ï}HôàèºN’$ÅÚ¬GqÊ}š#l;>¦/IÒÊ1}×usZÏóR“¿÷EÞ˜¾ã8;ÓX7Tð¨ EQèää$v[¿ßßê«ä4M#˲Èó<º¼¼LT)Ygo»Mã3}-ËZù1Ó&}ý~¬ÿ?QIÓ4²m›‚  áp˜ÈÞÕ¶6wÞy'=òÈ#©¿ûó?ÿs$wìEQèž{î¡þáNý½mÛ46<ªýÃÏm‹.Å+Ër¢â[ÑÕø…v¾’$¥%èw»Ý­=ï!Jαו€‘ö8ggg•8ÿIKÈIKìÚUø‡8ówÿðÿ€ä€-÷Üç>—þéŸþiæïßð†7У>ºÁm‡´Øm§Ó)a$°¬"búUžÓVA–˜þ.T=Ø$xT”mÛ‰ í&¯¾,2X+Ë2ù¾Ÿšä±mÂ0L´—YGSEj4‰ÛQ¦8¦i‰}†áVSó\½z•Þõ®w¥þîŽ;î ·¾õ­TÁ­·ÞJøÀR÷ðÃÓwÞ¹áíŸ2’ømn"phFì߸²j>Y–©Ýn'n?>>ÞÊ•žçÅŽ±u´g‰Tõü'‚DÉuI’*QYdÞõ®wÑÿüÏÿ¤þî-oy ýÆoüƆGEøÙŸýYºûî»S÷ÀÐÛÞö¶ ¨úlÛN,Lû¾¿Õ•ÚöIZÜx]1}þœ‰(=ñnÄôƒ ˆ­ƒEU>`>$xT”(Љ aT¢j6q5Ÿ»_ÜüëÑh4ÖÖ‡=mR¹«U)ÖAQ”DPxײ}ÿæoþ&õö›nº‰ÞùÎwnx4P%/xÁ èe/{YêïðQ¼´+øò&gçMLå·ÉË•p‘ÖszþñûýþÒ ð»6O›Å¶íDb;cŒêõúZ΂ ØX¿u—šN{¼2ûÙA@ÇÇljcuŸ›þú¯ÿ:õö[o½•ÞøÆ7nx4P¤—¿üåtÛm·¥þ®Ìïã*K‹Ów:­Œqï~^«ªjjÌe ¦Ÿ(Љó¼‡C‚@…™¦IµZ-v[§ÓÙH0t_¢|"Ä6yùòÛë¼’Ë4ÍDß÷Q {¾Tò6Só|ìcK½Ý²,zêSŸºáÑ@ÕÌkÓõÑ~tƒ#Ù?iWjyž—99Û¶m:??ϵMMÓ‰Ýn7óÕa¦iæžWʲœh%Ùl6sŸ;xžG‡‡‡¹î³Í<ÏKœ×EIË^ÍÇ£N§CGGG¹ -!hÝ º®'ÎÊjÔív©^¯'¶Ýh4ö¦‡:cŒ>ýéO§þîÿý¿ÿ·áÑÀ&œžž¦ÞŽ+êÓ麞˜¯3‘7z¼uÆ7ù¹VQÖudQø¤¥uÎït]OTwA{Ëùva`ÓàPq|°Ž1¶–~pó„a˜«ox†KMPøûl[c>ÙB„B‚œ¼²ËoBKMäø+_וy]÷ß?}ñ‹_LýÝk_ûÚ ªèððŽS7+IÖgV‹Åf³9w^cšæÒýºÓ* 4›Í¹Ç£ããã\ó}~›ÓÉ Q;Ë•¾ïS½^ŸTEصvz³ˆ¢H¾ï§&y4›Mª×ë™_0 ©ÓéÐáááF+Iðç ’$rþ–vþ³©’ÖŒ1êv»txxH–e%Þ·µZm¯Êkä#I½ý)Oy ÝqÇ l³Ÿýlú¥_ú¥Ôßá|"?7&úÞ|{Õ$ Ö’,2¯ÞT›9EQbIUJMK¶X÷~I{¼}hß³lLÛ׉à{ÎÏÏ?PŒÇõÀAä.IKtãek)ŠBªªV>Û Hš¦‘a±«¥úý>™¦Iš¦åz¬¬Iy'\žçQ«Õ"Û¶éää$Ó{6ºâlÚ¼/î´çêyÞÌÉ—ã8…'ÂðÁ½"&Ȧi&®”ëv»…?·²Y–EW¯^%ÇqRû¦ ‚ 1aØ¥ÉଫçžóœçÐSžò” ªêE/z ƒÄíŸúÔ§JÍ~‘e™Ç¡f³»Ýu]òù¾O²,“¦i$Ëò$Q9ÚgaR©þ¼¯á2øs’¢ÎG,ËJl«ßïçNf¹víZæÄ©h¿Î;> ÃØ«ä¢Ùç¿ù›¿¹á‘À&Ý~ûíôoÿöo‰Ûq>‘.šãišFW¯^܆!‘mÛÔn·s=f”л®¹‡iš$Ë21Ær¯'¬Â÷} ‚ 6·­~¿†±ö5HÓ4çhggg;ŸäU¦ÌÓççÿ»Óßugggäy^¦Ê󚦑¢(“j¤Xû_Ñx<~t\€áp8&¢µü(Š2¶m{<Š*ÀÚ¤÷ív{åǽ¼¼ ‚x_,bFì>¢(Ž/..ænGÓ´™ïÅYNNNbgšæØó¼™ïÙáp8V%vA¾ÇÓöŸáp8Öu}LDsŸë:ˆ¢Ïp8,d;’$%^‹EÏ­Ýn'îSÔø²xúÓŸžÏC=4óï§Ÿ³,Ëc˲ƾïÏüû^¯—x= Ã(â©”æ=ïyOêû²Ùl–=4¨O~ò“3Ï©ªHUÕBç,Ë>þ#<’¸ßý×eÚ&?ÏòcFbN=oþÍk4¹·Ùn·sFUU3oóòòr\«Õ–>ÏWUu|yy™úØiçUyð¯û:ÎÉÖéôô4qn³ì$IãÁ`Pèx///ÛõÚ­Ã2ç?ëØ—ëÞ¿ÏxÆ3÷àƒ.õXexÕ«^•ºOÞýîw—=4(Ð?ÿó?§~þÿÚ¯ýZÙC«´Ñh4sn,Ëòضí¹ó§ËË˱ëºcÓ4÷ïõz|&»!5—N;‹¦ÅôË<—ù™Ÿù™Äxþ÷ÿwæßO?gQ—Šéç9'…òض=–ey¥s-]× _ÃÛe[Ñ¢%²m›¨Õj¡ÿìY–WHA°0ã“ÏÈÊ'·Z-:;;›”Hêv»Ôl6éððpR&™/-7YtµàÁÁQ½^Ÿü¤––³m{aÆÿ|‚  ÃÃÃÄcG僋,ù<}å#ÑÅEe@§UTÙå«ÇctíڵɿÃ0$ÇqHÓ4ºråJìxª×ëtåÊ•DésAv®ÊÉ׿þõÔÛìÇ~lÃ#€*›õ½0ë{ÖÏuÝ™ýËy‚ Ðéé)¹®»ÒÕ+®ëf¾BJ’$ +·÷e™|ßÏ}E¢$IÔëõ&+ö‘eY†!µÛí¥û  ‚@ív›Â0,¼Ô6ßž¥V«úÚ¥Íã7}µ£ªªÔëõ6²« çû çËE‘‚  “““ÄïÂ0$Û¶éðð®\¹‹—Ñ•+WèððLÓLùb=l}<ÏKÄ‹šëí[LŸˆbUlc¹cúDûÑÊf›ù¾?iºj…Î}¯ò¹ªÂZ´¤QUuá(clÒ§iúà â8yžG½^o£å¤Ê•Yž^øît:dšæÌ`°išdÛvì>Ñë¬/JAȶmR…êõz¦±)Š2³—V–†adZŒ·,+QÎx^ïî"¿ø g‘A¿´¾ìý~g';Œ1RUuæ1µ(qGrgçJ¹!À YÜ|óÍ©·õ«_ÝðH²Iû¾^g™Îeÿû¾ïûHUÕØm?ôC?”y»–e‘®ëdÛv¢Ü,Ñsã¨eK4Y–ÛÌ*j›ÍÿÓæQFƒt]ùmæ?‰¢H¶m“iš“sõésˆ$I¤(J¢MͼÇ]v_%ŸGI¢}gYÖ¤]ïûsÛ­‚@š¦%^Ç¢A{=ŠN¤Öu=q¾µhac•ãEÅÉ1• ^Ç窪ôô§?=vÛ÷ÿ÷¯ü¸›‚ó€ý„Õ8Ž3™«¥Í‹‰²Åˉn$ÕF ä°›ŒéëºN­V+v¿¶±KVéõz½‹éï’V«5w]1:—ŠÚ2EkýAÌ<×­â¹úÖo°EKÞRB£ÑhÜëõf–¶Bi*¨š¢Z´DƒAâñµ¡¸¸¸H-qËÿ‚0n·Û“–'yË"_^^ŽÛív¦mE?’$å~g)ymF¡íHF£Qb›E—’JûœW>nÛ[´ŒÇ7ŽAÃ0r•¯VUugËzÍ*‘|÷Ýw—=4¨˜'>ñ‰©ß?üpÙCÛ[ãáp¸ÑùXÛŒDÛ‡…¶òØE£Ñ(¶ÿ†ÃáÎÎo¡Úžõ¬g¥~—Üwß}e –öùÓM7•=¬­ÓëõR[F.ú©ÕjXû*@1ý´Všó^ÛmoÑ2ß8]&¦_æÚ,–Ö>*zí²~^Eë=Y×a¾+ãñøQ"z­™ïû‰«ÿÛíöÒe`=Ï#Ó4>ÃáŒPQ6Ú´([m]Ò2³TÆq]—|ßO\ù¤iÚ䇿ÿ\²¾×¢Œ¼0 S3’E™\y¶ ×uåÌ¢ÇÔ4m­W}¦Yeß,+ ÃDE’yÇVÚ߯ëJ´eüË¿ü =ú裱Ûî¸ãŽÌ÷÷}rL¥UfÑu}’!º«^ýêWÓ{ÞóžÄíwß}7½üå//aDPU7ß|3=ôÐC‰Û~øá\U(`ýäOþ$}ö³ŸMÜ~ß}÷ÑOüÄO”0"Ø”+W®$n»é¦›èÛßþv £Ù~a’ïûÁÌêÑUﺮãŠö‚lkLÝëKyüë¿þkbMö¶Ûn£Ç?þñ™î¿(¦­írL4›ÍÔöBË®ù‡aH–eͭ΋mM‚ÑEcMÓb(²,ÓÅÅEi‹–›€È °*$xì/$xÑöœÝn7v› äyÞÊ Ra"¡m-{y(ŠB®ëÒñññä¶0 Éqœ•G¶M†±>Î’$m´ÿ.ìß÷ÉD7*쯣ú ’;V³U D7Êð«ªJççç“ÛúýþÞ%xL?_UU‘àKcŒQ³ÙLÜ~zzJº®—0"à=¦ì,ƒOfˆz˜@~ŽãP†±ÛTU%˲Jð¶2Áe[Öƒ1–Úš¥ª4Ç¡ƒƒ:::"ÆØF¶É£z½Nä8ÎF¶ÉÛº-³lêE€ÝÁ£óós ‚€‚ ˆÅeYŽý¨ªZâHŠãºnbÍÝ0 Ò4­¤Í×jµˆˆ(rg#‰(®ëN:‹´Z­R*›le‚_†ˆHÅFYضMNgéû‹¢HŠ¢¦iÔh4HQ”5ŽŠ iŸŸOþÝn· `3Æ(‚Øm7ß|3ýÔOýTaÛ,ƒïûT¯×c·Çã¹÷ùÚ×¾FŸûÜçb·ÝrË-ô´§=míãØ&ý~ŸÇIÌ#Ñ4t]§F£JÃÙôùÄ7¾ñ úÌg>»í)Oy Ýzë­…m³ ü¹¹ªª [ŸéK_¢ûî»/vÛáá!I’TÈ <ý~?q›®ë%Œ¤ºø˜0 7~N°• žç%n«jæ1FW¯^¥Z­†¤€Œcäû>ù¾O¶m“,ËdY†ïS "¢O|âô¼ç=/vÛññ1}ðƒ,iDÕñ¡}ˆ^õªWÅnkµZôö·¿½¤”«ßï“mÛ©‘e›X–EƒÁAïàû>ýÖoýVì¶W¿úÕôîw¿»¤UÇûßÿ~zÃÞ»íMozýÅ_üEI#€"„a˜H|–$ sÝà‘ïûtvv»Í0ŒL÷»råÊäßy,Â0¤k×®Mþ-Bæ+‡ƒ  ~¿O¾ï§^ åŠd~ìW¯^ýþúõ뱌v^žñlƒ0 ɲ,r‡z½ÞÖ$z@yct||¼°bÑ`ötfØNAP½^O”T&º‘ÌaYÖä",^»óïxÇ; j ÀzÍ î¨Õjdšfê+^°‡—Õ¶Ãw÷wGúÌ·ÞzkA­Ù,7ÝtSäÜpWPk /q‰ 6-É\¶Ö£££@©“y¼”ì‹I­V‹t]ϲy™°,‹ŽŽŽü¿†!˲b#œf9lÛ&]×i0D>,Óé4rŒÙ²-(Áä85›MFE7JD×uºxñ"u:¢› °,K–eE‚<H’$tøÙétð[¥àýöîÒw6€Çqj4$Š"õû}Ìå¤Ýn“ã8û*• ~{¶€ã8þ\^8Ë ÀªÇ¡ýý}ôÓ Ù;6ÙÆ—hñpG𦑢(E7e¡ð 1í•ø°¬f0¦i‘ó–ד$‰ºÝ.¾—7œ T¯×éððпo0`Â`ÃyÙá+ªveY´··Gš¦Q«ÕJ].æ³,+’¥ÃË´‹ó Pn^ 8ÆôÓ‹åºn sw.\TÙˆÃ0ÌÂÄ ¶mÓÅ‹—gÖùóçéÔ©S ·©T*™¾‡6>ÀƒeYF‰²`l‚p€:ù²,‹šÍ&; s¦i’iš¤( u»]tà6˜ ×uÉu]¼fÙñ4M#]×IUUL g$®L´ªªynÇ¡££#ªT*kµm›ÎŸ?Oõz}#Ï @ưn³ýô]+ï¾,Ð!/š¦Åöå—1 #QFAh4ú¿®ëÒþþ>Ù¶ú¸ªª&z\¿ßÏ,‘Å™ì%¡N§CÓétám8¶q]w¥“Y”ð ¬×ëÔ’íæ¥£ßßßGgreíííÑÁÁ‚ö6TÜh™ú»À»òEQôßæp]—4M£jµJƒÁ èæ”Z\™h/;ð&’$‰E¡jµzâòÖI™¦IÕj•E¡F£±–c¬j0`<…ñúé{{{;ÕO/jŽÝ4Í\÷oÛvä¹ÅÝ—µ$Á'I­5À# I’"õÒÚíviÕDQ ümY5 t:22ر®/Àl›'î7WŸlf¤ç8)вsÈYŠ+Ù¸©ÁŽãÒO¯k¾kvsl°©(›dÛûéÇÝ""ây>×ý3 9ÏóÄ0L®ÇÍ2SßF–hñ®–öx kqƒ³M#Iq¨¿ã¥ù$I"A¨R©äþÝ&ƒÁ€ ÃÀ€ 5û{¤( µZ-|—o€¸ÈÚ²”vØVƒÁ€t]GF%€ð&5M#UUI–e2'àºn „£G’¤Z³,‚¼ïq”b€Mµ­ýtžçëÛD—íÂÉ òfš&†‘è7`¶”K­V[ÚV–eI’¤ØÛ¶É4Í¥øZ–EGGGþß²,/]'òb²²‘<ÏS«Õ ”7éõz¤(J)l àýýýÈýáô.Þ›H–åµ8ÊÀu]êõz‰?Äëâº.éºNº®“$IÔjµð=^¸ÉÛz½^Pk’q]—ŽŽŽæ¦ìb¨eYtêÔ)ÿïp6·Mà8N`€Ãq\æ¯Óìy`¦ý^¢õœÛ¶ýºŸIÏÍì6•Jeé@Û²,:þ|dDz, ‚°‘ïËMã8ŽØlWÙq‡TU%UUý@ó²ôŠ—Òy[&Ý!^úÑOÌ·Žs3»“ôÜÌnƒñÄz8Žã¯`<eàõÓ5M#I’¨Óé”z^WÅÀïQ1DDŠ¢$zÜl€‡(Š'ÊÚÇó<©ªºôqš¦Γ¢(k?GàAtùä†áOÊ].Õ2 lU2¢(Òp8$EQís]— à Ã0HEêv»¥éxçɶm¿#°é¼,M<Ï“¦iT¯×1q¸FÍf32è_Ö ³m›Úívà¾4¿ÁªªR(W*•DYÆ,Ë¢^¯—¨† ž¼k{øùƒHG|–,ˉ;Èyñs¼ÏO˲¤ª*µZ­TŸ§ûþyÿï_üÅ_¤ýÑ]¸Mxà2ü¹ëºþbu\°©×éoµZ‰Ûæ8ÄF‡³,K¢(ž8ˆl:F‚çw~‡Þõ®w-ÜnÙ¹Yˆ+‚êƒeYR…:Žÿ±m›ƒY–  ê÷û±ï{×uéàà ñ¢$I$I¾ëC,Ëò3î@¾fç‘E9Ñoí¶B†¿íçõÓMÓŒÍö»êxâî»ï¦K—.ùÿÆoüýÐýÐÂmN2žÁÚZ•7žˆë‡euqáÅ‹#Rôûý@î8³AüDÁsã-䛦9÷Üt:]éºh¬Åó¼î½÷ˆ7F _¤nû,×u©Ýn'ºÚ—èñ¾»ƒÒÌ—l¢ðzoYûéq}fdfÝPÓéôµiF£Ñ”ˆ·N§“jý~?²~¿¿R{ÂûF‰·ít:mkµZ¢í&“ÉT–åȱçÝX–ŽÇã¥û ŸÛ¤íÙdÇÇÇSÃ0¦¢(&>_Ëni„¿ëW½±,;U%Ñ÷y<ð@ìñ~øáL“—¸ó›æ·8Ž¢(‘}Öëõ¥ÛÅõQÒ´¥V«¥þnµZ+¿§ºÝî¶§½¥í­*|ž¼ãv»Ý)˲‰Ú*BªÏÒ 7ÜØ~0¤n§÷^FSžç·óøø8õ9Js.DQœŽÇãØ÷À2¯¿þzd›£££•ÏÍp8LÜnI’RŸ—4Ç`YvªiÚÒ×*î}??ðmÓûßgÏžm÷+¯¼’Ù1¼þ» 'þ^Jú^Ø&áßÙUo<ÏO5M›N&“LÛwÛm·ÅïßøF¦ÇÉCܹÍz|–¥pÿn]ýõðmÓÌOt:Tã‰4Ÿ«®º*°ýc=–º«ô™EQ\y<‘ô»BÅéd2Yižû…^ˆìï™gžYº]xïܤ)Š’ú¼L§—×’ƒçù©ªªK;;.÷lóx"®Í§OŸÎôÇÇÇS]×»Ë~N <6½Ÿž7†a"Ïe“ŸC\1oáþÔI×9Vqm0EQ¨R©îk·Û¥IÏÅó…«0# IDAT<†A“É„ºÝ.Õëubfîã]×¥ýýý*GbY5›MÚÛÛ#EQb£îÊċ֭V«T­V©×ëíÔ÷ú:X–EÕj5r…Çqyõ¸ªª²sŽã¨V«Q­V[Ø?Ø–« Ç¡jµšª/gÛv!}#¯Ü^ÒãÚ¶MÍf3Õ1t]Ou.¼÷ý`0Huœ¬išFF#q»MÓL”Úp–a±Ç`&òYq]7Q]æpÓ{oÅ=ïs‡Ì*sºÍ“:<<¤f³IgΜ!EQp%@ÁÇ!MÓhooö÷÷i0”fÞ,/qÙì¶¥O½ËlÛ¦jµJ©ÇëþLÌëÏÎcYV$Sã2Š¢¤ÚÆO„Kœ®›×î¤çÆ0ŒÔ©Öu]ÍöÉq\d<á8N¢ò‚áñÆIÇ»ütxxHFƒÎœ9CªªbÎ ¶Öl?½Ñh”¦Ÿ—=kçÜwÝÆ–hñèºH)íMâ&I…¾)¼ôÝÞä¶ã8dÛ¶Ÿ–|¶Œ‹ëº¤ªêV§#óÒgÏKÁ°-lÛö¿ÿ‘ÖÿdŽŽŽüßθ`ÀJ¥B†alܹõÒÎΪ×ë¤ëzì±WZÂ0 ¿ ÌìÄÏóÔét"ÛÌNb×jµ…éw‹¨™HDÀŽãHÓ4âyžxžôÂò®ëR£Ñ ñx¼¶vzƒŽãüŠ^;Ç!Ã0"íôÞ›Iίas'ceY&I’ˆeYÿ˜†aø}Æ"Tás÷꺨ŸMDÔëõHUÕDAqÁ2­V+°½ëº¤ëz Æ¦÷8I’ü6Í ÷9UU ª+•Š_/5Ìq²,‹LÓô'Äw-ÀÃë¿£6Àf³,‹,ËòË2xã]·h‘Êc60a^_tvåq‡ö÷÷ O$í3†AN'Q?Ó0ŒØÀo†aã¢7.Bñ•Š Îm·ÛþñgÏ Ë²~ÛâÎÍÁÁ©ªšh¼ošfd¬ÕétÛ{c¬ðxÂ+ݺêxB×õØñ`Üxb×<¼’ìIKÙlo=¸ ýtEQ"ýŒÁ`:àòµñ¢(’,Ë7S¯×#EQJÛò:‰’$‘뺤(J`rxxHŽãlÕÄñÑÑ‘ÿ¶® d€4òþnò¾‰Þ¨¹Z«Õ¶ê»>­ÙΓ¨Õj~yÓ„ãëõú NQIERU•,ËŠ­ð<éLkš6Eq£;ÜÝn7’ÑçyÿyëºNš¦`½‰¾´™ Vá½f•JÅ_ ™m'ÑåNÜ`Ç«³¹ˆW£9¬V«‘a‘ïïÜØ¶MŠ¢D&¬×iÙ¹ñjŒªª{n’¼/Ãç¦ßï“¢(ûX–%MÓHÅÀ÷ÈáááÜ ðÙójÛvà3Ã0Läù„·õ^s/¸ä$µÀËâððПˆÞÖþû5×\CwÜqGnûùå—éé§ŸÎmÿËœ;wŽn¹å–Üöÿ¯ÿú¯ôÜsÏå¶ÿen¹å:wî\nûöÙgéÅ_ÌmÿËÜqÇtÍ5×ä¶ÿ¿û»¿£ÿú¯ÿÊmÿËäpZä|@Þß-IÌÖŸD®ÕjÙgÎRÜoÖ¶?ç]×? 'Â}J/ø#¼]’ô™UUO躾ô¢FÇqb³Öëõ¹=xÇ”$)<±N^p‡,˱ëÞxB’¤H@½a‰Æƒá×~8FúîÞ¸šçùÀ¹<<<œ{Œ¬ÆÞÕÜ»0txxèÏ…­#¨Ãu]¬@&òüÎ*C?]EªÕjß:ï÷k“çœwÎt:}-Ú/qõÁW­}s||©ù#Šbª}„Û’¦Î*µ Óâ8.pŒ~¿?÷±ás»‰õåÆãñT×õ©$I™ÔªÂ 7ÜpÛÖ›WïÕ4Í…5wxàØí~øá5~»¯.ü[šÅ㸅¿—óÄõQÒô Âuýϫǜ¥ð¹]W­ÁeâêU&}½Æãqd[–e—Ö¥¾á†Û ƒ•ÚÉ0L¢Ú’áþÏóK·‘e9rŸIÞcáç¿LΞ=û½ùÊ+¯ÌÝf<O5M›Š¢XøoãºnÕj5××áK_úR¡ÏïÁÌõù=ôÐC…>¿Ï|æ3¹>¿F£Qèó{ê©§r}~7ÝtS¡Ïïõ×_Ïí¹½øâ‹…>7Aµ3«ÚÞ«´OÓ´©eY ÛwÛm·Ånÿo|#‹—)7q}ýMœ7›nsQµÃ7MÜg$éxj8F¶MÒW¿êª«Û<öØc+µ3IŸy:Ž'’|œd<1™LVê§¿ð ‘c>óÌ3K·‹ûá8n¥ñD½^_z¼~¿Ÿú¼¬2f§Õj-ݦlâ^»Ó§O/ÜÆ²¬Oà†n¸eyKÚO_‡¸¹Y"J4_ºn³í+ªÇœÿ2ŸÁƒèr¤½ªª´iÞU­ëˆ¼^ÇkŠ¢ž_ÙJ—8Žã_ågYR­$äÕ{õ®ÒDQô#w!ª^¯“$IkéœTø÷pS"±‹Ðjµ¿f‚ P·Û \}åº.™¦¹–×]Q”DWT¥í¿¹®¹JÏ+/”˲‘c®›¦iKßÇ^;gË%É<>I^ëð•IÞ#᫺váê¹8Þ•‡è¿ìÛ¶%¼ rõz½´™rgmÒïºëºtpp°´$Fø7x0D²„ñÆ:ŽY–Å츬rëèûT*•Ä i4ÂÁõz½T‹"y/~¬òþ·)É:@x›Á`@¢(îÄxBQjµ™¦¹SÁòE ÷Ó×…eY2M“A¬ýzAÃápå~ˆ—éβ,Ç'jg½^÷ûxëä% fu.* û…uE¢(FNT¯×KYË0Làï$QéŽãP³ÙLÕF˲¨Z­R»ÝN<à±m;’æ&Íd¿ëºsŸ÷!É‹—ÚÏ» p<S§ÓAY€”8Ž#Y–©ßïÓññ±ŸÅc]’M%ɲ¸¯×ë•fR1<ÁcÛ6ííí%JÕ ñò¼Ï[ž¤áɯ²}¾óD†ûëyE‘8Ž Ü×l6iŸ·þJ4Aüþût:¥ÑhDN‡*•JÑM€5ªT*Ôjµh8Òt:õ³xlC¶¹ðï<ÑzÂ4M˵Ójµ"¯WÜÜi–8Ž+M°=Qt~ÕuÝÜÇ’yŽ'Âù•)Xœ¨íMò™•$)ò¸f³IÍfs'¨½ñ„eYþx¢Õja<‘Mê§ó üˆÓyÇi·Û©€Þ›Q×uaN’$ªT*‘cyuÃH–ÕSŠë ·Ûí@´”Wã]×ur'Qü,‚h»iš~vug)à6GÒ4¸Ya&¡£LWݬ›®ëdš¦)캮ÿ»·é¼:‰³}/™71*Š" ‚àOÆ"»Çâ~Ëó.s“×g1nÀR¶¾JÞßSY”4Jºˆ¢iZ${6õ¥×§¡tWF¦åýišæŽ{u´Ód2̺ƒÄo¹å–\÷íµ×ø~뭷溞ç }~çÎËuÿ?ð?@/¿ür®ÇXä-oyK®ûÿáþáÈÜÊ:]qE~×½éMo*ô½™÷w˪†!I’üïýmþm!òfYÖÚƒkEItE¿eYŒÅNgå –eO2kš¸(l:®tÌM×ßÎ;x^c•¸×u²²Äq\êþkø¼&kšFív;pŸa~–•]O½q!ª·&°Îñ˲øL@&lÛ^kpðl?}3? ‚à÷¥g¿×]×õKây™ºã²ÿ:ŽCçÏŸ÷3èæqn‹øþ/úw§t<ÏS§Ó @’¤U–$)²¸R­VIQ”@Ëu]2MÓ_äc†xžOœž¼7M3ŽÛ{Á}A$)9S©T"uöööHr'²o˲ Iç¸]þ›¦I†a¬%ØcYÐÀ¬ðäV¼ÎÚìw#,DzldòÄ›,(ùa‘Tv³¼ÅTï÷_Qêt:[=te½ânÛ³BdAÅ@=I€G¸ìMÒïVEQȲ, ±ÿn۶߯WUÕ¿J-œQhÛ°,ëÿFyâëì¿uÕC^Þóž÷lÝsšuÿý÷Óý÷ß_t3ró+¿ò+E7!WŸÿüç‹nBn†ÙêÏ^Ç‘$I /pÚF¢(F®¢·mc°·@R–lI”a<¼Náà.Ó4—~îÃsùIÏ©ªªdÛvªñD·ÛÝú×lv{5=l'¯LºÇË1¦iï…eeÓçíÃO$醱³ã Aü‹k‡ÃáÖgGðl[?]’$r‡úý~êÒ˜Çùe™×ßT¹•h!’+Ë”×áÒ*IÛä8†ØyeSA Q# ^í ϲ…–eIUURUÕÏØaÛ69ŽãG#yÇäy~åÚ§Þ‚¡WR†çyÿV¦zª‚ øm¯VaÞéòÀ0 )ŠBªª–æ;¸LDQ¤z½¸ú®×ë­Ô'(ŠW›Öu]?U©×Oˆ+áÒn·ýþÉ®ZGYˆ¢”¥ÌÐ:išøŒ{€ªªúƒFÛ¶©×ëE&kWÍzÃ󼿭÷¹ôÆ qï?Û¶©ÙlÒp8\éxÛ`ö»Ì4MÒu}«?«›Ê n,Sx]TUŠêºŽ,yPÚþ7>ãÉhšFFÃÿ»ÙlÒÑѵZ-AͶm:88‹3 “ùx²¬@ÉmÛ~&ñ]5[Ò0 Òu=ö\”Õ.ôÓ½ç7»îÍy½±Ntù·Ò[‡‡läàÁ²lîæU÷ŸöÊ>/hbáºsYËsßEð¾lÛ&]×É4ÍØ/€MR©THUU’$ Ùr¦ëz`ñ×u]j·Û¥[hõúI³}˲"Ïèr™Š²NBžTÜUMe=ønHfv’uö¾¸ûgõûýLÞáÁ¦®ëz O:`½ËX–ôßçÕ!€ìÔëuRe«æƒ²&Iišøý ¤iÚÎÿ~ï’mÏÚ‚€ñ¨¸¾¨wAá"–eeòÝt<Ñëõpq/”õ2®`<e¶‹ýô¼×Á!^)K´Àöó²zxånP›6‘,Ë4ü[XÀÍÏó‘·¦i’eYµ(;¢(’išÔï÷÷[–µ³õã^ײN€ÅE¨oû„sZ®ëÒÁÁ]¾Ò!Iÿa‡©¸“òʒضI¹Œ+€ƒ¼þûññ1u:ôß2æÕìžL&dš&&P—ðJ‡5›ÍZE‰ëo—õÊѸ@Ž]'ÎcÛ¶^©T•Lá8ŽÆãqnï oxÄ›OàÂOØdEõÓˆà%â¥~F‘€¼y¶ããc2 ¶yƒýYŽãDîËË:®’ mC€G\¹•e—«){@U8áððWÝ͘=‚ øå?lÛ¦étJ£ÑˆF£M§S¿nõ:'èËzµg‘E!Çqh8"P %Žã¨ßï“ëºkÿÍÛ,ËÆs´Ûí­è_ÃbŽãDÆe¿¢6< O̘ý\³,ëÏÌOä•pŒ'Ò _ø‰@Øè§Ã&@€”Ž(ŠdY ‡Ctì`-dYöÐaÛ qY.z½^î“[–eÑ… r=Q4ˆ$ÍDЦ^Åutt”êñŠ¢D‚BÖÄ“—¸ åv»j›úúfavB6î³,Šb¡A>iƒ”à ’$ùYÐXÌ ,/bñqI’D­V+pŸëº´¿¿ŸIGæáþͺ.&˜Û–¡BÚñD\‰ž²¦âž“Wâ0©]ÎQôxVçŽ÷ûýR|_ÀvšÍØQö>”< ´$IB/äª^¯û¥XرyÂå\×M´X~’ ´“·Š¢P»ÝNµ0ìºndòrÑ$oø½¹,¥¨+¼lÛNœ[Ó´ÈÕvõz½ô™sxž'Y–÷™¦y/Ï£iZê‰í2™ d ¹Dz¬•uÂÁ5¸/=ob¶Ûíbb †7aŒÀòléº郹®KÕj•z½ÞÊûíõzT­V3 À‡T«ÕH–åµ-(ŠB²,S­V+EÙ˲ŸkEQ"ã‰V«µã‰ð…†a$~ýE¡óçÏçÑ´s’Ïö2Þx"íØ:ü:!Ø$=o<Ñét0ž€µ™ ì(ûÅg°=à¥ç¥îît:E7¶D¥R¡ÑhD¦i–~h› ‚»X¾Êk’«˜EI½¸îÕ`ÜÛÛ£ƒƒƒ¥@^Êìã8Ž[¸þ7ÇqæžMÓ¨Ñh¤xÙj6› ']×¥F£¹ a˜ÄA›.n Øn·—)Š’úê¼²™ý¾õ&Mƒ-¼¥Xµm›,Ë¢jµJÍf32ùÇ0ŒÈù/{Šï"y©–ÃWTìªZ­F“É92 #2v ºü›´¿¿Ÿ¨?@t¹¿: hooTU Î^…$IdYÖZ-¼6–e•¦_Óh4ŽÝ¼ñD8X˜a˜­Y‰5›Í…c×u©ÙlæD½ f&LÓôß ËÆi3õyÁF{{{Ôl6ÍAèº9ÿeùÜm¯ôŽã8±ßëYª×ë…” Xæ;‹n@¼Ž¢(+-À½1é—ö6“®ëdš&]¼xÑ¿¯ÙlÒd2Y¸]¥R \¹ÔëõèÌ™3Ôjµu×uéððПE8{öllÛ_yå•¢›6WšÏ:À6Øôy‹[o½5ö·äë_ÿzÑM;±áp8å8.“>Ã0Ón·[ôSÚJá>[½^Ï}Á6Þn‚"ÆwÝu]ºtÉÿûìÙ³+µ3©´}æ0MÓHE2 cáxb¶›f<ë¹òÊ+#í¼úê«—nÞ&͹I;î±,‹ö÷÷µÃ“d<Ñh4h4îŸOÌŽóçí«¨19l¯SÓéô5"ú®¢ó=øàƒô¹Ï}.rÿÃ?LýèG hÑv±m;°°¼Ž+?ÂYB¼:½Yî· W°8Žãg[ñêïªÙ×.«÷CYT«Õ@]êJ¥Bº®'z{µ­ à Ó4#[ý~?ñDêìû‘¨¼ïÉ·¾õ­ôÒK/Eîå•Wèšk®) EP6·Ývýó?ÿsäþ¯ýëô=ßó=´h}Âc¢rô«wÕìëUÖ¾[VfÏÅ.½g]×¥½½½Àç¶^¯“¦i‰X\×%˲È4ÍØ@™Ñh”ø|†¿?Êúž9¼ØGGG¿%I:ÑþÂÛ#`6ÍwÝ€]aF †ŸWWÞpÒ€ tìŽã%mÛ&AVÞ_8cÇq+ï Ê϶í@98"¢Ñ.v«GfIDAThTPk.C€Çš8ލý7N l ÀfE1pÕ]¯×;ÑUw¿ëõúÊû€Í&ŠbàÂʃƒ‡+ï/<ž8I°”Ÿëº5þM€-PUU‰aÿo˲¨Ñh¤®uíº.5›ÍH–¼“Ôà€Í¦iZàoÓ4©Ùl¦Îìçº.5 2MsáþІ( ˲‘(xÓ4©Z­R³ÙŒÔÔ³m›¨Z­’aët:$Šbæm€ÍÀó<õûýÀ}†aÐÞÞµÛm²m{áö^Úõ½½½HpG¿ß'žç3o3ÀI D JF$I]¼x‘ˆ._Ag†´!±,ØnQzÄn·‹ì;@QbY–E Œ't]÷3üÅ~ÏO0 Cº®“¢(ù5`Eð€Â‰¢HŽãªªÚžeWÞyjµ麎ZÙ;D’$²m›4M‹O, Ÿ%Ë2iš†Ì°±P¢6˲dM&êv»T©TmÇqµZ-ÇdY‚;vÏó+'*• u»]šL&d‚;`£!ƒ@ œ:uªè&¬ Ï󤪪_bŶmr]×ÿ/Ñ)–ãR-ïºét{?~K ©+®ˆ¿& ¿%Páñ„—½Ãû/˲~P8ÆP6ð(3gÎÄÞ||¼æ–¬&_Óùö·¿{ÿ›ßüæ5·ÊŠeÙØû_~ùeºùæ›×Ü€“Apxr/½ôRìý×]wÝš[ó D @ ¼ímo‹½ÿùçŸ_sK`“½ð ±÷ßxãkn ”Æ»é?þã?bï¿þúë×ܘ%0o ýôÓO¯¹%°ÉΟ?{ÿÛßþö5·Ê ã€Ý„ñÀæC€@ Ì»‚î¯þê¯ÖÜØdþç{?®¸€4æ?¾üå/¯¹%°NOl>x”@µZ½ÿÕW_¥'žxbÍ­€M5oBö=ïyÏš[e6ïwãÉ'Ÿ¤ÿþïÿ^sk`]¾ô¥/ÅÞñÀæøÎuв,:uêTà¾J¥B,Ëf²×u#iÄjµZ&ûÞ$ŽãÐ… ü¿†!A läéºë®£|àôñ‘ûô§?Mï{ßû hl’¿þë¿&Û¶cÿí'ò'×Ü(³÷¿ÿýô–·¼…^yå•Àýÿ÷ÿG¿÷{¿Gív» –@^yäzñÅcÿíÞ{ï]sk`ÓØ¶M/^ ÜÇqñ<ŸÙ1ÂqYÆlŠ,brðp]—É0 ²,kîãxž'I’H–åÔ ®ëÒ`0 Ã0æNh*ŠB²,“(Š©ö=ã8þ1ÇñïçyžDQ$QI–åLŽåñž§®ëcÎ[QjµZ[÷f¢øÃ±ò'B?þ8Ýu×]´ 6Ń>{ÿ÷ÿ÷Ó;ßùÎ5·ÊìÊ+¯¤z½N?üpäß:}ô£¥·¾õ­´ ò2/xoŸ®½öÚ5·6ištxxH¦i’ëºs§( I’Dõz=õ1 ÃðGRU5ÓuwÃ0¨×ëâ X– ¬ñg½Ö¾ìy¦‰e85N_#¢ïÊ´…ÿŸeYÔl6cƒQ…:N¢ˆÃ0¨Ýn/|SÍE‘úýþ‰¢‰’“çyÒ4dY&MÓèààÀÿ·Z­¶0à%Ì4Mj·Û‰Î%˲Ôï÷I’¤Äû€Í÷ꫯÒM7ÝD/¿üräßÎ;G_ùÊWèܹs´ Šös?÷sôû¿ÿû±ÿöÙÏ~vnðÀ<ÿ÷Oï~÷»cÿíG~äGè/ÿò/éÊ+¯\s« þð‡é‘G‰ý·ÃÃCú‰Ÿø‰5·Šä85›ÍTkÙD—ƒ1ºÝn¢ ˲¨ÝnÏMÞÆó<õûý%s°m›šÍæÒc²,ëÇ+ضMûûûŸN§‰™ö\ªªJÝnwácr ðP…ƒÁÊÛ×ëõ¹,'=˲4Wz¨ªJ½^/Õ6¢(Çq¶¦ ð0 ƒšÍfªcõû}R%õv°¹>ýéOÓÇ?þñØ»å–[èñǧ·½ímkn)L>ë¶Ûn£ú§Zs‹`[üÔOýýñÿqì¿5 zôÑG×Ü"ÈÚÇ>ö1úÌg>ûoï}ï{éÉ'Ÿ\s‹ Hi“+ÄY±êÚ7Ñåy°N§“z;˲"ËðJ×\sÍš[YøéŸþiúüç??÷ßÿáþn¿ýö5¶Š4o-Ü['OðÖøŽŽüû–­Çƒa¿Ì ÏóIJ,Ù¶M–e‘a‘õïea‹-8Žó×ø½ãš¦ˆ[Kà1V+6¦ ÷ÐívIUÕ¹ xmš¡áp8%¢À­R©L'“ÉÒmG£Ñ´V«M‰h:ç>®ÕjEŽÑívî{2™øûön,ËNÇãq¢ç5™L"Ç$¢i­V[øÜ:ÎÜí–F‘ídYžÏÝF–åÀãEQLôü <¾ò•¯Äþ¶ÌÞ~þç¾èf@޾öµ¯Mï¹çž…¿Š¢ÝLØŸùÌgþÞ¼ë]ïš>ñÄE7RxöÙg§wÝu×Âï÷O~ò“E7Öh2™LY– ü0 ³pÍ~v[oZ–å¹[eíûøø866 ßï'~n•J%²ý²ç6§ ÃÄþF.s||<åy>/±(.¡ßïGŽ7ï¼dà÷Â' dë÷ûsƒ&â^ø4/`½^l+B¢íÂÁ!ËÞ áç³J€Çq+/ü&F‰¶€òøâ¿¸4Èãºë®›6›Íéc=Vts ¯¾úêôÑG~èCZú°Ê8 `ž¸ ÕðíŽ;î˜~îsŸ›~ûÛß.º¹ã?ÿó?§ôG4ýà?¸ô;½ÑhÝ\X³ðZ8Ã0‰8ÌÇsƒ&Ž#qI×¾§Óèz;˲‰Ú—Œ¡R©, *™}>qAË„ÇOÇ%:^8‘F§Ó‰}\¦%ZÂ¥Y†!ÇqˆeÙ,vODD¢(Ò¼,+åæº. ‚H岬T‹mÛT­V÷Õëu2Msåv§MOÃqÙ¶è\†ŸcÚ¶@9üê¯þ*ýò/ÿr¢Ç^}õÕÔjµèMozSέ€,]ºt‰¾õ­oÑ·¾õ-úÛ¿ý[ºtéÒÒmÞñŽwÐSO=EgΜYC `WÜsÏ=ô§ú§‰{çwÒ7ÞHoûÛ‰a˜œ[ó¼öÚkôÍo~“þýßÿüñDÛÜ~ûíôÄOÐUW]•së`SÄ•MF‘’,'¡iø/[+#IR ”‰,ËdÆÂmX–¥‹/ú§_ˆ;7Ó%ZÇ¡½½½À}iÎål¼˲t||}Ð4£ ÇÇÇ'ʬ‘D8{Ã0‰¢]ÂÂ><Ï/||¸ì ¥ŽX G=-»¢.œ½#í¹œFbY6Õ¶P¿þ뿾ôª Üpà 7ÜvçV­V§ßüæ7‹þy€-téÒ¥éG>ò‘Âëpà 7ÜpËïV«Õ¦/¿ürÑ?9°fáuìz½žéþã²w¬Rb2™D~»­ÙÇUÙH»æW]d‘p\Aš,%Óéå¬!³ÛÇ•u¹‚2ŽŽafaVŒUèºø[Q”•²ƒ(ЏzÀqœ…Báì²,Ïó©›”mÛ #Ç¥>—’$ùÿïº.Ù¶Yû`s|ò“Ÿ¤Gy„NŸ>]tS `ùÈGèoþæoèܹsE7¶ÐéÓ§é _ø=ôÐCtêÔ©¢›ûØÇ>F–e! Àޱm;P…‚ˆ2_ã7M“\×õÿ®T*+eáyždYÜŽ˜^ÿ_eÍ=­ð1UUMµ½ Äqœÿw\•ŽÌ< 0ØÄc„ß4óJ˜Ø¶HÛrÒã&‘Åó!ÄÛéCú=ýôÓô¾÷½¯è¦@®¿þzúÃ?üCú¾€€?Èݧ>õ)zòÉ'éû¾ïûŠn dàÆo¤?û³?£ßýÝß-º)P€ðº4Ã0™¯…‡×á³\ã§Ì ?·,KÎĉKâ Bêý̶3n?·U»lÿá@‹“¼áöÍËpwÞ/~ø\öz=:uêTêÛìùB€íöÎw¾“üqúƒ?øºöÚk‹n¬ÉÇ?þqúÚ×¾F÷ßÑM€rçwÒÓO?M¿ýÛ¿Mo~ó›‹n¬èSŸú}õ«_¥û±+º)P¼×øãŽq’µöð¶¶m²ƒx\× [­?‰Ã… VZã þ>r ð_äñâg)üâŸ?>öqq'm•²0iĽ ’h6›ôoÿöoôÅ/~‘~æg~&Í ¶Ã»ßýnú¥_ú%zöÙg©×ëaa ñßñô ¿ð ô/ÿò/ô[¿õ[ôþ÷¿¿è&@ï}ï{é×~í×è¹çž£‡zYv\x]:Dá8‚“ày>r_\¢ƒ¸û¶eÿ;³ØI8%ácÔjµL÷Ÿô„g}Ü8ð€“¸êª«èÞ{ï¥{ï½—ˆˆž{î9úêW¿JÿøÿHÿó?ÿSpë +¯¼’Μ9CgΜ¡k¯½–n¿ýv:{ölÑÍð;wŽ>ñ‰OÐ'>ñ zõÕWé©§ž¢—^z‰Žéøø˜.]ºTtvÖéÓ§‰eY:sæ ={–~ð@@ÞU â’)Äi¬CQÇ=‰¸$™x!œRe›Çãψ›ëæ›o¦›o¾™~üǼè¦À»úê«i¿èfÀ†ˆ ðp§`‹u³Óé¦i™ï7“-ë>§L‰{3¤±êöë, ?Wdô€,å½Î¿II ÖQ•d2 ðˆ«WsÒŒ°¸ÿ$áöq·ÒvyÈ:˜`‘¬K¶dG¤wŒ¸ûò>f^åo2 ð "ªT*¿³np\Ê”“DÙ„·=$Šbä¾¼.ÂÇÜ–h"Ø áuéóçÏg~ŒpÁIÖ¾Ã1 ÃÄ®óÇÝ—WÀ…G’¤ÀßGGG¹'³pƒ³Ú5]ð¿ø¦i®´/×u#'4Ü~OÜ‹ŸwÀEøƒtxxˆ2-™ðº´ã8™B„q’À‡p|@\²O­V ü÷?Ïóª!®ëærÌÜ<ÇY9#é1ƒÁJº®Gî›÷â³, ,éõz©™† ‘?ës »KÅÀº4QüZúI(ŠøÛq2 #õ~lÛNœÄ(šÈáðð0÷Jáöd~ŒÌ<AˆDÁ´Ûí•3OÄm§ª*1 ¸¯Ùl¦Ú¯ã8‘ Y–cKÀxÂo:Û¶SEÛ¸®K.\HÕNMÓg}.`·…×¥ƒA¦Y<ââR¯a«ªø›ã¸È:þ¢ÇEŸë2i“0„iYVæ‰2 ð ŠžÇq¨Ýn§Þa±/˲‘“bšfâ×u©ÑhÞ, Ã,}!E‰–„÷³ˆ¦i©£E dq]—ö÷÷S¿ÑmÛ¦ýýýTÛÀö“$)6ÉÂ*ëÒÕj5v]<.Ž M"EQ"Ù;–eáy>X2 \˜¦™º²ÏóÔjµ÷5›ÍÔ3®ëR³ÙŒM:‘i€‡(ŠÔét÷†‘8²,Úßß§f³I‡‡‡±Ñ4-R2¥Ùl.Moâ8íïïGNž®ë ³wÅ–¸®KÕjué‹¡(ÊÊ%] Ã|˜¼`$Á"®ëÒÁÁA¢6ÀîaY6ôà­K'Ygö‚5¼u鸵ì¸8Ó4—®}{ƒÁ p¿,Ë Ë³xâ‚@ÆÒ†a¤®$â Ç3x‰’V1 ƒöööÈ0ŒØ‹SÓéô5"ú®•Z7‡(Š‘–eIQ’$‰8Ž#–eéüùóäº.Y–E–eEÞ Óé4vÿ®ëÏótñâÅÀý<Ï“ªª$U*r]—Ο??7ËG«ÕJUCH:þ|ä~EQ¨Õjùu|\×¥ÃÃÃ…™;jµZ¢qÞ›GUU’e9P;Èq:::"˲"Ïw<Gê Ì[—ž]ã,Ë¢S§Nùküá5ïáp87øBQ”H°Æ¼8o?äP©TȲ,bY6ÑóRU56!ƒ(Фª*Õj5_¦iÒáááÂy1 ³lÛ&Q#ñ ’$‘¢(T¯×ýûfcLÓ Ät:Hö“\<ˆâ_œ48Ž#Û¶ç¾0®ë’(бIÄŒeÇ!A"/Ä2²,“mÛ¶& ð :Y„ÑåsiYÖÒL%°›Nº.Í0 †±0»ÆIâjµ™¦™8¸Ã— b™J¥BŠ¢P»ÝÜŸ$Àƒèr‡$ItáÂ…TÇ,“i‰–Y†aP§Ó‰ÔëI¢Óé, î ºÉcYɲœjßÇÑp8LÜAt9CˆeY‘1ó0 CÝn— ÃHý&›¥( F£ÄÇÕjµÈ¶mwÀ\Þº4Çq©·­×ë~PÃ"†aP·ÛMGÀ0 u:T™;f™¦Èš±L½^'˲NT!C²m;Õq=µZ&“Iì¹Ì-Àƒèr}Û¶©Õj-}pGÝn—ŽIÓ´D/ ˲dÇc’eyá› R©P·ÛMô¦ZÄK;³(xÅ{ƒ9ŽCªª®|¬Y¢(’mÛÔï÷—zpGN‡&“ éº~¢àØ ¢(’ã8Ôív—®K3 C­V‹&“ ™¦™8逪ªä8u:…qÇù VIààaY–LÓ¤~¿¿ðx²,ûÏ%‹5v︣Ñhi Ã0$Ë2Çã…Õ9r+ÑǶmr‡lÛöïE‘AÈ,Á²,rǯM#Š"ñ<ŸK ×uɶm²m›\×%žçI„Eò$å=GïØDÙŸKØ]Þº´eYþ}ÞšxVkðá8oßy­»{kü³1¢(ær¬Y^|Ál`. This is to safeguard against things like mem::swap-ing the contents of two mutable references, given that Rust doesn't have information about the size of the underlying object and couldn't invoke an appropriate C++ move constructor anyway. **Thread safety:** Be aware that CXX does not assume anything about the thread safety of your extern C++ types. In other words the `MyType` etc bindings which CXX produces for you in Rust *do not* come with `Send` and `Sync` impls. If you are sure that your C++ type satisfies the requirements of `Send` and/or `Sync` and need to leverage that fact from Rust, you must provide your own unsafe marker trait impls. ```rust,noplayground # #[cxx::bridge] # mod ffi { # extern "C++" { # include!("path/to/header.h"); # # type MyType; # } # } # /// The C++ implementation of MyType is thread safe. unsafe impl Send for ffi::MyType {} unsafe impl Sync for ffi::MyType {} ``` Take care in doing this because thread safety in C++ can be extremely tricky to assess if you are coming from a Rust background. For example the `BlobstoreClient` type in the tutorial is *not thread safe* despite doing only completely innocuous things in its implementation. Concurrent calls to the `tag` member function trigger a data race on the `blobs` map. ## Functions and member functions This largely follows the same principles as ***[extern "Rust"](extern-rust.md)*** functions and methods. In particular, any signature with a `self` parameter is interpreted as a C++ non-static member function and exposed to Rust as a method. The programmer **does not** need to promise that the signatures they have typed in are accurate; that would be unreasonable. CXX performs static assertions that the signatures exactly correspond with what is declared in C++. Rather, the programmer is only on the hook for things that C++'s static information is not precise enough to capture, i.e. things that would only be represented at most by comments in the C++ code unintelligible to a static assertion: namely whether the C++ function is safe or unsafe to be called from Rust. **Safety:** the extern "C++" block is responsible for deciding whether to expose each signature inside as safe-to-call or unsafe-to-call. If an extern block contains at least one safe-to-call signature, it must be written as an `unsafe extern` block, which serves as an item level unsafe block to indicate that an unchecked safety claim is being made about the contents of the block. ```rust,noplayground #[cxx::bridge] mod ffi { unsafe extern "C++" { # include!("path/to/header.h"); # fn f(); // safe to call } extern "C++" { unsafe fn g(); // unsafe to call } } ``` ## Lifetimes C++ types holding borrowed data may be described naturally in Rust by an extern type with a generic lifetime parameter. For example in the case of the following pair of types: ```cpp // header.h class Resource; class TypeContainingBorrow { TypeContainingBorrow(const Resource &res) : res(res) {} const Resource &res; }; std::shared_ptr create(const Resource &res); ``` we'd want to expose this to Rust as: ```rust,noplayground #[cxx::bridge] mod ffi { unsafe extern "C++" { # include!("path/to/header.h"); # type Resource; type TypeContainingBorrow<'a>; fn create<'a>(res: &'a Resource) -> SharedPtr>; // or with lifetime elision: fn create(res: &Resource) -> SharedPtr; } } ``` ## Reusing existing binding types Extern C++ types support a syntax for declaring that a Rust binding of the correct C++ type already exists outside of the current bridge module. This avoids generating a fresh new binding which Rust's type system would consider non-interchangeable with the first. ```rust,noplayground #[cxx::bridge(namespace = "path::to")] mod ffi { extern "C++" { type MyType = crate::existing::MyType; } extern "Rust" { fn f(x: &MyType) -> usize; } } ``` In this case rather than producing a unique new Rust type `ffi::MyType` for the Rust binding of C++'s `::path::to::MyType`, CXX will reuse the already existing binding at `crate::existing::MyType` in expressing the signature of `f` and any other uses of `MyType` within the bridge module. CXX safely validates that `crate::existing::MyType` is in fact a binding for the right C++ type `::path::to::MyType` by generating a static assertion based on `crate::existing::MyType`'s implementation of [`ExternType`], which is a trait automatically implemented by CXX for bindings that it generates but can also be manually implemented as described below. [`ExternType`]: https://docs.rs/cxx/*/cxx/trait.ExternType.html `ExternType` serves the following two related use cases. #### Safely unifying occurrences of an extern type across bridges In the following snippet, two #\[cxx::bridge\] invocations in different files (possibly different crates) both contain function signatures involving the same C++ type `example::Demo`. If both were written just containing `type Demo;`, then both macro expansions would produce their own separate Rust type called `Demo` and thus the compiler wouldn't allow us to take the `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo` argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two `Demo`s has been defined as an extern type alias of the other, making them the same type in Rust. ```rust,noplayground // file1.rs #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { type Demo; fn create_demo() -> UniquePtr; } } ``` ```rust,noplayground // file2.rs #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { type Demo = crate::file1::ffi::Demo; fn take_ref_demo(demo: &Demo); } } ``` #### Integrating with bindgen-generated or handwritten unsafe bindings Handwritten `ExternType` impls make it possible to plug in a data structure emitted by bindgen as the definition of a C++ type emitted by CXX. By writing the unsafe `ExternType` impl, the programmer asserts that the C++ namespace and type name given in the type id refers to a C++ type that is equivalent to Rust type that is the `Self` type of the impl. ```rust,noplayground mod folly_sys; // the bindgen-generated bindings use cxx::{type_id, ExternType}; unsafe impl ExternType for folly_sys::StringPiece { type Id = type_id!("folly::StringPiece"); type Kind = cxx::kind::Opaque; } #[cxx::bridge(namespace = "folly")] pub mod ffi { unsafe extern "C++" { include!("rust_cxx_bindings.h"); type StringPiece = crate::folly_sys::StringPiece; fn print_string_piece(s: &StringPiece); } } // Now if we construct a StringPiece or obtain one through one // of the bindgen-generated signatures, we are able to pass it // along to ffi::print_string_piece. ``` The `ExternType::Id` associated type encodes a type-level representation of the type's C++ namespace and type name. It will always be defined using the `type_id!` macro exposed in the cxx crate. The `ExternType::Kind` associated type will always be either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`] identifying whether a C++ type is soundly relocatable by Rust's move semantics. A C++ type is only okay to hold and pass around by value in Rust if its [move constructor is trivial] and it has no destructor. In CXX, these are called Trivial extern C++ types, while types with nontrivial move behavior or a destructor must be considered Opaque and handled by Rust only behind an indirection, such as a reference or UniquePtr. [`cxx::kind::Opaque`]: https://docs.rs/cxx/*/cxx/kind/enum.Opaque.html [`cxx::kind::Trivial`]: https://docs.rs/cxx/*/cxx/kind/enum.Trivial.html [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible If you believe your C++ type reflected by the ExternType impl is indeed fine to hold by value and move in Rust, you can specify: ```rust,noplayground # unsafe impl cxx::ExternType for TypeName { # type Id = cxx::type_id!("name::space::of::TypeName"); type Kind = cxx::kind::Trivial; # } ``` which will enable you to pass it into C++ functions by value, return it by value, and include it in `struct`s that you have declared to `cxx::bridge`. Your claim about the triviality of the C++ type will be checked by a `static_assert` in the generated C++ side of the binding. ## Explicit shim trait impls This is a somewhat niche feature, but important when you need it. CXX's support for C++'s std::unique\_ptr and std::vector is built on a set of internal trait impls connecting the Rust API of UniquePtr and CxxVector to underlying template instantiations performed by the C++ compiler. When reusing a binding type across multiple bridge modules as described in the previous section, you may find that your code needs some trait impls which CXX hasn't decided to generate. ```rust,noplayground #[cxx::bridge] mod ffi1 { extern "C++" { include!("path/to/header.h"); type A; type B; // Okay: CXX sees UniquePtr using a type B defined within the same // bridge, and automatically emits the right template instantiations // corresponding to std::unique_ptr. fn get_b() -> UniquePtr; } } #[cxx::bridge] mod ffi2 { extern "C++" { type A = crate::ffi1::A; // Rust trait error: CXX processing this module has no visibility into // whether template instantiations corresponding to std::unique_ptr // have already been emitted by the upstream library, so it does not // emit them here. If the upstream library does not have any signatures // involving UniquePtr, an explicit instantiation of the template // needs to be requested in one module or the other. fn get_a() -> UniquePtr; } } ``` You can request a specific template instantiation at a particular location in the Rust crate hierarchy by writing `impl UniquePtr {}` inside of the bridge module which defines `A` but does not otherwise contain any use of `UniquePtr`. ```rust,noplayground #[cxx::bridge] mod ffi1 { extern "C++" { include!("path/to/header.h"); type A; type B; fn get_b() -> UniquePtr; } impl UniquePtr {} // explicit instantiation } ``` cxx-1.0.141/book/src/extern-rust.md000064400000000000000000000107231046102023000151400ustar 00000000000000{{#title extern "Rust" — Rust ♡ C++}} # extern "Rust" ```rust,noplayground #[cxx::bridge] mod ffi { extern "Rust" { } } ``` The `extern "Rust"` section of a CXX bridge declares Rust types and signatures to be made available to C++. The CXX code generator uses your extern "Rust" section(s) to produce a C++ header file containing the corresponding C++ declarations. The generated header has the same path as the Rust source file containing the bridge, except with a `.rs.h` file extension. A bridge module may contain zero or more extern "Rust" blocks. ## Opaque Rust types Types defined in Rust that are made available to C++, but only behind an indirection. ```rust,noplayground # #[cxx::bridge] # mod ffi { extern "Rust" { type MyType; type MyOtherType; type OneMoreType<'a>; } # } ``` For example in the ***[Tutorial](tutorial.md)*** we saw `MultiBuf` used in this way. Rust code created the `MultiBuf`, passed a `&mut MultiBuf` to C++, and C++ later passed a `&mut MultiBuf` back across the bridge to Rust. Another example is the one on the ***[Box\](binding/box.md)*** page, which exposes the Rust standard library's `std::fs::File` to C++ as an opaque type in a similar way but with Box as the indirection rather than &mut. The types named as opaque types (`MyType` etc) refer to types in the `super` module, the parent module of the CXX bridge. You can think of an opaque type `T` as being like a re-export `use super::T` made available to C++ via the generated header. Opaque types are currently required to be [`Sized`] and [`Unpin`]. In particular, a trait object `dyn MyTrait` or slice `[T]` may not be used for an opaque Rust type. These restrictions may be lifted in the future. [`Sized`]: https://doc.rust-lang.org/std/marker/trait.Sized.html [`Unpin`]: https://doc.rust-lang.org/std/marker/trait.Unpin.html For now, types used as extern Rust types are required to be defined by the same crate that contains the bridge using them. This restriction may be lifted in the future. The bridge's parent module will contain the appropriate imports or definitions for these types. ```rust,noplayground use path::to::MyType; pub struct MyOtherType { ... } # # #[cxx::bridge] # mod ffi { # extern "Rust" { # type MyType; # type MyOtherType; # } # } ``` ## Functions Rust functions made callable to C++. Just like for opaque types, these functions refer implicitly to something in scope in the `super` module, whether defined there or imported by some `use` statement. ```rust,noplayground #[cxx::bridge] mod ffi { extern "Rust" { type MyType; fn f() -> Box; } } struct MyType(i32); fn f() -> Box { return Box::new(MyType(1)); } ``` Extern Rust function signature may consist of types defined in the bridge, primitives, and [any of these additional bindings](bindings.md). ## Methods Any signature with a `self` parameter is interpreted as a Rust method and exposed to C++ as a non-static member function. ```rust,noplayground # #[cxx::bridge] # mod ffi { extern "Rust" { type MyType; fn f(&self) -> usize; } # } ``` The `self` parameter may be a shared reference `&self`, an exclusive reference `&mut self`, or a pinned reference `self: Pin<&mut Self>`. A by-value `self` is not currently supported. If the surrounding `extern "Rust"` block contains exactly one extern type, that type is implicitly the receiver for a `&self` or `&mut self` method. If the surrounding block contains *more than one* extern type, a receiver type must be provided explicitly for the self parameter, or you can consider splitting into multiple extern blocks. ```rust,noplayground # #[cxx::bridge] # mod ffi { extern "Rust" { type First; type Second; fn bar(self: &First); fn foo(self: &mut Second); } # } ``` ## Functions with explicit lifetimes An extern Rust function signature is allowed to contain explicit lifetimes but in this case the function must be declared unsafe-to-call. This is pretty meaningless given we're talking about calls from C++, but at least it draws some extra attention from the caller that they may be responsible for upholding some atypical lifetime relationship. ```rust,noplayground #[cxx::bridge] mod ffi { extern "Rust" { type MyType; unsafe fn f<'a>(&'a self, s: &str) -> &'a str; } } ``` Bounds on a lifetime (like `<'a, 'b: 'a>`) are not currently supported. Nor are type parameters or where-clauses. cxx-1.0.141/book/src/index.md000064400000000000000000000077531046102023000137600ustar 00000000000000 # CXX — safe interop between Rust and C++ This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++. It carves out a regime of commonality where Rust and C++ are semantically very similar and guides the programmer to express their language boundary effectively within this regime. CXX fills in the low level stuff so that you get a safe binding, preventing the pitfalls of doing a foreign function interface over unsafe C-style signatures.
    From a high level description of the language boundary, CXX uses static analysis of the types and function signatures to protect both Rust's and C++'s invariants. Then it uses a pair of code generators to implement the boundary efficiently on both sides together with any necessary static assertions for later in the build process to verify correctness. The resulting FFI bridge operates at zero or negligible overhead, i.e. no copying, no serialization, no memory allocation, no runtime checks needed. The FFI signatures are able to use native data structures from whichever side they please. In addition, CXX provides builtin bindings for key standard library types like strings, vectors, Box, unique\_ptr, etc to expose an idiomatic API on those types to the other language. ## Example In this example we are writing a Rust application that calls a C++ client of a large-file blobstore service. The blobstore supports a `put` operation for a discontiguous buffer upload. For example we might be uploading snapshots of a circular buffer which would tend to consist of 2 pieces, or fragments of a file spread across memory for some other reason (like a rope data structure). ```rust,noplayground #[cxx::bridge] mod ffi { extern "Rust" { type MultiBuf; fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } unsafe extern "C++" { include!("example/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result; } } ``` Now we simply provide Rust definitions of all the things in the `extern "Rust"` block and C++ definitions of all the things in the `extern "C++"` block, and get to call back and forth safely. The [***Tutorial***](tutorial.md) chapter walks through a fleshed out version of this blobstore example in full detail, including all of the Rust code and all of the C++ code. The code is also provided in runnable form in the *demo* directory of . To try it out, run `cargo run` from that directory. - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs) - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h) - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc) The key takeaway, which is enabled by the CXX library, is that the Rust code in main.rs is 100% ordinary safe Rust code working idiomatically with Rust types while the C++ code in blobstore.cc is 100% ordinary C++ code working idiomatically with C++ types. The Rust code feels like Rust and the C++ code feels like C++, not like C-style "FFI glue".
    ***Chapter outline:** See the hamburger menu in the top left if you are on a small screen and it didn't open with a sidebar by default.* cxx-1.0.141/book/src/overview.svg000064400000000000000000001230271046102023000147070ustar 00000000000000 cxx-1.0.141/book/src/reference.md000064400000000000000000000026321046102023000145760ustar 00000000000000{{#title The bridge module — Rust ♡ C++}} # The bridge module reference The ***[Core concepts](concepts.md)*** in chapter 2 covered the high level model that CXX uses to represent a language boundary. This chapter builds on that one to document an exhaustive reference on the syntax and functionality of \#\[cxx::bridge\]. - ***[extern "Rust"](extern-rust.md)*** — exposing opaque Rust types, Rust functions, Rust methods to C++; functions with lifetimes. - ***[extern "C++"](extern-c++.md)*** — binding opaque C++ types, C++ functions, C++ member functions; sharing an opaque type definition across multiple bridge modules or different crates; using bindgen-generated data structures across a CXX bridge; Rust orphan-rule-compatible way to request that particular glue code be emitted in a specific bridge module. - ***[Shared types](shared.md)*** — shared structs; shared enums; using Rust as source of truth vs C++ as source of truth. - ***[Attributes](attributes.md)*** — working with namespaces; giving functions a different name in their non-native language. - ***[Async functions](async.md)*** — integrating async C++ with async Rust. - ***[Error handling](binding/result.md)*** — representing fallibility on the language boundary; accessing a Rust error message from C++; customizing the set of caught exceptions and their conversion to a Rust error message. cxx-1.0.141/book/src/shared.md000064400000000000000000000131731046102023000141100ustar 00000000000000{{#title Shared types — Rust ♡ C++}} # Shared types Shared types enable *both* languages to have visibility into the internals of a type. This is in contrast to opaque Rust types and opaque C++ types, for which only one side gets to manipulate the internals. Unlike opaque types, the FFI bridge is allowed to pass and return shared types by value. The order in which shared types are written is not important. C++ is order sensitive but CXX will topologically sort and forward-declare your types as necessary. ## Shared structs and enums For enums, only C-like a.k.a. unit variants are currently supported. ```rust,noplayground #[cxx::bridge] mod ffi { struct PlayingCard { suit: Suit, value: u8, // A=1, J=11, Q=12, K=13 } enum Suit { Clubs, Diamonds, Hearts, Spades, } unsafe extern "C++" { fn deck() -> Vec; fn sort(cards: &mut Vec); } } ``` ## The generated data structures Shared structs compile to an aggregate-initialization compatible C++ struct. Shared enums compile to a C++ `enum class` with a sufficiently sized integral base type decided by CXX. ```cpp // generated header struct PlayingCard final { Suit suit; uint8_t value; }; enum class Suit : uint8_t { Clubs = 0, Diamonds = 1, Hearts = 2, Spades = 3, }; ``` Because it is not UB in C++ for an `enum class` to hold a value different from all of the listed variants, we use a Rust representation for shared enums that is compatible with this. The API you'll get is something like: ```rust,noplayground #[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Suit { pub repr: u8, } #[allow(non_upper_case_globals)] impl Suit { pub const Clubs: Self = Suit { repr: 0 }; pub const Diamonds: Self = Suit { repr: 1 }; pub const Hearts: Self = Suit { repr: 2 }; pub const Spades: Self = Suit { repr: 3 }; } ``` Notice you're free to treat the enum as an integer in Rust code via the public `repr` field. Pattern matching with `match` still works but will require you to write wildcard arms to handle the situation of an enum value that is not one of the listed variants. ```rust,noplayground fn main() { let suit: Suit = /*...*/; match suit { Suit::Clubs => ..., Suit::Diamonds => ..., Suit::Hearts => ..., Suit::Spades => ..., _ => ..., // fallback arm } } ``` If a shared struct has generic lifetime parameters, the lifetimes are simply not represented on the C++ side. C++ code will need care when working with borrowed data (as usual in C++). ```rust,noplayground #[cxx::bridge] mod ffi { struct Borrowed<'a> { flags: &'a [&'a str], } } ``` ```cpp // generated header struct Borrowed final { rust::Slice flags; }; ``` ## Enum discriminants You may provide explicit discriminants for some or all of the enum variants, in which case those numbers will be propagated into the generated C++ `enum class`. ```rust,noplayground #[cxx::bridge] mod ffi { enum SmallPrime { Two = 2, Three = 3, Five = 5, Seven = 7, } } ``` Variants without an explicit discriminant are assigned the previous discriminant plus 1. If the first variant has not been given an explicit discriminant, it is assigned discriminant 0. By default CXX represents your enum using the smallest integer type capable of fitting all the discriminants (whether explicit or implicit). If you need a different representation for reasons, provide a `repr` attribute. ```rust,noplayground #[cxx::bridge] mod ffi { #[repr(i32)] enum Enum { Zero, One, Five = 5, Six, } } ``` ```cpp // generated header enum class Enum : int32_t { Zero = 0, One = 1, Five = 5, Six = 6, }; ``` ## Extern enums If you need to interoperate with an already existing enum for which an existing C++ definition is the source of truth, make sure that definition is provided by some header in the bridge and then declare your enum *additionally* as an extern C++ type. ```rust,noplayground #[cxx::bridge] mod ffi { enum Enum { Yes, No, } extern "C++" { include!("path/to/the/header.h"); type Enum; } } ``` CXX will recognize this pattern and, instead of generating a C++ definition of the enum, will instead generate C++ static assertions asserting that the variants and discriminant values and integer representation written in Rust all correctly match the existing C++ enum definition. Extern enums support all the same features as ordinary shared enums (explicit discriminants, repr). Again, CXX will static assert that all of those things you wrote are correct. ## Derives The following standard traits are supported in `derive(...)` within the CXX bridge module. - `Clone` - `Copy` - `Debug` - `Default` - `Eq` - `Hash` - `Ord` - `PartialEq` - `PartialOrd` Note that shared enums automatically always come with impls of `Copy`, `Clone`, `Eq`, and `PartialEq`, so you're free to omit those derives on an enum. ```rust,noplayground #[cxx::bridge] mod ffi { #[derive(Clone, Debug, Hash)] struct ExampleStruct { x: u32, s: String, } #[derive(Hash, Ord, PartialOrd)] enum ExampleEnum { Yes, No, } } ``` The derives naturally apply to *both* the Rust data type *and* the corresponding C++ data type: - `Hash` gives you a specialization of [`template <> struct std::hash`][hash] in C++ - `PartialEq` produces `operator==` and `operator!=` - `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=` [hash]: https://en.cppreference.com/w/cpp/utility/hash cxx-1.0.141/book/src/tutorial.md000064400000000000000000000502061046102023000145030ustar 00000000000000{{#title Tutorial — Rust ♡ C++}} # Tutorial: CXX blobstore client This example walks through a Rust application that calls into a C++ client of a blobstore service. In fact we'll see calls going in both directions: Rust to C++ as well as C++ to Rust. For your own use case it may be that you need just one of these directions. All of the code involved in the example is shown on this page, but it's also provided in runnable form in the *demo* directory of . To try it out directly, run `cargo run` from that directory. This tutorial assumes you've read briefly about **shared structs**, **opaque types**, and **functions** in the [*Core concepts*](concepts.md) page. ## Creating the project We'll use Cargo, which is the build system commonly used by open source Rust projects. (CXX works with other build systems too; refer to chapter 5.) Create a blank Cargo project: `mkdir cxx-demo`; `cd cxx-demo`; `cargo init`. Edit the Cargo.toml to add a dependency on the `cxx` crate: ```toml,hidelines=... # Cargo.toml ...[package] ...name = "cxx-demo" ...version = "0.1.0" ...edition = "2021" [dependencies] cxx = "1.0" ``` We'll revisit this Cargo.toml later when we get to compiling some C++ code. ## Defining the language boundary CXX relies on a description of the function signatures that will be exposed from each language to the other. You provide this description using `extern` blocks in a Rust module annotated with the `#[cxx::bridge]` attribute macro. We'll open with just the following at the top of src/main.rs and walk through each item in detail. ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { } # # fn main() {} ``` The contents of this module will be everything that needs to be agreed upon by both sides of the FFI boundary. ## Calling a C++ function from Rust Let's obtain an instance of the C++ blobstore client, a class `BlobstoreClient` defined in C++. We'll treat `BlobstoreClient` as an *opaque type* in CXX's classification so that Rust does not need to assume anything about its implementation, not even its size or alignment. In general, a C++ type might have a move-constructor which is incompatible with Rust's move semantics, or may hold internal references which cannot be modeled by Rust's borrowing system. Though there are alternatives, the easiest way to not care about any such thing on an FFI boundary is to require no knowledge about a type by treating it as opaque. Opaque types may only be manipulated behind an indirection such as a reference `&`, a Rust `Box`, or a `UniquePtr` (Rust binding of `std::unique_ptr`). We'll add a function through which C++ can return a `std::unique_ptr` to Rust. ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("cxx-demo/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; } } fn main() { let client = ffi::new_blobstore_client(); } ``` The nature of `unsafe` extern blocks is clarified in more detail in the [*extern "C++"*](extern-c++.md) chapter. In brief: the programmer is **not** promising that the signatures they have typed in are accurate; that would be unreasonable. CXX performs static assertions that the signatures exactly match what is declared in C++. Rather, the programmer is only on the hook for things that C++'s semantics are not precise enough to capture, i.e. things that would only be represented at most by comments in the C++ code. In this case, it's whether `new_blobstore_client` is safe or unsafe to call. If that function said something like "must be called at most once or we'll stomp yer memery", Rust would instead want to expose it as `unsafe fn new_blobstore_client`, this time inside a safe `extern "C++"` block because the programmer is no longer on the hook for any safety claim about the signature. If you build this file right now with `cargo build`, it won't build because we haven't written a C++ implementation of `new_blobstore_client` nor instructed Cargo about how to link it into the resulting binary. You'll see an error from the linker like this: ```console error: linking with `cc` failed: exit code: 1 | = /bin/ld: target/debug/deps/cxx-demo-7cb7fddf3d67d880.rcgu.o: in function `cxx_demo::ffi::new_blobstore_client': src/main.rs:1: undefined reference to `cxxbridge1$new_blobstore_client' collect2: error: ld returned 1 exit status ``` ## Adding in the C++ code In CXX's integration with Cargo, all #include paths begin with a crate name by default (when not explicitly selected otherwise by a crate; see `CFG.include_prefix` in chapter 5). That's why we see `include!("cxx-demo/include/blobstore.h")` above — we'll be putting the C++ header at relative path `include/blobstore.h` within the Rust crate. If your crate is named something other than `cxx-demo` according to the `name` field in Cargo.toml, you will need to use that name everywhere in place of `cxx-demo` throughout this tutorial. ```cpp // include/blobstore.h #pragma once #include class BlobstoreClient { public: BlobstoreClient(); }; std::unique_ptr new_blobstore_client(); ``` ```cpp // src/blobstore.cc #include "cxx-demo/include/blobstore.h" BlobstoreClient::BlobstoreClient() {} std::unique_ptr new_blobstore_client() { return std::unique_ptr(new BlobstoreClient()); } ``` Using `std::make_unique` would work too, as long as you pass `std("c++14")` to the C++ compiler as described later on. The placement in *include/* and *src/* is not significant; you can place C++ code anywhere else in the crate as long as you use the right paths throughout the tutorial. Be aware that *CXX does not look at any of these files.* You're free to put arbitrary C++ code in here, #include your own libraries, etc. All we do is emit static assertions against what you provide in the headers. ## Compiling the C++ code with Cargo Cargo has a [build scripts] feature suitable for compiling non-Rust code. We need to introduce a new build-time dependency on CXX's C++ code generator in Cargo.toml: ```toml,hidelines=... # Cargo.toml ...[package] ...name = "cxx-demo" ...version = "0.1.0" ...edition = "2021" [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` Then add a build.rs build script adjacent to Cargo.toml to run the cxx-build code generator and C++ compiler. The relevant arguments are the path to the Rust source file containing the cxx::bridge language boundary definition, and the paths to any additional C++ source files to be compiled during the Rust crate's build. ```rust,noplayground // build.rs fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") .compile("cxx-demo"); println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=src/blobstore.cc"); println!("cargo:rerun-if-changed=include/blobstore.h"); } ``` This build.rs would also be where you set up C++ compiler flags, for example if you'd like to have access to `std::make_unique` from C++14. See the page on ***[Cargo-based builds](build/cargo.md)*** for more details about CXX's Cargo integration. ```rust,noplayground # // build.rs # # fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") .std("c++14") .compile("cxx-demo"); # } ``` [build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html The project should now build and run successfully, though not do anything useful yet. ```console cxx-demo$ cargo run Compiling cxx-demo v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.34s Running `target/debug/cxx-demo` cxx-demo$ ``` ## Calling a Rust function from C++ Our C++ blobstore supports a `put` operation for a discontiguous buffer upload. For example we might be uploading snapshots of a circular buffer which would tend to consist of 2 pieces, or fragments of a file spread across memory for some other reason (like a rope data structure). We'll express this by handing off an iterator over contiguous borrowed chunks. This loosely resembles the API of the widely used `bytes` crate's `Buf` trait. During a `put`, we'll make C++ call back into Rust to obtain contiguous chunks of the upload (all with no copying or allocation on the language boundary). In reality the C++ client might contain some sophisticated batching of chunks and/or parallel uploading that all of this ties into. ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { extern "Rust" { type MultiBuf; fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } unsafe extern "C++" { include!("cxx-demo/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; fn put(&self, parts: &mut MultiBuf) -> u64; } } # # fn main() { # let client = ffi::new_blobstore_client(); # } ``` Any signature having a `self` parameter (the Rust name for C++'s `this`) is considered a method / non-static member function. If there is only one `type` in the surrounding extern block, it'll be a method of that type. If there is more than one `type`, you can disambiguate which one a method belongs to by writing `self: &BlobstoreClient` in the argument list. As usual, now we need to provide Rust definitions of everything declared by the `extern "Rust"` block and a C++ definition of the new signature declared by the `extern "C++"` block. ```rust,noplayground // src/main.rs # # #[cxx::bridge] # mod ffi { # extern "Rust" { # type MultiBuf; # # fn next_chunk(buf: &mut MultiBuf) -> &[u8]; # } # # unsafe extern "C++" { # include!("cxx-demo/include/blobstore.h"); # # type BlobstoreClient; # # fn new_blobstore_client() -> UniquePtr; # fn put(&self, parts: &mut MultiBuf) -> u64; # } # } // An iterator over contiguous chunks of a discontiguous file object. Toy // implementation uses a Vec> but in reality this might be iterating // over some more complex Rust data structure like a rope, or maybe loading // chunks lazily from somewhere. pub struct MultiBuf { chunks: Vec>, pos: usize, } pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { let next = buf.chunks.get(buf.pos); buf.pos += 1; next.map_or(&[], Vec::as_slice) } # # fn main() { # let client = ffi::new_blobstore_client(); # } ``` ```cpp,hidelines=... // include/blobstore.h ...#pragma once ...#include ... struct MultiBuf; class BlobstoreClient { public: BlobstoreClient(); uint64_t put(MultiBuf &buf) const; }; ... ...std::unique_ptr new_blobstore_client(); ``` In blobstore.cc we're able to call the Rust `next_chunk` function, exposed to C++ by a header `main.rs.h` generated by the CXX code generator. In CXX's Cargo integration this generated header has a path containing the crate name, the relative path of the Rust source file within the crate, and a `.rs.h` extension. ```cpp,hidelines=... // src/blobstore.cc #include "cxx-demo/include/blobstore.h" #include "cxx-demo/src/main.rs.h" #include #include ... ...BlobstoreClient::BlobstoreClient() {} ... ...std::unique_ptr new_blobstore_client() { ... return std::make_unique(); ...} // Upload a new blob and return a blobid that serves as a handle to the blob. uint64_t BlobstoreClient::put(MultiBuf &buf) const { // Traverse the caller's chunk iterator. std::string contents; while (true) { auto chunk = next_chunk(buf); if (chunk.size() == 0) { break; } contents.append(reinterpret_cast(chunk.data()), chunk.size()); } // Pretend we did something useful to persist the data. auto blobid = std::hash{}(contents); return blobid; } ``` This is now ready to use. :) ```rust,noplayground // src/main.rs # # #[cxx::bridge] # mod ffi { # extern "Rust" { # type MultiBuf; # # fn next_chunk(buf: &mut MultiBuf) -> &[u8]; # } # # unsafe extern "C++" { # include!("cxx-demo/include/blobstore.h"); # # type BlobstoreClient; # # fn new_blobstore_client() -> UniquePtr; # fn put(&self, parts: &mut MultiBuf) -> u64; # } # } # # pub struct MultiBuf { # chunks: Vec>, # pos: usize, # } # pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { # let next = buf.chunks.get(buf.pos); # buf.pos += 1; # next.map_or(&[], Vec::as_slice) # } fn main() { let client = ffi::new_blobstore_client(); // Upload a blob. let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); println!("blobid = {}", blobid); } ``` ```console cxx-demo$ cargo run Compiling cxx-demo v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.41s Running `target/debug/cxx-demo` blobid = 9851996977040795552 ``` ## Interlude: What gets generated? For the curious, it's easy to look behind the scenes at what CXX has done to make these function calls work. You shouldn't need to do this during normal usage of CXX, but for the purpose of this tutorial it can be educative. CXX comprises *two* code generators: a Rust one (which is the cxx::bridge attribute procedural macro) and a C++ one. ### Rust generated code It's easiest to view the output of the procedural macro by installing [cargo-expand]. Then run `cargo expand ::ffi` to macro-expand the `mod ffi` module. [cargo-expand]: https://github.com/dtolnay/cargo-expand ```console cxx-demo$ cargo install cargo-expand cxx-demo$ cargo expand ::ffi ``` You'll see some deeply unpleasant code involving `#[repr(C)]`, `#[link_name]`, and `#[export_name]`. ### C++ generated code For debugging convenience, `cxx_build` links all generated C++ code into Cargo's target directory under *target/cxxbridge/*. ```console cxx-demo$ exa -T target/cxxbridge/ target/cxxbridge ├── cxx-demo │ └── src │ ├── main.rs.cc -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/sources/cxx-demo/src/main.rs.cc │ └── main.rs.h -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/include/cxx-demo/src/main.rs.h └── rust └── cxx.h -> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cxx-1.0.0/include/cxx.h ``` In those files you'll see declarations or templates of any CXX Rust types present in your language boundary (like `rust::Slice` for `&[T]`) and `extern "C"` signatures corresponding to your extern functions. If it fits your workflow better, the CXX C++ code generator is also available as a standalone executable which outputs generated code to stdout. ```console cxx-demo$ cargo install cxxbridge-cmd cxx-demo$ cxxbridge src/main.rs ``` ## Shared data structures So far the calls in both directions above only used **opaque types**, not **shared structs**. Shared structs are data structures whose complete definition is visible to both languages, making it possible to pass them by value across the language boundary. Shared structs translate to a C++ aggregate-initialization compatible struct exactly matching the layout of the Rust one. As the last step of this demo, we'll use a shared struct `BlobMetadata` to pass metadata about blobs between our Rust application and C++ blobstore client. ```rust,noplayground // src/main.rs #[cxx::bridge] mod ffi { struct BlobMetadata { size: usize, tags: Vec, } extern "Rust" { // ... # type MultiBuf; # # fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } unsafe extern "C++" { // ... # include!("cxx-demo/include/blobstore.h"); # # type BlobstoreClient; # # fn new_blobstore_client() -> UniquePtr; # fn put(&self, parts: &mut MultiBuf) -> u64; fn tag(&self, blobid: u64, tag: &str); fn metadata(&self, blobid: u64) -> BlobMetadata; } } # # pub struct MultiBuf { # chunks: Vec>, # pos: usize, # } # pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { # let next = buf.chunks.get(buf.pos); # buf.pos += 1; # next.map_or(&[], Vec::as_slice) # } fn main() { let client = ffi::new_blobstore_client(); // Upload a blob. let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); println!("blobid = {}", blobid); // Add a tag. client.tag(blobid, "rust"); // Read back the tags. let metadata = client.metadata(blobid); println!("tags = {:?}", metadata.tags); } ``` ```cpp,hidelines=... // include/blobstore.h #pragma once #include "rust/cxx.h" ...#include struct MultiBuf; struct BlobMetadata; class BlobstoreClient { public: BlobstoreClient(); uint64_t put(MultiBuf &buf) const; void tag(uint64_t blobid, rust::Str tag) const; BlobMetadata metadata(uint64_t blobid) const; private: class impl; std::shared_ptr impl; }; ... ...std::unique_ptr new_blobstore_client(); ``` ```cpp,hidelines=... // src/blobstore.cc #include "cxx-demo/include/blobstore.h" #include "cxx-demo/src/main.rs.h" #include #include #include #include #include // Toy implementation of an in-memory blobstore. // // In reality the implementation of BlobstoreClient could be a large // complex C++ library. class BlobstoreClient::impl { friend BlobstoreClient; using Blob = struct { std::string data; std::set tags; }; std::unordered_map blobs; }; BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} ... ...// Upload a new blob and return a blobid that serves as a handle to the blob. ...uint64_t BlobstoreClient::put(MultiBuf &buf) const { ... // Traverse the caller's chunk iterator. ... std::string contents; ... while (true) { ... auto chunk = next_chunk(buf); ... if (chunk.size() == 0) { ... break; ... } ... contents.append(reinterpret_cast(chunk.data()), chunk.size()); ... } ... ... // Insert into map and provide caller the handle. ... auto blobid = std::hash{}(contents); ... impl->blobs[blobid] = {std::move(contents), {}}; ... return blobid; ...} // Add tag to an existing blob. void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { impl->blobs[blobid].tags.emplace(tag); } // Retrieve metadata about a blob. BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { BlobMetadata metadata{}; auto blob = impl->blobs.find(blobid); if (blob != impl->blobs.end()) { metadata.size = blob->second.data.size(); std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(), [&](auto &t) { metadata.tags.emplace_back(t); }); } return metadata; } ... ...std::unique_ptr new_blobstore_client() { ... return std::make_unique(); ...} ``` ```console cxx-demo$ cargo run Running `target/debug/cxx-demo` blobid = 9851996977040795552 tags = ["rust"] ``` *You've now seen all the code involved in the tutorial. It's available all together in runnable form in the* demo *directory of . You can run it directly without stepping through the steps above by running `cargo run` from that directory.*
    # Takeaways The key contribution of CXX is it gives you Rust–C++ interop in which *all* of the Rust side of the code you write *really* looks like you are just writing normal Rust, and the C++ side *really* looks like you are just writing normal C++. You've seen in this tutorial that none of the code involved feels like C or like the usual perilous "FFI glue" prone to leaks or memory safety flaws. An expressive system of opaque types, shared types, and key standard library type bindings enables API design on the language boundary that captures the proper ownership and borrowing contracts of the interface. CXX plays to the strengths of the Rust type system *and* C++ type system *and* the programmer's intuitions. An individual working on the C++ side without a Rust background, or the Rust side without a C++ background, will be able to apply all their usual intuitions and best practices about development in their language to maintain a correct FFI.

    cxx-1.0.141/book/theme/head.hbs000064400000000000000000000005301046102023000142230ustar 00000000000000 cxx-1.0.141/build.rs000064400000000000000000000044011046102023000122360ustar 00000000000000#![allow(unknown_lints)] #![allow(unexpected_cfgs)] use std::env; use std::path::{Path, PathBuf}; use std::process::Command; fn main() { let manifest_dir_opt = env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from); let manifest_dir = manifest_dir_opt.as_deref().unwrap_or(Path::new("")); cc::Build::new() .file(manifest_dir.join("src/cxx.cc")) .cpp(true) .cpp_link_stdlib(None) // linked via link-cplusplus crate .std(cxxbridge_flags::STD) .warnings_into_errors(cfg!(deny_warnings)) .compile("cxxbridge1"); println!("cargo:rerun-if-changed=src/cxx.cc"); println!("cargo:rerun-if-changed=include/cxx.h"); println!("cargo:rustc-cfg=built_with_cargo"); if let Some(manifest_dir) = &manifest_dir_opt { let cxx_h = manifest_dir.join("include").join("cxx.h"); println!("cargo:HEADER={}", cxx_h.to_string_lossy()); } if let Some(rustc) = rustc_version() { if rustc.minor >= 80 { println!("cargo:rustc-check-cfg=cfg(built_with_cargo)"); println!("cargo:rustc-check-cfg=cfg(compile_error_if_alloc)"); println!("cargo:rustc-check-cfg=cfg(compile_error_if_std)"); println!("cargo:rustc-check-cfg=cfg(cxx_experimental_no_alloc)"); println!("cargo:rustc-check-cfg=cfg(error_in_core)"); println!("cargo:rustc-check-cfg=cfg(skip_ui_tests)"); } if rustc.minor < 73 { println!("cargo:warning=The cxx crate requires a rustc version 1.73.0 or newer."); println!( "cargo:warning=You appear to be building with: {}", rustc.version, ); } if rustc.minor >= 81 { // core::error::Error println!("cargo:rustc-cfg=error_in_core"); } } } struct RustVersion { version: String, minor: u32, } fn rustc_version() -> Option { let rustc = env::var_os("RUSTC")?; let output = Command::new(rustc).arg("--version").output().ok()?; let version = String::from_utf8(output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } let minor = pieces.next()?.parse().ok()?; Some(RustVersion { version, minor }) } cxx-1.0.141/compile_flags.txt000064400000000000000000000000131046102023000141310ustar 00000000000000-std=c++11 cxx-1.0.141/include/cxx.h000064400000000000000000000711041046102023000131730ustar 00000000000000#pragma once #include #include #include #include #include #include #include #include #include #include #if __cplusplus >= 202002L #include #endif #include #include #include #include #include #if defined(_WIN32) #include #else #include #endif namespace rust { inline namespace cxxbridge1 { struct unsafe_bitcopy_t; namespace { template class impl; } #ifndef CXXBRIDGE1_RUST_STRING #define CXXBRIDGE1_RUST_STRING // https://cxx.rs/binding/string.html class String final { public: String() noexcept; String(const String &) noexcept; String(String &&) noexcept; ~String() noexcept; String(const std::string &); String(const char *); String(const char *, std::size_t); String(const char16_t *); String(const char16_t *, std::size_t); #if __cplusplus >= 202002L String(const char8_t *s); String(const char8_t *s, std::size_t len); #endif // Replace invalid Unicode data with the replacement character (U+FFFD). static String lossy(const std::string &) noexcept; static String lossy(const char *) noexcept; static String lossy(const char *, std::size_t) noexcept; static String lossy(const char16_t *) noexcept; static String lossy(const char16_t *, std::size_t) noexcept; String &operator=(const String &) & noexcept; String &operator=(String &&) & noexcept; explicit operator std::string() const; // Note: no null terminator. const char *data() const noexcept; std::size_t size() const noexcept; std::size_t length() const noexcept; bool empty() const noexcept; const char *c_str() noexcept; std::size_t capacity() const noexcept; void reserve(size_t new_cap) noexcept; using iterator = char *; iterator begin() noexcept; iterator end() noexcept; using const_iterator = const char *; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; bool operator==(const String &) const noexcept; bool operator!=(const String &) const noexcept; bool operator<(const String &) const noexcept; bool operator<=(const String &) const noexcept; bool operator>(const String &) const noexcept; bool operator>=(const String &) const noexcept; void swap(String &) noexcept; // Internal API only intended for the cxxbridge code generator. String(unsafe_bitcopy_t, const String &) noexcept; private: struct lossy_t; String(lossy_t, const char *, std::size_t) noexcept; String(lossy_t, const char16_t *, std::size_t) noexcept; friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } // Size and alignment statically verified by rust_string.rs. std::array repr; }; #endif // CXXBRIDGE1_RUST_STRING #ifndef CXXBRIDGE1_RUST_STR #define CXXBRIDGE1_RUST_STR // https://cxx.rs/binding/str.html class Str final { public: Str() noexcept; Str(const String &) noexcept; Str(const std::string &); Str(const char *); Str(const char *, std::size_t); Str &operator=(const Str &) & noexcept = default; explicit operator std::string() const; // Note: no null terminator. const char *data() const noexcept; std::size_t size() const noexcept; std::size_t length() const noexcept; bool empty() const noexcept; // Important in order for System V ABI to pass in registers. Str(const Str &) noexcept = default; ~Str() noexcept = default; using iterator = const char *; using const_iterator = const char *; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; bool operator==(const Str &) const noexcept; bool operator!=(const Str &) const noexcept; bool operator<(const Str &) const noexcept; bool operator<=(const Str &) const noexcept; bool operator>(const Str &) const noexcept; bool operator>=(const Str &) const noexcept; void swap(Str &) noexcept; private: class uninit; Str(uninit) noexcept; friend impl; std::array repr; }; #endif // CXXBRIDGE1_RUST_STR #ifndef CXXBRIDGE1_RUST_SLICE namespace detail { template struct copy_assignable_if {}; template <> struct copy_assignable_if { copy_assignable_if() noexcept = default; copy_assignable_if(const copy_assignable_if &) noexcept = default; copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete; copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default; }; } // namespace detail // https://cxx.rs/binding/slice.html template class Slice final : private detail::copy_assignable_if::value> { public: using value_type = T; Slice() noexcept; Slice(T *, std::size_t count) noexcept; template explicit Slice(C &c) : Slice(c.data(), c.size()) {} Slice &operator=(const Slice &) & noexcept = default; Slice &operator=(Slice &&) & noexcept = default; T *data() const noexcept; std::size_t size() const noexcept; std::size_t length() const noexcept; bool empty() const noexcept; T &operator[](std::size_t n) const noexcept; T &at(std::size_t n) const; T &front() const noexcept; T &back() const noexcept; // Important in order for System V ABI to pass in registers. Slice(const Slice &) noexcept = default; ~Slice() noexcept = default; class iterator; iterator begin() const noexcept; iterator end() const noexcept; void swap(Slice &) noexcept; private: class uninit; Slice(uninit) noexcept; friend impl; friend void sliceInit(void *, const void *, std::size_t) noexcept; friend void *slicePtr(const void *) noexcept; friend std::size_t sliceLen(const void *) noexcept; std::array repr; }; template class Slice::iterator final { public: #if __cplusplus >= 202002L using iterator_category = std::contiguous_iterator_tag; #else using iterator_category = std::random_access_iterator_tag; #endif using value_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::add_pointer::type; using reference = typename std::add_lvalue_reference::type; reference operator*() const noexcept; pointer operator->() const noexcept; reference operator[](difference_type) const noexcept; iterator &operator++() noexcept; iterator operator++(int) noexcept; iterator &operator--() noexcept; iterator operator--(int) noexcept; iterator &operator+=(difference_type) noexcept; iterator &operator-=(difference_type) noexcept; iterator operator+(difference_type) const noexcept; friend inline iterator operator+(difference_type lhs, iterator rhs) noexcept { return rhs + lhs; } iterator operator-(difference_type) const noexcept; difference_type operator-(const iterator &) const noexcept; bool operator==(const iterator &) const noexcept; bool operator!=(const iterator &) const noexcept; bool operator<(const iterator &) const noexcept; bool operator<=(const iterator &) const noexcept; bool operator>(const iterator &) const noexcept; bool operator>=(const iterator &) const noexcept; private: friend class Slice; void *pos; std::size_t stride; }; #if __cplusplus >= 202002L static_assert(std::ranges::contiguous_range>); static_assert(std::contiguous_iterator::iterator>); #endif #endif // CXXBRIDGE1_RUST_SLICE #ifndef CXXBRIDGE1_RUST_BOX // https://cxx.rs/binding/box.html template class Box final { public: using element_type = T; using const_pointer = typename std::add_pointer::type>::type; using pointer = typename std::add_pointer::type; Box() = delete; Box(Box &&) noexcept; ~Box() noexcept; explicit Box(const T &); explicit Box(T &&); Box &operator=(Box &&) & noexcept; const T *operator->() const noexcept; const T &operator*() const noexcept; T *operator->() noexcept; T &operator*() noexcept; template static Box in_place(Fields &&...); void swap(Box &) noexcept; // Important: requires that `raw` came from an into_raw call. Do not pass a // pointer from `new` or any other source. static Box from_raw(T *) noexcept; T *into_raw() noexcept; /* Deprecated */ using value_type = element_type; private: class uninit; class allocation; Box(uninit) noexcept; void drop() noexcept; friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); } T *ptr; }; #endif // CXXBRIDGE1_RUST_BOX #ifndef CXXBRIDGE1_RUST_VEC // https://cxx.rs/binding/vec.html template class Vec final { public: using value_type = T; Vec() noexcept; Vec(std::initializer_list); Vec(const Vec &); Vec(Vec &&) noexcept; ~Vec() noexcept; Vec &operator=(Vec &&) & noexcept; Vec &operator=(const Vec &) &; std::size_t size() const noexcept; bool empty() const noexcept; const T *data() const noexcept; T *data() noexcept; std::size_t capacity() const noexcept; const T &operator[](std::size_t n) const noexcept; const T &at(std::size_t n) const; const T &front() const noexcept; const T &back() const noexcept; T &operator[](std::size_t n) noexcept; T &at(std::size_t n); T &front() noexcept; T &back() noexcept; void reserve(std::size_t new_cap); void push_back(const T &value); void push_back(T &&value); template void emplace_back(Args &&...args); void truncate(std::size_t len); void clear(); using iterator = typename Slice::iterator; iterator begin() noexcept; iterator end() noexcept; using const_iterator = typename Slice::iterator; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; void swap(Vec &) noexcept; // Internal API only intended for the cxxbridge code generator. Vec(unsafe_bitcopy_t, const Vec &) noexcept; private: void reserve_total(std::size_t new_cap) noexcept; void set_len(std::size_t len) noexcept; void drop() noexcept; friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); } // Size and alignment statically verified by rust_vec.rs. std::array repr; }; #endif // CXXBRIDGE1_RUST_VEC #ifndef CXXBRIDGE1_RUST_FN // https://cxx.rs/binding/fn.html template class Fn; template class Fn final { public: Ret operator()(Args... args) const noexcept; Fn operator*() const noexcept; private: Ret (*trampoline)(Args..., void *fn) noexcept; void *fn; }; #endif // CXXBRIDGE1_RUST_FN #ifndef CXXBRIDGE1_RUST_ERROR #define CXXBRIDGE1_RUST_ERROR // https://cxx.rs/binding/result.html class Error final : public std::exception { public: Error(const Error &); Error(Error &&) noexcept; ~Error() noexcept override; Error &operator=(const Error &) &; Error &operator=(Error &&) & noexcept; const char *what() const noexcept override; private: Error() noexcept = default; friend impl; const char *msg; std::size_t len; }; #endif // CXXBRIDGE1_RUST_ERROR #ifndef CXXBRIDGE1_RUST_ISIZE #define CXXBRIDGE1_RUST_ISIZE #if defined(_WIN32) using isize = SSIZE_T; #else using isize = ssize_t; #endif #endif // CXXBRIDGE1_RUST_ISIZE std::ostream &operator<<(std::ostream &, const String &); std::ostream &operator<<(std::ostream &, const Str &); #ifndef CXXBRIDGE1_RUST_OPAQUE #define CXXBRIDGE1_RUST_OPAQUE // Base class of generated opaque Rust types. class Opaque { public: Opaque() = delete; Opaque(const Opaque &) = delete; ~Opaque() = delete; }; #endif // CXXBRIDGE1_RUST_OPAQUE template std::size_t size_of(); template std::size_t align_of(); // IsRelocatable is used in assertions that a C++ type passed by value // between Rust and C++ is soundly relocatable by Rust. // // There may be legitimate reasons to opt out of the check for support of types // that the programmer knows are soundly Rust-movable despite not being // recognized as such by the C++ type system due to a move constructor or // destructor. To opt out of the relocatability check, do either of the // following things in any header used by `include!` in the bridge. // // --- if you define the type: // struct MyType { // ... // + using IsRelocatable = std::true_type; // }; // // --- otherwise: // + template <> // + struct rust::IsRelocatable : std::true_type {}; template struct IsRelocatable; using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t; using u64 = std::uint64_t; using usize = std::size_t; // see static asserts in cxx.cc using i8 = std::int8_t; using i16 = std::int16_t; using i32 = std::int32_t; using i64 = std::int64_t; using f32 = float; using f64 = double; // Snake case aliases for use in code that uses this style for type names. using string = String; using str = Str; template using slice = Slice; template using box = Box; template using vec = Vec; using error = Error; template using fn = Fn; template using is_relocatable = IsRelocatable; //////////////////////////////////////////////////////////////////////////////// /// end public API, begin implementation details #ifndef CXXBRIDGE1_PANIC #define CXXBRIDGE1_PANIC template void panic [[noreturn]] (const char *msg); #endif // CXXBRIDGE1_PANIC #ifndef CXXBRIDGE1_RUST_FN #define CXXBRIDGE1_RUST_FN template Ret Fn::operator()(Args... args) const noexcept { return (*this->trampoline)(std::forward(args)..., this->fn); } template Fn Fn::operator*() const noexcept { return *this; } #endif // CXXBRIDGE1_RUST_FN #ifndef CXXBRIDGE1_RUST_BITCOPY_T #define CXXBRIDGE1_RUST_BITCOPY_T struct unsafe_bitcopy_t final { explicit unsafe_bitcopy_t() = default; }; #endif // CXXBRIDGE1_RUST_BITCOPY_T #ifndef CXXBRIDGE1_RUST_BITCOPY #define CXXBRIDGE1_RUST_BITCOPY constexpr unsafe_bitcopy_t unsafe_bitcopy{}; #endif // CXXBRIDGE1_RUST_BITCOPY #ifndef CXXBRIDGE1_RUST_SLICE #define CXXBRIDGE1_RUST_SLICE template Slice::Slice() noexcept { sliceInit(this, reinterpret_cast(align_of()), 0); } template Slice::Slice(T *s, std::size_t count) noexcept { assert(s != nullptr || count == 0); sliceInit(this, s == nullptr && count == 0 ? reinterpret_cast(align_of()) : const_cast::type *>(s), count); } template T *Slice::data() const noexcept { return reinterpret_cast(slicePtr(this)); } template std::size_t Slice::size() const noexcept { return sliceLen(this); } template std::size_t Slice::length() const noexcept { return this->size(); } template bool Slice::empty() const noexcept { return this->size() == 0; } template T &Slice::operator[](std::size_t n) const noexcept { assert(n < this->size()); auto ptr = static_cast(slicePtr(this)) + size_of() * n; return *reinterpret_cast(ptr); } template T &Slice::at(std::size_t n) const { if (n >= this->size()) { panic("rust::Slice index out of range"); } return (*this)[n]; } template T &Slice::front() const noexcept { assert(!this->empty()); return (*this)[0]; } template T &Slice::back() const noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template typename Slice::iterator::reference Slice::iterator::operator*() const noexcept { return *static_cast(this->pos); } template typename Slice::iterator::pointer Slice::iterator::operator->() const noexcept { return static_cast(this->pos); } template typename Slice::iterator::reference Slice::iterator::operator[]( typename Slice::iterator::difference_type n) const noexcept { auto ptr = static_cast(this->pos) + this->stride * n; return *reinterpret_cast(ptr); } template typename Slice::iterator &Slice::iterator::operator++() noexcept { this->pos = static_cast(this->pos) + this->stride; return *this; } template typename Slice::iterator Slice::iterator::operator++(int) noexcept { auto ret = iterator(*this); this->pos = static_cast(this->pos) + this->stride; return ret; } template typename Slice::iterator &Slice::iterator::operator--() noexcept { this->pos = static_cast(this->pos) - this->stride; return *this; } template typename Slice::iterator Slice::iterator::operator--(int) noexcept { auto ret = iterator(*this); this->pos = static_cast(this->pos) - this->stride; return ret; } template typename Slice::iterator &Slice::iterator::operator+=( typename Slice::iterator::difference_type n) noexcept { this->pos = static_cast(this->pos) + this->stride * n; return *this; } template typename Slice::iterator &Slice::iterator::operator-=( typename Slice::iterator::difference_type n) noexcept { this->pos = static_cast(this->pos) - this->stride * n; return *this; } template typename Slice::iterator Slice::iterator::operator+( typename Slice::iterator::difference_type n) const noexcept { auto ret = iterator(*this); ret.pos = static_cast(this->pos) + this->stride * n; return ret; } template typename Slice::iterator Slice::iterator::operator-( typename Slice::iterator::difference_type n) const noexcept { auto ret = iterator(*this); ret.pos = static_cast(this->pos) - this->stride * n; return ret; } template typename Slice::iterator::difference_type Slice::iterator::operator-(const iterator &other) const noexcept { auto diff = std::distance(static_cast(other.pos), static_cast(this->pos)); return diff / static_cast::iterator::difference_type>( this->stride); } template bool Slice::iterator::operator==(const iterator &other) const noexcept { return this->pos == other.pos; } template bool Slice::iterator::operator!=(const iterator &other) const noexcept { return this->pos != other.pos; } template bool Slice::iterator::operator<(const iterator &other) const noexcept { return this->pos < other.pos; } template bool Slice::iterator::operator<=(const iterator &other) const noexcept { return this->pos <= other.pos; } template bool Slice::iterator::operator>(const iterator &other) const noexcept { return this->pos > other.pos; } template bool Slice::iterator::operator>=(const iterator &other) const noexcept { return this->pos >= other.pos; } template typename Slice::iterator Slice::begin() const noexcept { iterator it; it.pos = slicePtr(this); it.stride = size_of(); return it; } template typename Slice::iterator Slice::end() const noexcept { iterator it = this->begin(); it.pos = static_cast(it.pos) + it.stride * this->size(); return it; } template void Slice::swap(Slice &rhs) noexcept { std::swap(*this, rhs); } #endif // CXXBRIDGE1_RUST_SLICE #ifndef CXXBRIDGE1_RUST_BOX #define CXXBRIDGE1_RUST_BOX template class Box::uninit {}; template class Box::allocation { static T *alloc() noexcept; static void dealloc(T *) noexcept; public: allocation() noexcept : ptr(alloc()) {} ~allocation() noexcept { if (this->ptr) { dealloc(this->ptr); } } T *ptr; }; template Box::Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } template Box::Box(const T &val) { allocation alloc; ::new (alloc.ptr) T(val); this->ptr = alloc.ptr; alloc.ptr = nullptr; } template Box::Box(T &&val) { allocation alloc; ::new (alloc.ptr) T(std::move(val)); this->ptr = alloc.ptr; alloc.ptr = nullptr; } template Box::~Box() noexcept { if (this->ptr) { this->drop(); } } template Box &Box::operator=(Box &&other) & noexcept { if (this->ptr) { this->drop(); } this->ptr = other.ptr; other.ptr = nullptr; return *this; } template const T *Box::operator->() const noexcept { return this->ptr; } template const T &Box::operator*() const noexcept { return *this->ptr; } template T *Box::operator->() noexcept { return this->ptr; } template T &Box::operator*() noexcept { return *this->ptr; } template template Box Box::in_place(Fields &&...fields) { allocation alloc; auto ptr = alloc.ptr; ::new (ptr) T{std::forward(fields)...}; alloc.ptr = nullptr; return from_raw(ptr); } template void Box::swap(Box &rhs) noexcept { using std::swap; swap(this->ptr, rhs.ptr); } template Box Box::from_raw(T *raw) noexcept { Box box = uninit{}; box.ptr = raw; return box; } template T *Box::into_raw() noexcept { T *raw = this->ptr; this->ptr = nullptr; return raw; } template Box::Box(uninit) noexcept {} #endif // CXXBRIDGE1_RUST_BOX #ifndef CXXBRIDGE1_RUST_VEC #define CXXBRIDGE1_RUST_VEC template Vec::Vec(std::initializer_list init) : Vec{} { this->reserve_total(init.size()); std::move(init.begin(), init.end(), std::back_inserter(*this)); } template Vec::Vec(const Vec &other) : Vec() { this->reserve_total(other.size()); std::copy(other.begin(), other.end(), std::back_inserter(*this)); } template Vec::Vec(Vec &&other) noexcept : repr(other.repr) { new (&other) Vec(); } template Vec::~Vec() noexcept { this->drop(); } template Vec &Vec::operator=(Vec &&other) & noexcept { this->drop(); this->repr = other.repr; new (&other) Vec(); return *this; } template Vec &Vec::operator=(const Vec &other) & { if (this != &other) { this->drop(); new (this) Vec(other); } return *this; } template bool Vec::empty() const noexcept { return this->size() == 0; } template T *Vec::data() noexcept { return const_cast(const_cast *>(this)->data()); } template const T &Vec::operator[](std::size_t n) const noexcept { assert(n < this->size()); auto data = reinterpret_cast(this->data()); return *reinterpret_cast(data + n * size_of()); } template const T &Vec::at(std::size_t n) const { if (n >= this->size()) { panic("rust::Vec index out of range"); } return (*this)[n]; } template const T &Vec::front() const noexcept { assert(!this->empty()); return (*this)[0]; } template const T &Vec::back() const noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template T &Vec::operator[](std::size_t n) noexcept { assert(n < this->size()); auto data = reinterpret_cast(this->data()); return *reinterpret_cast(data + n * size_of()); } template T &Vec::at(std::size_t n) { if (n >= this->size()) { panic("rust::Vec index out of range"); } return (*this)[n]; } template T &Vec::front() noexcept { assert(!this->empty()); return (*this)[0]; } template T &Vec::back() noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template void Vec::reserve(std::size_t new_cap) { this->reserve_total(new_cap); } template void Vec::push_back(const T &value) { this->emplace_back(value); } template void Vec::push_back(T &&value) { this->emplace_back(std::move(value)); } template template void Vec::emplace_back(Args &&...args) { auto size = this->size(); this->reserve_total(size + 1); ::new (reinterpret_cast(reinterpret_cast(this->data()) + size * size_of())) T(std::forward(args)...); this->set_len(size + 1); } template void Vec::clear() { this->truncate(0); } template typename Vec::iterator Vec::begin() noexcept { return Slice(this->data(), this->size()).begin(); } template typename Vec::iterator Vec::end() noexcept { return Slice(this->data(), this->size()).end(); } template typename Vec::const_iterator Vec::begin() const noexcept { return this->cbegin(); } template typename Vec::const_iterator Vec::end() const noexcept { return this->cend(); } template typename Vec::const_iterator Vec::cbegin() const noexcept { return Slice(this->data(), this->size()).begin(); } template typename Vec::const_iterator Vec::cend() const noexcept { return Slice(this->data(), this->size()).end(); } template void Vec::swap(Vec &rhs) noexcept { using std::swap; swap(this->repr, rhs.repr); } // Internal API only intended for the cxxbridge code generator. template Vec::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {} #endif // CXXBRIDGE1_RUST_VEC #ifndef CXXBRIDGE1_IS_COMPLETE #define CXXBRIDGE1_IS_COMPLETE namespace detail { namespace { template struct is_complete : std::false_type {}; template struct is_complete : std::true_type {}; } // namespace } // namespace detail #endif // CXXBRIDGE1_IS_COMPLETE #ifndef CXXBRIDGE1_LAYOUT #define CXXBRIDGE1_LAYOUT class layout { template friend std::size_t size_of(); template friend std::size_t align_of(); template static typename std::enable_if::value, std::size_t>::type do_size_of() { return T::layout::size(); } template static typename std::enable_if::value, std::size_t>::type do_size_of() { return sizeof(T); } template static typename std::enable_if::value, std::size_t>::type size_of() { return do_size_of(); } template static typename std::enable_if::value, std::size_t>::type do_align_of() { return T::layout::align(); } template static typename std::enable_if::value, std::size_t>::type do_align_of() { return alignof(T); } template static typename std::enable_if::value, std::size_t>::type align_of() { return do_align_of(); } }; template std::size_t size_of() { return layout::size_of(); } template std::size_t align_of() { return layout::align_of(); } #endif // CXXBRIDGE1_LAYOUT #ifndef CXXBRIDGE1_RELOCATABLE #define CXXBRIDGE1_RELOCATABLE namespace detail { template struct make_void { using type = void; }; template using void_t = typename make_void::type; template class, typename...> struct detect : std::false_type {}; template