Showing preview only (1,376K chars total). Download the full file or copy to clipboard to get everything.
Repository: dtolnay/cxx
Branch: master
Commit: 9634c7d5167e
Files: 463
Total size: 1.2 MB
Directory structure:
gitextract_dh2rnm1j/
├── .bazelignore
├── .bazelrc
├── .bcr/
│ ├── README.md
│ ├── config.yml
│ ├── metadata.template.json
│ ├── presubmit.yml
│ └── source.template.json
├── .buckconfig
├── .buckroot
├── .clang-format
├── .clang-tidy
├── .devcontainer/
│ ├── Dockerfile
│ ├── README.md
│ ├── build.Dockerfile
│ └── devcontainer.json
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── buck2.yml
│ ├── ci.yml
│ ├── install.yml
│ ├── release.yml
│ └── site.yml
├── .gitignore
├── .vscode/
│ ├── README.md
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .watchmanconfig
├── BUCK
├── BUILD.bazel
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── MODULE.bazel
├── README.md
├── book/
│ ├── .gitignore
│ ├── README.md
│ ├── book.toml
│ ├── build.js
│ ├── build.sh
│ ├── css/
│ │ └── cxx.css
│ ├── diagram/
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ └── overview.tex
│ ├── eslint.config.mjs
│ ├── package.json
│ ├── src/
│ │ ├── 404.md
│ │ ├── SUMMARY.md
│ │ ├── async.md
│ │ ├── attributes.md
│ │ ├── binding/
│ │ │ ├── box.md
│ │ │ ├── cxxstring.md
│ │ │ ├── cxxvector.md
│ │ │ ├── fn.md
│ │ │ ├── rawptr.md
│ │ │ ├── result.md
│ │ │ ├── sharedptr.md
│ │ │ ├── slice.md
│ │ │ ├── str.md
│ │ │ ├── string.md
│ │ │ ├── uniqueptr.md
│ │ │ └── vec.md
│ │ ├── bindings.md
│ │ ├── build/
│ │ │ ├── bazel.md
│ │ │ ├── cargo.md
│ │ │ ├── cmake.md
│ │ │ └── other.md
│ │ ├── building.md
│ │ ├── concepts.md
│ │ ├── context.md
│ │ ├── extern-c++.md
│ │ ├── extern-rust.md
│ │ ├── index.md
│ │ ├── reference.md
│ │ ├── shared.md
│ │ └── tutorial.md
│ └── theme/
│ └── head.hbs
├── build.rs
├── compile_flags.txt
├── demo/
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── Cargo.toml
│ ├── build.rs
│ ├── include/
│ │ └── blobstore.h
│ └── src/
│ ├── blobstore.cc
│ └── main.rs
├── flags/
│ ├── Cargo.toml
│ └── src/
│ ├── impl.rs
│ └── lib.rs
├── gen/
│ ├── README.md
│ ├── build/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ └── src/
│ │ ├── cargo.rs
│ │ ├── cfg.rs
│ │ ├── deps.rs
│ │ ├── error.rs
│ │ ├── intern.rs
│ │ ├── lib.rs
│ │ ├── out.rs
│ │ ├── paths.rs
│ │ ├── target.rs
│ │ └── vec.rs
│ ├── cmd/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ └── src/
│ │ ├── app.rs
│ │ ├── cfg.rs
│ │ ├── main.rs
│ │ ├── output.rs
│ │ └── test.rs
│ ├── lib/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── src/
│ │ │ ├── error.rs
│ │ │ └── lib.rs
│ │ └── tests/
│ │ └── test.rs
│ └── src/
│ ├── block.rs
│ ├── builtin/
│ │ ├── alignmax.h
│ │ ├── deleter_if.h
│ │ ├── destroy.h
│ │ ├── friend_impl.h
│ │ ├── manually_drop.h
│ │ ├── maybe_uninit.h
│ │ ├── maybe_uninit_detail.h
│ │ ├── ptr_len.h
│ │ ├── relocatable_or_array.h
│ │ ├── repr_fat.h
│ │ ├── rust_error.h
│ │ ├── rust_slice_uninit.h
│ │ ├── rust_str_uninit.h
│ │ ├── shared_ptr.h
│ │ ├── trycatch.h
│ │ ├── trycatch_detail.h
│ │ └── vector.h
│ ├── builtin.rs
│ ├── cfg.rs
│ ├── check.rs
│ ├── error.rs
│ ├── file.rs
│ ├── fs.rs
│ ├── guard.rs
│ ├── ifndef.rs
│ ├── include.rs
│ ├── mod.rs
│ ├── names.rs
│ ├── namespace.rs
│ ├── nested.rs
│ ├── out.rs
│ ├── pragma.rs
│ └── write.rs
├── include/
│ └── cxx.h
├── macro/
│ ├── Cargo.toml
│ ├── README.md
│ ├── build.rs
│ └── src/
│ ├── attrs.rs
│ ├── cfg.rs
│ ├── derive.rs
│ ├── expand.rs
│ ├── generics.rs
│ ├── lib.rs
│ ├── tests.rs
│ ├── tokens.rs
│ └── type_id.rs
├── reindeer.toml
├── rust-toolchain.toml
├── src/
│ ├── cxx.cc
│ ├── cxx_string.rs
│ ├── cxx_vector.rs
│ ├── exception.rs
│ ├── extern_type.rs
│ ├── fmt.rs
│ ├── function.rs
│ ├── hash.rs
│ ├── lib.rs
│ ├── lossy.rs
│ ├── macros/
│ │ ├── assert.rs
│ │ └── mod.rs
│ ├── memory.rs
│ ├── opaque.rs
│ ├── result.rs
│ ├── rust_slice.rs
│ ├── rust_str.rs
│ ├── rust_string.rs
│ ├── rust_type.rs
│ ├── rust_vec.rs
│ ├── shared_ptr.rs
│ ├── symbols/
│ │ ├── exception.rs
│ │ ├── mod.rs
│ │ ├── rust_slice.rs
│ │ ├── rust_str.rs
│ │ ├── rust_string.rs
│ │ └── rust_vec.rs
│ ├── type_id.rs
│ ├── unique_ptr.rs
│ ├── unwind.rs
│ ├── vector.rs
│ └── weak_ptr.rs
├── syntax/
│ ├── atom.rs
│ ├── attrs.rs
│ ├── cfg.rs
│ ├── check.rs
│ ├── derive.rs
│ ├── discriminant.rs
│ ├── doc.rs
│ ├── error.rs
│ ├── file.rs
│ ├── ident.rs
│ ├── impls.rs
│ ├── improper.rs
│ ├── instantiate.rs
│ ├── mangle.rs
│ ├── map.rs
│ ├── message.rs
│ ├── mod.rs
│ ├── names.rs
│ ├── namespace.rs
│ ├── parse.rs
│ ├── pod.rs
│ ├── primitive.rs
│ ├── qualified.rs
│ ├── query.rs
│ ├── report.rs
│ ├── repr.rs
│ ├── resolve.rs
│ ├── set.rs
│ ├── signature.rs
│ ├── symbol.rs
│ ├── tokens.rs
│ ├── toposort.rs
│ ├── trivial.rs
│ ├── types.rs
│ ├── unpin.rs
│ └── visit.rs
├── tests/
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── README.md
│ ├── compiletest.rs
│ ├── cpp_compile/
│ │ ├── mod.rs
│ │ └── smoke_test.rs
│ ├── cpp_ui_tests.rs
│ ├── cxx_gen.rs
│ ├── cxx_string.rs
│ ├── cxx_vector.rs
│ ├── ffi/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── cast.rs
│ │ ├── lib.rs
│ │ ├── module.rs
│ │ ├── tests.cc
│ │ └── tests.h
│ ├── test.rs
│ ├── ui/
│ │ ├── array_len_expr.rs
│ │ ├── array_len_expr.stderr
│ │ ├── array_len_suffix.rs
│ │ ├── array_len_suffix.stderr
│ │ ├── async_fn.rs
│ │ ├── async_fn.stderr
│ │ ├── bad_explicit_impl.rs
│ │ ├── bad_explicit_impl.stderr
│ │ ├── by_value_not_supported.rs
│ │ ├── by_value_not_supported.stderr
│ │ ├── const_fn.rs
│ │ ├── const_fn.stderr
│ │ ├── cxx_crate_name_qualified_cxx_string.rs
│ │ ├── cxx_crate_name_qualified_cxx_string.stderr
│ │ ├── data_enums.rs
│ │ ├── data_enums.stderr
│ │ ├── deny_elided_lifetimes.rs
│ │ ├── deny_elided_lifetimes.stderr
│ │ ├── deny_missing_docs.rs
│ │ ├── deny_missing_docs.stderr
│ │ ├── derive_bit_struct.rs
│ │ ├── derive_bit_struct.stderr
│ │ ├── derive_default.rs
│ │ ├── derive_default.stderr
│ │ ├── derive_duplicate.rs
│ │ ├── derive_duplicate.stderr
│ │ ├── derive_noncopy.rs
│ │ ├── derive_noncopy.stderr
│ │ ├── drop_shared.rs
│ │ ├── drop_shared.stderr
│ │ ├── duplicate_method.rs
│ │ ├── duplicate_method.stderr
│ │ ├── empty_enum.rs
│ │ ├── empty_enum.stderr
│ │ ├── empty_struct.rs
│ │ ├── empty_struct.stderr
│ │ ├── enum_assoc.rs
│ │ ├── enum_assoc.stderr
│ │ ├── enum_inconsistent.rs
│ │ ├── enum_inconsistent.stderr
│ │ ├── enum_match_without_wildcard.rs
│ │ ├── enum_match_without_wildcard.stderr
│ │ ├── enum_out_of_bounds.rs
│ │ ├── enum_out_of_bounds.stderr
│ │ ├── enum_overflows.rs
│ │ ├── enum_overflows.stderr
│ │ ├── enum_receiver.rs
│ │ ├── enum_receiver.stderr
│ │ ├── enum_unsatisfiable.rs
│ │ ├── enum_unsatisfiable.stderr
│ │ ├── expected_named.rs
│ │ ├── expected_named.stderr
│ │ ├── explicit_impl_of_bad_unique_ptr.rs
│ │ ├── explicit_impl_of_bad_unique_ptr.stderr
│ │ ├── extern_fn_abi.rs
│ │ ├── extern_fn_abi.stderr
│ │ ├── extern_shared_struct.rs
│ │ ├── extern_shared_struct.stderr
│ │ ├── extern_type_bound.rs
│ │ ├── extern_type_bound.stderr
│ │ ├── extern_type_generic.rs
│ │ ├── extern_type_generic.stderr
│ │ ├── extern_type_lifetime_bound.rs
│ │ ├── extern_type_lifetime_bound.stderr
│ │ ├── fallible_fnptr.rs
│ │ ├── fallible_fnptr.stderr
│ │ ├── function_with_body.rs
│ │ ├── function_with_body.stderr
│ │ ├── generic_enum.rs
│ │ ├── generic_enum.stderr
│ │ ├── impl_trait_for_type.rs
│ │ ├── impl_trait_for_type.stderr
│ │ ├── include.rs
│ │ ├── include.stderr
│ │ ├── lifetime_extern_cxx.rs
│ │ ├── lifetime_extern_cxx.stderr
│ │ ├── lifetime_extern_rust.rs
│ │ ├── lifetime_extern_rust.stderr
│ │ ├── missing_unsafe.rs
│ │ ├── missing_unsafe.stderr
│ │ ├── multiple_parse_error.rs
│ │ ├── multiple_parse_error.stderr
│ │ ├── mut_return.rs
│ │ ├── mut_return.stderr
│ │ ├── non_integer_discriminant_enum.rs
│ │ ├── non_integer_discriminant_enum.stderr
│ │ ├── nonempty_impl_block.rs
│ │ ├── nonempty_impl_block.stderr
│ │ ├── nonlocal_rust_type.rs
│ │ ├── nonlocal_rust_type.stderr
│ │ ├── opaque_autotraits.rs
│ │ ├── opaque_autotraits.stderr
│ │ ├── opaque_not_sized.rs
│ │ ├── opaque_not_sized.stderr
│ │ ├── pin_mut_alias.rs
│ │ ├── pin_mut_alias.stderr
│ │ ├── pin_mut_opaque.rs
│ │ ├── pin_mut_opaque.stderr
│ │ ├── ptr_in_fnptr.rs
│ │ ├── ptr_in_fnptr.stderr
│ │ ├── ptr_missing_unsafe.rs
│ │ ├── ptr_missing_unsafe.stderr
│ │ ├── ptr_no_const_mut.rs
│ │ ├── ptr_no_const_mut.stderr
│ │ ├── ptr_unsupported.rs
│ │ ├── ptr_unsupported.stderr
│ │ ├── raw_ident_namespace.rs
│ │ ├── raw_ident_namespace.stderr
│ │ ├── reference_to_reference.rs
│ │ ├── reference_to_reference.stderr
│ │ ├── repr_align_suffixed.rs
│ │ ├── repr_align_suffixed.stderr
│ │ ├── repr_unsupported.rs
│ │ ├── repr_unsupported.stderr
│ │ ├── reserved_lifetime.rs
│ │ ├── reserved_lifetime.stderr
│ │ ├── reserved_name.rs
│ │ ├── reserved_name.stderr
│ │ ├── result_no_display.rs
│ │ ├── result_no_display.stderr
│ │ ├── root_namespace.rs
│ │ ├── root_namespace.stderr
│ │ ├── rust_pinned.rs
│ │ ├── rust_pinned.stderr
│ │ ├── self_lifetimes.rs
│ │ ├── self_lifetimes.stderr
│ │ ├── self_type_and_receiver.rs
│ │ ├── self_type_and_receiver.stderr
│ │ ├── slice_of_pinned.rs
│ │ ├── slice_of_pinned.stderr
│ │ ├── slice_of_type_alias.rs
│ │ ├── slice_of_type_alias.stderr
│ │ ├── slice_unsupported.rs
│ │ ├── slice_unsupported.stderr
│ │ ├── struct_align.rs
│ │ ├── struct_align.stderr
│ │ ├── struct_cycle.rs
│ │ ├── struct_cycle.stderr
│ │ ├── type_alias_rust.rs
│ │ ├── type_alias_rust.stderr
│ │ ├── undeclared_lifetime.rs
│ │ ├── undeclared_lifetime.stderr
│ │ ├── unique_ptr_as_mut.rs
│ │ ├── unique_ptr_as_mut.stderr
│ │ ├── unique_ptr_to_opaque.rs
│ │ ├── unique_ptr_to_opaque.stderr
│ │ ├── unique_ptr_twice.rs
│ │ ├── unique_ptr_twice.stderr
│ │ ├── unnamed_receiver.rs
│ │ ├── unnamed_receiver.stderr
│ │ ├── unpin_impl.rs
│ │ ├── unpin_impl.stderr
│ │ ├── unrecognized_receiver.rs
│ │ ├── unrecognized_receiver.stderr
│ │ ├── unsupported_elided.rs
│ │ ├── unsupported_elided.stderr
│ │ ├── vec_opaque.rs
│ │ ├── vec_opaque.stderr
│ │ ├── vector_autotraits.rs
│ │ ├── vector_autotraits.stderr
│ │ ├── wrong_type_id.rs
│ │ └── wrong_type_id.stderr
│ └── unique_ptr.rs
├── third-party/
│ ├── .cargo/
│ │ └── .gitignore
│ ├── .gitignore
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── Cargo.toml
│ ├── bazel/
│ │ ├── BUILD.anstyle-1.0.13.bazel
│ │ ├── BUILD.bazel
│ │ ├── BUILD.cc-1.2.53.bazel
│ │ ├── BUILD.clap-4.5.54.bazel
│ │ ├── BUILD.clap_builder-4.5.54.bazel
│ │ ├── BUILD.clap_lex-0.7.7.bazel
│ │ ├── BUILD.codespan-reporting-0.13.1.bazel
│ │ ├── BUILD.equivalent-1.0.2.bazel
│ │ ├── BUILD.find-msvc-tools-0.1.8.bazel
│ │ ├── BUILD.foldhash-0.2.0.bazel
│ │ ├── BUILD.hashbrown-0.16.1.bazel
│ │ ├── BUILD.indexmap-2.13.0.bazel
│ │ ├── BUILD.proc-macro2-1.0.105.bazel
│ │ ├── BUILD.quote-1.0.43.bazel
│ │ ├── BUILD.rustversion-1.0.22.bazel
│ │ ├── BUILD.scratch-1.0.9.bazel
│ │ ├── BUILD.serde-1.0.228.bazel
│ │ ├── BUILD.serde_core-1.0.228.bazel
│ │ ├── BUILD.serde_derive-1.0.228.bazel
│ │ ├── BUILD.shlex-1.3.0.bazel
│ │ ├── BUILD.syn-2.0.114.bazel
│ │ ├── BUILD.termcolor-1.4.1.bazel
│ │ ├── BUILD.unicode-ident-1.0.22.bazel
│ │ ├── BUILD.unicode-width-0.2.2.bazel
│ │ ├── BUILD.winapi-util-0.1.11.bazel
│ │ ├── BUILD.windows-link-0.2.1.bazel
│ │ ├── BUILD.windows-sys-0.61.2.bazel
│ │ ├── alias_rules.bzl
│ │ ├── crates.bzl
│ │ └── defs.bzl
│ ├── fixups/
│ │ ├── proc-macro2/
│ │ │ └── fixups.toml
│ │ ├── quote/
│ │ │ └── fixups.toml
│ │ ├── rustversion/
│ │ │ └── fixups.toml
│ │ ├── scratch/
│ │ │ └── fixups.toml
│ │ ├── serde/
│ │ │ └── fixups.toml
│ │ ├── serde_core/
│ │ │ └── fixups.toml
│ │ ├── serde_derive/
│ │ │ └── fixups.toml
│ │ ├── winapi-util/
│ │ │ └── fixups.toml
│ │ └── windows-sys/
│ │ └── fixups.toml
│ └── src/
│ └── lib.rs
└── tools/
├── bazel/
│ ├── BUILD.bazel
│ ├── extension.bzl
│ └── rust_cxx_bridge.bzl
├── buck/
│ ├── rust_cxx_bridge.bzl
│ └── toolchains/
│ └── BUCK
└── cargo/
└── build.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .bazelignore
================================================
buck-out/
target/
tools/buck/buck2/
================================================
FILE: .bazelrc
================================================
###############################################################################
## Bazel Configuration Flags
##
## `.bazelrc` is a Bazel configuration file.
## https://bazel.build/docs/best-practices#bazelrc-file
###############################################################################
build --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
###############################################################################
## Custom user flags
##
## This should always be the last thing in the `.bazelrc` file to ensure
## consistent behavior when setting flags in that file as `.bazelrc` files are
## evaluated top to bottom.
###############################################################################
try-import %workspace%/user.bazelrc
================================================
FILE: .bcr/README.md
================================================
# Bazel Central Registry
When the ruleset is released, we want it to be published to the
Bazel Central Registry automatically:
<https://registry.bazel.build>
This folder contains configuration files to automate the publish step.
See <https://github.com/bazel-contrib/publish-to-bcr/blob/main/templates/README.md>
for authoritative documentation about these files.
================================================
FILE: .bcr/config.yml
================================================
fixedReleaser:
login: dtolnay
email: dtolnay@gmail.com
================================================
FILE: .bcr/metadata.template.json
================================================
{
"homepage": "https://cxx.rs",
"maintainers": [
{
"github": "dtolnay",
"github_user_id": 1940490,
"email": "dtolnay@gmail.com",
"name": "David Tolnay"
}
],
"repository": [
"github:dtolnay/cxx"
],
"versions": [],
"yanked_versions": {}
}
================================================
FILE: .bcr/presubmit.yml
================================================
matrix:
platform:
- macos_arm64
- ubuntu2404
- windows
bazel: [8.x, 9.x]
tasks:
verify_targets:
name: Verify build targets
platform: ${{ platform }}
bazel: ${{ bazel }}
build_targets:
- '@cxx.rs//...'
test_targets:
- '@cxx.rs//...'
================================================
FILE: .bcr/source.template.json
================================================
{
"integrity": "",
"strip_prefix": "{REPO}-{VERSION}",
"url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{VERSION}.tar.gz"
}
================================================
FILE: .buckconfig
================================================
[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
================================================
FILE: .buckroot
================================================
================================================
FILE: .clang-format
================================================
AlwaysBreakTemplateDeclarations: true
MaxEmptyLinesToKeep: 3
ReflowComments: false
================================================
FILE: .clang-tidy
================================================
Checks:
clang-analyzer-*,
clang-diagnostic-*,
cppcoreguidelines-*,
modernize-*,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-special-member-functions,
-modernize-concat-nested-namespaces,
-modernize-return-braced-init-list,
-modernize-type-traits,
-modernize-use-constraints,
-modernize-use-nodiscard,
-modernize-use-ranges,
-modernize-use-trailing-return-type,
HeaderFilterRegex: cxx\.h
================================================
FILE: .devcontainer/Dockerfile
================================================
FROM dtolnay/devcontainer:latest
================================================
FILE: .devcontainer/README.md
================================================
This directory contains the container setup used when developing CXX inside of
GitHub [Codespaces].
[Codespaces]: https://github.com/features/codespaces
================================================
FILE: .devcontainer/build.Dockerfile
================================================
FROM 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
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"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"
]
}
================================================
FILE: .gitattributes
================================================
/MODULE.bazel.lock linguist-generated
/third-party/BUCK linguist-generated
/third-party/bazel/** linguist-generated
================================================
FILE: .github/FUNDING.yml
================================================
github: dtolnay
================================================
FILE: .github/workflows/buck2.yml
================================================
name: 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@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: rust-src
- uses: dtolnay/install-buck2@latest
- run: buck2 run demo
- run: buck2 build ...
- run: buck2 test ...
================================================
FILE: .github/workflows/ci.yml
================================================
name: 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.runs-on || format('{0}-latest', matrix.os)}}
strategy:
fail-fast: false
matrix:
rust: [nightly, beta, stable, 1.85.0]
os: [ubuntu]
cc: [g++]
flags: ['']
include:
- name: Cargo on macOS
rust: nightly
os: macos
- name: Cargo on Windows (msvc)
rust: nightly-x86_64-pc-windows-msvc
os: windows
- name: Clang
rust: nightly
os: ubuntu
cc: clang++
flags: -std=c++20
- name: Clang (no exceptions)
rust: nightly
os: ubuntu
cc: clang++
flags: -std=c++20 -fno-exceptions
- name: C++14 on Linux
rust: nightly
os: ubuntu
cc: g++
flags: -std=c++14
- name: C++14 on macOS
rust: nightly
os: macos
flags: -std=c++14
- name: C++14 on Windows
rust: nightly-x86_64-pc-windows-msvc
os: windows
flags: /std:c++14
- name: C++17 on Linux
rust: nightly
os: ubuntu
cc: g++
flags: -std=c++17
- name: C++17 on macOS
rust: nightly
os: macos
flags: -std=c++17
- name: C++17 on Windows
rust: nightly-x86_64-pc-windows-msvc
os: windows
flags: /std:c++17
- name: C++20 on Linux
rust: nightly
os: ubuntu
cc: g++
flags: -std=c++20
- name: C++20 on macOS
rust: nightly
os: macos
flags: -std=c++20
runs-on: macos-15
- name: C++20 on Windows
rust: nightly-x86_64-pc-windows-msvc
os: windows
flags: /std:c++20
- name: Pedantic
rust: nightly
os: ubuntu
cc: clang++
flags:
-Weverything
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-c++20-compat
-Wno-implicit-int-conversion
-Wno-missing-prototypes
-Wno-padded
-Wno-sign-conversion
-Wno-undefined-func-template
-Wno-unsafe-buffer-usage
-Wno-unused-macros
env:
CXX: ${{matrix.cc}}
CXXFLAGS: ${{matrix.flags}} ${{matrix.os == 'windows' && '/EHsc /WX' || '-Werror -Wall -Wpedantic'}}
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@v6
- 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 >> $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: contains(matrix.flags, '-fno-exceptions') == false
- 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@v6
if: matrix.os == 'ubuntu' && matrix.rust == 'nightly' && matrix.cc == '' && matrix.flags == '' && always()
with:
name: Cargo.lock
path: Cargo.lock
continue-on-error: true
wasi:
name: WebAssembly
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
with:
targets: wasm32-wasip1
components: rust-src
- uses: dtolnay/install@wasmtime-cli
- run: curl https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz --location --silent --show-error --fail --retry 2 --output ${{runner.temp}}/wasi-sdk-27.0-x86_64-linux.tar.gz
- run: tar xf ${{runner.temp}}/wasi-sdk-27.0-x86_64-linux.tar.gz -C ${{runner.temp}}
- run: cargo build --target=wasm32-wasip1 --manifest-path=demo/Cargo.toml --release
--config='target.wasm32-wasip1.linker="${{runner.temp}}/wasi-sdk-27.0-x86_64-linux/bin/lld"'
--config='target.wasm32-wasip1.rustflags=["-Clink-args=-L${{runner.temp}}/wasi-sdk-27.0-x86_64-linux/share/wasi-sysroot/lib/wasm32-wasip1", "-Clink-args=-lc++abi"]'
env:
CXX: ${{runner.temp}}/wasi-sdk-27.0-x86_64-linux/bin/clang++
CXXFLAGS: --sysroot=${{runner.temp}}/wasi-sdk-27.0-x86_64-linux/share/wasi-sysroot
- run: wasmtime target/wasm32-wasip1/release/demo.wasm
emscripten:
name: Emscripten
needs: pre_ci
if: needs.pre_ci.outputs.continue
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
with:
targets: wasm32-unknown-emscripten
components: rust-src
- name: Disable initramfs update
run: sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf
- name: Disable man-db update
run: sudo rm -f /var/lib/man-db/auto-update
- name: Install emscripten
run: sudo apt-get install emscripten
- run: cargo build --target=wasm32-unknown-emscripten --manifest-path=demo/Cargo.toml --release -Zbuild-std
env:
RUSTFLAGS: -Clink-arg=--emrun ${{env.RUSTFLAGS}}
- name: Create demo.html for demo.js
run: echo '<!DOCTYPE html><script src="demo.js"></script>' > target/wasm32-unknown-emscripten/release/demo.html
- name: Install firefox
run: sudo snap install firefox
- run: emrun target/wasm32-unknown-emscripten/release/demo.html
--browser=/snap/firefox/current/usr/lib/firefox/firefox
--browser_args=-headless
--safe_firefox_profile
--log_stdout=${{runner.temp}}/demo.log
--timeout=60
--kill_exit
- run: cat ${{runner.temp}}/demo.log
- run: grep --silent blobid ${{runner.temp}}/demo.log
reindeer:
name: Reindeer
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- 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@v6
- name: Disable initramfs update
run: sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf
if: matrix.os == 'ubuntu'
- name: Disable man-db update
run: sudo rm -f /var/lib/man-db/auto-update
if: matrix.os == 'ubuntu'
- name: Install lld
run: sudo apt-get install lld
if: matrix.os == 'ubuntu'
- name: Set bazelrc for Windows
run: echo "startup --output_user_root=D:/bzl" > user.bazelrc
if: matrix.os == 'windows'
- run: bazel --version
- run: bazel run demo --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}}
- run: bazel test ... --verbose_failures --noshow_progress ${{matrix.os == 'macos' && '--xcode_version_config=tools/bazel:github_actions_xcodes' || ''}}
- name: Check MODULE.bazel.lock up to date
run: git diff --exit-code
- 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@v6
- 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@v6
- 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@v6
- 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@v6
- name: Disable initramfs update
run: sudo sed -i 's/^update_initramfs=yes$/update_initramfs=no/' /etc/initramfs-tools/update-initramfs.conf
- name: Disable man-db update
run: sudo rm -f /var/lib/man-db/auto-update
- name: Install clang-tidy
run: sudo apt-get update && sudo apt-get install clang-tidy-20
- name: Run clang-tidy
run: clang-tidy-20 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@v6
- 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@v6
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --workspace --exit-code 1
================================================
FILE: .github/workflows/install.yml
================================================
name: 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
================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
release:
types: [released]
permissions:
attestations: write
contents: write
id-token: write
jobs:
upload:
uses: dtolnay/.github/.github/workflows/release_tgz.yml@master
publish-to-bcr:
needs: upload
uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@92ae43f10e552721931f98b61fe5506bbdf32ce6
with:
tag_name: ${{github.event.release.tag_name}}
registry_fork: dtolnay-contrib/bazel-central-registry
attest: false
secrets:
publish_token: ${{secrets.PUBLISH_TOKEN}}
================================================
FILE: .github/workflows/site.yml
================================================
name: 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@v6
- 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
================================================
FILE: .gitignore
================================================
/.buckconfig.d/
/.buckconfig.local
/.buckd
/bazel-bin
/bazel-cxx
/bazel-out
/bazel-testlogs
/user.bazelrc
/buck-out
/expand.cc
/expand.rs
/target/
/Cargo.lock
================================================
FILE: .vscode/README.md
================================================
VS Code actions and configuration. Applicable when developing CXX inside of
GitHub [Codespaces].
[Codespaces]: https://github.com/features/codespaces
================================================
FILE: .vscode/launch.json
================================================
{
"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"
}
}
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"search.exclude": {
"**/target": true
}
}
================================================
FILE: .vscode/tasks.json
================================================
{
"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"
}
]
}
================================================
FILE: .watchmanconfig
================================================
{
"ignore_dirs": ["buck-out"]
}
================================================
FILE: BUCK
================================================
load(":Cargo.toml", cargo_toml = "value")
CARGO_PKG_VERSION_PATCH = cargo_toml["package"]["version"].split(".")[2]
rust_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/src/builtin/*.h",
]) + [
"gen/cmd/src/gen",
"gen/cmd/src/syntax",
],
edition = "2021",
env = {
"CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH,
},
deps = [
"//third-party:clap",
"//third-party:codespan-reporting",
"//third-party:indexmap",
"//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",
env = {
"CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH,
},
proc_macro = True,
deps = [
"//third-party:indexmap",
"//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/src/builtin/*.h",
]) + [
"gen/build/src/gen",
"gen/build/src/syntax",
],
doctests = False,
edition = "2021",
env = {
"CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH,
},
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:indexmap",
"//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/src/builtin/*.h",
]) + [
"gen/lib/src/gen",
"gen/lib/src/syntax",
],
edition = "2021",
env = {
"CARGO_PKG_VERSION_PATCH": CARGO_PKG_VERSION_PATCH,
},
visibility = ["PUBLIC"],
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:indexmap",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)
================================================
FILE: BUILD.bazel
================================================
load("@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",
],
version = module_version(),
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 = glob(["gen/cmd/src/gen/**/*.h"]),
edition = "2021",
version = module_version(),
deps = [
"@crates.io//:clap",
"@crates.io//:codespan-reporting",
"@crates.io//:indexmap",
"@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"],
linkstatic = True,
)
rust_proc_macro(
name = "cxxbridge-macro",
srcs = glob(["macro/src/**/*.rs"]),
edition = "2021",
proc_macro_deps = [
"@crates.io//:rustversion",
],
version = module_version(),
deps = [
"@crates.io//:indexmap",
"@crates.io//:proc-macro2",
"@crates.io//:quote",
"@crates.io//:syn",
],
)
rust_library(
name = "cxx-build",
srcs = glob(["gen/build/src/**/*.rs"]),
compile_data = glob(["gen/build/src/gen/**/*.h"]),
edition = "2021",
version = module_version(),
deps = [
"@crates.io//:cc",
"@crates.io//:codespan-reporting",
"@crates.io//:indexmap",
"@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 = glob(["gen/lib/src/gen/**/*.h"]),
edition = "2021",
version = module_version(),
visibility = ["//visibility:public"],
deps = [
"@crates.io//:cc",
"@crates.io//:codespan-reporting",
"@crates.io//:indexmap",
"@crates.io//:proc-macro2",
"@crates.io//:quote",
"@crates.io//:syn",
],
)
================================================
FILE: Cargo.toml
================================================
[package]
name = "cxx"
version = "1.0.194"
authors = ["David Tolnay <dtolnay@gmail.com>"]
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.85"
[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.194", path = "macro" }
foldhash = { version = "0.2", default-features = false }
link-cplusplus = "1.0.11"
[build-dependencies]
cc = "1.0.101"
cxxbridge-flags = { version = "=1.0.194", path = "flags", default-features = false }
[dev-dependencies]
cc = "1.0.101"
cxx-build = { version = "1", path = "gen/build" }
cxx-gen = { version = "=0.7.194", path = "gen/lib" }
cxx-test-suite = { version = "0", path = "tests/ffi" }
indoc = "2"
proc-macro2 = "1.0.95"
quote = "1.0.40"
rustversion = "1.0.13"
scratch = "1"
target-triple = "1"
tempfile = "3.8"
trybuild = { version = "1.0.108", features = ["diff"] }
# Disallow incompatible version appearing in the same lockfile.
[target.'cfg(any())'.build-dependencies]
cxx-build = { version = "=1.0.194", path = "gen/build" }
cxxbridge-cmd = { version = "=1.0.194", 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",
"--generate-macro-expansion",
"--extern-html-root-url=core=https://doc.rust-lang.org",
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
"--extern-html-root-url=std=https://doc.rust-lang.org",
]
[package.metadata.bazel]
additive_build_file_content = """
load("@rules_cc//cc:defs.bzl", "cc_library")
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" }
================================================
FILE: LICENSE-APACHE
================================================
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
================================================
FILE: LICENSE-MIT
================================================
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: MODULE.bazel
================================================
module(
name = "cxx.rs",
version = "0.0.0",
bazel_compatibility = [">=8.0.0"],
compatibility_level = 1,
)
bazel_dep(name = "apple_support", version = "2.1.0")
bazel_dep(name = "bazel_features", version = "1.33.0")
bazel_dep(name = "bazel_skylib", version = "1.8.2")
bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_cc", version = "0.2.14")
bazel_dep(name = "rules_rust", version = "0.69.0")
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
rust.toolchain(versions = ["1.94.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", "vendor")
================================================
FILE: README.md
================================================
CXX — safe FFI between Rust and C++
=========================================
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/cxx-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/cxx)
[<img alt="crates.io" src="https://img.shields.io/crates/v/cxx.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/cxx)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/cxx)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/cxx/ci.yml?branch=master&style=for-the-badge" height="20">](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.85+ and c++11 or newer*<br>
*[Release notes](https://github.com/dtolnay/cxx/releases)*
<br>
## Guide
Please see **<https://cxx.rs>** for a tutorial, reference material, and example
code.
<br>
## 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()`.
<br>
## 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<String>,
}
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<BlobstoreClient>;
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
```
<br>
## 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.
<br>
## 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.
<br>
## 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/demo.cc");
println!("cargo:rerun-if-changed=include/demo.h");
}
```
<br>
## 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
```
<br>
## 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\<T\> 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
<br>
## 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.
<table>
<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
<tr><td>String</td><td>rust::String</td><td></td></tr>
<tr><td>&str</td><td>rust::Str</td><td></td></tr>
<tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td>&mut [T]</td><td>rust::Slice<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
<tr><td>Box<T></td><td>rust::Box<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr<T></a></td><td>std::unique_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr<T></a></td><td>std::shared_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
<tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td>Vec<T></td><td>rust::Vec<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector<T></a></td><td>std::vector<T></td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
<tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
<tr><td>fn(T, U) -> V</td><td>rust::Fn<V(T, U)></td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
<tr><td>Result<T></td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
</table>
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.
<table>
<tr><th>name in Rust</th><th>name in C++</th></tr>
<tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr>
</table>
<br>
## 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.
<br>
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
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.
</sub>
================================================
FILE: book/.gitignore
================================================
/build/
/mdbook
/node_modules/
================================================
FILE: book/README.md
================================================
Published 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
================================================
FILE: book/book.toml
================================================
[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"
================================================
FILE: book/build.js
================================================
#!/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 = `\
<li class="part-title">\
<a href="https://github.com/dtolnay/cxx">\
<i class="fa fa-github"></i>\
https://github.com/dtolnay/cxx\
</a>\
</li>`;
const opengraph = `\
<meta property="og:image" content="https://cxx.rs/cxx.png" />\
<meta property="og:site_name" content="CXX" />\
<meta property="og:title" content="CXX — safe interop between Rust and C++" />\
<meta name="twitter:image:src" content="https://cxx.rs/cxx.png" />\
<meta name="twitter:site" content="@davidtolnay" />\
<meta name="twitter:card" content="summary" />\
<meta name="twitter:title" content="CXX — safe interop between Rust and C++" />`;
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('<span class="boring">'),
);
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 = '<span class="boring">' + line;
} else if (ellipsis[i]) {
line = '<span class="ellipsis">' + line;
}
if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) {
line = '</span>' + line;
}
if (i + 1 === highlightedLines.length && (boring[i] || ellipsis[i])) {
line = line + '</span>';
}
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 in ${path}`);
}
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);
================================================
FILE: book/build.sh
================================================
#!/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
================================================
FILE: book/css/cxx.css
================================================
: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;
}
================================================
FILE: book/diagram/.gitignore
================================================
/*.aux
/*.fdb_latexmk
/*.fls
/*.log
/*.pdf
/*.png
/*.svg
================================================
FILE: book/diagram/Makefile
================================================
overview.svg: overview.pdf
pdf2svg $< $@
overview.pdf: overview.tex
latexmk $<
overview.png: overview.svg
svgexport $< $@ 3x
================================================
FILE: book/diagram/overview.tex
================================================
\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}
================================================
FILE: book/eslint.config.mjs
================================================
import pluginJs from '@eslint/js';
/** @type {import('eslint').Linter.Config[]} */
export default [
{ ignores: ['build/*'] },
{ files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } },
pluginJs.configs.recommended,
];
================================================
FILE: book/package.json
================================================
{
"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
}
}
================================================
FILE: book/src/404.md
================================================
### Whoops, this page doesn’t exist :-(
<br>
<img src="https://www.rust-lang.org/static/images/ferris-error.png" alt="ferris" width="325">
================================================
FILE: book/src/SUMMARY.md
================================================
# 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\<T\>](binding/slice.md)
- [CxxString — std::string](binding/cxxstring.md)
- [Box\<T\> — rust::Box\<T\>](binding/box.md)
- [UniquePtr\<T\> — std::unique\_ptr\<T\>](binding/uniqueptr.md)
- [SharedPtr\<T\> — std::shared\_ptr\<T\>](binding/sharedptr.md)
- [Vec\<T\> — rust::Vec\<T\>](binding/vec.md)
- [CxxVector\<T\> — std::vector\<T\>](binding/cxxvector.md)
- [*mut T, *const T raw pointers](binding/rawptr.md)
- [Function pointers](binding/fn.md)
- [Result\<T\>](binding/result.md)
================================================
FILE: book/src/async.md
================================================
{{#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<Ret> 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.31/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<DoThingContext>, ret: Ret),
ctx: Box<DoThingContext>,
);
}
}
struct DoThingContext(oneshot::Sender<Ret>);
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<void(rust::Box<DoThingContext> ctx, Ret ret)> done,
rust::Box<DoThingContext> ctx) noexcept {
doThing(arg)
.then([done, ctx(std::move(ctx))](auto &&res) mutable {
(*done)(std::move(ctx), std::move(res));
});
}
```
## Streams
Through a multishot channel such as [`futures::channel::mpsc::unbounded`] in
place of the `futures::channel::oneshot` from above, C++ can send a stream of
values that become a `futures::Stream` in Rust.
[`futures::channel::mpsc::unbounded`]: https://docs.rs/futures/0.3.31/futures/channel/mpsc/fn.unbounded.html
In this case the callback function will take the channel sender by reference,
not as a Box. `rust::Fn<void(const StreamThingsContext &ctx, Item item)>`
================================================
FILE: book/src/attributes.md
================================================
{{#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.
## Self
Indicates the name of the type in which to place a [Rust associated function] or
[C++ static member function].
[Rust associated function]: extern-rust.md#associated-functions
[C++ static member function]: extern-c++.md#functions-and-member-functions
```rust,noplayground
#[cxx::bridge]
mod ffi {
extern "Rust" {
type RustType;
#[Self = "RustType"]
fn member(); // callable from C++ as `RustType::member()`
}
unsafe extern "C++" {
type CppType;
#[Self = "CppType"]
fn member(); // callable from Rust as `CppType::member()`
}
}
```
================================================
FILE: book/src/binding/box.md
================================================
{{#title rust::Box<T> — Rust ♡ C++}}
# rust::Box\<T\>
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...#include <type_traits>
...
...namespace rust {
template <typename T>
class Box final {
public:
using element_type = T;
using const_pointer =
typename std::add_pointer<typename std::add_const<T>::type>::type;
using pointer = typename std::add_pointer<T>::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 <typename... Fields>
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\<T\> does not support T being an opaque C++ type. You should use
[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](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<File>, fst: &str, snd: &str),
out: Box<File>,
);
}
}
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<void(rust::Box<File>, rust::Str, rust::Str)> callback,
rust::Box<File> out);
```
```cpp
// include/example.cc
#include "example/include/example.h"
void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
rust::Box<File> out) {
callback(std::move(out), "fearless", "concurrency");
}
```
================================================
FILE: book/src/binding/cxxstring.md
================================================
{{#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\<CxxString\>.
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<Json>;
fn getObject(self: &Json) -> &Object;
#[cxx_name = "at"]
fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json;
fn load_config() -> UniquePtr<Json>;
}
}
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 <map>
#include <memory>
#include <string>
#include <variant>
#include <vector>
class json final {
public:
static const json null;
using number = double;
using string = std::string;
using array = std::vector<json>;
using object = std::map<string, json>;
json() noexcept = default;
json(const json &) = default;
json(json &&) = default;
template <typename... T>
json(T &&...value) : value(std::forward<T>(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<std::monostate, number, string, array, object> value;
};
using object = json::object;
std::unique_ptr<json> load_config();
```
```cpp
// include/json.cc
#include "example/include/json.h"
#include <initializer_list>
#include <utility>
const json json::null{};
bool json::isNull() const { return std::holds_alternative<std::monostate>(value); }
bool json::isNumber() const { return std::holds_alternative<number>(value); }
bool json::isString() const { return std::holds_alternative<string>(value); }
bool json::isArray() const { return std::holds_alternative<array>(value); }
bool json::isObject() const { return std::holds_alternative<object>(value); }
json::number json::getNumber() const { return std::get<number>(value); }
const json::string &json::getString() const { return std::get<string>(value); }
const json::array &json::getArray() const { return std::get<array>(value); }
const json::object &json::getObject() const { return std::get<object>(value); }
std::unique_ptr<json> load_config() {
return std::make_unique<json>(
std::in_place_type<json::object>,
std::initializer_list<std::pair<const std::string, json>>{
{"name", "cxx-example"},
{"edition", 2021.},
{"repository", json::null}});
}
```
================================================
FILE: book/src/binding/cxxvector.md
================================================
{{#title std::vector<T> — Rust ♡ C++}}
# std::vector\<T\>
The Rust binding of std::vector\<T\> is called **[`CxxVector<T>`]**. See the
link for documentation of the Rust API.
[`CxxVector<T>`]: 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\<T\> or UniquePtr\<CxxVector\<T\>\>.
CxxVector\<T\> does not support T being an opaque Rust type. You should use a
Vec\<T\> (C++ rust::Vec\<T\>) instead for collections of opaque Rust types on
the language boundary.
## Example
This program involves Rust code converting a `CxxVector<CxxString>` (i.e.
`std::vector<std::string>`) into a Rust `Vec<String>`.
```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<CxxString>);
}
}
fn f(vec: &CxxVector<CxxString>) {
let vec: Vec<String> = 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 <string>
#include <vector>
int main() {
std::vector<std::string> vec{"fearless", "concurrency"};
f(vec);
}
```
================================================
FILE: book/src/binding/fn.md
================================================
{{#title Function pointers — Rust ♡ C++}}
# Function pointers
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...namespace rust {
template <typename Signature>
class Fn;
template <typename Ret, typename... Args>
class Fn<Ret(Args...)> 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.
================================================
FILE: book/src/binding/rawptr.md
================================================
{{#title *mut T, *const T — Rust ♡ C++}}
# *mut T, *const T
Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>]
where possible over raw pointers, but raw pointers are available too as an
unsafe fallback option.
[std::unique_ptr\<T\>]: 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 <iostream>
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<CString> = 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<CString> 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<Box<CStr>> up front, then simply casting
// from *mut [Box<CStr>] 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.
}
```
================================================
FILE: book/src/binding/result.md
================================================
{{#title Result<T> — Rust ♡ C++}}
# Result\<T\>
Result\<T\> 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\<T\>, leaf::result\<T\>, StatusOr\<T\>, etc then you'll need to
handle the translation of those to Rust Result\<T\> 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<String>;
fn fallible2() -> Result<()>;
}
}
fn fallible1(depth: usize) -> anyhow::Result<String> {
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<String>;
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 <typename Try, typename Fail>
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 <exception>
...
...namespace rust {
...namespace behavior {
...
template <typename Try, typename Fail>
static void trycatch(Try &&func, Fail &&fail) noexcept try {
func();
} catch (const std::exception &e) {
fail(e.what());
}
...
...} // namespace behavior
...} // namespace rust
```
================================================
FILE: book/src/binding/sharedptr.md
================================================
{{#title std::shared_ptr<T> — Rust ♡ C++}}
# std::shared\_ptr\<T\>
The Rust binding of std::shared\_ptr\<T\> is called **[`SharedPtr<T>`]**. See
the link for documentation of the Rust API.
[`SharedPtr<T>`]: https://docs.rs/cxx/*/cxx/struct.SharedPtr.html
### Restrictions:
SharedPtr\<T\> does not support T being an opaque Rust type. You should use a
Box\<T\> (C++ [rust::Box\<T\>](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<Object>;
}
}
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<Object>.
// 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 <memory>
class Object {
public:
Object();
~Object();
};
std::shared_ptr<Object> create_shared_ptr();
```
```cpp
// src/example.cc
#include "example/include/example.h"
#include <iostream>
Object::Object() { std::cout << "construct Object" << std::endl; }
Object::~Object() { std::cout << "~Object" << std::endl; }
std::shared_ptr<Object> create_shared_ptr() {
return std::make_shared<Object>();
}
```
================================================
FILE: book/src/binding/slice.md
================================================
{{#title rust::Slice<T> — Rust ♡ C++}}
# rust::Slice\<const T\>, rust::Slice\<T\>
- Rust `&[T]` is written `rust::Slice<const T>` in C++
- Rust `&mut [T]` is written `rust::Slice<T>` in C++
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...#include <iterator>
...#include <type_traits>
...
...namespace rust {
template <typename T>
class Slice final {
public:
using value_type = T;
Slice() noexcept;
Slice(const Slice<T> &) noexcept;
Slice(T *, size_t count) noexcept;
template <typename C>
explicit Slice(C &c) : Slice(c.data(), c.size());
Slice &operator=(Slice<T> &&) & noexcept;
Slice &operator=(const Slice<T> &) & noexcept
requires std::is_const_v<T>;
T *data() const noexcept;
size_t size() 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 <typename T>
...class Slice<T>::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\<const T\> is copy-assignable, not rust::Slice\<T\>. (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<usize> {
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 <iostream>
#include <iterator>
#include <string>
#include <vector>
int main() {
// Read json from stdin.
std::istreambuf_iterator<char> begin{std::cin}, end;
std::vector<unsigned char> input{begin, end};
rust::Slice<const uint8_t> 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"
}
```
================================================
FILE: book/src/binding/str.md
================================================
{{#title rust::Str — Rust ♡ C++}}
# rust::Str
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...#include <iosfwd>
...#include <string>
...
...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;
#if __cplusplus >= 201703L
explicit operator std::string_view() const;
#endif
// Note: no null terminator.
const char *data() const noexcept;
// Length in bytes.
size_t size() const noexcept;
// Length in bytes, same as size().
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 <iostream>
void c(rust::Str greeting) {
std::cout << greeting << std::endl;
r("hello from C++");
}
```
================================================
FILE: book/src/binding/string.md
================================================
{{#title rust::String — Rust ♡ C++}}
# rust::String
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...#include <iosfwd>
...#include <string>
...
...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;
// Length in bytes.
size_t size() const noexcept;
// Length in bytes, same as size().
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);
}
```
================================================
FILE: book/src/binding/uniqueptr.md
================================================
{{#title std::unique_ptr<T> — Rust ♡ C++}}
# std::unique\_ptr\<T\>
The Rust binding of std::unique\_ptr\<T\> is called **[`UniquePtr<T>`]**. See
the link for documentation of the Rust API.
[`UniquePtr<T>`]: https://docs.rs/cxx/*/cxx/struct.UniquePtr.html
### Restrictions:
Only `std::unique_ptr<T, std::default_delete<T>>` is currently supported. Custom
deleters may be supported in the future.
UniquePtr\<T\> does not support T being an opaque Rust type. You should use a
Box\<T\> (C++ [rust::Box\<T\>](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<BlobstoreClient>;
// ...
}
}
fn main() {
let client = ffi::new_blobstore_client();
// ...
}
```
```cpp
// include/blobstore.h
#pragma once
#include <memory>
class BlobstoreClient;
std::unique_ptr<BlobstoreClient> new_blobstore_client();
```
```cpp
// src/blobstore.cc
#include "example/include/blobstore.h"
std::unique_ptr<BlobstoreClient> new_blobstore_client() {
return std::make_unique<BlobstoreClient>();
}
```
================================================
FILE: book/src/binding/vec.md
================================================
{{#title rust::Vec<T> — Rust ♡ C++}}
# rust::Vec\<T\>
### Public API:
```cpp,hidelines=...
// rust/cxx.h
...
...#include <initializer_list>
...#include <iterator>
...#include <type_traits>
...
...namespace rust {
template <typename T>
class Vec final {
public:
using value_type = T;
Vec() noexcept;
Vec(std::initializer_list<T>);
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 <typename... Args>
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 <typename T>
...class Vec<T>::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 <typename T>
...class Vec<T>::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\<T\> does not support T being an opaque C++ type. You should use
CxxVector\<T\> (C++ std::vector\<T\>) 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<Shared>);
}
}
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<Shared> elements);
```
```cpp
// src/example.cc
#include "example/include/example.h"
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <vector>
void f(rust::Vec<Shared> v) {
for (auto shared : v) {
std::cout << shared.v << std::endl;
}
// Copy the elements to a C++ std::vector using STL algorithm.
std::vector<Shared> stdv;
std::copy(v.begin(), v.end(), std::back_inserter(stdv));
assert(v.size() == stdv.size());
}
```
================================================
FILE: book/src/bindings.md
================================================
{{#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.
<br>
<table>
<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
<tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
<tr><td style="padding:3px 6px">&str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
<tr><td style="padding:3px 6px">&[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice<const T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px">&mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
<tr><td style="padding:3px 6px">Box<T></td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr<T></a></b></td><td style="padding:3px 6px">std::unique_ptr<T></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/sharedptr.md">SharedPtr<T></a></b></td><td style="padding:3px 6px">std::shared_ptr<T></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array<T, N></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px">Vec<T></td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector<T></a></b></td><td style="padding:3px 6px">std::vector<T></td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*mut T, *const T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
<tr><td style="padding:3px 6px">fn(T, U) -> V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn<V(T, U)></a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
<tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result<T></a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
</table>
<br>
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.
<br>
<table>
<tr><th>name in Rust</th><th>name in C++</th></tr>
<tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr>
</table>
================================================
FILE: book/src/build/bazel.md
================================================
{{#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
```
<div class="warning">
**Important:** The version number of `cxxbridge-cmd` used for the C++ side of
the binding must always be identical to the version number of `cxx` used for the
Rust side. You must use some form of lockfile or version pinning to ensure that
this is the case.
</div>
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"],
)
```
================================================
FILE: book/src/build/cargo.md
================================================
{{#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/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
<br><br><br>
# 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");
}
```
<br>
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");
}
```
================================================
FILE: book/src/build/cmake.md
================================================
{{#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.
<br>
---
- **<https://github.com/XiangpengHao/cxx-cmake-example>**
- Supports cross-language link time optimization (LTO)
---
- **<https://github.com/david-cattermole/cxx-demo-example>**
- Includes a cbindgen component
- Tested on Windows 10 with MSVC, and on Linux
---
- **<https://github.com/trondhe/rusty_cmake>**
- Alias target that can be linked into a C++ project
- Tested on Windows 10 with GNU target, and on Linux
---
- **<https://github.com/geekbrother/cxx-corrosion-cmake>**
- 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
---
- **<https://github.com/paandahl/cpp-with-rust>**
- Same blobstore example as the official demo, but inverted languages
- Minimal CMake configuration
- Tested on Linux, macOS, and Windows
---
================================================
FILE: book/src/build/other.md
================================================
{{#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 overlay 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.
<div class="warning">
**Important:** The Rust side and C++ side of a binding must always be created
using the same release of CXX. If using `cxxbridge-cmd` for the C++ side, the
version number of `cxxbridge-cmd` must be identical to the version number of
`cxx` used for the Rust side. If using `cxx-gen` for the C++ side, its patch
number must be identical to the patch number of `cxx`.
</div>
[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 LLD, 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
<directory>` and `-l<library>` 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
================================================
FILE: book/src/building.md
================================================
{{#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.
================================================
FILE: book/src/concepts.md
================================================
{{#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<String>,
# }
#
# 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<BlobstoreClient>;
# 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.
<br><br>
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.
<br>
================================================
FILE: book/src/context.md
================================================
{{#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\<T\> 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.
================================================
FILE: book/src/extern-c++.md
================================================
{{#title extern "C++" — Rust ♡ C++}}
# extern "C++"
```rust,noplayground
#[cxx::bridge]
mod ffi {
extern "C++" {
include!("path/to/header.h");
include!("path/to/another.h");
...
}
}
```
The `extern "C++"` section of a CXX bridge declares C++ types and signatures to
be made available to Rust, and gives the paths of the header(s) which contain
the corresponding C++ declarations.
A bridge module may contain zero or more extern "C++" blocks.
## Opaque C++ types
Type defined in C++ that are made available to Rust, but only behind an
indirection.
```rust,noplayground
# #[cxx::bridge]
# mod ffi {
extern "C++" {
# include!("path/to/header.h");
#
type MyType;
type MyOtherType;
}
# }
```
For example in the ***[Tutorial](tutorial.md)*** we saw `BlobstoreClient`
implemented as an opaque C++ type. The blobstore client was created in C++ and
returned to Rust by way of a UniquePtr.
**Mutability:** Unlike extern Rust types and shared types, an extern C++ type is
not permitted to be passed by plain mutable reference `&mut MyType` across the
FFI bridge. For mutation support, the bridge is required to use `Pin<&mut
MyType>`. 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; any signature with a `#[Self = "…"]` attribute is
interpreted as a C++ static member function and exposed to Rust as an associated
function.
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<TypeContainingBorrow> 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<TypeContainingBorrow<'a>>;
// or with lifetime elision:
fn create(res: &Resource) -> SharedPtr<TypeContainingBorrow>;
}
}
```
## 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<Demo>;
}
}
```
```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<B> using a type B defined within the same
// bridge, and automatically emits the right template instantiations
// corresponding to std::unique_ptr<B>.
fn get_b() -> UniquePtr<B>;
}
}
#[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<A>
// 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<A>, an explicit instantiation of the template
// needs to be requested in one module or the other.
fn get_a() -> UniquePtr<A>;
}
}
```
You can request a specific template instantiation at a particular location in
the Rust crate hierarchy by writing `impl UniquePtr<A> {}` inside of the bridge
module which defines `A` but does not otherwise contain any use of
`UniquePtr<A>`.
```rust,noplayground
#[cxx::bridge]
mod ffi1 {
extern "C++" {
include!("path/to/header.h");
type A;
type B;
fn get_b() -> UniquePtr<B>;
}
impl UniquePtr<A> {} // explicit instantiation
}
```
================================================
FILE: book/src/extern-rust.md
================================================
{{#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\<T\>](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<MyType>;
}
}
struct MyType(i32);
fn f() -> Box<MyType> {
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);
}
# }
```
## Associated functions
A function with a `Self` attribute is interpreted as a Rust associated function
and exposed to C++ as a static member function. These must not have a `self`
argument.
In the following example, the `builder` associated function is callable as
`MyType::builder()` from both Rust and C++.
```rust,noplayground
#[cxx::bridge]
mod ffi {
extern "Rust" {
type MyType;
type MyTypeBuilder;
#[Self = "MyType"]
fn builder() -> Box<MyTypeBuilder>;
}
}
pub struct MyType;
pub struct MyTypeBuilder;
impl MyType {
pub fn builder() -> Box<MyTypeBuilder> {
...
}
}
```
## 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.
================================================
FILE: book/src/index.md
================================================
<div class="badges">
<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" alt="docs-rs" height="28" class="badge"></a>
</div>
# 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.
<div style="height:190px;width=718px;padding:44px 0 44px">
<object type="image/svg+xml" data="overview.svg"></object>
</div>
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<BlobstoreClient>;
fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
}
}
```
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 <https://github.com/dtolnay/cxx>. 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".
<br>
***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.*
================================================
FILE: book/src/reference.md
================================================
{{#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.
================================================
FILE: book/src/shared.md
================================================
{{#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<PlayingCard>;
fn sort(cards: &mut Vec<PlayingCard>);
}
}
```
## 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<const rust::Str> 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`
- `BitAnd` (enums only)
- `BitOr` (enums only)
- `BitXor` (enums only)
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<T>`][hash] in C++
- `PartialEq` produces `operator==` and `operator!=`
- `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=`
- `BitAnd` produces `operator&`
- `BitOr` produces `operator|`
- `BitXor` produces `operator^`
[hash]: https://en.cppreference.com/w/cpp/utility/hash
## Alignment
The attribute `repr(align(…))` sets a minimum required alignment for a shared
struct. The alignment value must be a power of two in the range 2<sup>0</sup> to
2<sup>13</sup>.
This turns into an [`alignas`] specifier in C++.
[`alignas`]: https://en.cppreference.com/w/cpp/language/alignas.html
```rust,noplayground
#[cxx::bridge]
mod ffi {
#[repr(align(4))]
struct ExampleStruct {
b: [u8; 4],
}
}
```
================================================
FILE: book/src/tutorial.md
================================================
{{#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
<https://github.com/dtolnay/cxx>. 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<BlobstoreClient>`
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<BlobstoreClient>;
}
}
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 <memory>
class BlobstoreClient {
public:
BlobstoreClient();
};
std::unique_ptr<BlobstoreClient> new_blobstore_client();
```
```cpp
// src/blobstore.cc
#include "cxx-demo/include/blobstore.h"
BlobstoreClient::BlobstoreClient() {}
std::unique_ptr<BlobstoreClient> new_blobstore_client() {
return std::unique_ptr<BlobstoreClient>(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/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<BlobstoreClient>;
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<BlobstoreClient>;
# fn put(&self, parts: &mut MultiBuf) -> u64;
# }
# }
// An iterator over contiguous chunks of a discontiguous file object. Toy
// implementation uses a Vec<Vec<u8>> 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<Vec<u8>>,
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 <memory>
...
struct MultiBuf;
class BlobstoreClient {
public:
BlobstoreClient();
uint64_t put(MultiBuf &buf) const;
};
...
...std::unique_ptr<BlobstoreClient> 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 <functional>
#include <string>
...
...BlobstoreClient::BlobstoreClient() {}
...
...std::unique_ptr<BlobstoreClient> new_blobstore_client() {
... return std::make_unique<BlobstoreClient>();
...}
// 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<const char *>(chunk.data()), chunk.size());
}
// Pretend we did something useful to persist the data.
auto blobid = std::hash<std::string>{}(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<BlobstoreClient>;
# fn put(&self, parts: &mut MultiBuf) -> u64;
# }
# }
#
# pub struct MultiBuf {
# chunks: Vec<Vec<u8>>,
# 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<T>` 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<String>,
}
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<BlobstoreClient>;
# 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<Vec<u8>>,
# 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 <memory>
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> impl;
};
...
...std::unique_ptr<BlobstoreClient> new_blobstore_client();
```
```cpp,hidelines=...
// src/blobstore.cc
#include "cxx-demo/include/blobstore.h"
#include "cxx-demo/src/main.rs.h"
#include <algorithm>
#include <functional>
#include <set>
#include <string>
#include <unordered_map>
// 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<std::string> tags;
};
std::unordered_map<uint64_t, Blob> 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<const char *>(chunk.data()), chunk.size());
... }
...
... // Insert into map and provide caller the handle.
... auto blobid = std::hash<std::string>{}(contents);
... impl->blobs[blobid] = {std::move(contents), {}};
... return blobid;
...}
// Add tag to an existing blo
gitextract_dh2rnm1j/
├── .bazelignore
├── .bazelrc
├── .bcr/
│ ├── README.md
│ ├── config.yml
│ ├── metadata.template.json
│ ├── presubmit.yml
│ └── source.template.json
├── .buckconfig
├── .buckroot
├── .clang-format
├── .clang-tidy
├── .devcontainer/
│ ├── Dockerfile
│ ├── README.md
│ ├── build.Dockerfile
│ └── devcontainer.json
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── buck2.yml
│ ├── ci.yml
│ ├── install.yml
│ ├── release.yml
│ └── site.yml
├── .gitignore
├── .vscode/
│ ├── README.md
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .watchmanconfig
├── BUCK
├── BUILD.bazel
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── MODULE.bazel
├── README.md
├── book/
│ ├── .gitignore
│ ├── README.md
│ ├── book.toml
│ ├── build.js
│ ├── build.sh
│ ├── css/
│ │ └── cxx.css
│ ├── diagram/
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ └── overview.tex
│ ├── eslint.config.mjs
│ ├── package.json
│ ├── src/
│ │ ├── 404.md
│ │ ├── SUMMARY.md
│ │ ├── async.md
│ │ ├── attributes.md
│ │ ├── binding/
│ │ │ ├── box.md
│ │ │ ├── cxxstring.md
│ │ │ ├── cxxvector.md
│ │ │ ├── fn.md
│ │ │ ├── rawptr.md
│ │ │ ├── result.md
│ │ │ ├── sharedptr.md
│ │ │ ├── slice.md
│ │ │ ├── str.md
│ │ │ ├── string.md
│ │ │ ├── uniqueptr.md
│ │ │ └── vec.md
│ │ ├── bindings.md
│ │ ├── build/
│ │ │ ├── bazel.md
│ │ │ ├── cargo.md
│ │ │ ├── cmake.md
│ │ │ └── other.md
│ │ ├── building.md
│ │ ├── concepts.md
│ │ ├── context.md
│ │ ├── extern-c++.md
│ │ ├── extern-rust.md
│ │ ├── index.md
│ │ ├── reference.md
│ │ ├── shared.md
│ │ └── tutorial.md
│ └── theme/
│ └── head.hbs
├── build.rs
├── compile_flags.txt
├── demo/
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── Cargo.toml
│ ├── build.rs
│ ├── include/
│ │ └── blobstore.h
│ └── src/
│ ├── blobstore.cc
│ └── main.rs
├── flags/
│ ├── Cargo.toml
│ └── src/
│ ├── impl.rs
│ └── lib.rs
├── gen/
│ ├── README.md
│ ├── build/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ └── src/
│ │ ├── cargo.rs
│ │ ├── cfg.rs
│ │ ├── deps.rs
│ │ ├── error.rs
│ │ ├── intern.rs
│ │ ├── lib.rs
│ │ ├── out.rs
│ │ ├── paths.rs
│ │ ├── target.rs
│ │ └── vec.rs
│ ├── cmd/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ └── src/
│ │ ├── app.rs
│ │ ├── cfg.rs
│ │ ├── main.rs
│ │ ├── output.rs
│ │ └── test.rs
│ ├── lib/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── src/
│ │ │ ├── error.rs
│ │ │ └── lib.rs
│ │ └── tests/
│ │ └── test.rs
│ └── src/
│ ├── block.rs
│ ├── builtin/
│ │ ├── alignmax.h
│ │ ├── deleter_if.h
│ │ ├── destroy.h
│ │ ├── friend_impl.h
│ │ ├── manually_drop.h
│ │ ├── maybe_uninit.h
│ │ ├── maybe_uninit_detail.h
│ │ ├── ptr_len.h
│ │ ├── relocatable_or_array.h
│ │ ├── repr_fat.h
│ │ ├── rust_error.h
│ │ ├── rust_slice_uninit.h
│ │ ├── rust_str_uninit.h
│ │ ├── shared_ptr.h
│ │ ├── trycatch.h
│ │ ├── trycatch_detail.h
│ │ └── vector.h
│ ├── builtin.rs
│ ├── cfg.rs
│ ├── check.rs
│ ├── error.rs
│ ├── file.rs
│ ├── fs.rs
│ ├── guard.rs
│ ├── ifndef.rs
│ ├── include.rs
│ ├── mod.rs
│ ├── names.rs
│ ├── namespace.rs
│ ├── nested.rs
│ ├── out.rs
│ ├── pragma.rs
│ └── write.rs
├── include/
│ └── cxx.h
├── macro/
│ ├── Cargo.toml
│ ├── README.md
│ ├── build.rs
│ └── src/
│ ├── attrs.rs
│ ├── cfg.rs
│ ├── derive.rs
│ ├── expand.rs
│ ├── generics.rs
│ ├── lib.rs
│ ├── tests.rs
│ ├── tokens.rs
│ └── type_id.rs
├── reindeer.toml
├── rust-toolchain.toml
├── src/
│ ├── cxx.cc
│ ├── cxx_string.rs
│ ├── cxx_vector.rs
│ ├── exception.rs
│ ├── extern_type.rs
│ ├── fmt.rs
│ ├── function.rs
│ ├── hash.rs
│ ├── lib.rs
│ ├── lossy.rs
│ ├── macros/
│ │ ├── assert.rs
│ │ └── mod.rs
│ ├── memory.rs
│ ├── opaque.rs
│ ├── result.rs
│ ├── rust_slice.rs
│ ├── rust_str.rs
│ ├── rust_string.rs
│ ├── rust_type.rs
│ ├── rust_vec.rs
│ ├── shared_ptr.rs
│ ├── symbols/
│ │ ├── exception.rs
│ │ ├── mod.rs
│ │ ├── rust_slice.rs
│ │ ├── rust_str.rs
│ │ ├── rust_string.rs
│ │ └── rust_vec.rs
│ ├── type_id.rs
│ ├── unique_ptr.rs
│ ├── unwind.rs
│ ├── vector.rs
│ └── weak_ptr.rs
├── syntax/
│ ├── atom.rs
│ ├── attrs.rs
│ ├── cfg.rs
│ ├── check.rs
│ ├── derive.rs
│ ├── discriminant.rs
│ ├── doc.rs
│ ├── error.rs
│ ├── file.rs
│ ├── ident.rs
│ ├── impls.rs
│ ├── improper.rs
│ ├── instantiate.rs
│ ├── mangle.rs
│ ├── map.rs
│ ├── message.rs
│ ├── mod.rs
│ ├── names.rs
│ ├── namespace.rs
│ ├── parse.rs
│ ├── pod.rs
│ ├── primitive.rs
│ ├── qualified.rs
│ ├── query.rs
│ ├── report.rs
│ ├── repr.rs
│ ├── resolve.rs
│ ├── set.rs
│ ├── signature.rs
│ ├── symbol.rs
│ ├── tokens.rs
│ ├── toposort.rs
│ ├── trivial.rs
│ ├── types.rs
│ ├── unpin.rs
│ └── visit.rs
├── tests/
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── README.md
│ ├── compiletest.rs
│ ├── cpp_compile/
│ │ ├── mod.rs
│ │ └── smoke_test.rs
│ ├── cpp_ui_tests.rs
│ ├── cxx_gen.rs
│ ├── cxx_string.rs
│ ├── cxx_vector.rs
│ ├── ffi/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── cast.rs
│ │ ├── lib.rs
│ │ ├── module.rs
│ │ ├── tests.cc
│ │ └── tests.h
│ ├── test.rs
│ ├── ui/
│ │ ├── array_len_expr.rs
│ │ ├── array_len_expr.stderr
│ │ ├── array_len_suffix.rs
│ │ ├── array_len_suffix.stderr
│ │ ├── async_fn.rs
│ │ ├── async_fn.stderr
│ │ ├── bad_explicit_impl.rs
│ │ ├── bad_explicit_impl.stderr
│ │ ├── by_value_not_supported.rs
│ │ ├── by_value_not_supported.stderr
│ │ ├── const_fn.rs
│ │ ├── const_fn.stderr
│ │ ├── cxx_crate_name_qualified_cxx_string.rs
│ │ ├── cxx_crate_name_qualified_cxx_string.stderr
│ │ ├── data_enums.rs
│ │ ├── data_enums.stderr
│ │ ├── deny_elided_lifetimes.rs
│ │ ├── deny_elided_lifetimes.stderr
│ │ ├── deny_missing_docs.rs
│ │ ├── deny_missing_docs.stderr
│ │ ├── derive_bit_struct.rs
│ │ ├── derive_bit_struct.stderr
│ │ ├── derive_default.rs
│ │ ├── derive_default.stderr
│ │ ├── derive_duplicate.rs
│ │ ├── derive_duplicate.stderr
│ │ ├── derive_noncopy.rs
│ │ ├── derive_noncopy.stderr
│ │ ├── drop_shared.rs
│ │ ├── drop_shared.stderr
│ │ ├── duplicate_method.rs
│ │ ├── duplicate_method.stderr
│ │ ├── empty_enum.rs
│ │ ├── empty_enum.stderr
│ │ ├── empty_struct.rs
│ │ ├── empty_struct.stderr
│ │ ├── enum_assoc.rs
│ │ ├── enum_assoc.stderr
│ │ ├── enum_inconsistent.rs
│ │ ├── enum_inconsistent.stderr
│ │ ├── enum_match_without_wildcard.rs
│ │ ├── enum_match_without_wildcard.stderr
│ │ ├── enum_out_of_bounds.rs
│ │ ├── enum_out_of_bounds.stderr
│ │ ├── enum_overflows.rs
│ │ ├── enum_overflows.stderr
│ │ ├── enum_receiver.rs
│ │ ├── enum_receiver.stderr
│ │ ├── enum_unsatisfiable.rs
│ │ ├── enum_unsatisfiable.stderr
│ │ ├── expected_named.rs
│ │ ├── expected_named.stderr
│ │ ├── explicit_impl_of_bad_unique_ptr.rs
│ │ ├── explicit_impl_of_bad_unique_ptr.stderr
│ │ ├── extern_fn_abi.rs
│ │ ├── extern_fn_abi.stderr
│ │ ├── extern_shared_struct.rs
│ │ ├── extern_shared_struct.stderr
│ │ ├── extern_type_bound.rs
│ │ ├── extern_type_bound.stderr
│ │ ├── extern_type_generic.rs
│ │ ├── extern_type_generic.stderr
│ │ ├── extern_type_lifetime_bound.rs
│ │ ├── extern_type_lifetime_bound.stderr
│ │ ├── fallible_fnptr.rs
│ │ ├── fallible_fnptr.stderr
│ │ ├── function_with_body.rs
│ │ ├── function_with_body.stderr
│ │ ├── generic_enum.rs
│ │ ├── generic_enum.stderr
│ │ ├── impl_trait_for_type.rs
│ │ ├── impl_trait_for_type.stderr
│ │ ├── include.rs
│ │ ├── include.stderr
│ │ ├── lifetime_extern_cxx.rs
│ │ ├── lifetime_extern_cxx.stderr
│ │ ├── lifetime_extern_rust.rs
│ │ ├── lifetime_extern_rust.stderr
│ │ ├── missing_unsafe.rs
│ │ ├── missing_unsafe.stderr
│ │ ├── multiple_parse_error.rs
│ │ ├── multiple_parse_error.stderr
│ │ ├── mut_return.rs
│ │ ├── mut_return.stderr
│ │ ├── non_integer_discriminant_enum.rs
│ │ ├── non_integer_discriminant_enum.stderr
│ │ ├── nonempty_impl_block.rs
│ │ ├── nonempty_impl_block.stderr
│ │ ├── nonlocal_rust_type.rs
│ │ ├── nonlocal_rust_type.stderr
│ │ ├── opaque_autotraits.rs
│ │ ├── opaque_autotraits.stderr
│ │ ├── opaque_not_sized.rs
│ │ ├── opaque_not_sized.stderr
│ │ ├── pin_mut_alias.rs
│ │ ├── pin_mut_alias.stderr
│ │ ├── pin_mut_opaque.rs
│ │ ├── pin_mut_opaque.stderr
│ │ ├── ptr_in_fnptr.rs
│ │ ├── ptr_in_fnptr.stderr
│ │ ├── ptr_missing_unsafe.rs
│ │ ├── ptr_missing_unsafe.stderr
│ │ ├── ptr_no_const_mut.rs
│ │ ├── ptr_no_const_mut.stderr
│ │ ├── ptr_unsupported.rs
│ │ ├── ptr_unsupported.stderr
│ │ ├── raw_ident_namespace.rs
│ │ ├── raw_ident_namespace.stderr
│ │ ├── reference_to_reference.rs
│ │ ├── reference_to_reference.stderr
│ │ ├── repr_align_suffixed.rs
│ │ ├── repr_align_suffixed.stderr
│ │ ├── repr_unsupported.rs
│ │ ├── repr_unsupported.stderr
│ │ ├── reserved_lifetime.rs
│ │ ├── reserved_lifetime.stderr
│ │ ├── reserved_name.rs
│ │ ├── reserved_name.stderr
│ │ ├── result_no_display.rs
│ │ ├── result_no_display.stderr
│ │ ├── root_namespace.rs
│ │ ├── root_namespace.stderr
│ │ ├── rust_pinned.rs
│ │ ├── rust_pinned.stderr
│ │ ├── self_lifetimes.rs
│ │ ├── self_lifetimes.stderr
│ │ ├── self_type_and_receiver.rs
│ │ ├── self_type_and_receiver.stderr
│ │ ├── slice_of_pinned.rs
│ │ ├── slice_of_pinned.stderr
│ │ ├── slice_of_type_alias.rs
│ │ ├── slice_of_type_alias.stderr
│ │ ├── slice_unsupported.rs
│ │ ├── slice_unsupported.stderr
│ │ ├── struct_align.rs
│ │ ├── struct_align.stderr
│ │ ├── struct_cycle.rs
│ │ ├── struct_cycle.stderr
│ │ ├── type_alias_rust.rs
│ │ ├── type_alias_rust.stderr
│ │ ├── undeclared_lifetime.rs
│ │ ├── undeclared_lifetime.stderr
│ │ ├── unique_ptr_as_mut.rs
│ │ ├── unique_ptr_as_mut.stderr
│ │ ├── unique_ptr_to_opaque.rs
│ │ ├── unique_ptr_to_opaque.stderr
│ │ ├── unique_ptr_twice.rs
│ │ ├── unique_ptr_twice.stderr
│ │ ├── unnamed_receiver.rs
│ │ ├── unnamed_receiver.stderr
│ │ ├── unpin_impl.rs
│ │ ├── unpin_impl.stderr
│ │ ├── unrecognized_receiver.rs
│ │ ├── unrecognized_receiver.stderr
│ │ ├── unsupported_elided.rs
│ │ ├── unsupported_elided.stderr
│ │ ├── vec_opaque.rs
│ │ ├── vec_opaque.stderr
│ │ ├── vector_autotraits.rs
│ │ ├── vector_autotraits.stderr
│ │ ├── wrong_type_id.rs
│ │ └── wrong_type_id.stderr
│ └── unique_ptr.rs
├── third-party/
│ ├── .cargo/
│ │ └── .gitignore
│ ├── .gitignore
│ ├── BUCK
│ ├── BUILD.bazel
│ ├── Cargo.toml
│ ├── bazel/
│ │ ├── BUILD.anstyle-1.0.13.bazel
│ │ ├── BUILD.bazel
│ │ ├── BUILD.cc-1.2.53.bazel
│ │ ├── BUILD.clap-4.5.54.bazel
│ │ ├── BUILD.clap_builder-4.5.54.bazel
│ │ ├── BUILD.clap_lex-0.7.7.bazel
│ │ ├── BUILD.codespan-reporting-0.13.1.bazel
│ │ ├── BUILD.equivalent-1.0.2.bazel
│ │ ├── BUILD.find-msvc-tools-0.1.8.bazel
│ │ ├── BUILD.foldhash-0.2.0.bazel
│ │ ├── BUILD.hashbrown-0.16.1.bazel
│ │ ├── BUILD.indexmap-2.13.0.bazel
│ │ ├── BUILD.proc-macro2-1.0.105.bazel
│ │ ├── BUILD.quote-1.0.43.bazel
│ │ ├── BUILD.rustversion-1.0.22.bazel
│ │ ├── BUILD.scratch-1.0.9.bazel
│ │ ├── BUILD.serde-1.0.228.bazel
│ │ ├── BUILD.serde_core-1.0.228.bazel
│ │ ├── BUILD.serde_derive-1.0.228.bazel
│ │ ├── BUILD.shlex-1.3.0.bazel
│ │ ├── BUILD.syn-2.0.114.bazel
│ │ ├── BUILD.termcolor-1.4.1.bazel
│ │ ├── BUILD.unicode-ident-1.0.22.bazel
│ │ ├── BUILD.unicode-width-0.2.2.bazel
│ │ ├── BUILD.winapi-util-0.1.11.bazel
│ │ ├── BUILD.windows-link-0.2.1.bazel
│ │ ├── BUILD.windows-sys-0.61.2.bazel
│ │ ├── alias_rules.bzl
│ │ ├── crates.bzl
│ │ └── defs.bzl
│ ├── fixups/
│ │ ├── proc-macro2/
│ │ │ └── fixups.toml
│ │ ├── quote/
│ │ │ └── fixups.toml
│ │ ├── rustversion/
│ │ │ └── fixups.toml
│ │ ├── scratch/
│ │ │ └── fixups.toml
│ │ ├── serde/
│ │ │ └── fixups.toml
│ │ ├── serde_core/
│ │ │ └── fixups.toml
│ │ ├── serde_derive/
│ │ │ └── fixups.toml
│ │ ├── winapi-util/
│ │ │ └── fixups.toml
│ │ └── windows-sys/
│ │ └── fixups.toml
│ └── src/
│ └── lib.rs
└── tools/
├── bazel/
│ ├── BUILD.bazel
│ ├── extension.bzl
│ └── rust_cxx_bridge.bzl
├── buck/
│ ├── rust_cxx_bridge.bzl
│ └── toolchains/
│ └── BUCK
└── cargo/
└── build.rs
SYMBOL INDEX (1963 symbols across 226 files)
FILE: build.rs
function main (line 7) | fn main() {
type RustVersion (line 55) | struct RustVersion {
function rustc_version (line 60) | fn rustc_version() -> Option<RustVersion> {
FILE: demo/build.rs
function main (line 1) | fn main() {
FILE: demo/include/blobstore.h
function namespace (line 5) | namespace org {
FILE: demo/src/blobstore.cc
type org (line 9) | namespace org {
type blobstore (line 10) | namespace blobstore {
class BlobstoreClient::impl (line 16) | class BlobstoreClient::impl {
class BlobstoreClient::impl (line 25) | class BlobstoreClient::impl
function BlobMetadata (line 55) | BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
function new_blobstore_client (line 66) | std::unique_ptr<BlobstoreClient> new_blobstore_client() {
FILE: demo/src/main.rs
type BlobMetadata (line 4) | struct BlobMetadata {
function next_chunk (line 13) | fn next_chunk(buf: &mut MultiBuf) -> &[u8];
function new_blobstore_client (line 22) | fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
function put (line 23) | fn put(&self, parts: &mut MultiBuf) -> u64;
function tag (line 24) | fn tag(&self, blobid: u64, tag: &str);
function metadata (line 25) | fn metadata(&self, blobid: u64) -> BlobMetadata;
type MultiBuf (line 34) | pub struct MultiBuf {
function next_chunk (line 38) | pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
function main (line 44) | fn main() {
FILE: flags/src/impl.rs
constant STD (line 2) | pub const STD: &str = {
FILE: gen/build/src/cargo.rs
type CargoEnv (line 11) | struct CargoEnv {
method load (line 48) | fn load() -> Self {
type CargoEnvCfgEvaluator (line 16) | pub(super) struct CargoEnvCfgEvaluator;
method eval (line 19) | fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult {
type Name (line 73) | struct Name(String);
method borrow (line 105) | fn borrow(&self) -> &Lookup {
method cmp (line 76) | fn cmp(&self, rhs: &Self) -> Ordering {
method partial_cmp (line 82) | fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
method eq (line 90) | fn eq(&self, rhs: &Self) -> bool {
type Lookup (line 96) | struct Lookup(str);
method new (line 99) | fn new(name: &str) -> &Self {
method cmp (line 111) | fn cmp(&self, rhs: &Self) -> Ordering {
method partial_cmp (line 120) | fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
method eq (line 128) | fn eq(&self, rhs: &Self) -> bool {
type CaseAgnosticByte (line 136) | struct CaseAgnosticByte(u8);
method cmp (line 139) | fn cmp(&self, rhs: &Self) -> Ordering {
method partial_cmp (line 145) | fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
method eq (line 153) | fn eq(&self, rhs: &Self) -> bool {
FILE: gen/build/src/cfg.rs
type Cfg (line 6) | pub struct Cfg<'a> {
method fmt (line 319) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
type CurrentCfg (line 353) | struct CurrentCfg {
method default (line 362) | fn default() -> Self {
function current (line 380) | fn current() -> &'static RwLock<CurrentCfg> {
type Handle (line 402) | struct Handle(*const Cfg<'static>);
function current (line 405) | fn current() -> super::Cfg<'a> {
function handle (line 422) | const fn handle(self: &Cfg<'a>) -> Handle {
type Cfg (line 429) | pub enum Cfg<'a> {
method fmt (line 435) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
type Target (line 445) | type Target = super::Cfg<'a>;
method deref (line 447) | fn deref(&self) -> &Self::Target {
method deref_mut (line 463) | fn deref_mut(&mut self) -> &mut Self::Target {
method drop (line 476) | fn drop(&mut self) {
FILE: gen/build/src/deps.rs
type Crate (line 7) | pub(crate) struct Crate {
method print_to_cargo (line 19) | pub(crate) fn print_to_cargo(&self) {
type HeaderDir (line 13) | pub(crate) struct HeaderDir {
function direct_dependencies (line 41) | pub(crate) fn direct_dependencies() -> Vec<Crate> {
FILE: gen/build/src/error.rs
type Result (line 8) | pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
type Error (line 11) | pub(super) enum Error {
method from (line 95) | fn from(err: fs::Error) -> Self {
constant LINKS_DOCUMENTATION (line 30) | const LINKS_DOCUMENTATION: &str =
method fmt (line 34) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method source (line 86) | fn source(&self) -> Option<&(dyn StdError + 'static)> {
FILE: gen/build/src/intern.rs
type InternedString (line 5) | pub(crate) struct InternedString(&'static str);
method str (line 8) | pub(crate) fn str(self) -> &'static str {
function intern (line 13) | pub(crate) fn intern(s: &str) -> InternedString {
FILE: gen/build/src/lib.rs
function bridge (line 119) | pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
function bridges (line 134) | pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Pa...
type Project (line 142) | struct Project {
method init (line 165) | fn init() -> Result<Self> {
function build (line 212) | fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) ...
function validate_cfg (line 239) | fn validate_cfg(prj: &Project) -> Result<()> {
function make_this_crate (line 267) | fn make_this_crate(prj: &Project) -> Result<Crate> {
function make_crate_dir (line 363) | fn make_crate_dir(prj: &Project) -> PathBuf {
function make_include_dir (line 382) | fn make_include_dir(prj: &Project) -> Result<PathBuf> {
function generate_bridge (line 396) | fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &...
function best_effort_copy_headers (line 432) | fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
function env_os (line 474) | fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
FILE: gen/build/src/out.rs
function write (line 7) | pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
function relative_symlink_file (line 32) | pub(crate) fn relative_symlink_file(
function absolute_symlink_file (line 45) | pub(crate) fn absolute_symlink_file(
function relative_symlink_dir (line 57) | pub(crate) fn relative_symlink_dir(
function prepare_parent_directory_for_symlink (line 70) | fn prepare_parent_directory_for_symlink(link: &Path) -> fs::Result<()> {
function symlink_file (line 80) | fn symlink_file(
function symlink_dir (line 108) | fn symlink_dir(
function best_effort_remove (line 121) | fn best_effort_remove(path: &Path) {
function best_effort_relativize_symlink (line 156) | fn best_effort_relativize_symlink(original: impl AsRef<Path>, link: impl...
function abstractly_relativize_symlink (line 180) | fn abstractly_relativize_symlink(
function path_contains_intermediate_components (line 230) | fn path_contains_intermediate_components(path: impl AsRef<Path>) -> bool {
function split_after_common_prefix (line 236) | fn split_after_common_prefix<'first, 'second>(
function test_relativize_symlink_unix (line 272) | fn test_relativize_symlink_unix() {
function test_relativize_symlink_windows (line 289) | fn test_relativize_symlink_windows() {
FILE: gen/build/src/paths.rs
function manifest_dir (line 6) | pub(crate) fn manifest_dir() -> Result<PathBuf> {
function out_dir (line 10) | pub(crate) fn out_dir() -> Result<PathBuf> {
function local_relative_path (line 18) | pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
type PathExt (line 30) | pub(crate) trait PathExt {
method with_appended_extension (line 31) | fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
method with_appended_extension (line 35) | fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf {
function symlink_or_copy (line 43) | pub(crate) fn symlink_or_copy(
function symlink_or_copy (line 52) | pub(crate) fn symlink_or_copy(
function symlink_or_copy (line 69) | pub(crate) fn symlink_or_copy(
FILE: gen/build/src/target.rs
type TargetDir (line 5) | pub(crate) enum TargetDir {
function find_target_dir (line 10) | pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
FILE: gen/build/src/vec.rs
type InternedVec (line 4) | pub(crate) trait InternedVec<T>
method vec (line 8) | fn vec(&self) -> Vec<&'static T>;
function vec (line 15) | fn vec(&self) -> Vec<&'static T> {
function intern (line 20) | pub(crate) fn intern<T>(elements: &[&T]) -> Vec<InternedString>
type Element (line 27) | pub(crate) trait Element {
method intern (line 28) | fn intern(&self) -> InternedString;
method unintern (line 29) | fn unintern(_: InternedString) -> &'static Self;
method intern (line 33) | fn intern(&self) -> InternedString {
method unintern (line 37) | fn unintern(interned: InternedString) -> &'static Self {
method intern (line 43) | fn intern(&self) -> InternedString {
method unintern (line 47) | fn unintern(interned: InternedString) -> &'static Self {
FILE: gen/cmd/src/app.rs
constant USAGE (line 17) | const USAGE: &str = "\
constant TEMPLATE (line 23) | const TEMPLATE: &str = "\
function app (line 34) | fn app() -> Command {
constant INPUT (line 54) | const INPUT: &str = "input";
constant CFG (line 55) | const CFG: &str = "cfg";
constant CXX_IMPL_ANNOTATIONS (line 56) | const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
constant HELP (line 57) | const HELP: &str = "help";
constant HEADER (line 58) | const HEADER: &str = "header";
constant INCLUDE (line 59) | const INCLUDE: &str = "include";
constant OUTPUT (line 60) | const OUTPUT: &str = "output";
constant VERSION (line 61) | const VERSION: &str = "version";
function from_args (line 63) | pub(super) fn from_args() -> Opt {
function arg_input (line 122) | fn arg_input() -> Arg {
function arg_cfg (line 129) | fn arg_cfg() -> Arg {
function arg_cxx_impl_annotations (line 156) | fn arg_cxx_impl_annotations() -> Arg {
function arg_header (line 171) | fn arg_header() -> Arg {
function arg_help (line 178) | fn arg_help() -> Arg {
function arg_include (line 185) | fn arg_include() -> Arg {
function arg_output (line 199) | fn arg_output() -> Arg {
function arg_version (line 212) | fn arg_version() -> Arg {
FILE: gen/cmd/src/cfg.rs
type CfgValue (line 8) | pub(crate) enum CfgValue {
constant FALSE (line 14) | const FALSE: Self = CfgValue::Bool(false);
constant TRUE (line 15) | const TRUE: Self = CfgValue::Bool(true);
type FlagsCfgEvaluator (line 18) | pub(crate) struct FlagsCfgEvaluator {
method new (line 23) | pub(crate) fn new(map: Map<String, Set<CfgValue>>) -> Self {
method eval (line 29) | fn eval(&self, name: &str, value: Option<&str>) -> CfgResult {
method fmt (line 68) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
function parse (line 76) | pub(crate) fn parse(input: ParseStream) -> syn::Result<(String, CfgValue...
FILE: gen/cmd/src/main.rs
type Opt (line 49) | struct Opt {
function main (line 58) | fn main() {
type Kind (line 65) | enum Kind {
function try_main (line 71) | fn try_main() -> Result<()> {
FILE: gen/cmd/src/output.rs
type Output (line 4) | pub(crate) enum Output {
method ends_with (line 10) | pub(crate) fn ends_with(&self, suffix: &str) -> bool {
FILE: gen/cmd/src/test.rs
constant EXPECTED (line 1) | const EXPECTED: &str = "\
function test_help (line 48) | fn test_help() {
function test_cli (line 59) | fn test_cli() {
FILE: gen/lib/src/error.rs
type Error (line 9) | pub struct Error {
method span (line 15) | pub fn span(&self) -> Option<proc_macro2::Span> {
method from (line 24) | fn from(err: crate::gen::Error) -> Self {
method fmt (line 30) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 36) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method source (line 42) | fn source(&self) -> Option<&(dyn StdError + 'static)> {
type Item (line 48) | type Item = Error;
type IntoIter (line 49) | type IntoIter = IntoIter;
method into_iter (line 51) | fn into_iter(self) -> Self::IntoIter {
type IntoIter (line 59) | pub enum IntoIter {
type Item (line 65) | type Item = Error;
method next (line 67) | fn next(&mut self) -> Option<Self::Item> {
FILE: gen/lib/src/lib.rs
function generate_header_and_cc (line 57) | pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Re...
FILE: gen/lib/tests/test.rs
function test_positive (line 5) | fn test_positive() {
function test_negative (line 24) | fn test_negative() {
FILE: gen/src/block.rs
type Block (line 4) | pub(crate) enum Block<'a> {
function write_begin (line 13) | pub(crate) fn write_begin(self, out: &mut String) {
function write_end (line 21) | pub(crate) fn write_end(self, out: &mut String) {
function write_common (line 27) | fn write_common(self, out: &mut String) {
FILE: gen/src/builtin.rs
type Builtins (line 8) | pub(crate) struct Builtins<'a> {
function new (line 44) | pub(crate) fn new() -> Self {
function write (line 49) | pub(super) fn write(out: &mut OutFile) {
function write_builtin (line 348) | fn write_builtin<'a>(
function test_write_builtin (line 452) | fn test_write_builtin() {
FILE: gen/src/builtin/alignmax.h
function namespace (line 4) | namespace rust {
FILE: gen/src/builtin/deleter_if.h
function namespace (line 3) | namespace rust {
FILE: gen/src/builtin/destroy.h
function namespace (line 3) | namespace rust {
FILE: gen/src/builtin/friend_impl.h
function namespace (line 3) | namespace rust {
FILE: gen/src/builtin/manually_drop.h
function namespace (line 6) | namespace rust {
FILE: gen/src/builtin/maybe_uninit.h
function namespace (line 5) | namespace rust {
FILE: gen/src/builtin/maybe_uninit_detail.h
function namespace (line 5) | namespace rust {
FILE: gen/src/builtin/ptr_len.h
function namespace (line 4) | namespace rust {
FILE: gen/src/builtin/relocatable_or_array.h
function namespace (line 5) | namespace rust {
FILE: gen/src/builtin/repr_fat.h
function namespace (line 5) | namespace rust {
FILE: gen/src/builtin/rust_error.h
function namespace (line 6) | namespace rust {
FILE: gen/src/builtin/rust_slice_uninit.h
function namespace (line 4) | namespace rust {
FILE: gen/src/builtin/rust_str_uninit.h
function namespace (line 4) | namespace rust {
FILE: gen/src/builtin/shared_ptr.h
function namespace (line 5) | namespace rust {
FILE: gen/src/builtin/trycatch.h
function namespace (line 7) | namespace rust {
FILE: gen/src/builtin/trycatch_detail.h
function namespace (line 8) | namespace rust {
FILE: gen/src/builtin/vector.h
function namespace (line 6) | namespace rust {
FILE: gen/src/cfg.rs
type UnsupportedCfgEvaluator (line 10) | pub(super) struct UnsupportedCfgEvaluator;
method eval (line 13) | fn eval(&self, name: &str, value: Option<&str>) -> CfgResult {
function strip (line 21) | pub(super) fn strip(
function eval (line 51) | pub(super) fn eval(
function try_eval (line 70) | fn try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result<...
method from (line 123) | fn from(value: bool) -> Self {
FILE: gen/src/check.rs
function precheck (line 9) | pub(super) fn precheck(cx: &mut Errors, apis: &[Api], opt: &Opt) {
function check_dot_includes (line 15) | fn check_dot_includes(cx: &mut Errors, apis: &[Api]) {
FILE: gen/src/error.rs
type Result (line 16) | pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
type Error (line 19) | pub(crate) enum Error {
method from (line 49) | fn from(err: fs::Error) -> Self {
method from (line 55) | fn from(err: syn::Error) -> Self {
method fmt (line 27) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method source (line 38) | fn source(&self) -> Option<&(dyn StdError + 'static)> {
function format_err (line 60) | pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
function report (line 85) | pub(crate) fn report(error: impl StdError) -> impl Display {
function sort_syn_errors (line 105) | fn sort_syn_errors(error: syn::Error) -> Vec<syn::Error> {
function display_syn_error (line 114) | fn display_syn_error(stderr: &mut dyn WriteStyle, path: &Path, source: &...
function diagnose (line 158) | fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diag...
FILE: gen/src/file.rs
type File (line 7) | pub(crate) struct File {
method parse (line 12) | fn parse(input: ParseStream) -> Result<Self> {
function parse (line 19) | fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
function parse_args (line 68) | fn parse_args(attr: &Attribute) -> Result<Namespace> {
FILE: gen/src/fs.rs
type Result (line 8) | pub(crate) type Result<T> = std::result::Result<T, Error>;
type Error (line 11) | pub(crate) struct Error {
method kind (line 17) | pub(crate) fn kind(&self) -> io::ErrorKind {
method fmt (line 26) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method source (line 32) | fn source(&self) -> Option<&(dyn StdError + 'static)> {
function copy (line 47) | pub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Resu...
function create_dir_all (line 56) | pub(crate) fn create_dir_all(path: impl AsRef<Path>) -> Result<()> {
function current_dir (line 64) | pub(crate) fn current_dir() -> Result<PathBuf> {
function exists (line 71) | pub(crate) fn exists(path: impl AsRef<Path>) -> bool {
function read (line 78) | pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
function read_stdin (line 86) | pub(crate) fn read_stdin() -> Result<Vec<u8>> {
function remove_file (line 94) | pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
function remove_dir (line 102) | pub(crate) fn remove_dir(path: impl AsRef<Path>) -> Result<()> {
function symlink (line 110) | fn symlink<'a>(
function symlink_fail (line 126) | pub(crate) fn symlink_fail(original: impl AsRef<Path>, link: impl AsRef<...
function symlink_file (line 144) | pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<...
function symlink_file (line 149) | pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<...
function symlink_dir (line 158) | pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<P...
function write (line 166) | pub(crate) fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) ...
FILE: gen/src/guard.rs
type Guard (line 6) | pub(crate) struct Guard {
method new (line 12) | pub fn new(out: &mut OutFile, kind: &'static str, name: &Pair) -> Self {
method fmt (line 20) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
FILE: gen/src/ifndef.rs
function write (line 4) | pub(super) fn write(out: &mut Content, needed: bool, guard: &str) {
function find_line (line 37) | fn find_line(mut offset: usize, line: &str) -> Option<usize> {
FILE: gen/src/include.rs
type Include (line 13) | pub struct Include {
method from (line 203) | fn from(include: &syntax::Include) -> Self {
type Includes (line 22) | pub(crate) struct Includes<'a> {
function new (line 50) | pub(crate) fn new() -> Self {
function insert (line 54) | pub(crate) fn insert(&mut self, include: impl Into<Include>) {
function has_cxx_header (line 58) | pub(crate) fn has_cxx_header(&self) -> bool {
function write (line 65) | pub(super) fn write(out: &mut OutFile) {
function extend (line 197) | fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
type Target (line 212) | type Target = Content<'a>;
method deref (line 214) | fn deref(&self) -> &Self::Target {
method deref_mut (line 220) | fn deref_mut(&mut self) -> &mut Self::Target {
FILE: gen/src/mod.rs
type Opt (line 48) | pub struct Opt {
type CfgEvaluator (line 70) | pub trait CfgEvaluator {
method eval (line 73) | fn eval(&self, name: &str, value: Option<&str>) -> CfgResult;
type CfgResult (line 77) | pub enum CfgResult {
type GeneratedCode (line 91) | pub struct GeneratedCode {
method default (line 99) | fn default() -> Self {
function generate_from_path (line 112) | pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
function read_to_string (line 123) | fn read_to_string(path: &Path) -> Result<String> {
function generate_from_string (line 135) | fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
function generate (line 145) | pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
FILE: gen/src/names.rs
method to_fully_qualified (line 4) | pub(crate) fn to_fully_qualified(&self) -> String {
FILE: gen/src/namespace.rs
method namespace (line 5) | pub(crate) fn namespace(&self) -> &Namespace {
FILE: gen/src/nested.rs
type NamespaceEntries (line 5) | pub(crate) struct NamespaceEntries<'a> {
function new (line 11) | pub(crate) fn new(apis: Vec<&'a Api>) -> Self {
function direct_content (line 15) | pub(crate) fn direct_content(&self) -> &[&'a Api] {
function nested_content (line 19) | pub(crate) fn nested_content(
function sort_by_inner_namespace (line 26) | fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEn...
function test_ns_entries_sort (line 65) | fn test_ns_entries_sort() {
function assert_ident (line 122) | fn assert_ident(api: &Api, expected: &str) {
function make_api (line 130) | fn make_api(ns: Option<&str>, ident: &str) -> Api {
FILE: gen/src/out.rs
type OutFile (line 11) | pub(crate) struct OutFile<'a> {
type Content (line 22) | pub(crate) struct Content<'a> {
type BlockBoundary (line 32) | enum BlockBoundary<'a> {
function new (line 38) | pub(crate) fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
function next_section (line 51) | pub(crate) fn next_section(&mut self) {
function suppress_next_section (line 55) | pub(crate) fn suppress_next_section(&mut self) {
function begin_block (line 59) | pub(crate) fn begin_block(&mut self, block: Block<'a>) {
function end_block (line 63) | pub(crate) fn end_block(&mut self, block: Block<'a>) {
function set_namespace (line 67) | pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
function content (line 71) | pub(crate) fn content(&mut self) -> Vec<u8> {
function flush (line 104) | fn flush(&mut self) {
method write_str (line 114) | fn write_str(&mut self, s: &str) -> fmt::Result {
method eq (line 121) | fn eq(&self, _other: &Self) -> bool {
function new (line 127) | pub(crate) fn new() -> Self {
function next_section (line 131) | pub(crate) fn next_section(&mut self) {
function suppress_next_section (line 135) | pub(crate) fn suppress_next_section(&mut self) {
function begin_block (line 139) | pub(crate) fn begin_block(&mut self, block: Block<'a>) {
function end_block (line 143) | pub(crate) fn end_block(&mut self, block: Block<'a>) {
function set_namespace (line 147) | pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
function write_fmt (line 157) | pub(crate) fn write_fmt(&mut self, args: Arguments) {
function write (line 161) | fn write(&mut self, b: &str) {
function push_block_boundary (line 176) | fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
function flush (line 186) | fn flush(&mut self) {
function flush_blocks (line 193) | fn flush_blocks(&mut self) {
function rev (line 225) | fn rev(self) -> BlockBoundary<'a> {
type InfallibleWrite (line 233) | pub(crate) trait InfallibleWrite {
method write_fmt (line 234) | fn write_fmt(&mut self, args: Arguments);
method write_fmt (line 238) | fn write_fmt(&mut self, args: Arguments) {
method write_fmt (line 244) | fn write_fmt(&mut self, args: Arguments) {
method write_fmt (line 250) | fn write_fmt(&mut self, args: Arguments) {
FILE: gen/src/pragma.rs
type Pragma (line 5) | pub(crate) struct Pragma<'a> {
function new (line 17) | pub fn new() -> Self {
function write (line 22) | pub(super) fn write(out: &mut OutFile) {
FILE: gen/src/write.rs
function gen (line 20) | pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) ...
function write_macros (line 40) | fn write_macros(out: &mut OutFile, apis: &[Api]) {
function write_forward_declarations (line 62) | fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
function write_data_structures (line 97) | fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
function write_functions (line 166) | fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
function write_std_specializations (line 194) | fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
function pick_includes_and_builtins (line 227) | fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
function write_doc (line 258) | fn write_doc(out: &mut OutFile, indent: &str, doc: &Doc) {
function write_struct (line 277) | fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &...
function write_struct_decl (line 383) | fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
function write_enum_decl (line 387) | fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
function write_struct_using (line 393) | fn write_struct_using(out: &mut OutFile, ident: &Pair) {
function write_opaque_type (line 397) | fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, met...
function write_enum (line 444) | fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
function check_enum (line 469) | fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
function write_discriminant (line 503) | fn write_discriminant(out: &mut OutFile, repr: Atom, discriminant: Discr...
function write_binary_bitwise_op (line 515) | fn write_binary_bitwise_op(out: &mut OutFile, op: &str, enm: &Enum) {
function write_enum_operators (line 529) | fn write_enum_operators(out: &mut OutFile, enm: &Enum) {
function check_trivial_extern_type (line 546) | fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reaso...
function write_struct_operator_decls (line 636) | fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Str...
function write_struct_operators (line 709) | fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
function write_opaque_type_layout_decls (line 797) | fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a Ex...
function write_opaque_type_layout (line 812) | fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternTy...
function begin_function_definition (line 841) | fn begin_function_definition(out: &mut OutFile) {
function write_cxx_function_shim (line 847) | fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
function write_function_pointer_trampoline (line 1026) | fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, ...
function write_rust_function_decl (line 1048) | fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
function write_rust_function_decl_impl (line 1057) | fn write_rust_function_decl_impl(
function write_rust_function_shim (line 1118) | fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
function write_rust_function_shim_decl (line 1141) | fn write_rust_function_shim_decl(
function write_rust_function_shim_impl (line 1183) | fn write_rust_function_shim_impl(
function write_return_type (line 1330) | fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
function indirect_return (line 1337) | fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool {
function write_indirect_return_type (line 1348) | fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
function write_indirect_return_type_space (line 1365) | fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
function write_extern_return_type_space (line 1374) | fn write_extern_return_type_space(out: &mut OutFile, sig: &Signature, la...
function write_extern_arg (line 1396) | fn write_extern_arg(out: &mut OutFile, arg: &Var) {
function write_type (line 1410) | fn write_type(out: &mut OutFile, ty: &Type) {
function stringify_type (line 1414) | fn stringify_type(ty: &Type, types: &Types) -> String {
function write_type_to_generic_writer (line 1420) | fn write_type_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Typ...
function write_atom (line 1505) | fn write_atom(out: &mut impl InfallibleWrite, atom: Atom) {
function write_type_space (line 1526) | fn write_type_space(out: &mut OutFile, ty: &Type) {
function write_type_space_to_generic_writer (line 1530) | fn write_type_space_to_generic_writer(out: &mut impl InfallibleWrite, ty...
function write_space_after_type (line 1535) | fn write_space_after_type(out: &mut impl InfallibleWrite, ty: &Type) {
function write_generic_instantiations (line 1553) | fn write_generic_instantiations(out: &mut OutFile) {
function write_rust_box_extern (line 1587) | fn write_rust_box_extern(out: &mut OutFile, key: &NamedImplKey) {
function write_rust_vec_extern (line 1610) | fn write_rust_vec_extern(out: &mut OutFile, key: &NamedImplKey) {
function write_rust_box_impl (line 1659) | fn write_rust_box_impl(out: &mut OutFile, key: &NamedImplKey) {
function write_rust_vec_impl (line 1692) | fn write_rust_vec_impl(out: &mut OutFile, key: &NamedImplKey) {
function write_unique_ptr (line 1780) | fn write_unique_ptr(out: &mut OutFile, key: &NamedImplKey) {
function write_unique_ptr_common (line 1785) | fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
function write_shared_ptr (line 1888) | fn write_shared_ptr(out: &mut OutFile, key: &NamedImplKey) {
function write_weak_ptr (line 1985) | fn write_weak_ptr(out: &mut OutFile, key: &NamedImplKey) {
function write_cxx_vector (line 2055) | fn write_cxx_vector(out: &mut OutFile, key: &NamedImplKey) {
FILE: include/cxx.h
type unsafe_bitcopy_t (line 34) | struct unsafe_bitcopy_t
function class (line 44) | class String final {
function class (line 120) | class Str final {
FILE: macro/src/attrs.rs
method all (line 7) | pub(crate) fn all(&self) -> PrintOtherAttrs {
method cfg (line 16) | pub(crate) fn cfg(&self) -> PrintOtherAttrs {
method cfg_and_lint (line 25) | pub(crate) fn cfg_and_lint(&self) -> PrintOtherAttrs {
type PrintOtherAttrs (line 35) | pub(crate) struct PrintOtherAttrs<'a> {
method to_tokens (line 43) | fn to_tokens(&self, tokens: &mut TokenStream) {
function print_attrs_as_outer (line 56) | fn print_attrs_as_outer(attrs: &[Attribute], tokens: &mut TokenStream) {
FILE: macro/src/cfg.rs
function into_attr (line 7) | pub(crate) fn into_attr(&self) -> Option<Attribute> {
function as_meta (line 25) | pub(crate) fn as_meta(&self) -> impl ToTokens + '_ {
type Print (line 33) | struct Print<'a, Cfg> {
method to_tokens (line 39) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 73) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: macro/src/derive.rs
function expand_struct (line 7) | pub(crate) fn expand_struct(
function expand_enum (line 44) | pub(crate) fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenS...
function struct_copy (line 106) | fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
function struct_clone (line 118) | fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
function struct_debug (line 150) | fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
function struct_default (line 171) | fn struct_default(strct: &Struct, span: Span) -> TokenStream {
function struct_ord (line 193) | fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
function struct_partial_ord (line 216) | fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
function enum_bitand (line 250) | fn enum_bitand(enm: &Enum, span: Span) -> TokenStream {
function enum_bitor (line 268) | fn enum_bitor(enm: &Enum, span: Span) -> TokenStream {
function enum_bitxor (line 286) | fn enum_bitxor(enm: &Enum, span: Span) -> TokenStream {
function enum_copy (line 304) | fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
function enum_clone (line 315) | fn enum_clone(enm: &Enum, span: Span) -> TokenStream {
function enum_debug (line 331) | fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
function enum_default (line 357) | fn enum_default(enm: &Enum, span: Span) -> TokenStream {
function enum_ord (line 379) | fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
function enum_partial_ord (line 394) | fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream {
FILE: macro/src/expand.rs
function bridge (line 28) | pub(crate) fn bridge(mut ffi: Module) -> Result<TokenStream> {
function expand (line 57) | fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types:...
function expand_struct (line 172) | fn expand_struct(strct: &Struct) -> TokenStream {
function expand_struct_nonempty (line 221) | fn expand_struct_nonempty(strct: &Struct) -> TokenStream {
function expand_struct_operators (line 248) | fn expand_struct_operators(strct: &Struct) -> TokenStream {
function expand_struct_forbid_drop (line 363) | fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
function expand_enum (line 377) | fn expand_enum(enm: &Enum) -> TokenStream {
function expand_cxx_type (line 439) | fn expand_cxx_type(ety: &ExternType) -> TokenStream {
function expand_cxx_type_assert_pinned (line 482) | fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> Tok...
function expand_extern_shared_struct (line 522) | fn expand_extern_shared_struct(ety: &ExternType, ffi: &Module) -> TokenS...
function expand_associated_functions (line 594) | fn expand_associated_functions(self_type: &Ident, types: &Types) -> Toke...
function expand_cxx_function_decl (line 673) | fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
function expand_cxx_function_shim (line 725) | fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
function expand_function_pointer_trampoline (line 993) | fn expand_function_pointer_trampoline(
function expand_rust_type_import (line 1037) | fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
function expand_rust_type_impl (line 1048) | fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
function expand_rust_type_assert_unpin (line 1082) | fn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> Tok...
function expand_rust_type_layout (line 1095) | fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStre...
function expand_forbid (line 1142) | fn expand_forbid(impls: TokenStream) -> TokenStream {
function expand_rust_function_shim (line 1154) | fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStre...
function expand_rust_function_shim_impl (line 1179) | fn expand_rust_function_shim_impl(
function expand_rust_function_shim_super (line 1383) | fn expand_rust_function_shim_super(
function expand_type_alias (line 1439) | fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
function expand_type_alias_verify (line 1457) | fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenSt...
function type_id (line 1643) | fn type_id(name: &Pair) -> TokenStream {
function expand_rust_box (line 1652) | fn expand_rust_box(
function expand_rust_vec (line 1707) | fn expand_rust_vec(
function expand_unique_ptr (line 1819) | fn expand_unique_ptr(
function expand_shared_ptr (line 1921) | fn expand_shared_ptr(
function expand_weak_ptr (line 2025) | fn expand_weak_ptr(
function expand_cxx_vector (line 2106) | fn expand_cxx_vector(
function expand_return_type (line 2288) | fn expand_return_type(ret: &Option<Type>) -> TokenStream {
function indirect_return (line 2295) | fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool {
function expand_extern_type (line 2306) | fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenSt...
function expand_extern_return_type (line 2382) | fn expand_extern_return_type(
function display_namespaced (line 2396) | pub(crate) fn display_namespaced(name: &Pair) -> impl Display + '_ {
FILE: macro/src/generics.rs
type ResolvedGenericType (line 9) | pub(crate) struct ResolvedGenericType<'a> {
function split_for_impl (line 21) | pub(crate) fn split_for_impl<'a>(
method to_tokens (line 40) | fn to_tokens(&self, tokens: &mut TokenStream) {
function get_impl_generics (line 79) | fn get_impl_generics<'a>(ty: &Type, types: &Types<'a>) -> &'a Lifetimes {
function format_for_prevent_unwind_label (line 87) | pub(crate) fn format_for_prevent_unwind_label(ty: &Type) -> TokenStream {
function concise_rust_name (line 105) | pub(crate) fn concise_rust_name(ty: &Type) -> String {
function concise_cxx_name (line 116) | pub(crate) fn concise_cxx_name(ty: &Type, types: &Types) -> String {
type UnderscoreLifetimes (line 130) | pub(crate) struct UnderscoreLifetimes<'a> {
method to_underscore_lifetimes (line 135) | pub(crate) fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes {
method to_tokens (line 141) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: macro/src/lib.rs
function bridge (line 67) | pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
function type_id (line 84) | pub fn type_id(input: TokenStream) -> TokenStream {
FILE: macro/src/tests.rs
function bridge (line 7) | fn bridge(cxx_bridge: TokenStream) -> String {
function test_unique_ptr_with_elided_lifetime_implicit_impl (line 24) | fn test_unique_ptr_with_elided_lifetime_implicit_impl() {
function test_unique_ptr_lifetimes_from_explicit_impl (line 51) | fn test_unique_ptr_lifetimes_from_explicit_impl() {
function test_vec_string (line 69) | fn test_vec_string() {
function test_mangling_covers_cpp_namespace_of_vec_elements (line 96) | fn test_mangling_covers_cpp_namespace_of_vec_elements() {
function test_struct_with_lifetime (line 111) | fn test_struct_with_lifetime() {
function test_original_lifetimes_used_in_impls (line 141) | fn test_original_lifetimes_used_in_impls() {
function test_vec_of_box (line 162) | fn test_vec_of_box() {
FILE: macro/src/tokens.rs
type ReceiverType (line 6) | pub(crate) struct ReceiverType<'a>(&'a Receiver);
type ReceiverTypeSelf (line 7) | pub(crate) struct ReceiverTypeSelf<'a>(&'a Receiver);
method ty (line 11) | pub(crate) fn ty(&self) -> ReceiverType {
method ty_self (line 16) | pub(crate) fn ty_self(&self) -> ReceiverTypeSelf {
method to_tokens (line 22) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 50) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: macro/src/type_id.rs
type Crate (line 6) | pub(crate) enum Crate {
method to_tokens (line 12) | fn to_tokens(&self, tokens: &mut TokenStream) {
function expand (line 21) | pub(crate) fn expand(krate: Crate, arg: QualifiedName) -> TokenStream {
FILE: src/cxx.cc
function cxxbridge1$cxx_string$init (line 34) | void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
function cxxbridge1$cxx_string$destroy (line 39) | void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
function cxxbridge1$cxx_string$length (line 48) | std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
function cxxbridge1$cxx_string$clear (line 52) | void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
function cxxbridge1$cxx_string$reserve_total (line 54) | void cxxbridge1$cxx_string$reserve_total(std::string &s,
function cxxbridge1$cxx_string$push (line 59) | void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
type rust (line 100) | namespace rust {
type cxxbridge1 (line 101) | inline namespace cxxbridge1 {
function is_aligned (line 116) | static bool is_aligned(const void *ptr) noexcept {
function initString (line 133) | static void initString(String *self, const char *s, std::size_t len) {
function initString (line 139) | static void initString(String *self, const char16_t *s, std::size_t ...
type String::lossy_t (line 181) | struct String::lossy_t {}
function String (line 196) | String String::lossy(const std::string &s) noexcept {
function String (line 200) | String String::lossy(const char *s) noexcept {
function String (line 205) | String String::lossy(const char *s, std::size_t len) noexcept {
function String (line 210) | String String::lossy(const char16_t *s) noexcept {
function String (line 216) | String String::lossy(const char16_t *s, std::size_t len) noexcept {
function String (line 222) | String &String::operator=(const String &other) & noexcept {
function String (line 230) | String &String::operator=(String &&other) & noexcept {
function initStr (line 330) | static void initStr(Str *self, const char *ptr, std::size_t len) {
function sliceInit (line 422) | void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
function sliceLen (line 428) | std::size_t sliceLen(const void *self) noexcept {
function Error (line 531) | Error &Error::operator=(const Error &other) & {
function Error (line 544) | Error &Error::operator=(Error &&other) & noexcept {
function MaybeUninit (line 560) | MaybeUninit() {}
type repr (line 565) | namespace repr {
type PtrLen (line 566) | struct PtrLen final {
type detail (line 576) | namespace detail {
type usize_ignore (line 584) | struct usize_ignore
type isize_ignore (line 588) | struct isize_ignore
type char_ignore (line 593) | struct char_ignore
class Fail (line 595) | class Fail final {
method Fail (line 599) | Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
type cxxbridge1 (line 865) | inline namespace cxxbridge1 {
function is_aligned (line 116) | static bool is_aligned(const void *ptr) noexcept {
function initString (line 133) | static void initString(String *self, const char *s, std::size_t len) {
function initString (line 139) | static void initString(String *self, const char16_t *s, std::size_t ...
type String::lossy_t (line 181) | struct String::lossy_t {}
function String (line 196) | String String::lossy(const std::string &s) noexcept {
function String (line 200) | String String::lossy(const char *s) noexcept {
function String (line 205) | String String::lossy(const char *s, std::size_t len) noexcept {
function String (line 210) | String String::lossy(const char16_t *s) noexcept {
function String (line 216) | String String::lossy(const char16_t *s, std::size_t len) noexcept {
function String (line 222) | String &String::operator=(const String &other) & noexcept {
function String (line 230) | String &String::operator=(String &&other) & noexcept {
function initStr (line 330) | static void initStr(Str *self, const char *ptr, std::size_t len) {
function sliceInit (line 422) | void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
function sliceLen (line 428) | std::size_t sliceLen(const void *self) noexcept {
function Error (line 531) | Error &Error::operator=(const Error &other) & {
function Error (line 544) | Error &Error::operator=(Error &&other) & noexcept {
function MaybeUninit (line 560) | MaybeUninit() {}
type repr (line 565) | namespace repr {
type PtrLen (line 566) | struct PtrLen final {
type detail (line 576) | namespace detail {
type usize_ignore (line 584) | struct usize_ignore
type isize_ignore (line 588) | struct isize_ignore
type char_ignore (line 593) | struct char_ignore
class Fail (line 595) | class Fail final {
method Fail (line 599) | Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
function destroy (line 618) | void destroy(T *ptr) {
function cxxbridge1$unique_ptr$std$string$null (line 624) | void cxxbridge1$unique_ptr$std$string$null(
function cxxbridge1$unique_ptr$std$string$raw (line 628) | void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *...
function cxxbridge1$unique_ptr$std$string$drop (line 640) | void cxxbridge1$unique_ptr$std$string$drop(
type rust (line 864) | namespace rust {
type cxxbridge1 (line 101) | inline namespace cxxbridge1 {
function is_aligned (line 116) | static bool is_aligned(const void *ptr) noexcept {
function initString (line 133) | static void initString(String *self, const char *s, std::size_t len) {
function initString (line 139) | static void initString(String *self, const char16_t *s, std::size_t ...
type String::lossy_t (line 181) | struct String::lossy_t {}
function String (line 196) | String String::lossy(const std::string &s) noexcept {
function String (line 200) | String String::lossy(const char *s) noexcept {
function String (line 205) | String String::lossy(const char *s, std::size_t len) noexcept {
function String (line 210) | String String::lossy(const char16_t *s) noexcept {
function String (line 216) | String String::lossy(const char16_t *s, std::size_t len) noexcept {
function String (line 222) | String &String::operator=(const String &other) & noexcept {
function String (line 230) | String &String::operator=(String &&other) & noexcept {
function initStr (line 330) | static void initStr(Str *self, const char *ptr, std::size_t len) {
function sliceInit (line 422) | void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
function sliceLen (line 428) | std::size_t sliceLen(const void *self) noexcept {
function Error (line 531) | Error &Error::operator=(const Error &other) & {
function Error (line 544) | Error &Error::operator=(Error &&other) & noexcept {
function MaybeUninit (line 560) | MaybeUninit() {}
type repr (line 565) | namespace repr {
type PtrLen (line 566) | struct PtrLen final {
type detail (line 576) | namespace detail {
type usize_ignore (line 584) | struct usize_ignore
type isize_ignore (line 588) | struct isize_ignore
type char_ignore (line 593) | struct char_ignore
class Fail (line 595) | class Fail final {
method Fail (line 599) | Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
type cxxbridge1 (line 865) | inline namespace cxxbridge1 {
function is_aligned (line 116) | static bool is_aligned(const void *ptr) noexcept {
function initString (line 133) | static void initString(String *self, const char *s, std::size_t len) {
function initString (line 139) | static void initString(String *self, const char16_t *s, std::size_t ...
type String::lossy_t (line 181) | struct String::lossy_t {}
function String (line 196) | String String::lossy(const std::string &s) noexcept {
function String (line 200) | String String::lossy(const char *s) noexcept {
function String (line 205) | String String::lossy(const char *s, std::size_t len) noexcept {
function String (line 210) | String String::lossy(const char16_t *s) noexcept {
function String (line 216) | String String::lossy(const char16_t *s, std::size_t len) noexcept {
function String (line 222) | String &String::operator=(const String &other) & noexcept {
function String (line 230) | String &String::operator=(String &&other) & noexcept {
function initStr (line 330) | static void initStr(Str *self, const char *ptr, std::size_t len) {
function sliceInit (line 422) | void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
function sliceLen (line 428) | std::size_t sliceLen(const void *self) noexcept {
function Error (line 531) | Error &Error::operator=(const Error &other) & {
function Error (line 544) | Error &Error::operator=(Error &&other) & noexcept {
function MaybeUninit (line 560) | MaybeUninit() {}
type repr (line 565) | namespace repr {
type PtrLen (line 566) | struct PtrLen final {
type detail (line 576) | namespace detail {
type usize_ignore (line 584) | struct usize_ignore
type isize_ignore (line 588) | struct isize_ignore
type char_ignore (line 593) | struct char_ignore
class Fail (line 595) | class Fail final {
method Fail (line 599) | Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
FILE: src/cxx_string.rs
function string_init (line 19) | fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: u...
function string_destroy (line 21) | fn string_destroy(this: &mut MaybeUninit<CxxString>);
function string_data (line 23) | fn string_data(this: &CxxString) -> *const u8;
function string_length (line 25) | fn string_length(this: &CxxString) -> usize;
function string_clear (line 27) | fn string_clear(this: Pin<&mut CxxString>);
function string_reserve_total (line 29) | fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize);
function string_push (line 31) | fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
type CxxString (line 45) | pub struct CxxString {
method new (line 95) | pub fn new<T: Private>() -> Self {
method len (line 104) | pub fn len(&self) -> usize {
method is_empty (line 113) | pub fn is_empty(&self) -> bool {
method as_bytes (line 118) | pub fn as_bytes(&self) -> &[u8] {
method as_ptr (line 137) | pub fn as_ptr(&self) -> *const u8 {
method as_c_str (line 150) | pub fn as_c_str(&self) -> &CStr {
method to_str (line 157) | pub fn to_str(&self) -> Result<&str, Utf8Error> {
method to_string_lossy (line 169) | pub fn to_string_lossy(&self) -> Cow<str> {
method clear (line 184) | pub fn clear(self: Pin<&mut Self>) {
method reserve (line 208) | pub fn reserve(self: Pin<&mut Self>, additional: usize) {
method push_str (line 217) | pub fn push_str(self: Pin<&mut Self>, s: &str) {
method push_bytes (line 222) | pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
method eq (line 252) | fn eq(&self, other: &str) -> bool {
method fmt (line 228) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 234) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method eq (line 240) | fn eq(&self, other: &Self) -> bool {
function eq (line 246) | fn eq(&self, other: &CxxString) -> bool {
method partial_cmp (line 260) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method cmp (line 266) | fn cmp(&self, other: &Self) -> Ordering {
method hash (line 272) | fn hash<H: Hasher>(&self, state: &mut H) {
function write_str (line 278) | fn write_str(&mut self, s: &str) -> fmt::Result {
function write (line 286) | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
function flush (line 291) | fn flush(&mut self) -> std::io::Result<()> {
type StackString (line 298) | pub struct StackString {
method new (line 305) | pub fn new() -> Self {
method init (line 311) | pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut Cxx...
method drop (line 322) | fn drop(&mut self) {
FILE: src/cxx_vector.rs
type CxxVector (line 26) | pub struct CxxVector<T> {
function new (line 44) | pub fn new() -> UniquePtr<Self> {
function len (line 53) | pub fn len(&self) -> usize {
function capacity (line 62) | pub fn capacity(&self) -> usize {
function is_empty (line 71) | pub fn is_empty(&self) -> bool {
function get (line 77) | pub fn get(&self, pos: usize) -> Option<&T> {
function index_mut (line 91) | pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
function get_unchecked (line 109) | pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
function index_unchecked_mut (line 132) | pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> P...
function as_slice (line 140) | pub fn as_slice(&self) -> &[T]
function as_mut_slice (line 162) | pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
function iter (line 176) | pub fn iter(&self) -> Iter<T> {
function iter_mut (line 181) | pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
function push (line 190) | pub fn push(self: Pin<&mut Self>, value: T)
function pop (line 203) | pub fn pop(self: Pin<&mut Self>) -> Option<T>
function reserve (line 239) | pub fn reserve(self: Pin<&mut Self>, additional: usize) {
function extend (line 252) | fn extend<I>(&mut self, iter: I)
type Iter (line 267) | pub struct Iter<'a, T> {
type Item (line 276) | type Item = &'a T;
type IntoIter (line 277) | type IntoIter = Iter<'a, T>;
method into_iter (line 279) | fn into_iter(self) -> Self::IntoIter {
type Item (line 288) | type Item = &'a T;
method next (line 290) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 296) | fn size_hint(&self) -> (usize, Option<usize>) {
method len (line 306) | fn len(&self) -> usize {
type IterMut (line 316) | pub struct IterMut<'a, T> {
type Item (line 325) | type Item = Pin<&'a mut T>;
type IntoIter (line 326) | type IntoIter = IterMut<'a, T>;
method into_iter (line 328) | fn into_iter(self) -> Self::IntoIter {
type Item (line 337) | type Item = Pin<&'a mut T>;
method next (line 339) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 350) | fn size_hint(&self) -> (usize, Option<usize>) {
method len (line 360) | fn len(&self) -> usize {
method fmt (line 371) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
type VectorElement (line 408) | pub unsafe trait VectorElement: Sized {
method __typename (line 410) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
method __vector_new (line 412) | fn __vector_new() -> *mut CxxVector<Self>;
method __vector_size (line 414) | fn __vector_size(v: &CxxVector<Self>) -> usize;
method __vector_capacity (line 416) | fn __vector_capacity(v: &CxxVector<Self>) -> usize;
method __get_unchecked (line 418) | unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut...
method __reserve (line 420) | unsafe fn __reserve(v: Pin<&mut CxxVector<Self>>, new_cap: usize);
method __push_back (line 422) | unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut Manual...
method __pop_back (line 430) | unsafe fn __pop_back(v: Pin<&mut CxxVector<Self>>, out: &mut MaybeUnin...
method __unique_ptr_null (line 438) | fn __unique_ptr_null() -> MaybeUninit<*mut c_void>;
method __unique_ptr_raw (line 440) | unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*...
method __unique_ptr_get (line 442) | unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const C...
method __unique_ptr_release (line 444) | unsafe fn __unique_ptr_release(repr: MaybeUninit<*mut c_void>) -> *mut...
method __unique_ptr_drop (line 446) | unsafe fn __unique_ptr_drop(repr: MaybeUninit<*mut c_void>);
FILE: src/exception.rs
type Exception (line 11) | pub struct Exception {
method what (line 25) | pub fn what(&self) -> &str {
method fmt (line 16) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
FILE: src/extern_type.rs
type ExternType (line 101) | pub unsafe trait ExternType {
type Opaque (line 164) | pub enum Opaque {}
type Trivial (line 169) | pub enum Trivial {}
type Kind (line 172) | pub trait Kind: private::Sealed {}
type Sealed (line 178) | pub trait Sealed {}
function verify_extern_type (line 184) | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
function verify_extern_kind (line 187) | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>(...
FILE: src/fmt.rs
function display (line 3) | pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) ...
type DisplayInvoke (line 7) | struct DisplayInvoke<T>(T);
method fmt (line 13) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
FILE: src/function.rs
type FatFunction (line 6) | pub struct FatFunction {
FILE: src/hash.rs
function hash (line 4) | pub fn hash<V: Hash>(value: &V) -> usize {
FILE: src/lib.rs
type String (line 480) | pub type String = CxxString;
type Vector (line 487) | pub type Vector<T> = CxxVector<T>;
type Private (line 513) | pub trait Private {}
type void (line 533) | struct void(core::ffi::c_void);
FILE: src/lossy.rs
function display (line 5) | pub(crate) fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::...
function debug (line 24) | pub(crate) fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Re...
FILE: src/opaque.rs
type Opaque (line 18) | pub struct Opaque {
type SyncUnsafeCell (line 28) | struct SyncUnsafeCell<T>(UnsafeCell<T>);
FILE: src/result.rs
type PtrLen (line 15) | pub(crate) struct PtrLen {
function r#try (line 26) | pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
function to_c_error (line 39) | unsafe fn to_c_error(msg: String) -> Result {
method exception (line 54) | pub unsafe fn exception(self) -> StdResult<(), Exception> {
FILE: src/rust_slice.rs
type RustSlice (line 9) | pub struct RustSlice {
method from_ref (line 14) | pub fn from_ref<T>(slice: &[T]) -> Self {
method from_mut (line 20) | pub fn from_mut<T>(slice: &mut [T]) -> Self {
method as_slice (line 26) | pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
method as_mut_slice (line 32) | pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
method from_raw_parts (line 38) | pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
method as_non_null_ptr (line 46) | pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> {
method len (line 52) | pub(crate) fn len(&self) -> usize {
FILE: src/rust_str.rs
type RustStr (line 9) | pub struct RustStr {
method from (line 14) | pub fn from(repr: &str) -> Self {
method as_str (line 19) | pub unsafe fn as_str<'a>(self) -> &'a str {
FILE: src/rust_string.rs
type RustString (line 10) | pub struct RustString {
method from (line 15) | pub fn from(s: String) -> Self {
method from_ref (line 19) | pub fn from_ref(s: &String) -> &Self {
method from_mut (line 23) | pub fn from_mut(s: &mut String) -> &mut Self {
method into_string (line 27) | pub fn into_string(self) -> String {
method as_string (line 31) | pub fn as_string(&self) -> &String {
method as_mut_string (line 35) | pub fn as_mut_string(&mut self) -> &mut String {
method drop (line 41) | fn drop(&mut self) {
FILE: src/rust_type.rs
type RustType (line 8) | pub unsafe trait RustType {}
type ImplBox (line 9) | pub unsafe trait ImplBox {}
type ImplVec (line 10) | pub unsafe trait ImplVec {}
function require_unpin (line 13) | pub fn require_unpin<T: ?Sized + Unpin>() {}
function require_box (line 15) | pub fn require_box<T: ImplBox>() {}
function require_vec (line 16) | pub fn require_vec<T: ImplVec>() {}
type With (line 18) | pub struct With<T: ?Sized>(PhantomData<T>);
type Without (line 19) | pub struct Without;
method check_slice (line 49) | pub const fn check_slice<U: SliceOfExternType<Kind = Trivial>>(&self) {}
function with (line 21) | pub const fn with<T: ?Sized>() -> With<T> {
function check_slice (line 27) | pub const fn check_slice<U>(&self) {}
type Target (line 31) | type Target = Without;
method deref (line 32) | fn deref(&self) -> &Self::Target {
type SliceOfExternType (line 37) | pub trait SliceOfExternType {
type Kind (line 41) | type Kind = T::Kind;
type Kind (line 44) | type Kind = T::Kind;
FILE: src/rust_vec.rs
type RustVec (line 12) | pub struct RustVec<T> {
function new (line 18) | pub fn new() -> Self {
function from (line 22) | pub fn from(v: Vec<T>) -> Self {
function from_ref (line 26) | pub fn from_ref(v: &Vec<T>) -> &Self {
function from_mut (line 30) | pub fn from_mut(v: &mut Vec<T>) -> &mut Self {
function into_vec (line 34) | pub fn into_vec(self) -> Vec<T> {
function as_vec (line 38) | pub fn as_vec(&self) -> &Vec<T> {
function as_mut_vec (line 42) | pub fn as_mut_vec(&mut self) -> &mut Vec<T> {
function len (line 46) | pub fn len(&self) -> usize {
function capacity (line 50) | pub fn capacity(&self) -> usize {
function as_ptr (line 54) | pub fn as_ptr(&self) -> *const T {
function reserve_total (line 58) | pub fn reserve_total(&mut self, new_cap: usize) {
function set_len (line 66) | pub unsafe fn set_len(&mut self, len: usize) {
function truncate (line 70) | pub fn truncate(&mut self, len: usize) {
method drop (line 76) | fn drop(&mut self) {
FILE: src/shared_ptr.rs
type SharedPtr (line 46) | pub struct SharedPtr<T>
function null (line 61) | pub fn null() -> Self {
function new (line 73) | pub fn new(value: T) -> Self
function from_raw (line 109) | pub unsafe fn from_raw(raw: *mut T) -> Self {
function is_null (line 131) | pub fn is_null(&self) -> bool {
function as_ref (line 146) | pub fn as_ref(&self) -> Option<&T> {
function pin_mut_unchecked (line 182) | pub unsafe fn pin_mut_unchecked(&mut self) -> Pin<&mut T> {
function as_ptr (line 194) | pub fn as_ptr(&self) -> *const T {
function as_mut_ptr (line 205) | pub fn as_mut_ptr(&self) -> *mut T {
function downgrade (line 214) | pub fn downgrade(&self) -> WeakPtr<T>
method clone (line 235) | fn clone(&self) -> Self {
method drop (line 254) | fn drop(&mut self) {
type Target (line 264) | type Target = T;
method deref (line 266) | fn deref(&self) -> &Self::Target {
method fmt (line 281) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 293) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method eq (line 305) | fn eq(&self, other: &Self) -> bool {
method partial_cmp (line 316) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method cmp (line 325) | fn cmp(&self, other: &Self) -> Ordering {
method hash (line 334) | fn hash<H>(&self, hasher: &mut H)
function from (line 346) | fn from(unique: UniquePtr<T>) -> Self {
type SharedPtrTarget (line 376) | pub unsafe trait SharedPtrTarget {
method __typename (line 378) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
method __null (line 380) | unsafe fn __null(new: *mut c_void);
method __new (line 382) | unsafe fn __new(value: Self, new: *mut c_void)
method __raw (line 393) | unsafe fn __raw(new: *mut c_void, raw: *mut Self);
method __clone (line 395) | unsafe fn __clone(this: *const c_void, new: *mut c_void);
method __get (line 397) | unsafe fn __get(this: *const c_void) -> *const Self;
method __drop (line 399) | unsafe fn __drop(this: *mut c_void);
FILE: src/symbols/exception.rs
function exception (line 10) | unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen {
FILE: src/symbols/rust_slice.rs
function slice_new (line 6) | unsafe extern "C" fn slice_new(this: &mut MaybeUninit<RustSlice>, ptr: N...
function slice_ptr (line 13) | unsafe extern "C" fn slice_ptr(this: &RustSlice) -> NonNull<()> {
function slice_len (line 18) | unsafe extern "C" fn slice_len(this: &RustSlice) -> usize {
FILE: src/symbols/rust_str.rs
function str_new (line 9) | unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) {
function str_ref (line 16) | unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string...
function str_from (line 23) | unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const ...
function str_ptr (line 36) | unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 {
function str_len (line 41) | unsafe extern "C" fn str_len(this: &&str) -> usize {
FILE: src/symbols/rust_string.rs
function string_new (line 11) | unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
function string_clone (line 18) | unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other:...
function string_from_utf8 (line 25) | unsafe extern "C" fn string_from_utf8(
function string_from_utf8_lossy (line 43) | unsafe extern "C" fn string_from_utf8_lossy(
function string_from_utf16 (line 55) | unsafe extern "C" fn string_from_utf16(
function string_from_utf16_lossy (line 72) | unsafe extern "C" fn string_from_utf16_lossy(
function string_drop (line 84) | unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
function string_ptr (line 89) | unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
function string_len (line 94) | unsafe extern "C" fn string_len(this: &String) -> usize {
function string_capacity (line 99) | unsafe extern "C" fn string_capacity(this: &String) -> usize {
function string_reserve_additional (line 104) | unsafe extern "C" fn string_reserve_additional(this: &mut String, additi...
function string_reserve_total (line 109) | unsafe extern "C" fn string_reserve_total(this: &mut String, new_cap: us...
FILE: src/unique_ptr.rs
type UniquePtr (line 23) | pub struct UniquePtr<T>
function null (line 38) | pub fn null() -> Self {
function new (line 46) | pub fn new(value: T) -> Self
function is_null (line 59) | pub fn is_null(&self) -> bool {
function as_ref (line 65) | pub fn as_ref(&self) -> Option<&T> {
function as_mut (line 72) | pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
function pin_mut (line 86) | pub fn pin_mut(&mut self) -> Pin<&mut T> {
function as_ptr (line 98) | pub fn as_ptr(&self) -> *const T {
function as_mut_ptr (line 109) | pub fn as_mut_ptr(&self) -> *mut T {
function into_raw (line 116) | pub fn into_raw(self) -> *mut T {
function from_raw (line 130) | pub unsafe fn from_raw(raw: *mut T) -> Self {
method drop (line 149) | fn drop(&mut self) {
type Target (line 158) | type Target = T;
method deref (line 160) | fn deref(&self) -> &Self::Target {
method deref_mut (line 175) | fn deref_mut(&mut self) -> &mut Self::Target {
method fmt (line 190) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 202) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method eq (line 214) | fn eq(&self, other: &Self) -> bool {
method partial_cmp (line 225) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method cmp (line 234) | fn cmp(&self, other: &Self) -> Ordering {
method hash (line 243) | fn hash<H>(&self, hasher: &mut H)
method read (line 261) | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
method read_to_end (line 266) | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
method read_to_string (line 271) | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
method read_exact (line 276) | fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
method seek (line 294) | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
method rewind (line 299) | fn rewind(&mut self) -> io::Result<()> {
method stream_position (line 304) | fn stream_position(&mut self) -> io::Result<u64> {
method seek_relative (line 309) | fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
method write (line 327) | fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
method write_vectored (line 332) | fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
method flush (line 337) | fn flush(&mut self) -> io::Result<()> {
method write_all (line 342) | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
method write_fmt (line 347) | fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
type UniquePtrTarget (line 380) | pub unsafe trait UniquePtrTarget {
method __typename (line 382) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
method __null (line 384) | fn __null() -> MaybeUninit<*mut c_void>;
method __new (line 386) | fn __new(value: Self) -> MaybeUninit<*mut c_void>
method __raw (line 396) | unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
method __get (line 398) | unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
method __release (line 400) | unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
method __drop (line 402) | unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
method __typename (line 419) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
method __null (line 422) | fn __null() -> MaybeUninit<*mut c_void> {
method __raw (line 429) | unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
method __get (line 434) | unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
method __release (line 437) | unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
method __drop (line 440) | unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
method __typename (line 449) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
method __null (line 452) | fn __null() -> MaybeUninit<*mut c_void> {
method __raw (line 455) | unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
method __get (line 458) | unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
method __release (line 461) | unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
method __drop (line 464) | unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
function unique_ptr_std_string_null (line 407) | fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
function unique_ptr_std_string_raw (line 409) | fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *...
function unique_ptr_std_string_get (line 411) | fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *...
function unique_ptr_std_string_release (line 413) | fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) ->...
function unique_ptr_std_string_drop (line 415) | fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
FILE: src/unwind.rs
function prevent_unwind (line 5) | pub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R
type Guard (line 30) | struct Guard {
method drop (line 36) | fn drop(&mut self) {
FILE: src/weak_ptr.rs
type WeakPtr (line 16) | pub struct WeakPtr<T>
function null (line 31) | pub fn null() -> Self {
function upgrade (line 44) | pub fn upgrade(&self) -> SharedPtr<T>
method clone (line 65) | fn clone(&self) -> Self {
method drop (line 80) | fn drop(&mut self) {
method fmt (line 90) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
type WeakPtrTarget (line 100) | pub unsafe trait WeakPtrTarget {
method __typename (line 102) | fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
method __null (line 104) | unsafe fn __null(new: *mut c_void);
method __clone (line 106) | unsafe fn __clone(this: *const c_void, new: *mut c_void);
method __downgrade (line 108) | unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
method __upgrade (line 110) | unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
method __drop (line 112) | unsafe fn __drop(this: *mut c_void);
FILE: syntax/atom.rs
type Atom (line 6) | pub(crate) enum Atom {
method from (line 26) | pub(crate) fn from(ident: &Ident) -> Option<Self> {
method from_str (line 30) | pub(crate) fn from_str(s: &str) -> Option<Self> {
method as_ref (line 61) | fn as_ref(&self) -> &str {
method fmt (line 55) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method eq (line 85) | fn eq(&self, atom: &Atom) -> bool {
function eq (line 94) | fn eq(&self, atom: &Atom) -> bool {
function eq (line 100) | fn eq(&self, atom: &Atom) -> bool {
FILE: syntax/attrs.rs
type Parser (line 29) | pub(crate) struct Parser<'a> {
function parse (line 48) | pub(crate) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: ...
type DocAttribute (line 204) | enum DocAttribute {
function parse_doc_attribute (line 213) | fn parse_doc_attribute(meta: &Meta) -> Result<DocAttribute> {
function parse_derive_attribute (line 231) | fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result...
function parse_default_attribute (line 247) | fn parse_default_attribute(meta: &Meta) -> Result<()> {
function parse_cxx_name_attribute (line 259) | fn parse_cxx_name_attribute(meta: &Meta) -> Result<ForeignName> {
function parse_rust_ident_attribute (line 278) | fn parse_rust_ident_attribute(meta: &Meta) -> Result<Ident> {
type OtherAttrs (line 304) | pub(crate) struct OtherAttrs {
method new (line 311) | pub(crate) fn new() -> Self {
method extend (line 319) | pub(crate) fn extend(&mut self, other: Self) {
FILE: syntax/cfg.rs
type CfgExpr (line 10) | pub(crate) enum CfgExpr {
method merge_and (line 26) | pub(crate) fn merge_and(&mut self, expr: CfgExpr) {
type ComputedCfg (line 19) | pub(crate) enum ComputedCfg<'a> {
function all (line 41) | pub(crate) fn all(one: &'a CfgExpr, two: &'a CfgExpr) -> Self {
function merge_or (line 51) | pub(crate) fn merge_or(&mut self, other: impl Into<ComputedCfg<'a>>) {
function from (line 72) | fn from(cfg: &'a CfgExpr) -> Self {
method eq (line 80) | fn eq(&self, other: &Self) -> bool {
method hash (line 102) | fn hash<H: Hasher>(&self, hasher: &mut H) {
method eq (line 120) | fn eq(&self, other: &Self) -> bool {
method hash (line 140) | fn hash<H: Hasher>(&self, hasher: &mut H) {
function parse_attribute (line 150) | pub(crate) fn parse_attribute(attr: &Attribute) -> Result<CfgExpr> {
function parse_single (line 158) | fn parse_single(input: ParseStream) -> Result<CfgExpr> {
function parse_multiple (line 188) | fn parse_multiple(input: ParseStream) -> Result<Vec<CfgExpr>> {
FILE: syntax/check.rs
type Check (line 14) | pub(crate) struct Check<'a> {
type Generator (line 21) | pub(crate) enum Generator {
function typecheck (line 34) | pub(crate) fn typecheck(cx: &mut Errors, apis: &[Api], types: &Types, ge...
function do_typecheck (line 43) | fn do_typecheck(cx: &mut Check) {
function error (line 78) | pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
function check_type_ident (line 83) | fn check_type_ident(cx: &mut Check, name: &NamedType) {
function check_type_box (line 96) | fn check_type_box(cx: &mut Check, ptr: &Ty1) {
function check_type_rust_vec (line 114) | fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
function check_type_unique_ptr (line 146) | fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
function check_type_shared_ptr (line 164) | fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
function check_type_weak_ptr (line 187) | fn check_type_weak_ptr(cx: &mut Check, ptr: &Ty1) {
function check_type_cxx_vector (line 210) | fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
function check_type_ref (line 233) | fn check_type_ref(cx: &mut Check, ty: &Ref) {
function check_type_ptr (line 270) | fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
function check_type_slice_ref (line 283) | fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
function check_type_array (line 307) | fn check_type_array(cx: &mut Check, ty: &Array) {
function check_type_fn (line 315) | fn check_type_fn(cx: &mut Check, ty: &Signature) {
function check_api_struct (line 332) | fn check_api_struct(cx: &mut Check, strct: &Struct) {
function check_api_enum (line 390) | fn check_api_enum(cx: &mut Check, enm: &Enum) {
function check_api_type (line 436) | fn check_api_type(cx: &mut Check, ety: &ExternType) {
function check_api_fn (line 470) | fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
function check_api_type_alias (line 584) | fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
function check_api_impl (line 593) | fn check_api_impl(cx: &mut Check, imp: &Impl) {
function check_mut_return_restriction (line 623) | fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
function check_reserved_name (line 685) | fn check_reserved_name(cx: &mut Check, ident: &Ident) {
function check_reserved_lifetime (line 699) | fn check_reserved_lifetime(cx: &mut Check, lifetime: &Lifetime) {
function check_lifetimes (line 710) | fn check_lifetimes(cx: &mut Check, generics: &Lifetimes) {
function check_generics (line 716) | fn check_generics(cx: &mut Check, generics: &Generics) {
function is_unsized (line 724) | fn is_unsized(types: &Types, ty: &Type) -> bool {
function span_for_struct_error (line 750) | fn span_for_struct_error(strct: &Struct) -> TokenStream {
function span_for_enum_error (line 757) | fn span_for_enum_error(enm: &Enum) -> TokenStream {
function span_for_receiver_error (line 764) | fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
function span_for_generics_error (line 777) | fn span_for_generics_error(efn: &ExternFn) -> TokenStream {
function describe (line 784) | fn describe(types: &Types, ty: &Type) -> String {
FILE: syntax/derive.rs
type Derive (line 5) | pub(crate) struct Derive {
method from (line 30) | pub(crate) fn from(ident: &Ident) -> Option<Self> {
method eq (line 55) | fn eq(&self, other: &Trait) -> bool {
type Trait (line 11) | pub(crate) enum Trait {
method as_ref (line 61) | fn as_ref(&self) -> &str {
method fmt (line 83) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
function contains (line 88) | pub(crate) fn contains(derives: &[Derive], query: Trait) -> bool {
FILE: syntax/discriminant.rs
type DiscriminantSet (line 10) | pub(crate) struct DiscriminantSet {
method new (line 29) | pub(crate) fn new(repr: Option<Atom>) -> Self {
method insert (line 37) | pub(crate) fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
method insert_next (line 64) | pub(crate) fn insert_next(&mut self) -> Result<Discriminant> {
method inferred_repr (line 88) | pub(crate) fn inferred_repr(&self) -> Result<Atom> {
type Discriminant (line 17) | pub(crate) struct Discriminant {
method zero (line 152) | pub(crate) const fn zero() -> Self {
method pos (line 159) | const fn pos(u: u64) -> Self {
method neg (line 166) | const fn neg(i: i64) -> Self {
type Sign (line 23) | enum Sign {
function expr_to_discriminant (line 107) | fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Ato...
function insert (line 134) | fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Resu...
method fmt (line 184) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method to_tokens (line 193) | fn to_tokens(&self, tokens: &mut TokenStream) {
type Err (line 202) | type Err = Error;
method from_str (line 204) | fn from_str(mut s: &str) -> Result<Self> {
method cmp (line 222) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 234) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
function parse_int_suffix (line 239) | fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
type Limits (line 254) | pub(crate) struct Limits {
method of (line 261) | pub(crate) fn of(repr: Atom) -> Option<Limits> {
constant LIMITS (line 271) | const LIMITS: [Limits; 8] = [
FILE: syntax/doc.rs
type Doc (line 5) | pub(crate) struct Doc {
method new (line 11) | pub(crate) fn new() -> Self {
method push (line 18) | pub(crate) fn push(&mut self, lit: LitStr) {
method is_empty (line 23) | pub(crate) fn is_empty(&self) -> bool {
method to_string (line 28) | pub(crate) fn to_string(&self) -> String {
method to_tokens (line 39) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: syntax/error.rs
type Error (line 4) | pub(crate) struct Error {
method fmt (line 13) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
FILE: syntax/file.rs
type Module (line 10) | pub(crate) struct Module {
type Item (line 27) | pub(crate) enum Item {
type ItemForeignMod (line 36) | pub(crate) struct ItemForeignMod {
method parse (line 46) | fn parse(input: ParseStream) -> Result<Self> {
method parse (line 88) | fn parse(input: ParseStream) -> Result<Self> {
FILE: syntax/ident.rs
function check (line 4) | fn check(cx: &mut Check, name: &Pair) {
function check_all (line 27) | pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
FILE: syntax/impls.rs
method eq (line 9) | fn eq(&self, other: &Self) -> bool {
type Target (line 29) | type Target = Signature;
method deref (line 31) | fn deref(&self) -> &Self::Target {
method deref_mut (line 37) | fn deref_mut(&mut self) -> &mut Self::Target {
method hash (line 43) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 67) | fn eq(&self, other: &Self) -> bool {
method eq (line 89) | fn eq(&self, other: &Self) -> bool {
method hash (line 105) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 121) | fn eq(&self, other: &Self) -> bool {
method hash (line 139) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 154) | fn eq(&self, other: &Self) -> bool {
method hash (line 178) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 198) | fn eq(&self, other: &Ptr) -> bool {
method hash (line 218) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 234) | fn eq(&self, other: &Self) -> bool {
method hash (line 256) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 274) | fn eq(&self, other: &Self) -> bool {
method hash (line 294) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 310) | fn eq(&self, other: &Self) -> bool {
method hash (line 366) | fn hash<H: Hasher>(&self, state: &mut H) {
method eq (line 402) | fn eq(&self, other: &Self) -> bool {
method hash (line 432) | fn hash<H: Hasher>(&self, state: &mut H) {
FILE: syntax/improper.rs
type ImproperCtype (line 7) | pub(crate) enum ImproperCtype<'a> {
function determine_improper_ctype (line 14) | pub(crate) fn determine_improper_ctype(
FILE: syntax/instantiate.rs
type ImplKey (line 9) | pub(crate) enum ImplKey<'a> {
function is_implicit_impl_ok (line 28) | pub(crate) fn is_implicit_impl_ok(&self, types: &Types) -> bool {
function inner (line 36) | fn inner(&self) -> &'a Type {
type NamedImplKey (line 49) | pub(crate) struct NamedImplKey<'a> {
method impl_key (line 64) | pub(crate) fn impl_key(&self, res: &UnorderedMap<&Ident, Resolution>) ->...
method eq (line 78) | fn eq(&self, other: &Self) -> bool {
method hash (line 86) | fn hash<H: Hasher>(&self, hasher: &mut H) {
function new (line 92) | fn new(outer: &'a Type, ty1: &'a Ty1, res: &UnorderedMap<&Ident, Resolut...
FILE: syntax/mangle.rs
constant CXXBRIDGE (line 77) | const CXXBRIDGE: &str = "cxxbridge1";
constant CXXVERSION (line 78) | const CXXVERSION: &str = env!("CARGO_PKG_VERSION_PATCH");
function extern_fn (line 86) | pub(crate) fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
function operator (line 102) | pub(crate) fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
function c_trampoline (line 114) | pub(crate) fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) ->...
function r_trampoline (line 119) | pub(crate) fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) ->...
function typename (line 133) | pub(crate) fn typename(t: &Type, res: &UnorderedMap<&Ident, Resolution>)...
FILE: syntax/map.rs
type OrderedMap (line 13) | pub(crate) struct OrderedMap<K, V>(indexmap::IndexMap<K, V>);
function new (line 16) | pub(crate) fn new() -> Self {
function keys (line 20) | pub(crate) fn keys(&self) -> indexmap::map::Keys<K, V> {
function contains_key (line 24) | pub(crate) fn contains_key<Q>(&self, key: &Q) -> bool
function insert (line 36) | pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V> {
function entry (line 40) | pub(crate) fn entry(&mut self, key: K) -> indexmap::map::Entry<K, V> {
type Item (line 46) | type Item = (&'a K, &'a V);
type IntoIter (line 47) | type IntoIter = indexmap::map::Iter<'a, K, V>;
method into_iter (line 48) | fn into_iter(self) -> Self::IntoIter {
type UnorderedMap (line 62) | pub(crate) struct UnorderedMap<K, V>(HashMap<K, V>);
function new (line 65) | pub(crate) fn new() -> Self {
function insert (line 74) | pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V> {
function contains_key (line 78) | pub(crate) fn contains_key<Q>(&self, key: &Q) -> bool
function get (line 86) | pub(crate) fn get<Q>(&self, key: &Q) -> Option<&V>
function entry (line 94) | pub(crate) fn entry(&mut self, key: K) -> Entry<K, V> {
function remove (line 99) | pub(crate) fn remove<Q>(&mut self, key: &Q) -> Option<V>
function keys (line 107) | pub(crate) fn keys(&self) -> UnorderedSet<K>
method default (line 121) | fn default() -> Self {
type Output (line 131) | type Output = V;
function index (line 133) | fn index(&self, key: &Q) -> &V {
FILE: syntax/message.rs
type Message (line 5) | pub(crate) struct Message(String);
method new (line 8) | pub fn new() -> Self {
method write_fmt (line 12) | pub fn write_fmt(&mut self, args: fmt::Arguments) {
method fmt (line 18) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method to_tokens (line 24) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: syntax/mod.rs
type Api (line 57) | pub(crate) enum Api {
type Include (line 70) | pub(crate) struct Include {
type IncludeKind (line 82) | pub enum IncludeKind {
type ExternType (line 89) | pub(crate) struct ExternType {
type Struct (line 109) | pub(crate) struct Struct {
type Enum (line 124) | pub(crate) struct Enum {
type EnumRepr (line 140) | pub(crate) struct EnumRepr {
type ExternFn (line 145) | pub(crate) struct ExternFn {
type TypeAlias (line 159) | pub(crate) struct TypeAlias {
type Impl (line 179) | pub(crate) struct Impl {
type Lifetimes (line 193) | pub(crate) struct Lifetimes {
type Signature (line 199) | pub(crate) struct Signature {
type FnKind (line 213) | pub(crate) enum FnKind {
type Var (line 222) | pub(crate) struct Var {
type Receiver (line 235) | pub(crate) struct Receiver {
type Variant (line 250) | pub(crate) struct Variant {
type Type (line 263) | pub(crate) enum Type {
type Ty1 (line 280) | pub(crate) struct Ty1 {
type Ref (line 287) | pub(crate) struct Ref {
type Ptr (line 297) | pub(crate) struct Ptr {
type SliceRef (line 305) | pub(crate) struct SliceRef {
type Array (line 314) | pub(crate) struct Array {
type Lang (line 323) | pub(crate) enum Lang {
type Pair (line 332) | pub(crate) struct Pair {
type NamedType (line 341) | pub(crate) struct NamedType {
FILE: syntax/names.rs
type ForeignName (line 11) | pub(crate) struct ForeignName {
method parse (line 38) | pub(crate) fn parse(text: &str, span: Span) -> Result<Self> {
method eq (line 58) | fn eq(&self, rhs: &str) -> bool {
method to_symbol (line 16) | pub(crate) fn to_symbol(&self) -> Symbol {
method new (line 27) | pub(crate) fn new(rust: Ident) -> Self {
method fmt (line 52) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
FILE: syntax/namespace.rs
type Namespace (line 11) | pub(crate) struct Namespace {
constant ROOT (line 16) | pub(crate) const ROOT: Self = Namespace {
method iter (line 20) | pub(crate) fn iter(&self) -> Iter<Ident> {
method parse_bridge_attr_namespace (line 24) | pub(crate) fn parse_bridge_attr_namespace(input: ParseStream) -> Resul...
method parse_meta (line 36) | pub(crate) fn parse_meta(meta: &Meta) -> Result<Self> {
method from_iter (line 91) | fn from_iter<I>(idents: I) -> Self
method default (line 69) | fn default() -> Self {
method parse (line 76) | fn parse(input: ParseStream) -> Result<Self> {
type Item (line 83) | type Item = &'a Ident;
type IntoIter (line 84) | type IntoIter = Iter<'a, Ident>;
method into_iter (line 85) | fn into_iter(self) -> Self::IntoIter {
FILE: syntax/parse.rs
function parse_items (line 31) | pub(crate) fn parse_items(
function parse_struct (line 59) | fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Names...
function parse_enum (line 203) | fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) ->...
function parse_variant (line 299) | fn parse_variant(
function parse_foreign_mod (line 354) | fn parse_foreign_mod(
function parse_lang (line 457) | fn parse_lang(abi: &Abi) -> Result<Lang> {
function parse_extern_type (line 476) | fn parse_extern_type(
function parse_extern_fn (line 534) | fn parse_extern_fn(
function parse_extern_verbatim (line 733) | fn parse_extern_verbatim(
function parse_extern_verbatim_type (line 770) | fn parse_extern_verbatim_type(
function extern_type_lifetimes (line 822) | fn extern_type_lifetimes(cx: &mut Errors, generics: Generics) -> Lifetim...
function parse_extern_verbatim_fn (line 862) | fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
function parse_type_alias (line 868) | fn parse_type_alias(
function parse_extern_type_bounded (line 930) | fn parse_extern_type_bounded(
function parse_impl (line 1019) | fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api> {
function parse_include (line 1109) | fn parse_include(input: ParseStream) -> Result<Include> {
function parse_type (line 1155) | fn parse_type(ty: &RustType) -> Result<Type> {
function parse_type_reference (line 1167) | fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
function parse_type_ptr (line 1210) | fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
function parse_type_path (line 1227) | fn parse_type_path(ty: &TypePath) -> Result<Type> {
function parse_type_array (line 1347) | fn parse_type_array(ty: &TypeArray) -> Result<Type> {
function parse_type_fn (line 1378) | fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
function parse_return_type (line 1450) | fn parse_return_type(
function visibility_pub (line 1482) | fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
function pair (line 1490) | fn pair(
FILE: syntax/pod.rs
function is_guaranteed_pod (line 6) | pub(crate) fn is_guaranteed_pod(&self, ty: impl Into<TypeQuery<'a>>) -> ...
FILE: syntax/primitive.rs
type PrimitiveKind (line 4) | pub(crate) enum PrimitiveKind {
function kind (line 10) | pub(crate) fn kind(ty: &Type) -> Option<PrimitiveKind> {
FILE: syntax/qualified.rs
type QualifiedName (line 5) | pub(crate) struct QualifiedName {
method parse_quoted (line 10) | pub(crate) fn parse_quoted(lit: &LitStr) -> Result<Self> {
method parse_unquoted (line 22) | pub(crate) fn parse_unquoted(input: ParseStream) -> Result<Self> {
method parse_quoted_or_unquoted (line 27) | pub(crate) fn parse_quoted_or_unquoted(input: ParseStream) -> Result<S...
function parse_unquoted (line 37) | fn parse_unquoted(input: ParseStream, allow_raw: bool) -> Result<Qualifi...
FILE: syntax/query.rs
type TypeQuery (line 4) | pub(crate) enum TypeQuery<'a> {
function from (line 22) | fn from(query: &'a NamedType) -> Self {
function from (line 28) | fn from(query: &'a Type) -> Self {
FILE: syntax/report.rs
type Errors (line 5) | pub(crate) struct Errors {
method new (line 10) | pub(crate) fn new() -> Self {
method error (line 14) | pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
method push (line 18) | pub(crate) fn push(&mut self, error: Error) {
method propagate (line 22) | pub(crate) fn propagate(&mut self) -> Result<()> {
FILE: syntax/repr.rs
type Repr (line 6) | pub(crate) enum Repr {
method parse (line 12) | fn parse(input: ParseStream) -> Result<Self> {
FILE: syntax/resolve.rs
type Resolution (line 6) | pub(crate) struct Resolution<'a> {
function resolve (line 14) | pub(crate) fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<...
function try_resolve (line 22) | pub(crate) fn try_resolve(&self, ident: &impl UnresolvedName) -> Option<...
type UnresolvedName (line 28) | pub(crate) trait UnresolvedName {
method ident (line 29) | fn ident(&self) -> &Ident;
method ident (line 33) | fn ident(&self) -> &Ident {
method ident (line 39) | fn ident(&self) -> &Ident {
FILE: syntax/set.rs
type OrderedSet (line 11) | pub(crate) struct OrderedSet<T> {
function new (line 20) | pub(crate) fn new() -> Self {
function insert (line 27) | pub(crate) fn insert(&mut self, value: &'a T) -> bool {
function is_empty (line 37) | pub(crate) fn is_empty(&self) -> bool {
function iter (line 41) | pub(crate) fn iter(&self) -> Iter<'_, 'a, T> {
type Item (line 47) | type Item = &'a T;
type IntoIter (line 48) | type IntoIter = Iter<'s, 'a, T>;
method into_iter (line 49) | fn into_iter(self) -> Self::IntoIter {
type Item (line 55) | type Item = &'a T;
type IntoIter (line 56) | type IntoIter = <Vec<&'a T> as IntoIterator>::IntoIter;
method into_iter (line 57) | fn into_iter(self) -> Self::IntoIter {
type UnorderedSet (line 70) | pub(crate) struct UnorderedSet<T>(HashSet<T>);
function new (line 76) | pub(crate) fn new() -> Self {
function insert (line 80) | pub(crate) fn insert(&mut self, value: T) -> bool {
function contains (line 84) | pub(crate) fn contains<Q>(&self, value: &Q) -> bool
function get (line 93) | pub(crate) fn get<Q>(&self, value: &Q) -> Option<&T>
function retain (line 101) | pub(crate) fn retain(&mut self, f: impl FnMut(&T) -> bool) {
function extend (line 106) | pub(crate) fn extend(&mut self, iter: impl IntoIterator<Item = T>) {
type Iter (line 114) | pub(crate) struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
type Item (line 117) | type Item = &'a T;
method next (line 119) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 123) | fn size_hint(&self) -> (usize, Option<usize>) {
method fmt (line 132) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
FILE: syntax/signature.rs
method receiver (line 7) | pub fn receiver(&self) -> Option<&Receiver> {
method receiver_mut (line 14) | pub fn receiver_mut(&mut self) -> Option<&mut Receiver> {
method self_type (line 21) | pub fn self_type(&self) -> Option<&Ident> {
method undeclared_lifetimes (line 30) | pub fn undeclared_lifetimes<'a>(&'a self) -> OrderedSet<&'a Lifetime> {
FILE: syntax/symbol.rs
type Symbol (line 10) | pub(crate) struct Symbol(String);
method push (line 25) | fn push(&mut self, segment: &dyn Display) {
method from_idents (line 34) | pub(crate) fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment...
method contains (line 44) | pub(crate) fn contains(&self, ch: char) -> bool {
method fmt (line 13) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method to_tokens (line 19) | fn to_tokens(&self, tokens: &mut TokenStream) {
type Segment (line 49) | pub(crate) trait Segment {
method write (line 50) | fn write(&self, symbol: &mut Symbol);
method write (line 54) | fn write(&self, symbol: &mut Symbol) {
method write (line 60) | fn write(&self, symbol: &mut Symbol) {
method write (line 66) | fn write(&self, symbol: &mut Symbol) {
method write (line 72) | fn write(&self, symbol: &mut Symbol) {
method write (line 78) | fn write(&self, symbol: &mut Symbol) {
method write (line 86) | fn write(&self, symbol: &mut Symbol) {
method write (line 93) | fn write(&self, symbol: &mut Symbol) {
method write (line 104) | fn write(&self, symbol: &mut Symbol) {
function join (line 109) | pub(crate) fn join(segments: &[&dyn Segment]) -> Symbol {
FILE: syntax/tokens.rs
method to_tokens (line 11) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 43) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 60) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 88) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 113) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 129) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 148) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 165) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 171) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 177) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 186) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 195) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 204) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 213) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 222) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 242) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 255) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 293) | fn to_tokens(&self, tokens: &mut TokenStream) {
method to_tokens (line 300) | fn to_tokens(&self, tokens: &mut TokenStream) {
FILE: syntax/toposort.rs
type Mark (line 5) | enum Mark {
function sort (line 10) | pub(crate) fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'...
function visit (line 21) | fn visit<'a>(
FILE: syntax/trivial.rs
type TrivialReason (line 12) | pub(crate) enum TrivialReason<'a> {
function required_trivial_reasons (line 30) | pub(crate) fn required_trivial_reasons<'a>(
function as_what (line 117) | pub(crate) fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) ...
FILE: syntax/types.rs
type Types (line 20) | pub(crate) struct Types<'a> {
type ConditionalImpl (line 39) | pub(crate) struct ConditionalImpl<'a> {
function collect (line 48) | pub(crate) fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
function needs_indirect_abi (line 302) | pub(crate) fn needs_indirect_abi(&self, ty: impl Into<TypeQuery<'a>>) ->...
function is_considered_improper_ctype (line 323) | pub(crate) fn is_considered_improper_ctype(&self, ty: impl Into<TypeQuer...
function is_maybe_trivial (line 332) | pub(crate) fn is_maybe_trivial(&self, ty: &Type) -> bool {
function contains_elided_lifetime (line 347) | pub(crate) fn contains_elided_lifetime(&self, ty: &Type) -> bool {
function is_local (line 371) | pub(crate) fn is_local(&self, ty: &Type) -> bool {
type Item (line 399) | type Item = &'a Type;
type IntoIter (line 400) | type IntoIter = std::iter::Copied<indexmap::map::Keys<'t, &'a Type, Comp...
method into_iter (line 401) | fn into_iter(self) -> Self::IntoIter {
function from (line 407) | fn from(cfg: ComputedCfg<'a>) -> Self {
function from (line 416) | fn from(imp: &'a Impl) -> Self {
type ItemName (line 424) | enum ItemName<'a> {
function duplicate_name (line 429) | fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, name: ItemName) {
FILE: syntax/unpin.rs
type UnpinReason (line 8) | pub(crate) enum UnpinReason<'a> {
function required_unpin_reasons (line 14) | pub(crate) fn required_unpin_reasons<'a>(
FILE: syntax/visit.rs
type Visit (line 3) | pub(crate) trait Visit<'a> {
method visit_type (line 4) | fn visit_type(&mut self, ty: &'a Type) {
function visit_type (line 9) | pub(crate) fn visit_type<'a, V>(visitor: &mut V, ty: &'a Type)
FILE: tests/compiletest.rs
function ui (line 6) | fn ui() {
FILE: tests/cpp_compile/mod.rs
type Test (line 18) | pub struct Test {
method new (line 48) | pub fn new(cxx_bridge: TokenStream) -> Self {
method write_file (line 74) | pub fn write_file(&self, filename: impl AsRef<Path>, contents: &str) {
method compile (line 85) | pub fn compile(&self) -> CompilationResult {
type CompilationResult (line 121) | pub struct CompilationResult(process::Output);
method stdout (line 124) | fn stdout(&self) -> Cow<str> {
method stderr (line 128) | fn stderr(&self) -> Cow<str> {
method dump_output_and_panic (line 132) | fn dump_output_and_panic(&self, msg: &str) -> ! {
method error_lines (line 138) | fn error_lines(&self) -> Vec<String> {
method assert_success (line 163) | pub fn assert_success(&self) {
method expect_single_error (line 180) | pub fn expect_single_error(&self) -> String {
FILE: tests/cpp_compile/smoke_test.rs
function test_success (line 6) | fn test_success() {
function test_failure (line 26) | fn test_failure() {
function test_unexpected_extra_error (line 47) | fn test_unexpected_extra_error() {
FILE: tests/cpp_ui_tests.rs
function test_unique_ptr_of_incomplete_foward_declared_pointee (line 9) | fn test_unique_ptr_of_incomplete_foward_declared_pointee() {
FILE: tests/cxx_gen.rs
constant CXXPREFIX (line 4) | const CXXPREFIX: &str = concat!("cxxbridge1$", env!("CARGO_PKG_VERSION_P...
constant BRIDGE0 (line 6) | const BRIDGE0: &str = r#"
function test_extern_c_function (line 16) | fn test_extern_c_function() {
function test_impl_annotation (line 27) | fn test_impl_annotation() {
constant BRIDGE1 (line 38) | const BRIDGE1: &str = r#"
function test_extern_rust_method_on_c_type (line 62) | fn test_extern_rust_method_on_c_type() {
FILE: tests/cxx_string.rs
function test_async_cxx_string (line 11) | fn test_async_cxx_string() {
function test_display (line 25) | fn test_display() {
function test_debug (line 32) | fn test_debug() {
function test_fmt_write (line 39) | fn test_fmt_write() {
function test_io_write (line 48) | fn test_io_write() {
FILE: tests/cxx_vector.rs
function test_cxx_vector_new (line 4) | fn test_cxx_vector_new() {
FILE: tests/ffi/build.rs
function main (line 6) | fn main() {
FILE: tests/ffi/cast.rs
function c_char_to_unsigned (line 4) | pub fn c_char_to_unsigned(slice: &[c_char]) -> &[u8] {
function unsigned_to_c_char (line 10) | pub fn unsigned_to_c_char(slice: &[u8]) -> &[c_char] {
FILE: tests/ffi/lib.rs
type Shared (line 39) | struct Shared {
type SharedString (line 45) | struct SharedString {
type Enum (line 50) | enum Enum {
type AShared (line 60) | struct AShared {
type AEnum (line 66) | enum AEnum {
type ABEnum (line 73) | enum ABEnum {
type ABShared (line 81) | struct ABShared {
type First (line 86) | struct First {
type Second (line 92) | struct Second {
type WithArray (line 97) | pub struct WithArray {
type OveralignedStruct (line 103) | pub struct OveralignedStruct {
type StructWithLifetime (line 108) | pub struct StructWithLifetime<'a> {
function c_return_primitive (line 115) | fn c_return_primitive() -> usize;
function c_return_shared (line 116) | fn c_return_shared() -> Shared;
function c_return_box (line 117) | fn c_return_box() -> Box<R>;
function c_return_unique_ptr (line 118) | fn c_return_unique_ptr() -> UniquePtr<C>;
function c_return_shared_ptr (line 119) | fn c_return_shared_ptr() -> SharedPtr<C>;
function c_return_ref (line 120) | fn c_return_ref(shared: &Shared) -> &usize;
function c_return_mut (line 121) | fn c_return_mut(shared: &mut Shared) -> &mut usize;
function c_return_str (line 122) | fn c_return_str(shared: &Shared) -> &str;
function c_return_slice_char (line 123) | fn c_return_slice_char(shared: &Shared) -> &[c_char];
function c_return_mutsliceu8 (line 124) | fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
function c_return_rust_string (line 125) | fn c_return_rust_string() -> String;
function c_return_rust_string_lossy (line 126) | fn c_return_rust_string_lossy() -> String;
function c_return_unique_ptr_string (line 127) | fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
function c_return_unique_ptr_vector_u8 (line 128) | fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
function c_return_unique_ptr_vector_f64 (line 129) | fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
function c_return_unique_ptr_vector_string (line 130) | fn c_return_unique_ptr_vector_string() -> UniquePtr<CxxVector<CxxString>>;
function c_return_unique_ptr_vector_shared (line 131) | fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
function c_return_unique_ptr_vector_opaque (line 132) | fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
function c_return_ref_vector (line 133) | fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
function c_return_mut_vector (line 134) | fn c_return_mut_vector(c: Pin<&mut C>) -> Pin<&mut CxxVector<u8>>;
function c_return_rust_vec_u8 (line 135) | fn c_return_rust_vec_u8() -> Vec<u8>;
function c_return_ref_rust_vec (line 136) | fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
function c_return_mut_rust_vec (line 137) | fn c_return_mut_rust_vec(c: Pin<&mut C>) -> &mut Vec<u8>;
function c_return_rust_vec_string (line 138) | fn c_return_rust_vec_string() -> Vec<String>;
function c_return_rust_vec_bool (line 139) | fn c_return_rust_vec_bool() -> Vec<bool>;
function c_return_identity (line 140) | fn c_return_identity(_: usize) -> usize;
function c_return_sum (line 141) | fn c_return_sum(_: usize, _: usize) -> usize;
function c_return_enum (line 142) | fn c_return_enum(n: u16) -> Enum;
function c_return_ns_ref (line 143) | fn c_return_ns_ref(shared: &AShared) -> &usize;
function c_return_nested_ns_ref (line 144) | fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
function c_return_ns_enum (line 145) | fn c_return_ns_enum(n: u16) -> AEnum;
function c_return_nested_ns_enum (line 146) | fn c_return_nested_ns_enum(n: u16) -> ABEnum;
function c_return_const_ptr (line 147) | fn c_return_const_ptr(n: usize) -> *const C;
function c_return_mut_ptr (line 148) | fn c_return_mut_ptr(n: usize) -> *mut C;
function c_take_primitive (line 150) | fn c_take_primitive(n: usize);
function c_take_shared (line 151) | fn c_take_shared(shared: Shared);
function c_take_box (line 152) | fn c_take_box(r: Box<R>);
function c_take_ref_r (line 153) | fn c_take_ref_r(r: &R);
function c_take_ref_c (line 154) | fn c_take_ref_c(c: &C);
function c_take_str (line 155) | fn c_take_str(s: &str);
function c_take_slice_char (line 156) | fn c_take_slice_char(s: &[c_char]);
function c_take_slice_shared (line 157) | fn c_take_slice_shared(s: &[Shared]);
function c_take_slice_shared_sort (line 158) | fn c_take_slice_shared_sort(s: &mut [Shared]);
function c_take_slice_r (line 159) | fn c_take_slice_r(s: &[R]);
function c_take_slice_r_sort (line 160) | fn c_take_slice_r_sort(s: &mut [R]);
function c_take_rust_string (line 161) | fn c_take_rust_string(s: String);
function c_take_unique_ptr_string (line 162) | fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
function c_take_unique_ptr_vector_u8 (line 163) | fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
function c_take_unique_ptr_vector_f64 (line 164) | fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
function c_take_unique_ptr_vector_string (line 165) | fn c_take_unique_ptr_vector_string(v: UniquePtr<CxxVector<CxxString>>);
function c_take_unique_ptr_vector_shared (line 166) | fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
function c_take_ref_vector (line 167) | fn c_take_ref_vector(v: &CxxVector<u8>);
function c_take_rust_vec (line 168) | fn c_take_rust_vec(v: Vec<u8>);
function c_take_rust_vec_shared (line 169) | fn c_take_rust_vec_shared(v: Vec<Shared>);
function c_take_rust_vec_string (line 170) | fn c_take_rust_vec_string(v: Vec<String>);
function c_take_rust_vec_index (line 171) | fn c_take_rust_vec_index(v: Vec<u8>);
function c_take_rust_vec_shared_index (line 172) | fn c_take_rust_vec_shared_index(v: Vec<Shared>);
function c_take_rust_vec_shared_push (line 173) | fn c_take_rust_vec_shared_push(v: Vec<Shared>);
function c_take_rust_vec_shared_truncate (line 174) | fn c_take_rust_vec_shared_truncate(v: Vec<Shared>);
function c_take_rust_vec_shared_clear (line 175) | fn c_take_rust_vec_shared_clear(v: Vec<Shared>);
function c_take_rust_vec_shared_forward_iterator (line 176) | fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
function c_take_rust_vec_shared_sort (line 177) | fn c_take_rust_vec_shared_sort(v: Vec<Shared>);
function c_take_ref_rust_vec (line 178) | fn c_take_ref_rust_vec(v: &Vec<u8>);
function c_take_ref_rust_vec_string (line 179) | fn c_take_ref_rust_vec_string(v: &Vec<String>);
function c_take_ref_rust_vec_index (line 180) | fn c_take_ref_rust_vec_index(v: &Vec<u8>);
function c_take_ref_rust_vec_copy (line 181) | fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
function c_take_ref_shared_string (line 182) | fn c_take_ref_shared_string(s: &SharedString) -> &SharedString;
function c_take_callback (line 183) | fn c_take_callback(callback: fn(String) -> usize);
function c_take_callback_ref (line 184) | fn c_take_callback_ref(callback: fn(&String));
function c_take_callback_ref_lifetime (line 186) | fn c_take_callback_ref_lifetime<'a>(callback: fn(&'a String));
function c_take_callback_mut (line 187) | fn c_take_callback_mut(callback: fn(&mut String));
function c_take_enum (line 188) | fn c_take_enum(e: Enum);
function c_take_ns_enum (line 189) | fn c_take_ns_enum(e: AEnum);
function c_take_nested_ns_enum (line 190) | fn c_take_nested_ns_enum(e: ABEnum);
function c_take_ns_shared (line 191) | fn c_take_ns_shared(shared: AShared);
function c_take_nested_ns_shared (line 192) | fn c_take_nested_ns_shared(shared: ABShared);
function c_take_rust_vec_ns_shared (line 193) | fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
function c_take_rust_vec_nested_ns_shared (line 194) | fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
function c_take_const_ptr (line 195) | unsafe fn c_take_const_ptr(c: *const C) -> usize;
function c_take_mut_ptr (line 196) | unsafe fn c_take_mut_ptr(c: *mut C) -> usize;
function c_try_return_void (line 198) | fn c_try_return_void() -> Result<()>;
function c_try_return_primitive (line 199) | fn c_try_return_primitive() -> Result<usize>;
function c_fail_return_primitive (line 200) | fn c_fail_return_primitive() -> Result<usize>;
function c_try_return_box (line 201) | fn c_try_return_box() -> Result<Box<R>>;
function c_try_return_ref (line 202) | fn c_try_return_ref(s: &String) -> Result<&String>;
function c_try_return_str (line 203) | fn c_try_return_str(s: &str) -> Result<&str>;
function c_try_return_sliceu8 (line 204) | fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
function c_try_return_mutsliceu8 (line 205) | fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
function c_try_return_rust_string (line 206) | fn c_try_return_rust_string() -> Result<String>;
function c_try_return_unique_ptr_string (line 207) | fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
function c_try_return_rust_vec (line 208) | fn c_try_return_rust_vec() -> Result<Vec<u8>>;
function c_try_return_rust_vec_string (line 209) | fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
function c_try_return_ref_rust_vec (line 210) | fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
function get (line 212) | fn get(self: &C) -> usize;
function set (line 213) | fn set(self: Pin<&mut C>, n: usize) -> usize;
function get2 (line 214) | fn get2(&self) -> usize;
function getRef (line 215) | fn getRef(self: &C) -> &usize;
function getMut (line 216) | fn getMut(self: Pin<&mut C>) -> &mut usize;
function set_succeed (line 217) | fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
function get_fail (line 218) | fn get_fail(self: Pin<&mut C>) -> Result<usize>;
function c_method_on_shared (line 219) | fn c_method_on_shared(self: &Shared) -> usize;
function c_method_ref_on_shared (line 220) | fn c_method_ref_on_shared(self: &Shared) -> &usize;
function c_method_mut_on_shared (line 221) | fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
function c_static_method_on_shared (line 223) | fn c_static_method_on_shared() -> usize;
function c_set_array (line 224) | fn c_set_array(self: &mut WithArray, value: i32);
function c_get_use_count (line 226) | fn c_get_use_count(weak: &WeakPtr<C>) -> usize;
function cOverloadedMethod (line 229) | fn cOverloadedMethod(&self, x: i32) -> String;
function cOverloadedMethod (line 231) | fn cOverloadedMethod(&self, x: &str) -> String;
function cOverloadedFunction (line 233) | fn cOverloadedFunction(x: i32) -> String;
function cOverloadedFunction (line 235) | fn cOverloadedFunction(x: &str) -> String;
function ns_c_take_ns_shared (line 238) | fn ns_c_take_ns_shared(shared: AShared);
function c_static_method (line 241) | fn c_static_method() -> usize;
type ContainsOpaqueRust (line 244) | struct ContainsOpaqueRust<'a> {
type Job (line 255) | type Job = crate::module::ffi::Job;
type OpaqueRust (line 256) | type OpaqueRust = crate::module::OpaqueRust;
function c_return_borrow (line 267) | fn c_return_borrow<'a>(s: &'a CxxString) -> UniquePtr<Borrow<'a>>;
function c_return_borrow (line 271) | fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
function const_member (line 273) | fn const_member(self: &Borrow);
function nonconst_member (line 274) | fn nonconst_member(self: Pin<&mut Borrow>);
type COwnedEnum (line 279) | enum COwnedEnum {
type Buffer (line 287) | type Buffer = crate::Buffer;
function r_return_primitive (line 293) | fn r_return_primitive() -> usize;
function r_return_shared (line 294) | fn r_return_shared() -> Shared;
function r_return_box (line 295) | fn r_return_box() -> Box<R>;
function r_return_unique_ptr (line 296) | fn r_return_unique_ptr() -> UniquePtr<C>;
function r_return_shared_ptr (line 297) | fn r_return_shared_ptr() -> SharedPtr<C>;
function r_return_ref (line 298) | fn r_return_ref(shared: &Shared) -> &usize;
function r_return_mut (line 299) | fn r_return_mut(shared: &mut Shared) -> &mut usize;
function r_return_str (line 300) | fn r_return_str(shared: &Shared) -> &str;
function r_return_str_via_out_param (line 301) | unsafe fn r_return_str_via_out_param<'a>(shared: &'a Shared, out_param: ...
function r_return_sliceu8 (line 302) | fn r_return_sliceu8(shared: &Shared) -> &[u8];
function r_return_mutsliceu8 (line 303) | fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
function r_return_rust_string (line 304) | fn r_return_rust_string() -> String;
function r_return_unique_ptr_string (line 305) | fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
function r_return_rust_vec (line 306) | fn r_return_rust_vec() -> Vec<u8>;
function r_return_rust_vec_string (line 307) | fn r_return_rust_vec_string() -> Vec<String>;
function r_return_rust_vec_extern_struct (line 308) | fn r_return_rust_vec_extern_struct() -> Vec<Job>;
function r_return_rust_vec_box (line 310) | fn r_return_rust_vec_box() -> Vec<Box<R>>;
function r_return_rust_vec_box_other_module_type (line 312) | fn r_return_rust_vec_box_other_module_type() -> Vec<Box<OpaqueRust>>;
function r_return_ref_rust_vec (line 313) | fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
function r_return_mut_rust_vec (line 314) | fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
function r_return_identity (line 315) | fn r_return_identity(_: usize) -> usize;
function r_return_sum (line 316) | fn r_return_sum(_: usize, _: usize) -> usize;
function r_return_enum (line 317) | fn r_return_enum(n: u32) -> Enum;
function r_take_primitive (line 319) | fn r_take_primitive(n: usize);
function r_take_shared (line 320) | fn r_take_shared(shared: Shared);
function r_take_box (line 321) | fn r_take_box(r: Box<R>);
function r_take_unique_ptr (line 322) | fn r_take_unique_ptr(c: UniquePtr<C>);
function r_take_shared_ptr (line 323) | fn r_take_shared_ptr(c: SharedPtr<C>);
function r_take_ref_r (line 324) | fn r_take_ref_r(r: &R);
function r_take_ref_c (line 325) | fn r_take_ref_c(c: &C);
function r_take_str (line 326) | fn r_take_str(s: &str);
function r_take_slice_char (line 327) | fn r_take_slice_char(s: &[c_char]);
function r_take_rust_string (line 328) | fn r_take_rust_string(s: String);
function r_take_unique_ptr_string (line 329) | fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
function r_take_ref_vector (line 330) | fn r_take_ref_vector(v: &CxxVector<u8>);
function r_take_ref_empty_vector (line 331) | fn r_take_ref_empty_vector(v: &CxxVector<u64>);
function r_take_rust_vec (line 332) | fn r_take_rust_vec(v: Vec<u8>);
function r_take_rust_vec_string (line 333) | fn r_take_rust_vec_string(v: Vec<String>);
function r_take_ref_rust_vec (line 334) | fn r_take_ref_rust_vec(v: &Vec<u8>);
function r_take_ref_rust_vec_string (line 335) | fn r_take_ref_rust_vec_string(v: &Vec<String>);
function r_take_enum (line 336) | fn r_take_enum(e: Enum);
function r_try_return_void (line 338) | fn r_try_return_void() -> Result<()>;
function r_try_return_primitive (line 339) | fn r_try_return_primitive() -> Result<usize>;
function r_try_return_box (line 340) | fn r_try_return_box() -> Result<Box<R>>;
function r_fail_return_primitive (line 341) | fn r_fail_return_primitive() -> Result<usize>;
function r_try_return_sliceu8 (line 342) | fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
function r_try_return_mutsliceu8 (line 343) | fn r_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
function get (line 345) | fn get(self: &R) -> usize;
function set (line 346) | fn set(self: &mut R, n: usize) -> usize;
function r_method_on_shared (line 347) | fn r_method_on_shared(self: &Shared) -> String;
function r_get_array_sum (line 348) | fn r_get_array_sum(self: &WithArray) -> i32;
function r_method_on_c_get_mut (line 350) | fn r_method_on_c_get_mut(self: Pin<&mut C>) -> &mut usize;
function r_aliased_function (line 353) | fn r_aliased_function(x: i32) -> String;
function r_static_method_on_shared (line 356) | fn r_static_method_on_shared() -> usize;
function r_static_method (line 359) | fn r_static_method() -> usize;
function c_member_function_on_rust_type (line 363) | fn c_member_function_on_rust_type(self: &R);
type Dag0 (line 366) | struct Dag0 {
type Dag1 (line 370) | struct Dag1 {
type Dag2 (line 375) | struct Dag2 {
type Dag3 (line 379) | struct Dag3 {
type Dag4 (line 383) | struct Dag4 {
type StructWithLifetime2 (line 400) | pub struct StructWithLifetime2<'a> {
function r_take_unique_ptr_of_struct_with_lifetime2 (line 404) | fn r_take_unique_ptr_of_struct_with_lifetime2(_: UniquePtr<StructWithLif...
type D (line 413) | pub struct D {
type E (line 418) | pub struct E {
type F (line 428) | pub struct F {
type Id (line 434) | type Id = type_id!("F::F");
type Kind (line 435) | type Kind = Opaque;
type G (line 440) | pub struct G {
type Id (line 445) | type Id = type_id!("G::G");
type Kind (line 446) | type Kind = Trivial;
type Id (line 450) | type Id = type_id!("tests::D");
type Kind (line 451) | type Kind = Trivial;
type Id (line 455) | type Id = type_id!("tests::E");
type Kind (line 456) | type Kind = Opaque;
type R (line 461) | pub struct R(pub usize);
method get (line 464) | fn get(&self) -> usize {
method set (line 468) | fn set(&mut self, n: usize) -> usize {
method r_static_method (line 473) | fn r_static_method() -> usize {
type Reference (line 478) | pub struct Reference<'a>(pub &'a String);
function r_method_on_shared (line 481) | fn r_method_on_shared(&self) -> String {
function r_static_method_on_shared (line 485) | fn r_static_method_on_shared() -> usize {
function r_get_array_sum (line 491) | pub fn r_get_array_sum(&self) -> i32 {
function r_method_on_c_get_mut (line 498) | pub fn r_method_on_c_get_mut(self: core::pin::Pin<&mut Self>) -> &mut us...
type Buffer (line 505) | pub struct Buffer([c_char; 12]);
type Id (line 508) | type Id = type_id!("tests::Buffer");
type Kind (line 509) | type Kind = cxx::kind::Trivial;
type Error (line 513) | struct Error;
method fmt (line 518) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function r_return_primitive (line 523) | fn r_return_primitive() -> usize {
function r_return_shared (line 527) | fn r_return_shared() -> ffi::Shared {
function r_return_box (line 531) | fn r_return_box() -> Box<R> {
function r_return_unique_ptr (line 535) | fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
function r_return_shared_ptr (line 543) | fn r_return_shared_ptr() -> SharedPtr<ffi::C> {
function r_return_ref (line 556) | fn r_return_ref(shared: &ffi::Shared) -> &usize {
function r_return_mut (line 560) | fn r_return_mut(shared: &mut ffi::Shared) -> &mut usize {
function r_return_str (line 564) | fn r_return_str(shared: &ffi::Shared) -> &str {
function r_return_str_via_out_param (line 569) | fn r_return_str_via_out_param<'a>(shared: &'a ffi::Shared, out_param: &m...
function r_return_sliceu8 (line 574) | fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
function r_return_mutsliceu8 (line 579) | fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8] {
function r_return_rust_string (line 583) | fn r_return_rust_string() -> String {
function r_return_unique_ptr_string (line 587) | fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
function r_return_rust_vec (line 595) | fn r_return_rust_vec() -> Vec<u8> {
function r_return_rust_vec_string (line 599) | fn r_return_rust_vec_string() -> Vec<String> {
function r_return_rust_vec_extern_struct (line 603) | fn r_return_rust_vec_extern_struct() -> Vec<ffi::Job> {
function r_return_rust_vec_box (line 608) | fn r_return_rust_vec_box() -> Vec<Box<R>> {
function r_return_rust_vec_box_other_module_type (line 613) | fn r_return_rust_vec_box_other_module_type() -> Vec<Box<module::OpaqueRu...
function r_return_ref_rust_vec (line 617) | fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
function r_return_mut_rust_vec (line 622) | fn r_return_mut_rust_vec(shared: &mut ffi::Shared) -> &mut Vec<u8> {
function r_return_identity (line 627) | fn r_return_identity(n: usize) -> usize {
function r_return_sum (line 631) | fn r_return_sum(n1: usize, n2: usize) -> usize {
function r_return_enum (line 635) | fn r_return_enum(n: u32) -> ffi::Enum {
function r_take_primitive (line 645) | fn r_take_primitive(n: usize) {
function r_take_shared (line 649) | fn r_take_shared(shared: ffi::Shared) {
function r_take_box (line 653) | fn r_take_box(r: Box<R>) {
function r_take_unique_ptr (line 657) | fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
function r_take_shared_ptr (line 661) | fn r_take_shared_ptr(c: SharedPtr<ffi::C>) {
function r_take_ref_r (line 665) | fn r_take_ref_r(r: &R) {
function r_take_ref_c (line 669) | fn r_take_ref_c(c: &ffi::C) {
function r_take_str (line 673) | fn r_take_str(s: &str) {
function r_take_rust_string (line 677) | fn r_take_rust_string(s: String) {
function r_take_slice_char (line 681) | fn r_take_slice_char(s: &[c_char]) {
function r_take_unique_ptr_string (line 687) | fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
function r_take_ref_vector (line 691) | fn r_take_ref_vector(v: &CxxVector<u8>) {
function r_take_ref_empty_vector (line 696) | fn r_take_ref_empty_vector(v: &CxxVector<u64>) {
function r_take_rust_vec (line 701) | fn r_take_rust_vec(v: Vec<u8>) {
function r_take_rust_vec_string (line 705) | fn r_take_rust_vec_string(v: Vec<String>) {
function r_take_ref_rust_vec (line 709) | fn r_take_ref_rust_vec(v: &Vec<u8>) {
function r_take_ref_rust_vec_string (line 713) | fn r_take_ref_rust_vec_string(v: &Vec<String>) {
function r_take_enum (line 717) | fn r_take_enum(e: ffi::Enum) {
function r_take_unique_ptr_of_struct_with_lifetime2 (line 721) | fn r_take_unique_ptr_of_struct_with_lifetime2(
function r_try_return_void (line 726) | fn r_try_return_void() -> Result<(), Error> {
function r_try_return_primitive (line 730) | fn r_try_return_primitive() -> Result<usize, Error> {
function r_try_return_box (line 734) | fn r_try_return_box() -> Result<Box<R>, Error> {
function r_fail_return_primitive (line 738) | fn r_fail_return_primitive() -> Result<usize, Error> {
function r_try_return_sliceu8 (line 742) | fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
function r_try_return_mutsliceu8 (line 746) | fn r_try_return_mutsliceu8(slice: &mut [u8]) -> Result<&mut [u8], Error> {
function r_aliased_function (line 750) | fn r_aliased_function(x: i32) -> String {
FILE: tests/ffi/module.rs
type OpaqueRust (line 3) | pub struct OpaqueRust(pub i32);
type Job (line 7) | struct Job {
type C (line 14) | type C = crate::ffi::C;
function c_take_unique_ptr (line 16) | fn c_take_unique_ptr(c: UniquePtr<C>);
function c_lifetime_elision_member_fn (line 17) | fn c_lifetime_elision_member_fn(self: &C) -> &CxxVector<u8>;
function c_lifetime_elision_fn (line 18) | fn c_lifetime_elision_fn(c: &C) -> &CxxVector<u8>;
type D (line 37) | type D = crate::other::D;
type E (line 38) | type E = crate::other::E;
type F (line 40) | type F = crate::other::f::F;
type G (line 42) | type G = crate::other::G;
function c_take_trivial_ptr (line 47) | fn c_take_trivial_ptr(d: UniquePtr<D>);
function c_take_trivial_ref (line 48) | fn c_take_trivial_ref(d: &D);
function c_take_trivial_mut_ref (line 49) | fn c_take_trivial_mut_ref(d: &mut D);
function c_take_trivial_pin_ref (line 50) | fn c_take_trivial_pin_ref(d: Pin<&D>);
function c_take_trivial_pin_mut_ref (line 51) | fn c_take_trivial_pin_mut_ref(d: Pin<&mut D>);
function c_take_trivial_ref_method (line 52) | fn c_take_trivial_ref_method(self: &D);
function c_take_trivial_mut_ref_method (line 53) | fn c_take_trivial_mut_ref_method(self: &mut D);
function c_take_trivial (line 54) | fn c_take_trivial(d: D);
function c_take_trivial_ns_ptr (line 55) | fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
function c_take_trivial_ns_ref (line 56) | fn c_take_trivial_ns_ref(g: &G);
function c_take_trivial_ns (line 57) | fn c_take_trivial_ns(g: G);
function c_take_opaque_ptr (line 58) | fn c_take_opaque_ptr(e: UniquePtr<E>);
function c_take_opaque_ref (line 59) | fn c_take_opaque_ref(e: &E);
function c_take_opaque_ref_method (line 60) | fn c_take_opaque_ref_method(self: &E);
function c_take_opaque_mut_ref_method (line 61) | fn c_take_opaque_mut_ref_method(self: Pin<&mut E>);
function c_take_opaque_ns_ptr (line 62) | fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
function c_take_opaque_ns_ref (line 63) | fn c_take_opaque_ns_ref(e: &F);
function c_return_trivial_ptr (line 64) | fn c_return_trivial_ptr() -> UniquePtr<D>;
function c_return_trivial (line 65) | fn c_return_trivial() -> D;
function c_return_trivial_ns_ptr (line 66) | fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
function c_return_trivial_ns (line 67) | fn c_return_trivial_ns() -> G;
function c_return_opaque_ptr (line 68) | fn c_return_opaque_ptr() -> UniquePtr<E>;
function c_return_opaque_mut_pin (line 69) | fn c_return_opaque_mut_pin(e: Pin<&mut E>) -> Pin<&mut E>;
function c_return_ns_opaque_ptr (line 70) | fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
function c_return_ns_unique_ptr (line 71) | fn c_return_ns_unique_ptr() -> UniquePtr<H>;
function c_take_ref_ns_c (line 72) | fn c_take_ref_ns_c(h: &H);
function ns_c_take_trivial (line 75) | fn ns_c_take_trivial(d: D);
function ns_c_return_trivial (line 77) | fn ns_c_return_trivial() -> D;
function get (line 82) | fn get(self: &I) -> u32;
function ns_c_return_unique_ptr_ns (line 85) | fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
FILE: tests/ffi/tests.cc
type tests (line 24) | namespace tests {
function c_return_primitive (line 67) | size_t c_return_primitive() { return 2020; }
function Shared (line 69) | Shared c_return_shared() { return Shared{2020}; }
function c_return_ns_shared (line 71) | ::A::AShared c_return_ns_shared() { return ::A::AShared{2020}; }
function c_return_nested_ns_shared (line 73) | ::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared...
function c_return_box (line 75) | rust::Box<R> c_return_box() {
function c_return_unique_ptr (line 87) | std::unique_ptr<C> c_return_unique_ptr() {
function c_return_shared_ptr (line 91) | std::shared_ptr<C> c_return_shared_ptr() {
function c_return_ns_unique_ptr (line 95) | std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
function c_return_str (line 111) | rust::Str c_return_str(const Shared &shared) {
function c_return_slice_char (line 116) | rust::Slice<const char> c_return_slice_char(const Shared &shared) {
function c_return_mutsliceu8 (line 121) | rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
function c_return_rust_string (line 125) | rust::String c_return_rust_string() { return "2020"; }
function c_return_rust_string_lossy (line 127) | rust::String c_return_rust_string_lossy() {
function c_return_unique_ptr_string (line 131) | std::unique_ptr<std::string> c_return_unique_ptr_string() {
function c_return_unique_ptr_vector_u8 (line 135) | std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
function c_return_unique_ptr_vector_f64 (line 144) | std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
function c_return_unique_ptr_vector_string (line 153) | std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_s...
function c_return_unique_ptr_vector_shared (line 158) | std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared...
function c_return_unique_ptr_vector_opaque (line 165) | std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque() {
function c_return_rust_vec_u8 (line 175) | rust::Vec<uint8_t> c_return_rust_vec_u8() {
function c_return_rust_vec_string (line 190) | rust::Vec<rust::String> c_return_rust_vec_string() {
function c_return_rust_vec_bool (line 194) | rust::Vec<bool> c_return_rust_vec_bool() { return {true, true, false}; }
function c_return_identity (line 196) | size_t c_return_identity(size_t n) { return n; }
function c_return_sum (line 198) | size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
function Enum (line 200) | Enum c_return_enum(uint16_t n) {
function c_return_ns_enum (line 210) | ::A::AEnum c_return_ns_enum(uint16_t n) {
function c_return_nested_ns_enum (line 220) | ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n) {
function C (line 230) | const C *c_return_const_ptr(size_t c) { return new C(c); }
function C (line 232) | C *c_return_mut_ptr(size_t c) { return new C(c); }
function c_return_borrow (line 240) | std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
function c_take_primitive (line 244) | void c_take_primitive(size_t n) {
function c_take_shared (line 250) | void c_take_shared(Shared shared) {
function c_take_ns_shared (line 256) | void c_take_ns_shared(::A::AShared shared) {
function c_take_nested_ns_shared (line 262) | void c_take_nested_ns_shared(::A::B::ABShared shared) {
function c_take_box (line 268) | void c_take_box(rust::Box<R> r) {
function c_take_unique_ptr (line 274) | void c_take_unique_ptr(std::unique_ptr<C> c) {
function c_take_ref_r (line 280) | void c_take_ref_r(const R &r) {
function c_take_ref_c (line 286) | void c_take_ref_c(const C &c) {
function c_take_ref_ns_c (line 292) | void c_take_ref_ns_c(const ::H::H &h) {
function c_take_str (line 298) | void c_take_str(rust::Str s) {
function c_take_slice_char (line 304) | void c_take_slice_char(rust::Slice<const char> s) {
function c_take_slice_shared (line 310) | void c_take_slice_shared(rust::Slice<const Shared> s) {
function c_take_slice_shared_sort (line 317) | void c_take_slice_shared_sort(rust::Slice<Shared> s) {
function c_take_slice_r (line 326) | void c_take_slice_r(rust::Slice<const R> s) {
function c_take_slice_r_sort (line 334) | void c_take_slice_r_sort(rust::Slice<R> s) {
function c_take_rust_string (line 346) | void c_take_rust_string(rust::String s) {
function c_take_unique_ptr_string (line 352) | void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
function c_take_unique_ptr_vector_u8 (line 358) | void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>>...
function c_take_unique_ptr_vector_f64 (line 364) | void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>>...
function c_take_unique_ptr_vector_string (line 370) | void c_take_unique_ptr_vector_string(
function c_take_unique_ptr_vector_shared (line 376) | void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Share...
function c_take_ref_vector (line 382) | void c_take_ref_vector(const std::vector<uint8_t> &v) {
function c_take_rust_vec (line 388) | void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
function c_take_rust_vec_index (line 390) | void c_take_rust_vec_index(rust::Vec<uint8_t> v) {
function c_take_rust_vec_shared (line 401) | void c_take_rust_vec_shared(rust::Vec<Shared> v) {
function c_take_rust_vec_ns_shared (line 411) | void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v) {
function c_take_rust_vec_nested_ns_shared (line 421) | void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v) {
function c_take_rust_vec_string (line 431) | void c_take_rust_vec_string(rust::Vec<rust::String> v) {
function c_take_rust_vec_shared_forward_iterator (line 436) | void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
function c_take_rust_vec_shared_sort (line 451) | void c_take_rust_vec_shared_sort(rust::Vec<Shared> v) {
function c_take_rust_vec_shared_index (line 460) | void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
function c_take_rust_vec_shared_push (line 467) | void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
function c_take_rust_vec_shared_truncate (line 475) | void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v) {
function c_take_rust_vec_shared_clear (line 485) | void c_take_rust_vec_shared_clear(rust::Vec<Shared> v) {
function c_take_ref_rust_vec (line 492) | void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
function c_take_ref_rust_vec_string (line 499) | void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
function c_take_ref_rust_vec_index (line 504) | void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
function c_take_ref_rust_vec_copy (line 511) | void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
function SharedString (line 523) | const SharedString &c_take_ref_shared_string(const SharedString &s) {
function c_take_callback (line 530) | void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
function c_take_callback_ref (line 534) | void c_take_callback_ref(rust::Fn<void(const rust::String &)> callback) {
function c_take_callback_mut (line 539) | void c_take_callback_mut(rust::Fn<void(rust::String &)> callback) {
function c_take_enum (line 544) | void c_take_enum(Enum e) {
function c_take_ns_enum (line 550) | void c_take_ns_enum(::A::AEnum e) {
function c_take_nested_ns_enum (line 556) | void c_take_nested_ns_enum(::A::B::ABEnum e) {
function c_take_const_ptr (line 562) | size_t c_take_const_ptr(const C *c) { return c->get(); }
function c_take_mut_ptr (line 564) | size_t c_take_mut_ptr(C *c) {
function c_try_return_void (line 570) | void c_try_return_void() {}
function c_try_return_primitive (line 572) | size_t c_try_return_primitive() { return 2020; }
function c_fail_return_primitive (line 574) | size_t c_fail_return_primitive() { throw std::logic_error("logic error...
function c_try_return_box (line 576) | rust::Box<R> c_try_return_box() { return c_return_box(); }
function c_try_return_str (line 580) | rust::Str c_try_return_str(rust::Str s) { return s; }
function c_try_return_sliceu8 (line 582) | rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint...
function c_try_return_mutsliceu8 (line 586) | rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) {
function c_try_return_rust_string (line 590) | rust::String c_try_return_rust_string() { return c_return_rust_string(...
function c_try_return_unique_ptr_string (line 592) | std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
function c_try_return_rust_vec (line 596) | rust::Vec<uint8_t> c_try_return_rust_vec() {
function c_try_return_rust_vec_string (line 600) | rust::Vec<rust::String> c_try_return_rust_vec_string() {
function c_get_use_count (line 609) | size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept {
function C (line 613) | C *cxx_test_suite_get_unique_ptr() noexcept {
function cxx_test_suite_get_shared_ptr (line 617) | void
function cOverloadedFunction (line 642) | rust::String cOverloadedFunction(int x) {
function cOverloadedFunction (line 646) | rust::String cOverloadedFunction(rust::Str x) {
function c_take_trivial_ptr (line 652) | void c_take_trivial_ptr(std::unique_ptr<D> d) {
function c_take_trivial_ref (line 658) | void c_take_trivial_ref(const D &d) {
function c_take_trivial_mut_ref (line 664) | void c_take_trivial_mut_ref(D &d) { (void)d; }
function c_take_trivial_pin_ref (line 666) | void c_take_trivial_pin_ref(const D &d) { (void)d; }
function c_take_trivial_pin_mut_ref (line 668) | void c_take_trivial_pin_mut_ref(D &d) { (void)d; }
function c_take_trivial (line 682) | void c_take_trivial(D d) {
function c_take_trivial_ns_ptr (line 688) | void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g) {
function c_take_trivial_ns_ref (line 694) | void c_take_trivial_ns_ref(const ::G::G &g) {
function c_take_trivial_ns (line 700) | void c_take_trivial_ns(::G::G g) {
function c_take_opaque_ptr (line 706) | void c_take_opaque_ptr(std::unique_ptr<E> e) {
function c_take_opaque_ns_ptr (line 712) | void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f) {
function c_take_opaque_ref (line 718) | void c_take_opaque_ref(const E &e) {
function c_take_opaque_ns_ref (line 736) | void c_take_opaque_ns_ref(const ::F::F &f) {
function c_return_trivial_ptr (line 742) | std::unique_ptr<D> c_return_trivial_ptr() {
function D (line 748) | D c_return_trivial() {
function c_return_trivial_ns_ptr (line 754) | std::unique_ptr<::G::G> c_return_trivial_ns_ptr() {
function c_return_trivial_ns (line 760) | ::G::G c_return_trivial_ns() {
function c_return_opaque_ptr (line 766) | std::unique_ptr<E> c_return_opaque_ptr() {
function E (line 773) | E &c_return_opaque_mut_pin(E &e) { return e; }
function c_return_ns_opaque_ptr (line 775) | std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
type other (line 1013) | namespace other {
function ns_c_take_trivial (line 1014) | void ns_c_take_trivial(::tests::D d) {
function ns_c_return_trivial (line 1020) | ::tests::D ns_c_return_trivial() {
function ns_c_take_ns_shared (line 1026) | void ns_c_take_ns_shared(::A::AShared shared) {
type I (line 1033) | namespace I {
function ns_c_return_unique_ptr_ns (line 1036) | std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
class rust::Box<tests::Shared> (line 1049) | class rust::Box<tests::Shared>
class rust::Slice<const char> (line 1050) | class rust::Slice<const char>
class rust::Slice<const uint8_t> (line 1051) | class rust::Slice<const uint8_t>
class rust::Slice<uint8_t> (line 1052) | class rust::Slice<uint8_t>
class rust::Slice<const tests::Shared> (line 1053) | class rust::Slice<const tests::Shared>
class rust::Slice<tests::Shared> (line 1054) | class rust::Slice<tests::Shared>
class rust::Slice<const tests::R> (line 1055) | class rust::Slice<const tests::R>
class rust::Slice<tests::R> (line 1056) | class rust::Slice<tests::R>
class rust::Vec<uint8_t> (line 1057) | class rust::Vec<uint8_t>
class rust::Vec<rust::String> (line 1058) | class rust::Vec<rust::String>
class rust::Vec<tests::Shared> (line 1059) | class rust::Vec<tests::Shared>
class rust::Fn<size_t(rust::String)> (line 1060) | class rust::Fn<size_t(rust::String)>
FILE: tests/ffi/tests.h
function namespace (line 6) | namespace A {
function namespace (line 15) | namespace F {
function namespace (line 22) | namespace G {
function namespace (line 28) | namespace H {
function class (line 39) | class Private {
type Unmovable (line 44) | struct Unmovable {
type R (line 50) | struct R
type Shared (line 51) | struct Shared
type SharedString (line 52) | struct SharedString
type class (line 53) | enum class
function get (line 58) | size_t get() const;
function namespace (line 246) | namespace I {
FILE: tests/test.rs
function cxx_test_suite_set_correct (line 23) | extern "C" fn cxx_test_suite_set_correct() {
function test_c_return (line 36) | fn test_c_return() {
function test_c_try_return (line 104) | fn test_c_try_return() {
function test_c_take (line 120) | fn test_c_take() {
function test_c_callback (line 213) | fn test_c_callback() {
function test_c_call_r (line 241) | fn test_c_call_r() {
function test_c_method_calls (line 256) | fn test_c_method_calls() {
function test_shared_ptr_weak_ptr (line 288) | fn test_shared_ptr_weak_ptr() {
function test_unique_to_shared_ptr_string (line 302) | fn test_unique_to_shared_ptr_string() {
function test_unique_to_shared_ptr_cpp_type (line 311) | fn test_unique_to_shared_ptr_cpp_type() {
function test_unique_to_shared_ptr_null (line 319) | fn test_unique_to_shared_ptr_null() {
function test_shared_ptr_from_raw (line 327) | fn test_shared_ptr_from_raw() {
function test_shared_ptr_from_raw_undefined (line 334) | fn test_shared_ptr_from_raw_undefined() {
function test_shared_ptr_from_raw_private (line 340) | fn test_shared_ptr_from_raw_private() {
function test_vector_reserve_unmovable (line 346) | fn test_vector_reserve_unmovable() {
function test_c_ns_method_calls (line 352) | fn test_c_ns_method_calls() {
function test_enum_representations (line 360) | fn test_enum_representations() {
function test_enum_default (line 367) | fn test_enum_default() {
function test_struct_repr_align (line 372) | fn test_struct_repr_align() {
function test_debug (line 377) | fn test_debug() {
function cxx_test_suite_get_box (line 384) | extern "C" fn cxx_test_suite_get_box() -> *mut R {
function cxx_test_suite_r_is_correct (line 389) | unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool {
function test_rust_name_attribute (line 394) | fn test_rust_name_attribute() {
function test_extern_trivial (line 403) | fn test_extern_trivial() {
function test_extern_opaque (line 426) | fn test_extern_opaque() {
function test_raw_ptr (line 439) | fn test_raw_ptr() {
function test_unwind_safe (line 456) | fn test_unwind_safe() {
FILE: tests/ui/array_len_expr.rs
type Shared (line 3) | struct Shared {
function main (line 10) | fn main() {}
FILE: tests/ui/array_len_suffix.rs
function array (line 4) | fn array() -> [String; 12u16];
function main (line 8) | fn main() {}
FILE: tests/ui/async_fn.rs
function f (line 4) | async fn f();
function g (line 8) | async fn g();
function f (line 12) | async fn f() {}
function main (line 14) | fn main() {}
FILE: tests/ui/bad_explicit_impl.rs
type S (line 3) | struct S {
function main (line 10) | fn main() {}
FILE: tests/ui/by_value_not_supported.rs
type S (line 3) | struct S {
function f (line 16) | fn f(c: C) -> C;
function g (line 17) | fn g(r: R) -> R;
function h (line 18) | fn h(s: CxxString) -> CxxString;
function main (line 22) | fn main() {}
FILE: tests/ui/const_fn.rs
function f (line 4) | const fn f();
function f (line 8) | const fn f() {}
function main (line 10) | fn main() {}
FILE: tests/ui/cxx_crate_name_qualified_cxx_string.rs
function foo (line 4) | fn foo(x: CxxString);
function bar (line 5) | fn bar(x: &cxx::CxxString);
function foo (line 9) | fn foo(_: &cxx::CxxString) {
function bar (line 13) | fn bar(_: &cxx::CxxString) {
function main (line 17) | fn main() {}
FILE: tests/ui/data_enums.rs
type A (line 3) | enum A {
function main (line 8) | fn main() {}
FILE: tests/ui/deny_elided_lifetimes.rs
type Alias (line 7) | struct Alias<'a> {
type Id (line 13) | type Id = cxx::type_id!("Alias");
type Kind (line 14) | type Kind = cxx::kind::Trivial;
type Struct (line 20) | struct Struct<'a> {
type Alias (line 30) | type Alias<'a> = crate::Alias<'a>;
function lifetime_named (line 32) | fn lifetime_named<'a>(s: &'a i32) -> UniquePtr<Cpp<'a>>;
function lifetime_underscore (line 34) | fn lifetime_underscore(s: &i32) -> UniquePtr<Cpp<'_>>;
function lifetime_elided (line 36) | fn lifetime_elided(s: &i32) -> UniquePtr<Cpp>;
type Rust (line 40) | pub struct Rust<'a>(&'a i32);
function main (line 42) | fn main() {}
FILE: tests/ui/deny_missing_docs.rs
type UndocumentedStruct (line 11) | pub struct UndocumentedStruct {
type DocumentedStruct (line 16) | pub struct DocumentedStruct {
type UndocumentedEnum (line 21) | pub enum UndocumentedEnum {
type DocumentedEnum (line 26) | pub enum DocumentedEnum {
function undocumented_rust_fn (line 37) | pub fn undocumented_rust_fn() -> u8;
function documented_rust_fn (line 40) | pub fn documented_rust_fn() -> u8;
type UndocumentedTypeAlias (line 49) | pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias;
type DocumentedTypeAlias (line 52) | pub type DocumentedTypeAlias = crate::bindgen::DocumentedTypeAlias;
function undocumented_foreign_fn (line 54) | pub fn undocumented_foreign_fn() -> u8;
function documented_foreign_fn (line 57) | pub fn documented_foreign_fn() -> u8;
type SuppressUndocumentedStruct (line 61) | pub struct SuppressUndocumentedStruct {
type UndocumentedRustType (line 66) | struct UndocumentedRustType;
type DocumentedRustType (line 67) | struct DocumentedRustType;
type UndocumentedTypeAlias (line 72) | pub struct UndocumentedTypeAlias;
type DocumentedTypeAlias (line 73) | pub struct DocumentedTypeAlias;
type Id (line 76) | type Id = type_id!("UndocumentedTypeAlias");
type Kind (line 77) | type Kind = cxx::kind::Opaque;
type Id (line 81) | type Id = type_id!("DocumentedTypeAlias");
type Kind (line 82) | type Kind = cxx::kind::Opaque;
function undocumented_rust_fn (line 86) | fn undocumented_rust_fn() -> u8 {
function documented_rust_fn (line 90) | fn documented_rust_fn() -> u8 {
function main (line 94) | fn main() {}
FILE: tests/ui/derive_bit_struct.rs
type Struct (line 4) | struct Struct {
function main (line 9) | fn main() {}
FILE: tests/ui/derive_default.rs
type NoDefault (line 4) | enum NoDefault {
type MultipleDefault (line 12) | enum MultipleDefault {
type BadDefault (line 25) | enum BadDefault {
function main (line 33) | fn main() {}
FILE: tests/ui/derive_duplicate.rs
type Struct (line 4) | struct Struct {
function main (line 9) | fn main() {}
FILE: tests/ui/derive_noncopy.rs
type TryCopy (line 4) | struct TryCopy {
type Other (line 8) | struct Other {
function main (line 13) | fn main() {}
FILE: tests/ui/drop_shared.rs
type Shared (line 3) | struct Shared {
method drop (line 9) | fn drop(&mut self) {
function main (line 14) | fn main() {}
FILE: tests/ui/duplicate_method.rs
function t_method (line 5) | fn t_method(&self);
function t_method (line 6) | fn t_method(&self);
function u_method (line 14) | fn u_method(&self);
function u_method (line 15) | fn u_method(&mut self);
function main (line 19) | fn main() {}
FILE: tests/ui/empty_enum.rs
type A (line 3) | enum A {}
function main (line 6) | fn main() {}
FILE: tests/ui/empty_struct.rs
type Empty (line 5) | struct Empty {}
type ConditionallyEmpty (line 10) | struct ConditionallyEmpty {
function main (line 18) | fn main() {}
FILE: tests/ui/enum_assoc.rs
type Enum (line 3) | enum Enum {
function f (line 8) | fn f();
function f (line 13) | fn f() {}
function main (line 16) | fn main() {}
FILE: tests/ui/enum_inconsistent.rs
type Bad (line 3) | enum Bad {
function main (line 9) | fn main() {}
FILE: tests/ui/enum_match_without_wildcard.rs
type A (line 3) | enum A {
function main (line 9) | fn main() {}
function matcher (line 11) | fn matcher(a: ffi::A) -> u32 {
FILE: tests/ui/enum_out_of_bounds.rs
type Bad1 (line 4) | enum Bad1 {
type Bad2 (line 7) | enum Bad2 {
function main (line 13) | fn main() {}
FILE: tests/ui/enum_overflows.rs
type Good1 (line 3) | enum Good1 {
type Good2 (line 6) | enum Good2 {
type Bad (line 10) | enum Bad {
function main (line 17) | fn main() {}
FILE: tests/ui/enum_receiver.rs
type Enum (line 3) | enum Enum {
function f (line 7) | fn f(self: &Enum);
function main (line 11) | fn main() {}
FILE: tests/ui/enum_unsatisfiable.rs
type Bad (line 3) | enum Bad {
function main (line 9) | fn main() {}
FILE: tests/ui/expected_named.rs
function borrowed (line 5) | fn borrowed() -> UniquePtr<Borrowed>;
function main (line 9) | fn main() {}
FILE: tests/ui/explicit_impl_of_bad_unique_ptr.rs
function main (line 6) | fn main() {}
FILE: tests/ui/extern_fn_abi.rs
function f (line 4) | extern "Java" fn f();
function main (line 8) | fn main() {}
FILE: tests/ui/extern_shared_struct.rs
type StructX (line 5) | struct StructX {
function main (line 15) | fn main() {}
FILE: tests/ui/extern_type_bound.rs
function main (line 15) | fn main() {}
FILE: tests/ui/extern_type_generic.rs
function main (line 8) | fn main() {}
FILE: tests/ui/extern_type_lifetime_bound.rs
function main (line 8) | fn main() {}
FILE: tests/ui/fallible_fnptr.rs
function f (line 4) | fn f(callback: fn() -> Result<()>);
function main (line 8) | fn main() {}
FILE: tests/ui/function_with_body.rs
function f (line 4) | fn f() {}
function main (line 8) | fn main() {}
FILE: tests/ui/generic_enum.rs
type A (line 3) | enum A<T> {
type B (line 7) | enum B<T> where T: Copy {
type C (line 11) | enum C where void: Copy {
function main (line 16) | fn main() {}
FILE: tests/ui/impl_trait_for_type.rs
type S (line 3) | struct S {
function main (line 10) | fn main() {}
FILE: tests/ui/include.rs
function main (line 12) | fn main() {}
FILE: tests/ui/lifetime_extern_cxx.rs
function f (line 5) | unsafe fn f<'a>(&'a self, arg: &str) -> &'a str;
function main (line 9) | fn main() {}
FILE: tests/ui/lifetime_extern_rust.rs
function f (line 5) | fn f<'a>(&'a self, arg: &str) -> &'a str;
type Opaque (line 9) | pub struct Opaque;
method f (line 12) | fn f(&self, _arg: &str) -> &str {
function main (line 17) | fn main() {}
FILE: tests/ui/missing_unsafe.rs
function f (line 4) | fn f(x: i32);
function f (line 8) | unsafe fn f(_x: i32) {}
function main (line 10) | fn main() {}
FILE: tests/ui/multiple_parse_error.rs
type Monad (line 3) | struct Monad<T>;
function main (line 8) | fn main() {}
FILE: tests/ui/mut_return.rs
function f (line 10) | fn f(t: &Thing) -> Pin<&mut CxxString>;
function g (line 11) | unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
function h (line 12) | fn h(t: Box<Mut>) -> Pin<&mut CxxString>;
function i (line 13) | fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>;
function j (line 14) | fn j(t: &Thing) -> &mut [u8];
function main (line 18) | fn main() {}
FILE: tests/ui/non_integer_discriminant_enum.rs
type A (line 3) | enum A {
function main (line 8) | fn main() {}
FILE: tests/ui/nonempty_impl_block.rs
type S (line 3) | struct S {
function new (line 8) | fn new() -> Self;
function main (line 12) | fn main() {}
FILE: tests/ui/nonlocal_rust_type.rs
type MyBuilder (line 1) | pub struct MyBuilder<'a> {
type OptBuilder (line 5) | type OptBuilder<'a> = Option<MyBuilder<'a>>;
type MyBuilder (line 13) | struct MyBuilder<'a> {
function main (line 18) | fn main() {}
FILE: tests/ui/opaque_autotraits.rs
function assert_send (line 8) | fn assert_send<T: Send>() {}
function assert_sync (line 9) | fn assert_sync<T: Sync>() {}
function assert_unpin (line 10) | fn assert_unpin<T: Unpin>() {}
function main (line 12) | fn main() {
FILE: tests/ui/opaque_not_sized.rs
type TypeR (line 8) | struct TypeR(str);
function main (line 10) | fn main() {}
FILE: tests/ui/pin_mut_alias.rs
type Arg (line 5) | struct Arg(PhantomPinned);
type Id (line 8) | type Id = cxx::type_id!("Arg");
type Kind (line 9) | type Kind = cxx::kind::Opaque;
type ArgLife (line 12) | struct ArgLife<'a>(PhantomPinned, PhantomData<&'a ()>);
type Id (line 15) | type Id = cxx::type_id!("ArgLife");
type Kind (line 16) | type Kind = cxx::kind::Opaque;
type Arg (line 22) | type Arg = crate::arg::Arg;
function f (line 23) | fn f(arg: &mut Arg);
type ArgLife (line 30) | type ArgLife<'a> = crate::arg::ArgLife<'a>;
function fl (line 31) | fn fl<'b, 'c>(arg: &'b mut ArgLife<'c>);
type Receiver (line 40) | struct Receiver(PhantomPinned);
type Id (line 43) | type Id = cxx::type_id!("Receiver");
type Kind (line 44) | type Kind = cxx::kind::Opaque;
type ReceiverLife (line 47) | struct ReceiverLife<'a>(PhantomPinned, PhantomData<&'a ()>);
type Id (line 50) | type Id = cxx::type_id!("ReceiverLife");
type Kind (line 51) | type Kind = cxx::kind::Opaque;
type Receiver (line 57) | type Receiver = crate::receiver::Receiver;
function g (line 58) | fn g(&mut self);
type ReceiverLife (line 65) | type ReceiverLife<'a> = crate::receiver::ReceiverLife<'a>;
function g (line 66) | fn g<'b>(&'b mut self);
type Receiver2 (line 75) | struct Receiver2(PhantomPinned);
type Id (line 78) | type Id = cxx::type_id!("Receiver2");
type Kind (line 79) | type Kind = cxx::kind::Opaque;
type ReveiverLife2 (line 82) | struct ReveiverLife2<'a>(PhantomPinned, PhantomData<&'a ()>);
type Id (line 85) | type Id = cxx::type_id!("ReveiverLife2");
type Kind (line 86) | type Kind = cxx::kind::Opaque;
type Receiver2 (line 92) | type Receiver2 = crate::receiver2::Receiver2;
function h (line 93) | fn h(self: &mut Receiver2);
type ReveiverLife2 (line 100) | type ReveiverLife2<'a> = crate::receiver2::ReveiverLife2<'a>;
function h (line 101) | fn h<'b, 'c>(self: &'b mut ReveiverLife2<'c>);
function main (line 106) | fn main() {}
FILE: tests/ui/pin_mut_opaque.rs
function f (line 5) | fn f(arg: &mut Opaque);
function g (line 6) | fn g(&mut self);
function h (line 7) | fn h(self: &mut Opaque);
function s (line 8) | fn s(s: &mut CxxString);
function v (line 9) | fn v(v: &mut CxxVector<u8>);
function main (line 13) | fn main() {}
FILE: tests/ui/ptr_in_fnptr.rs
function f (line 4) | fn f(callback: fn(p: *const u8));
function main (line 8) | fn main() {}
FILE: tests/ui/ptr_missing_unsafe.rs
function not_unsafe_ptr (line 6) | fn not_unsafe_ptr(c: *mut C);
function main (line 10) | fn main() {}
FILE: tests/ui/ptr_no_const_mut.rs
function get_neither_const_nor_mut (line 6) | fn get_neither_const_nor_mut() -> *C;
function main (line 10) | fn main() {}
FILE: tests/ui/ptr_unsupported.rs
function get_ptr_to_reference (line 6) | fn get_ptr_to_reference() -> *mut &C;
function get_uniqueptr_to_ptr (line 7) | fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
function get_vector_of_ptr (line 8) | fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
function main (line 12) | fn main() {}
FILE: tests/ui/raw_ident_namespace.rs
type QuotedRaw (line 4) | pub struct QuotedRaw(usize);
type Id (line 7) | type Id = type_id!("org::r#box::implementation::QuotedRaw");
type Kind (line 8) | type Kind = cxx::kind::Trivial;
type QuotedKeyword (line 12) | pub struct QuotedKeyword(usize);
type Id (line 15) | type Id = type_id!("org::box::implementation::QuotedKeyword");
type Kind (line 16) | type Kind = cxx::kind::Trivial;
type UnquotedRaw (line 20) | pub struct UnquotedRaw(usize);
type Id (line 23) | type Id = type_id!(org::r#box::implementation::UnquotedRaw);
type Kind (line 24) | type Kind = cxx::kind::Trivial;
type UnquotedKeyword (line 28) | pub struct UnquotedKeyword(usize);
type Id (line 31) | type Id = type_id!(org::box::implementation::UnquotedKeyword);
type Kind (line 32) | type Kind = cxx::kind::Trivial;
type QuotedRaw (line 39) | type QuotedRaw = crate::QuotedRaw;
type QuotedKeyword (line 42) | type QuotedKeyword = crate::QuotedKeyword;
type UnquotedRaw (line 45) | type UnquotedRaw = crate::UnquotedRaw;
function main (line 53) | fn main() {}
FILE: tests/ui/reference_to_reference.rs
function repro_c (line 5) | fn repro_c(t: &&ThingC);
function repro_r (line 9) | fn repro_r(t: &&ThingR);
function main (line 13) | fn main() {}
FILE: tests/ui/repr_align_suffixed.rs
type StructSuffix (line 4) | struct StructSuffix {
function main (line 9) | fn main() {}
FILE: tests/ui/repr_unsupported.rs
type EnumAlign (line 4) | enum EnumAlign {
type StructInt (line 9) | struct StructInt {
type StructExpr (line 14) | struct StructExpr {
function main (line 19) | fn main() {}
FILE: tests/ui/reserved_lifetime.rs
function logger (line 6) | fn logger<'static>() -> Pin<&'static Logger>;
function main (line 10) | fn main() {}
FILE: tests/ui/reserved_name.rs
type UniquePtr (line 3) | struct UniquePtr {
function main (line 16) | fn main() {}
FILE: tests/ui/result_no_display.rs
function f (line 4) | fn f() -> Result<()>;
type NonError (line 8) | pub struct NonError;
function f (line 10) | fn f() -> Result<(), NonError> {
function main (line 14) | fn main() {}
FILE: tests/ui/root_namespace.rs
function main (line 13) | fn main() {}
FILE: tests/ui/rust_pinned.rs
type Pinned (line 10) | pub struct Pinned {
function main (line 14) | fn main() {}
FILE: tests/ui/self_lifetimes.rs
function zero (line 6) | fn zero(self: &Thing<>);
function one (line 7) | fn one<'a>(self: &Thing<'a>);
function three (line 8) | fn three<'a, 'b, 'c>(self: &Thing<'a, 'b, 'c>);
function main (line 12) | fn main() {}
FILE: tests/ui/self_type_and_receiver.rs
function method (line 7) | fn method(self: &T);
function main (line 11) | fn main() {}
FILE: tests/ui/slice_of_pinned.rs
type Pinned (line 5) | struct Pinned(usize, PhantomPinned);
type Pinned (line 10) | type Pinned = crate::Pinned;
function f (line 11) | fn f(_: &[Pinned], _: &mut [Pinned]);
type Id (line 16) | type Id = type_id!("Pinned");
type Kind (line 17) | type Kind = cxx::kind::Trivial;
function main (line 20) | fn main() {}
FILE: tests/ui/slice_of_type_alias.rs
type ElementTrivial (line 4) | struct ElementTrivial(usize);
type ElementOpaque (line 7) | struct ElementOpaque(usize);
type ElementTrivial (line 12) | type ElementTrivial = crate::ElementTrivial;
type ElementOpaque (line 13) | type ElementOpaque = crate::ElementOpaque;
function f (line 15) | fn f(slice: &mut [ElementTrivial]);
function g (line 16) | fn g(slice: &[ElementOpaque]);
type Id (line 21) | type Id = type_id!("ElementTrivial");
type Kind (line 22) | type Kind = cxx::kind::Trivial;
type Id (line 26) | type Id = type_id!("ElementOpaque");
type Kind (line 27) | type Kind = cxx::kind::Opaque;
function main (line 30) | fn main() {}
FILE: tests/ui/slice_unsupported.rs
function f (line 6) | fn f(_: &mut [Opaque]);
function main (line 10) | fn main() {}
FILE: tests/ui/struct_align.rs
type SharedA (line 4) | struct SharedA {
type SharedB (line 10) | struct SharedB {
type SharedC (line 15) | struct SharedC {
function main (line 20) | fn main() {}
FILE: tests/ui/struct_cycle.rs
type Node0 (line 3) | struct Node0 {
type Node1 (line 7) | struct Node1 {
type Node2 (line 12) | struct Node2 {
type Node3 (line 16) | struct Node3 {
type Node4 (line 20) | struct Node4 {
type Node5 (line 25) | struct Node5 {
type Node6 (line 29) | struct Node6 {
function main (line 34) | fn main() {}
FILE: tests/ui/type_alias_rust.rs
type Alias (line 5) | type Alias = crate::Type;
function main (line 9) | fn main() {}
FILE: tests/ui/undeclared_lifetime.rs
function f0 (line 4) | fn f0(_: &'a CxxString);
function g0 (line 5) | fn g0<'a>(_: &'b CxxString);
function f1 (line 8) | fn f1(self: &This, _: &'a CxxString);
function g1 (line 9) | fn g1<'a>(self: &This, _: &'b CxxString);
function f2 (line 10) | fn f2(self: &'a This);
function g2 (line 11) | fn g2<'a>(self: &'b This);
function f3 (line 12) | fn f3(self: &This<'a>);
function g3 (line 13) | fn g3<'a>(self: &This<'b>);
function main (line 17) | fn main() {}
FILE: tests/ui/unique_ptr_as_mut.rs
type Shared (line 5) | struct Shared {
function main (line 17) | fn main() {
FILE: tests/ui/unique_ptr_to_opaque.rs
type C (line 3) | pub struct C {
type Id (line 7) | type Id = cxx::type_id!("C");
type Kind (line 8) | type Kind = cxx::kind::Opaque;
type C (line 15) | type C = crate::outside::C;
type Id (line 7) | type Id = cxx::type_id!("C");
type Kind (line 8) | type Kind = cxx::kind::Opaque;
function main (line 21) | fn main() {
FILE: tests/ui/unique_ptr_twice.rs
type C (line 13) | type C = crate::here::C;
function main (line 19) | fn main() {}
FILE: tests/ui/unnamed_receiver.rs
function f (line 6) | fn f(&mut self);
function f (line 10) | fn f(self: &Self);
function main (line 14) | fn main() {}
FILE: tests/ui/unpin_impl.rs
function main (line 10) | fn main() {}
FILE: tests/ui/unrecognized_receiver.rs
function f (line 4) | fn f(self: &Unrecognized);
function main (line 8) | fn main() {}
FILE: tests/ui/unsupported_elided.rs
function f (line 8) | fn f(t: &T) -> &str;
type T (line 12) | pub struct T<'a> {
function f (line 16) | fn f<'a>(_t: &T<'a>) -> &'a str {
function main (line 20) | fn main() {}
FILE: tests/ui/vec_opaque.rs
function f (line 15) | fn f() -> Vec<Job>;
type Job (line 22) | type Job = crate::handle::Job;
function f (line 26) | fn f() -> Vec<Job>;
function f (line 30) | fn f() -> Vec<handle::Job> {
function main (line 34) | fn main() {}
FILE: tests/ui/vector_autotraits.rs
function assert_send (line 16) | fn assert_send<T: Send>() {}
function main (line 18) | fn main() {
FILE: tests/ui/wrong_type_id.rs
type ByteRange (line 11) | type ByteRange = crate::here::StringPiece;
function main (line 15) | fn main() {}
FILE: tests/unique_ptr.rs
function test_deref_null (line 5) | fn test_deref_null() {
FILE: tools/cargo/build.rs
constant MISSING (line 9) | const MISSING: &str = "
constant DENIED (line 31) | const DENIED: &str = "
function main (line 50) | fn main() {
Condensed preview — 463 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,381K chars).
[
{
"path": ".bazelignore",
"chars": 36,
"preview": "buck-out/\ntarget/\ntools/buck/buck2/\n"
},
{
"path": ".bazelrc",
"chars": 870,
"preview": "###############################################################################\n## Bazel Configuration Flags\n##\n## `.baz"
},
{
"path": ".bcr/README.md",
"chars": 366,
"preview": "# Bazel Central Registry\n\nWhen the ruleset is released, we want it to be published to the\nBazel Central Registry automat"
},
{
"path": ".bcr/config.yml",
"chars": 59,
"preview": "fixedReleaser:\n login: dtolnay\n email: dtolnay@gmail.com\n"
},
{
"path": ".bcr/metadata.template.json",
"chars": 287,
"preview": "{\n \"homepage\": \"https://cxx.rs\",\n \"maintainers\": [\n {\n \"github\": \"dtolnay\",\n \"github_user_id\": 1940490,\n "
},
{
"path": ".bcr/presubmit.yml",
"chars": 282,
"preview": "matrix:\n platform:\n - macos_arm64\n - ubuntu2404\n - windows\n bazel: [8.x, 9.x]\ntasks:\n verify_targets:\n na"
},
{
"path": ".bcr/source.template.json",
"chars": 154,
"preview": "{\n \"integrity\": \"\",\n \"strip_prefix\": \"{REPO}-{VERSION}\",\n \"url\": \"https://github.com/{OWNER}/{REPO}/releases/download"
},
{
"path": ".buckconfig",
"chars": 704,
"preview": "[cells]\nroot = .\nprelude = tools/buck/prelude\ntoolchains = tools/buck/toolchains\nnone = none\n\n[external_cells]\nprelude ="
},
{
"path": ".buckroot",
"chars": 0,
"preview": ""
},
{
"path": ".clang-format",
"chars": 83,
"preview": "AlwaysBreakTemplateDeclarations: true\nMaxEmptyLinesToKeep: 3\nReflowComments: false\n"
},
{
"path": ".clang-tidy",
"chars": 695,
"preview": "Checks:\n clang-analyzer-*,\n clang-diagnostic-*,\n cppcoreguidelines-*,\n modernize-*,\n -cppcoreguidelines-avoid-const"
},
{
"path": ".devcontainer/Dockerfile",
"chars": 33,
"preview": "FROM dtolnay/devcontainer:latest\n"
},
{
"path": ".devcontainer/README.md",
"chars": 154,
"preview": "This directory contains the container setup used when developing CXX inside of\nGitHub [Codespaces].\n\n[Codespaces]: https"
},
{
"path": ".devcontainer/build.Dockerfile",
"chars": 851,
"preview": "FROM mcr.microsoft.com/devcontainers/rust:bookworm\n\nRUN apt-get update \\\n && export DEBIAN_FRONTEND=noninteractive \\\n"
},
{
"path": ".devcontainer/devcontainer.json",
"chars": 520,
"preview": "{\n \"name\": \"Rust\",\n \"build\": {\n \"dockerfile\": \"Dockerfile\"\n },\n \"runArgs\": [\"--cap-add=SYS_PTRACE\", \""
},
{
"path": ".gitattributes",
"chars": 116,
"preview": "/MODULE.bazel.lock linguist-generated\n/third-party/BUCK linguist-generated\n/third-party/bazel/** linguist-generated\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 16,
"preview": "github: dtolnay\n"
},
{
"path": ".github/workflows/buck2.yml",
"chars": 678,
"preview": "name: Buck2\n\non:\n push:\n workflow_dispatch:\n schedule: [cron: \"40 1,13 * * *\"]\n\npermissions:\n contents: read\n\njobs:\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 12254,
"preview": "name: CI\n\non:\n push:\n pull_request:\n workflow_dispatch:\n schedule: [cron: \"40 1 * * *\"]\n\npermissions:\n contents: re"
},
{
"path": ".github/workflows/install.yml",
"chars": 284,
"preview": "name: Install\n\non:\n workflow_dispatch:\n schedule: [cron: \"40 1 * * *\"]\n push: {tags: ['*']}\n\npermissions: {}\n\nenv:\n "
},
{
"path": ".github/workflows/release.yml",
"chars": 558,
"preview": "name: Release\n\non:\n release:\n types: [released]\n\npermissions:\n attestations: write\n contents: write\n id-token: wr"
},
{
"path": ".github/workflows/site.yml",
"chars": 923,
"preview": "name: Deploy\n\non:\n push:\n branches:\n - master\n paths:\n - book/**\n - .github/workflows/site.yml\n w"
},
{
"path": ".gitignore",
"chars": 159,
"preview": "/.buckconfig.d/\n/.buckconfig.local\n/.buckd\n/bazel-bin\n/bazel-cxx\n/bazel-out\n/bazel-testlogs\n/user.bazelrc\n/buck-out\n/exp"
},
{
"path": ".vscode/README.md",
"chars": 151,
"preview": "VS Code actions and configuration. Applicable when developing CXX inside of\nGitHub [Codespaces].\n\n[Codespaces]: https://"
},
{
"path": ".vscode/launch.json",
"chars": 724,
"preview": "{\n \"version\": \"0.2.0\",\n \"configurations\": [\n {\n \"name\": \"Run cxx demo\",\n \"type\": \"lld"
},
{
"path": ".vscode/settings.json",
"chars": 60,
"preview": "{\n \"search.exclude\": {\n \"**/target\": true\n }\n}\n"
},
{
"path": ".vscode/tasks.json",
"chars": 773,
"preview": "{\n \"version\": \"2.0.0\",\n \"tasks\": [\n {\n \"label\": \"Cargo test\",\n \"type\": \"shell\",\n "
},
{
"path": ".watchmanconfig",
"chars": 34,
"preview": "{\n \"ignore_dirs\": [\"buck-out\"]\n}\n"
},
{
"path": "BUCK",
"chars": 2840,
"preview": "load(\":Cargo.toml\", cargo_toml = \"value\")\n\nCARGO_PKG_VERSION_PATCH = cargo_toml[\"package\"][\"version\"].split(\".\")[2]\n\nrus"
},
{
"path": "BUILD.bazel",
"chars": 2538,
"preview": "load(\"@rules_cc//cc:defs.bzl\", \"cc_library\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_binary\", \"rust_library\", \"rust_pro"
},
{
"path": "Cargo.toml",
"chars": 2569,
"preview": "[package]\nname = \"cxx\"\nversion = \"1.0.194\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ncategories = [\"development-too"
},
{
"path": "LICENSE-APACHE",
"chars": 9723,
"preview": " Apache License\n Version 2.0, January 2004\n http"
},
{
"path": "LICENSE-MIT",
"chars": 1023,
"preview": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentati"
},
{
"path": "MODULE.bazel",
"chars": 758,
"preview": "module(\n name = \"cxx.rs\",\n version = \"0.0.0\",\n bazel_compatibility = [\">=8.0.0\"],\n compatibility_level = 1,\n"
},
{
"path": "README.md",
"chars": 17266,
"preview": "CXX — safe FFI between Rust and C++\n=========================================\n\n[<img alt=\"github\" src=\"https://img"
},
{
"path": "book/.gitignore",
"chars": 31,
"preview": "/build/\n/mdbook\n/node_modules/\n"
},
{
"path": "book/README.md",
"chars": 263,
"preview": "Published automatically to https://cxx.rs from master branch.\n\nTo build and view locally:\n\n- Install [mdBook]: `cargo in"
},
{
"path": "book/book.toml",
"chars": 586,
"preview": "[book]\n#title = \"Rust ♡ C++\"\nauthors = [\"David Tolnay\"]\ndescription = \"CXX — safe interop between Rust and C++ by David "
},
{
"path": "book/build.js",
"chars": 4371,
"preview": "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst cheerio = require('cheerio');\nconst entities = require('html-entiti"
},
{
"path": "book/build.sh",
"chars": 175,
"preview": "#!/bin/bash\n\nset -e\n\ncd \"$(dirname \"$0\")\"\n\nif [ -f ./mdbook ]; then\n ./mdbook build\nelse\n mdbook build\nfi\n\nif [ ! "
},
{
"path": "book/css/cxx.css",
"chars": 669,
"preview": ":root {\n --sidebar-width: 310px;\n}\n\n.badges img {\n margin: 0 7px 7px 0;\n}\n\n.badges {\n margin: 16px 0 120px;\n}\n\n"
},
{
"path": "book/diagram/.gitignore",
"chars": 57,
"preview": "/*.aux\n/*.fdb_latexmk\n/*.fls\n/*.log\n/*.pdf\n/*.png\n/*.svg\n"
},
{
"path": "book/diagram/Makefile",
"chars": 130,
"preview": "overview.svg: overview.pdf\n\tpdf2svg $< $@\n\noverview.pdf: overview.tex\n\tlatexmk $<\n\noverview.png: overview.svg\n\tsvgexport"
},
{
"path": "book/diagram/overview.tex",
"chars": 1897,
"preview": "\\documentclass{standalone}\n\\usepackage{makecell}\n\\usepackage{pgfplots}\n\\usepackage{sansmath}\n\\usetikzlibrary{arrows.meta"
},
{
"path": "book/eslint.config.mjs",
"chars": 235,
"preview": "import pluginJs from '@eslint/js';\n\n/** @type {import('eslint').Linter.Config[]} */\nexport default [\n { ignores: ['buil"
},
{
"path": "book/package.json",
"chars": 281,
"preview": "{\n \"name\": \"cxx-book-build\",\n \"version\": \"0.0.0\",\n \"main\": \"build.js\",\n \"dependencies\": {\n \"cheerio\": \"^1.0.0\",\n "
},
{
"path": "book/src/404.md",
"chars": 141,
"preview": "### Whoops, this page doesn’t exist :-(\n\n<br>\n\n<img src=\"https://www.rust-lang.org/static/images/ferris-error.png\" alt=\""
},
{
"path": "book/src/SUMMARY.md",
"chars": 1357,
"preview": "# Summary\n\n- [Rust ❤️ C++](index.md)\n\n- [Core concepts](concepts.md)\n\n- [Tutorial](tutorial.md)\n\n- [Other Rust–C++"
},
{
"path": "book/src/async.md",
"chars": 2333,
"preview": "{{#title Async functions — Rust ♡ C++}}\n# Async functions\n\nDirect FFI of async functions is absolutely in scope for CXX "
},
{
"path": "book/src/attributes.md",
"chars": 2807,
"preview": "{{#title Attributes — Rust ♡ C++}}\n# Attributes\n\n## namespace\n\nThe top-level cxx::bridge attribute macro takes an option"
},
{
"path": "book/src/binding/box.md",
"chars": 2674,
"preview": "{{#title rust::Box<T> — Rust ♡ C++}}\n# rust::Box\\<T\\>\n\n### Public API:\n\n```cpp,hidelines=...\n// rust/cxx.h\n...\n...#inclu"
},
{
"path": "book/src/binding/cxxstring.md",
"chars": 4091,
"preview": "{{#title std::string — Rust ♡ C++}}\n# std::string\n\nThe Rust binding of std::string is called **[`CxxString`]**. See the "
},
{
"path": "book/src/binding/cxxvector.md",
"chars": 1403,
"preview": "{{#title std::vector<T> — Rust ♡ C++}}\n# std::vector\\<T\\>\n\nThe Rust binding of std::vector\\<T\\> is called **[`CxxVector<"
},
{
"path": "book/src/binding/fn.md",
"chars": 739,
"preview": "{{#title Function pointers — Rust ♡ C++}}\n# Function pointers\n\n### Public API:\n\n```cpp,hidelines=...\n// rust/cxx.h\n...\n."
},
{
"path": "book/src/binding/rawptr.md",
"chars": 2884,
"preview": "{{#title *mut T, *const T — Rust ♡ C++}}\n# *mut T, *const T\n\nGenerally you should use references (`&mut T`, `&T`) o"
},
{
"path": "book/src/binding/result.md",
"chars": 4363,
"preview": "{{#title Result<T> — Rust ♡ C++}}\n# Result\\<T\\>\n\nResult\\<T\\> is allowed as the return type of an extern function in eith"
},
{
"path": "book/src/binding/sharedptr.md",
"chars": 1749,
"preview": "{{#title std::shared_ptr<T> — Rust ♡ C++}}\n# std::shared\\_ptr\\<T\\>\n\nThe Rust binding of std::shared\\_ptr\\<T\\> is called "
},
{
"path": "book/src/binding/slice.md",
"chars": 4740,
"preview": "{{#title rust::Slice<T> — Rust ♡ C++}}\n# rust::Slice\\<const T\\>, rust::Slice\\<T\\>\n\n- Rust `&[T]` is written `rust::"
},
{
"path": "book/src/binding/str.md",
"chars": 2602,
"preview": "{{#title rust::Str — Rust ♡ C++}}\n# rust::Str\n\n### Public API:\n\n```cpp,hidelines=...\n// rust/cxx.h\n...\n...#include <iosf"
},
{
"path": "book/src/binding/string.md",
"chars": 3282,
"preview": "{{#title rust::String — Rust ♡ C++}}\n# rust::String\n\n### Public API:\n\n```cpp,hidelines=...\n// rust/cxx.h\n...\n...#include"
},
{
"path": "book/src/binding/uniqueptr.md",
"chars": 1420,
"preview": "{{#title std::unique_ptr<T> — Rust ♡ C++}}\n# std::unique\\_ptr\\<T\\>\n\nThe Rust binding of std::unique\\_ptr\\<T\\> is called "
},
{
"path": "book/src/binding/vec.md",
"chars": 5097,
"preview": "{{#title rust::Vec<T> — Rust ♡ C++}}\n# rust::Vec\\<T\\>\n\n### Public API:\n\n```cpp,hidelines=...\n// rust/cxx.h\n...\n...#inclu"
},
{
"path": "book/src/bindings.md",
"chars": 4724,
"preview": "{{#title Built-in bindings — Rust ♡ C++}}\n# Built-in bindings reference\n\nIn addition to all the primitive types (i32 <"
},
{
"path": "book/src/build/bazel.md",
"chars": 2856,
"preview": "{{#title Bazel, Buck2 — Rust ♡ C++}}\n## Bazel, Buck2, potentially other similar environments\n\nStarlark-based build syste"
},
{
"path": "book/src/build/cargo.md",
"chars": 10262,
"preview": "{{#title Cargo-based setup — Rust ♡ C++}}\n# Cargo-based builds\n\nAs one aspect of delivering a good Rust–C++ intero"
},
{
"path": "book/src/build/cmake.md",
"chars": 1233,
"preview": "{{#title CMake — Rust ♡ C++}}\n# CMake\n\nThere is not an officially endorsed CMake setup for CXX, but a few developers\nhav"
},
{
"path": "book/src/build/other.md",
"chars": 4030,
"preview": "{{#title Other build systems — Rust ♡ C++}}\n# Some other build system\n\nYou will need to achieve at least these three thi"
},
{
"path": "book/src/building.md",
"chars": 949,
"preview": "{{#title Multi-language build system options — Rust ♡ C++}}\n# Multi-language build system options\n\nCXX is designed to be"
},
{
"path": "book/src/concepts.md",
"chars": 3655,
"preview": "{{#title Core concepts — Rust ♡ C++}}\n# Core concepts\n\nThis page is a brief overview of the major concepts of CXX, enoug"
},
{
"path": "book/src/context.md",
"chars": 6369,
"preview": "{{#title Other Rust–C++ interop tools — Rust ♡ C++}}\n# Context: other Rust–C++ interop tools\n\nWhen it comes to int"
},
{
"path": "book/src/extern-c++.md",
"chars": 11853,
"preview": "{{#title extern \"C++\" — Rust ♡ C++}}\n# extern \"C++\"\n\n```rust,noplayground\n#[cxx::bridge]\nmod ffi {\n extern \"C++\" {\n "
},
{
"path": "book/src/extern-rust.md",
"chars": 5198,
"preview": "{{#title extern \"Rust\" — Rust ♡ C++}}\n# extern \"Rust\"\n\n```rust,noplayground\n#[cxx::bridge]\nmod ffi {\n extern \"Rust\" {"
},
{
"path": "book/src/index.md",
"chars": 4073,
"preview": "<div class=\"badges\">\n<a href=\"https://github.com/dtolnay/cxx\"><img src=\"https://img.shields.io/badge/github-8da0cb?style"
},
{
"path": "book/src/reference.md",
"chars": 1430,
"preview": "{{#title The bridge module — Rust ♡ C++}}\n# The bridge module reference\n\nThe ***[Core concepts](concepts.md)*** in chapt"
},
{
"path": "book/src/shared.md",
"chars": 6355,
"preview": "{{#title Shared types — Rust ♡ C++}}\n# Shared types\n\nShared types enable *both* languages to have visibility into the in"
},
{
"path": "book/src/tutorial.md",
"chars": 20512,
"preview": "{{#title Tutorial — Rust ♡ C++}}\n# Tutorial: CXX blobstore client\n\nThis example walks through a Rust application that ca"
},
{
"path": "book/theme/head.hbs",
"chars": 344,
"preview": "<script async src=\"https://www.googletagmanager.com/gtag/js?id=G-DG41MK6DDN\"></script>\n<script>\n window.dataLayer = win"
},
{
"path": "build.rs",
"chars": 2307,
"preview": "#![expect(unexpected_cfgs)]\n\nuse std::env;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\n\nfn main() {\n l"
},
{
"path": "compile_flags.txt",
"chars": 11,
"preview": "-std=c++20\n"
},
{
"path": "demo/BUCK",
"chars": 652,
"preview": "load(\"//tools/buck:rust_cxx_bridge.bzl\", \"rust_cxx_bridge\")\n\nrust_binary(\n name = \"demo\",\n srcs = glob([\"src/**/*."
},
{
"path": "demo/BUILD.bazel",
"chars": 714,
"preview": "load(\"@rules_cc//cc:defs.bzl\", \"cc_library\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_binary\")\nload(\"//tools/bazel:rust_"
},
{
"path": "demo/Cargo.toml",
"chars": 330,
"preview": "[package]\nname = \"demo\"\nversion = \"0.0.0\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ndescription = \"Toy project from"
},
{
"path": "demo/build.rs",
"chars": 261,
"preview": "fn main() {\n cxx_build::bridge(\"src/main.rs\")\n .file(\"src/blobstore.cc\")\n .std(\"c++14\")\n .compil"
},
{
"path": "demo/include/blobstore.h",
"chars": 480,
"preview": "#pragma once\n#include \"rust/cxx.h\"\n#include <memory>\n\nnamespace org {\nnamespace blobstore {\n\nstruct MultiBuf;\nstruct Blo"
},
{
"path": "demo/src/blobstore.cc",
"chars": 2023,
"preview": "#include \"demo/include/blobstore.h\"\n#include \"demo/src/main.rs.h\"\n#include <algorithm>\n#include <functional>\n#include <s"
},
{
"path": "demo/src/main.rs",
"chars": 1648,
"preview": "#[cxx::bridge(namespace = \"org::blobstore\")]\nmod ffi {\n // Shared structs with fields visible to both languages.\n "
},
{
"path": "flags/Cargo.toml",
"chars": 764,
"preview": "[package]\nname = \"cxxbridge-flags\"\nversion = \"1.0.194\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ncategories = [\"dev"
},
{
"path": "flags/src/impl.rs",
"chars": 283,
"preview": "#[allow(unused_assignments, unused_mut, unused_variables)]\npub const STD: &str = {\n let mut flag = \"c++11\";\n\n #[cf"
},
{
"path": "flags/src/lib.rs",
"chars": 168,
"preview": "//! This crate is an implementation detail of the `cxx` and `cxx-build` crates,\n//! and does not expose any public API.\n"
},
{
"path": "gen/README.md",
"chars": 391,
"preview": "This directory contains CXX's C++ code generator. This code generator has two\npublic frontends, one a command-line appli"
},
{
"path": "gen/build/Cargo.toml",
"chars": 1377,
"preview": "[package]\nname = \"cxx-build\"\nversion = \"1.0.194\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ncategories = [\"developme"
},
{
"path": "gen/build/build.rs",
"chars": 40,
"preview": "include!(\"../../tools/cargo/build.rs\");\n"
},
{
"path": "gen/build/src/cargo.rs",
"chars": 4210,
"preview": "use crate::gen::{CfgEvaluator, CfgResult};\nuse std::borrow::Borrow;\nuse std::cmp::Ordering;\nuse std::collections::{BTree"
},
{
"path": "gen/build/src/cfg.rs",
"chars": 17125,
"preview": "use std::fmt::{self, Debug};\nuse std::marker::PhantomData;\nuse std::path::Path;\n\n/// Build configuration. See [CFG].\npub"
},
{
"path": "gen/build/src/deps.rs",
"chars": 3673,
"preview": "use std::collections::BTreeMap;\nuse std::env;\nuse std::ffi::OsString;\nuse std::path::PathBuf;\n\n#[derive(Default)]\npub(cr"
},
{
"path": "gen/build/src/error.rs",
"chars": 3211,
"preview": "use crate::cfg::CFG;\nuse crate::gen::fs;\nuse std::error::Error as StdError;\nuse std::ffi::OsString;\nuse std::fmt::{self,"
},
{
"path": "gen/build/src/intern.rs",
"chars": 749,
"preview": "use crate::syntax::set::UnorderedSet as Set;\nuse std::sync::{Mutex, OnceLock, PoisonError};\n\n#[derive(Copy, Clone, Defau"
},
{
"path": "gen/build/src/lib.rs",
"chars": 16000,
"preview": "//! The CXX code generator for constructing and compiling C++ code.\n//!\n//! This is intended to be used from Cargo build"
},
{
"path": "gen/build/src/out.rs",
"chars": 10554,
"preview": "use crate::error::{Error, Result};\nuse crate::gen::fs;\nuse crate::paths;\nuse std::path::{Component, Path, PathBuf};\nuse "
},
{
"path": "gen/build/src/paths.rs",
"chars": 2423,
"preview": "use crate::error::Result;\nuse crate::gen::fs;\nuse std::ffi::OsStr;\nuse std::path::{Component, Path, PathBuf};\n\npub(crate"
},
{
"path": "gen/build/src/target.rs",
"chars": 1455,
"preview": "use std::env;\nuse std::ffi::OsStr;\nuse std::path::{Path, PathBuf};\n\npub(crate) enum TargetDir {\n Path(PathBuf),\n U"
},
{
"path": "gen/build/src/vec.rs",
"chars": 1050,
"preview": "use crate::intern::{self, InternedString};\nuse std::path::Path;\n\npub(crate) trait InternedVec<T>\nwhere\n T: ?Sized,\n{\n"
},
{
"path": "gen/cmd/Cargo.toml",
"chars": 1017,
"preview": "[package]\nname = \"cxxbridge-cmd\"\nversion = \"1.0.194\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ncategories = [\"devel"
},
{
"path": "gen/cmd/build.rs",
"chars": 40,
"preview": "include!(\"../../tools/cargo/build.rs\");\n"
},
{
"path": "gen/cmd/src/app.rs",
"chars": 6365,
"preview": "#[cfg(test)]\n#[path = \"test.rs\"]\nmod test;\n\nuse super::{Opt, Output};\nuse crate::cfg::{self, CfgValue};\nuse crate::gen::"
},
{
"path": "gen/cmd/src/cfg.rs",
"chars": 2963,
"preview": "use crate::gen::{CfgEvaluator, CfgResult};\nuse std::collections::{BTreeMap as Map, BTreeSet as Set};\nuse std::fmt::{self"
},
{
"path": "gen/cmd/src/main.rs",
"chars": 3294,
"preview": "#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]\n#![allow(\n clippy::cast_sign_loss,\n clippy::default_trait_acc"
},
{
"path": "gen/cmd/src/output.rs",
"chars": 326,
"preview": "use std::path::PathBuf;\n\n#[derive(Debug)]\npub(crate) enum Output {\n Stdout,\n File(PathBuf),\n}\n\nimpl Output {\n p"
},
{
"path": "gen/cmd/src/test.rs",
"chars": 1984,
"preview": "const EXPECTED: &str = \"\\\ncxxbridge $VERSION\nDavid Tolnay <dtolnay@gmail.com>\nhttps://github.com/dtolnay/cxx\n\nUsage:\n "
},
{
"path": "gen/lib/Cargo.toml",
"chars": 1097,
"preview": "[package]\nname = \"cxx-gen\"\nversion = \"0.7.194\"\nauthors = [\"Adrian Taylor <adetaylor@chromium.org>\"]\ncategories = [\"devel"
},
{
"path": "gen/lib/build.rs",
"chars": 40,
"preview": "include!(\"../../tools/cargo/build.rs\");\n"
},
{
"path": "gen/lib/src/error.rs",
"chars": 1755,
"preview": "// We can expose more detail on the error as the need arises, but start with an\n// opaque error type for now.\n\nuse std::"
},
{
"path": "gen/lib/src/lib.rs",
"chars": 2175,
"preview": "//! The CXX code generator for constructing and compiling C++ code.\n//!\n//! This is intended as a mechanism for embeddin"
},
{
"path": "gen/lib/tests/test.rs",
"chars": 625,
"preview": "use cxx_gen::Opt;\nuse quote::quote;\n\n#[test]\nfn test_positive() {\n let rs = quote! {\n #[cxx::bridge]\n m"
},
{
"path": "gen/src/block.rs",
"chars": 1261,
"preview": "use proc_macro2::Ident;\n\n#[derive(Copy, Clone, PartialEq, Debug)]\npub(crate) enum Block<'a> {\n AnonymousNamespace,\n "
},
{
"path": "gen/src/builtin/alignmax.h",
"chars": 859,
"preview": "#pragma once\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\n#ifndef CXXBRIDGE_ALIGN"
},
{
"path": "gen/src/builtin/deleter_if.h",
"chars": 328,
"preview": "#pragma once\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <bool> struct deleter_if {\n template "
},
{
"path": "gen/src/builtin/destroy.h",
"chars": 194,
"preview": "#pragma once\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T>\nvoid destroy(T *ptr) {\n "
},
{
"path": "gen/src/builtin/friend_impl.h",
"chars": 168,
"preview": "#pragma once\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T>\nclass impl;\n} // namespac"
},
{
"path": "gen/src/builtin/manually_drop.h",
"chars": 304,
"preview": "#pragma once\n#include <utility>\n\n#pragma GCC diagnostic ignored \"-Wshadow\"\n\nnamespace rust {\ninline namespace cxxbridge1"
},
{
"path": "gen/src/builtin/maybe_uninit.h",
"chars": 337,
"preview": "#pragma once\n#include \"./maybe_uninit_detail.h\"\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\ntempl"
},
{
"path": "gen/src/builtin/maybe_uninit_detail.h",
"chars": 474,
"preview": "#pragma once\n#include <cstddef>\n#include <new>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace detail {\ntempla"
},
{
"path": "gen/src/builtin/ptr_len.h",
"chars": 222,
"preview": "#pragma once\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\nstruct PtrLen final {\n "
},
{
"path": "gen/src/builtin/relocatable_or_array.h",
"chars": 366,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n#include <cstdint>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamesp"
},
{
"path": "gen/src/builtin/repr_fat.h",
"chars": 227,
"preview": "#pragma once\n#include <array>\n#include <cstdint>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\nusing "
},
{
"path": "gen/src/builtin/rust_error.h",
"chars": 436,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n#include \"./friend_impl.h\"\n#include \"./ptr_len.h\"\n\nnamespace rust {\ninlin"
},
{
"path": "gen/src/builtin/rust_slice_uninit.h",
"chars": 258,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\ntemplate <typename T>\ncla"
},
{
"path": "gen/src/builtin/rust_str_uninit.h",
"chars": 202,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\nclass Str::uninit {};\n//\n"
},
{
"path": "gen/src/builtin/shared_ptr.h",
"chars": 807,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n#include <memory>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespa"
},
{
"path": "gen/src/builtin/trycatch.h",
"chars": 535,
"preview": "#pragma once\n#include \"./trycatch_detail.h\"\n#include <exception>\n#include <type_traits>\n#include <utility>\n\nnamespace ru"
},
{
"path": "gen/src/builtin/trycatch_detail.h",
"chars": 524,
"preview": "#pragma once\n#include \"./ptr_len.h\"\n#include <string>\n\n#pragma GCC diagnostic ignored \"-Wshadow\"\n#pragma clang diagnosti"
},
{
"path": "gen/src/builtin/vector.h",
"chars": 587,
"preview": "#pragma once\n#include \"../../../include/cxx.h\"\n#include <type_traits>\n#include <vector>\n\nnamespace rust {\ninline namespa"
},
{
"path": "gen/src/builtin.rs",
"chars": 14255,
"preview": "use crate::gen::block::Block;\nuse crate::gen::ifndef;\nuse crate::gen::include::Includes;\nuse crate::gen::out::{Content, "
},
{
"path": "gen/src/cfg.rs",
"chars": 4002,
"preview": "use crate::gen::{CfgEvaluator, CfgResult};\nuse crate::syntax::cfg::CfgExpr;\nuse crate::syntax::report::Errors;\nuse crate"
},
{
"path": "gen/src/check.rs",
"chars": 924,
"preview": "use crate::gen::Opt;\nuse crate::syntax::report::Errors;\nuse crate::syntax::{error, Api};\nuse quote::{quote, quote_spanne"
},
{
"path": "gen/src/error.rs",
"chars": 5160,
"preview": "use crate::gen::fs;\nuse crate::syntax;\nuse codespan_reporting::diagnostic::{Diagnostic, Label};\nuse codespan_reporting::"
},
{
"path": "gen/src/file.rs",
"chars": 2240,
"preview": "use crate::syntax::file::Module;\nuse crate::syntax::namespace::Namespace;\nuse syn::parse::discouraged::Speculative;\nuse "
},
{
"path": "gen/src/fs.rs",
"chars": 4595,
"preview": "#![allow(dead_code)]\n\nuse std::error::Error as StdError;\nuse std::fmt::{self, Display};\nuse std::io::{self, Read};\nuse s"
},
{
"path": "gen/src/guard.rs",
"chars": 588,
"preview": "use crate::gen::out::OutFile;\nuse crate::syntax::symbol::Symbol;\nuse crate::syntax::Pair;\nuse std::fmt::{self, Display};"
},
{
"path": "gen/src/ifndef.rs",
"chars": 1461,
"preview": "use crate::gen::include::HEADER;\nuse crate::gen::out::Content;\n\npub(super) fn write(out: &mut Content, needed: bool, gua"
},
{
"path": "gen/src/include.rs",
"chars": 5708,
"preview": "use crate::gen::out::{Content, OutFile};\nuse crate::syntax::{self, IncludeKind};\nuse std::ops::{Deref, DerefMut};\n\n/// T"
},
{
"path": "gen/src/mod.rs",
"chars": 6110,
"preview": "// Functionality that is shared between the cxx_build::bridge entry point and\n// the cxxbridge CLI command.\n\nmod block;\n"
},
{
"path": "gen/src/names.rs",
"chars": 399,
"preview": "use crate::syntax::Pair;\n\nimpl Pair {\n pub(crate) fn to_fully_qualified(&self) -> String {\n let mut fully_qual"
},
{
"path": "gen/src/namespace.rs",
"chars": 519,
"preview": "use crate::syntax::namespace::Namespace;\nuse crate::syntax::Api;\n\nimpl Api {\n pub(crate) fn namespace(&self) -> &Name"
},
{
"path": "gen/src/nested.rs",
"chars": 4896,
"preview": "use crate::syntax::map::UnorderedMap as Map;\nuse crate::syntax::Api;\nuse proc_macro2::Ident;\n\npub(crate) struct Namespac"
},
{
"path": "gen/src/out.rs",
"chars": 7227,
"preview": "use crate::gen::block::Block;\nuse crate::gen::builtin::Builtins;\nuse crate::gen::include::Includes;\nuse crate::gen::prag"
},
{
"path": "gen/src/pragma.rs",
"chars": 2644,
"preview": "use crate::gen::out::{Content, OutFile};\nuse std::collections::BTreeSet;\n\n#[derive(Default)]\npub(crate) struct Pragma<'a"
},
{
"path": "gen/src/write.rs",
"chars": 69150,
"preview": "use crate::gen::block::Block;\nuse crate::gen::guard::Guard;\nuse crate::gen::nested::NamespaceEntries;\nuse crate::gen::ou"
},
{
"path": "include/cxx.h",
"chars": 29568,
"preview": "#pragma once\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstddef>\n#include <cstdint>\n#include <ex"
},
{
"path": "macro/Cargo.toml",
"chars": 1038,
"preview": "[package]\nname = \"cxxbridge-macro\"\nversion = \"1.0.194\"\nauthors = [\"David Tolnay <dtolnay@gmail.com>\"]\ncategories = [\"dev"
},
{
"path": "macro/README.md",
"chars": 202,
"preview": "This directory contains CXX's Rust code generator, which is a procedural macro.\nUsers won't depend on this crate directl"
},
{
"path": "macro/build.rs",
"chars": 37,
"preview": "include!(\"../tools/cargo/build.rs\");\n"
},
{
"path": "macro/src/attrs.rs",
"chars": 1675,
"preview": "use crate::syntax::attrs::OtherAttrs;\nuse proc_macro2::TokenStream;\nuse quote::ToTokens;\nuse syn::Attribute;\n\nimpl Other"
},
{
"path": "macro/src/cfg.rs",
"chars": 3572,
"preview": "use crate::syntax::cfg::{CfgExpr, ComputedCfg};\nuse proc_macro2::{Delimiter, Group, Ident, Span, TokenStream};\nuse quote"
},
{
"path": "macro/src/derive.rs",
"chars": 13820,
"preview": "use crate::syntax::{derive, Enum, Struct};\nuse proc_macro2::{Ident, Span, TokenStream};\nuse quote::{quote, quote_spanned"
},
{
"path": "macro/src/expand.rs",
"chars": 94890,
"preview": "use crate::syntax::atom::Atom::*;\nuse crate::syntax::attrs::{self, OtherAttrs};\nuse crate::syntax::cfg::{CfgExpr, Comput"
},
{
"path": "macro/src/generics.rs",
"chars": 5193,
"preview": "use crate::expand::display_namespaced;\nuse crate::syntax::instantiate::NamedImplKey;\nuse crate::syntax::types::Condition"
},
{
"path": "macro/src/lib.rs",
"chars": 2971,
"preview": "#![allow(\n clippy::cast_sign_loss,\n clippy::doc_markdown,\n clippy::elidable_lifetime_names,\n clippy::enum_gl"
},
{
"path": "macro/src/tests.rs",
"chars": 6331,
"preview": "use crate::expand;\nuse crate::syntax::file::Module;\nuse proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::File;\n\nfn b"
},
{
"path": "macro/src/tokens.rs",
"chars": 2078,
"preview": "use crate::syntax::Receiver;\nuse proc_macro2::TokenStream;\nuse quote::{quote_spanned, ToTokens};\nuse syn::Token;\n\npub(cr"
},
{
"path": "macro/src/type_id.rs",
"chars": 1215,
"preview": "use crate::syntax::qualified::QualifiedName;\nuse proc_macro2::{TokenStream, TokenTree};\nuse quote::{format_ident, quote,"
},
{
"path": "reindeer.toml",
"chars": 92,
"preview": "error = \"This is the wrong directory. Run `reindeer buckify` in the third-party directory.\"\n"
},
{
"path": "rust-toolchain.toml",
"chars": 38,
"preview": "[toolchain]\ncomponents = [\"rust-src\"]\n"
},
{
"path": "src/cxx.cc",
"chars": 36739,
"preview": "#include \"../include/cxx.h\"\n#include <cstdio>\n#include <cstring>\n#include <iostream>\n#include <memory>\n\n#ifdef __cpp_lib"
},
{
"path": "src/cxx_string.rs",
"chars": 10674,
"preview": "use crate::actually_private::Private;\nuse crate::lossy;\n#[cfg(feature = \"alloc\")]\nuse alloc::borrow::Cow;\n#[cfg(feature "
},
{
"path": "src/cxx_vector.rs",
"chars": 20186,
"preview": "//! Less used details of `CxxVector` are exposed in this module. `CxxVector`\n//! itself is exposed at the crate root.\n\nu"
},
{
"path": "src/exception.rs",
"chars": 563,
"preview": "#![cfg(feature = \"alloc\")]\n\nuse alloc::boxed::Box;\nuse core::fmt::{self, Display};\n\nuse core::error::Error as StdError;\n"
},
{
"path": "src/extern_type.rs",
"chars": 7444,
"preview": "use self::kind::{Kind, Opaque, Trivial};\nuse crate::string::CxxString;\n#[cfg(feature = \"alloc\")]\nuse alloc::string::Stri"
},
{
"path": "src/fmt.rs",
"chars": 373,
"preview": "use core::fmt::{self, Display};\n\npub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display"
},
{
"path": "src/function.rs",
"chars": 150,
"preview": "#![allow(missing_docs)]\n\nuse core::ffi::c_void;\n\n#[repr(C)]\npub struct FatFunction {\n pub trampoline: *const c_void,\n"
},
{
"path": "src/hash.rs",
"chars": 173,
"preview": "use core::hash::{BuildHasher as _, Hash};\n\n#[doc(hidden)]\npub fn hash<V: Hash>(value: &V) -> usize {\n foldhash::quali"
},
{
"path": "src/lib.rs",
"chars": 21814,
"preview": "//! [![github]](https://github.com/dtolnay/cxx) [![crates-io]](https://crates.io/crates/cxx) [![docs-rs]](http"
},
{
"path": "src/lossy.rs",
"chars": 2175,
"preview": "use core::char;\nuse core::fmt::{self, Write as _};\nuse core::str;\n\npub(crate) fn display(mut bytes: &[u8], f: &mut fmt::"
},
{
"path": "src/macros/assert.rs",
"chars": 157,
"preview": "#[macro_export]\n#[doc(hidden)]\nmacro_rules! const_assert_eq {\n ($left:expr, $right:expr $(,)?) => {\n const _: "
},
{
"path": "src/macros/mod.rs",
"chars": 25,
"preview": "#[macro_use]\nmod assert;\n"
},
{
"path": "src/memory.rs",
"chars": 306,
"preview": "//! Less used details of `UniquePtr` and `SharedPtr`.\n//!\n//! The pointer types themselves are exposed at the crate root"
},
{
"path": "src/opaque.rs",
"chars": 734,
"preview": "#![allow(missing_docs)]\n\nuse crate::void;\nuse core::cell::UnsafeCell;\nuse core::marker::{PhantomData, PhantomPinned};\nus"
},
{
"path": "src/result.rs",
"chars": 1573,
"preview": "#![cfg(feature = \"alloc\")]\n#![allow(missing_docs)]\n\nuse crate::exception::Exception;\nuse alloc::boxed::Box;\nuse alloc::s"
},
{
"path": "src/rust_slice.rs",
"chars": 2373,
"preview": "#![allow(missing_docs)]\n\nuse core::mem::{self, MaybeUninit};\nuse core::ptr::{self, NonNull};\nuse core::slice;\n\n// ABI co"
},
{
"path": "src/rust_str.rs",
"chars": 790,
"preview": "#![allow(missing_docs)]\n\nuse core::mem::{self, MaybeUninit};\nuse core::ptr::NonNull;\nuse core::str;\n\n// ABI compatible w"
},
{
"path": "src/rust_string.rs",
"chars": 1430,
"preview": "#![cfg(feature = \"alloc\")]\n#![allow(missing_docs)]\n\nuse alloc::string::String;\nuse core::mem::{self, MaybeUninit};\nuse c"
},
{
"path": "src/rust_type.rs",
"chars": 1112,
"preview": "#![allow(missing_docs)]\n\nuse crate::extern_type::ExternType;\nuse crate::kind::Trivial;\nuse core::marker::{PhantomData, U"
},
{
"path": "src/rust_vec.rs",
"chars": 2000,
"preview": "#![cfg(feature = \"alloc\")]\n#![allow(missing_docs)]\n\nuse alloc::vec::Vec;\nuse core::ffi::c_void;\nuse core::marker::Phanto"
},
{
"path": "src/shared_ptr.rs",
"chars": 15720,
"preview": "use crate::extern_type::ExternType;\nuse crate::fmt::display;\nuse crate::kind::Trivial;\nuse crate::string::CxxString;\nuse"
},
{
"path": "src/symbols/exception.rs",
"chars": 601,
"preview": "#![cfg(feature = \"alloc\")]\n\nuse crate::result::PtrLen;\nuse alloc::boxed::Box;\nuse alloc::string::String;\nuse core::ptr::"
},
{
"path": "src/symbols/mod.rs",
"chars": 76,
"preview": "mod exception;\nmod rust_slice;\nmod rust_str;\nmod rust_string;\nmod rust_vec;\n"
},
{
"path": "src/symbols/rust_slice.rs",
"chars": 625,
"preview": "use crate::rust_slice::RustSlice;\nuse core::mem::MaybeUninit;\nuse core::ptr::{self, NonNull};\n\n#[export_name = \"cxxbridg"
},
{
"path": "src/symbols/rust_str.rs",
"chars": 1174,
"preview": "#[cfg(feature = \"alloc\")]\nuse alloc::string::String;\nuse core::mem::MaybeUninit;\nuse core::ptr;\nuse core::slice;\nuse cor"
},
{
"path": "src/symbols/rust_string.rs",
"chars": 3215,
"preview": "#![cfg(feature = \"alloc\")]\n\nuse alloc::borrow::ToOwned;\nuse alloc::string::String;\nuse core::mem::{ManuallyDrop, MaybeUn"
},
{
"path": "src/symbols/rust_vec.rs",
"chars": 3037,
"preview": "#![cfg(feature = \"alloc\")]\n\nuse crate::rust_string::RustString;\nuse crate::rust_vec::RustVec;\nuse alloc::vec::Vec;\nuse c"
},
{
"path": "src/type_id.rs",
"chars": 237,
"preview": "/// For use in impls of the `ExternType` trait. See [`ExternType`].\n///\n/// [`ExternType`]: crate::ExternType\n#[macro_ex"
},
{
"path": "src/unique_ptr.rs",
"chars": 13513,
"preview": "use crate::cxx_vector::{CxxVector, VectorElement};\nuse crate::extern_type::ExternType;\nuse crate::fmt::display;\nuse crat"
},
{
"path": "src/unwind.rs",
"chars": 1396,
"preview": "#![allow(missing_docs)]\n\nuse core::mem;\n\npub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R\nwhere\n "
},
{
"path": "src/vector.rs",
"chars": 235,
"preview": "//! Less used details of `CxxVector`.\n//!\n//! `CxxVector` itself is exposed at the crate root.\n\npub use crate::cxx_vecto"
},
{
"path": "src/weak_ptr.rs",
"chars": 5875,
"preview": "use crate::shared_ptr::{SharedPtr, SharedPtrTarget};\nuse crate::string::CxxString;\nuse core::ffi::c_void;\nuse core::fmt:"
},
{
"path": "syntax/atom.rs",
"chars": 2252,
"preview": "use crate::syntax::Type;\nuse proc_macro2::Ident;\nuse std::fmt::{self, Display};\n\n#[derive(Copy, Clone, PartialEq)]\npub(c"
},
{
"path": "syntax/attrs.rs",
"chars": 10247,
"preview": "use crate::syntax::cfg::CfgExpr;\nuse crate::syntax::namespace::Namespace;\nuse crate::syntax::report::Errors;\nuse crate::"
},
{
"path": "syntax/cfg.rs",
"chars": 6507,
"preview": "use indexmap::{indexset as set, IndexSet as Set};\nuse proc_macro2::Ident;\nuse std::hash::{Hash, Hasher};\nuse std::iter;\n"
},
{
"path": "syntax/check.rs",
"chars": 26760,
"preview": "use crate::syntax::atom::Atom::{self, *};\nuse crate::syntax::message::Message;\nuse crate::syntax::report::Errors;\nuse cr"
},
{
"path": "syntax/derive.rs",
"chars": 2328,
"preview": "use proc_macro2::{Ident, Span};\nuse std::fmt::{self, Display};\n\n#[derive(Copy, Clone)]\npub(crate) struct Derive {\n pu"
}
]
// ... and 263 more files (download for full content)
About this extraction
This page contains the full source code of the dtolnay/cxx GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 463 files (1.2 MB), approximately 347.7k tokens, and a symbol index with 1963 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.