Vendor dependencies

Let's see how I like this workflow.
This commit is contained in:
John Doty 2022-12-19 08:27:18 -08:00
parent 34d1830413
commit 9c435dc440
7500 changed files with 1665121 additions and 99 deletions

1
vendor/cxx/.cargo-checksum.json vendored Normal file

File diff suppressed because one or more lines are too long

92
vendor/cxx/BUCK vendored Normal file
View file

@ -0,0 +1,92 @@
rust_library(
name = "cxx",
srcs = glob(["src/**/*.rs"]),
edition = "2018",
features = [
"alloc",
"std",
],
visibility = ["PUBLIC"],
deps = [
":core",
":macro",
],
)
rust_binary(
name = "codegen",
srcs = glob(["gen/cmd/src/**/*.rs"]) + [
"gen/cmd/src/gen",
"gen/cmd/src/syntax",
],
crate = "cxxbridge",
edition = "2018",
visibility = ["PUBLIC"],
deps = [
"//third-party:clap",
"//third-party:codespan-reporting",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)
cxx_library(
name = "core",
srcs = ["src/cxx.cc"],
exported_headers = {
"cxx.h": "include/cxx.h",
},
exported_linker_flags = ["-lstdc++"],
header_namespace = "rust",
visibility = ["PUBLIC"],
)
rust_library(
name = "macro",
srcs = glob(["macro/src/**/*.rs"]) + ["macro/src/syntax"],
crate = "cxxbridge_macro",
edition = "2018",
proc_macro = True,
deps = [
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)
rust_library(
name = "build",
srcs = glob(["gen/build/src/**/*.rs"]) + [
"gen/build/src/gen",
"gen/build/src/syntax",
],
edition = "2018",
visibility = ["PUBLIC"],
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:once_cell",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:scratch",
"//third-party:syn",
],
)
rust_library(
name = "lib",
srcs = glob(["gen/lib/src/**/*.rs"]) + [
"gen/lib/src/gen",
"gen/lib/src/syntax",
],
edition = "2018",
visibility = ["PUBLIC"],
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)

89
vendor/cxx/BUILD vendored Normal file
View file

@ -0,0 +1,89 @@
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 = "2018",
proc_macro_deps = [
":cxxbridge-macro",
],
visibility = ["//visibility:public"],
deps = [":core-lib"],
)
rust_binary(
name = "codegen",
srcs = glob(["gen/cmd/src/**/*.rs"]),
data = ["gen/cmd/src/gen/include/cxx.h"],
edition = "2018",
visibility = ["//visibility:public"],
deps = [
"//third-party:clap",
"//third-party:codespan-reporting",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)
cc_library(
name = "core",
hdrs = ["include/cxx.h"],
include_prefix = "rust",
strip_include_prefix = "include",
visibility = ["//visibility:public"],
)
cc_library(
name = "core-lib",
srcs = ["src/cxx.cc"],
hdrs = ["include/cxx.h"],
)
rust_proc_macro(
name = "cxxbridge-macro",
srcs = glob(["macro/src/**/*.rs"]),
edition = "2018",
deps = [
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)
rust_library(
name = "build",
srcs = glob(["gen/build/src/**/*.rs"]),
data = ["gen/build/src/gen/include/cxx.h"],
edition = "2018",
visibility = ["//visibility:public"],
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:once_cell",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:scratch",
"//third-party:syn",
],
)
rust_library(
name = "lib",
srcs = glob(["gen/lib/src/**/*.rs"]),
data = ["gen/lib/src/gen/include/cxx.h"],
edition = "2018",
visibility = ["//visibility:public"],
deps = [
"//third-party:cc",
"//third-party:codespan-reporting",
"//third-party:proc-macro2",
"//third-party:quote",
"//third-party:syn",
],
)

89
vendor/cxx/Cargo.toml vendored Normal file
View file

@ -0,0 +1,89 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.48"
name = "cxx"
version = "1.0.85"
authors = ["David Tolnay <dtolnay@gmail.com>"]
links = "cxxbridge1"
exclude = [
"/demo",
"/gen",
"/syntax",
"/third-party",
]
description = "Safe interop between Rust and C++"
homepage = "https://cxx.rs"
documentation = "https://docs.rs/cxx"
readme = "README.md"
keywords = [
"ffi",
"c++",
]
categories = [
"development-tools::ffi",
"api-bindings",
"no-std",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/cxx"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = [
"--cfg",
"doc_cfg",
]
[lib]
doc-scrape-examples = false
[dependencies.cxxbridge-macro]
version = "=1.0.85"
[dependencies.link-cplusplus]
version = "1.0"
[dev-dependencies.cxx-build]
version = "=1.0.85"
[dev-dependencies.cxx-gen]
version = "0.7"
[dev-dependencies.cxx-test-suite]
version = "0"
[dev-dependencies.rustversion]
version = "1.0"
[dev-dependencies.trybuild]
version = "1.0.66"
features = ["diff"]
[build-dependencies.cc]
version = "1.0.49"
[build-dependencies.cxxbridge-flags]
version = "=1.0.85"
default-features = false
[features]
alloc = []
"c++14" = ["cxxbridge-flags/c++14"]
"c++17" = ["cxxbridge-flags/c++17"]
"c++20" = ["cxxbridge-flags/c++20"]
default = [
"std",
"cxxbridge-flags/default",
]
std = ["alloc"]

201
vendor/cxx/LICENSE-APACHE vendored Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
vendor/cxx/LICENSE-MIT vendored Normal file
View file

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

388
vendor/cxx/README.md vendored Normal file
View file

@ -0,0 +1,388 @@
CXX &mdash; 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.48+ 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** &mdash; their fields are made visible to both languages.
The definition written within cxx::bridge is the single source of truth.
- **Opaque types** &mdash; 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** &mdash; 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")
.flag_if_supported("-std=c++11")
.compile("cxxbridge-demo");
println!("cargo:rerun-if-changed=src/main.rs");
println!("cargo:rerun-if-changed=src/demo.cc");
println!("cargo:rerun-if-changed=include/demo.h");
}
```
<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 &lt;=&gt; 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>&amp;str</td><td>rust::Str</td><td></td></tr>
<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</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&lt;T&gt;</td><td>rust::Box&lt;T&gt;</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&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</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&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</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&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</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) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
<tr><td>Result&lt;T&gt;</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&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</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>

31
vendor/cxx/WORKSPACE vendored Normal file
View file

@ -0,0 +1,31 @@
workspace(name = "cxx.rs")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_rust",
sha256 = "617082067629939c0a22f587811a3e822a50a203119a90380e21f5aec3373da9",
strip_prefix = "rules_rust-e07881fa22a5f0d16230d8b23bbff2bf358823b8",
urls = [
# Main branch as of 2022-04-27
"https://github.com/bazelbuild/rules_rust/archive/e07881fa22a5f0d16230d8b23bbff2bf358823b8.tar.gz",
],
)
load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains")
RUST_VERSION = "1.65.0"
rules_rust_dependencies()
rust_register_toolchains(
version = RUST_VERSION,
)
load("//tools/bazel:vendor.bzl", "vendor")
vendor(
name = "third-party",
cargo_version = RUST_VERSION,
lockfile = "//third-party:Cargo.lock",
)

9
vendor/cxx/book/README.md vendored Normal file
View file

@ -0,0 +1,9 @@
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

22
vendor/cxx/book/book.toml vendored Normal file
View file

@ -0,0 +1,22 @@
[book]
#title = "Rust ♡ C++"
authors = ["David Tolnay"]
description = "CXX — safe interop between Rust and C++"
[rust]
edition = "2018"
[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"

104
vendor/cxx/book/build.js vendored Normal file
View file

@ -0,0 +1,104 @@
#!/usr/bin/env node
const fs = require('fs');
const cheerio = require('cheerio');
const hljs = require('./build/highlight.js');
const Entities = require('html-entities').AllHtmlEntities;
const entities = new Entities();
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 htmljs = `\
var html = document.querySelector('html');
html.classList.remove('no-js');
html.classList.add('js');`;
const dirs = ['build'];
while (dirs.length) {
const dir = dirs.pop();
fs.readdirSync(dir).forEach((entry) => {
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 });
$('head').append(opengraph);
$('script:nth-of-type(3)').text(htmljs);
$('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 lines = node.html().split('\n');
const boring = lines.map((line) =>
line.includes('<span class="boring">')
);
const ellipsis = lines.map((line) => line.includes('// ...'));
const target = entities.decode(node.text());
const highlighted = hljs.highlight(lang, target).value;
const result = highlighted
.split('\n')
.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;
}
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');
});
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);', '');
fs.writeFileSync('build/book.js', bookjs);

17
vendor/cxx/book/build.sh vendored Normal file
View file

@ -0,0 +1,17 @@
#!/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

44
vendor/cxx/book/css/cxx.css vendored Normal file
View file

@ -0,0 +1,44 @@
: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;
}

8
vendor/cxx/book/diagram/Makefile vendored Normal file
View file

@ -0,0 +1,8 @@
overview.svg: overview.pdf
pdf2svg $< $@
overview.pdf: overview.tex
latexmk $<
overview.png: overview.svg
svgexport $< $@ 3x

45
vendor/cxx/book/diagram/overview.tex vendored Normal file
View file

@ -0,0 +1,45 @@
\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}

207
vendor/cxx/book/package-lock.json generated vendored Normal file
View file

@ -0,0 +1,207 @@
{
"name": "cxx-book-build",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"cheerio": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
"integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
"requires": {
"css-select": "~1.2.0",
"dom-serializer": "~0.1.0",
"entities": "~1.1.1",
"htmlparser2": "^3.9.1",
"lodash.assignin": "^4.0.9",
"lodash.bind": "^4.1.4",
"lodash.defaults": "^4.0.1",
"lodash.filter": "^4.4.0",
"lodash.flatten": "^4.2.0",
"lodash.foreach": "^4.3.0",
"lodash.map": "^4.4.0",
"lodash.merge": "^4.4.0",
"lodash.pick": "^4.2.1",
"lodash.reduce": "^4.4.0",
"lodash.reject": "^4.4.0",
"lodash.some": "^4.4.0"
}
},
"css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"requires": {
"boolbase": "~1.0.0",
"css-what": "2.1",
"domutils": "1.5.1",
"nth-check": "~1.0.1"
}
},
"css-what": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
},
"dom-serializer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
"integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
"requires": {
"domelementtype": "^1.3.0",
"entities": "^1.1.1"
}
},
"domelementtype": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
},
"domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"requires": {
"domelementtype": "1"
}
},
"domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
"requires": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
"entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
},
"html-entities": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
"integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
"requires": {
"domelementtype": "^1.3.1",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.1.1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"lodash.assignin": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
"integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI="
},
"lodash.bind": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
"integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
},
"lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
},
"lodash.filter": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
"integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4="
},
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
},
"lodash.foreach": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
},
"lodash.map": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
"integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="
},
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.pick": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
},
"lodash.reduce": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
"integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
},
"lodash.reject": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
"integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU="
},
"lodash.some": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
"integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
},
"nth-check": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
"requires": {
"boolbase": "~1.0.0"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}
}
}

12
vendor/cxx/book/package.json vendored Normal file
View file

@ -0,0 +1,12 @@
{
"name": "cxx-book-build",
"version": "0.0.0",
"main": "build.js",
"dependencies": {
"cheerio": "^0.22.0",
"html-entities": "^1.3.1"
},
"prettier": {
"singleQuote": true
}
}

5
vendor/cxx/book/src/404.md vendored Normal file
View file

@ -0,0 +1,5 @@
### Whoops, this page doesnt exist :-(
<br>
<img src="https://www.rust-lang.org/static/images/ferris-error.png" alt="ferris" width="325">

37
vendor/cxx/book/src/SUMMARY.md vendored Normal file
View file

@ -0,0 +1,37 @@
# Summary
- [Rust ❤️ C++](index.md)
- [Core concepts](concepts.md)
- [Tutorial](tutorial.md)
- [Other Rust&ndash;C++ interop tools](context.md)
- [Multi-language build system options](building.md)
- [Cargo](build/cargo.md)
- [Bazel](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 &mdash; rust::String](binding/string.md)
- [&str &mdash; rust::Str](binding/str.md)
- [&&#91;T&#93;, &mut &#91;T&#93; &mdash; rust::Slice\<T\>](binding/slice.md)
- [CxxString &mdash; std::string](binding/cxxstring.md)
- [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
- [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
- [SharedPtr\<T\> &mdash; std::shared\_ptr\<T\>](binding/sharedptr.md)
- [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
- [CxxVector\<T\> &mdash; 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)

86
vendor/cxx/book/src/async.md vendored Normal file
View file

@ -0,0 +1,86 @@
{{#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,hidelines
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.8/futures/channel/oneshot/index.html
```rust,noplayground
// bridge.rs
use futures::channel::oneshot;
#[cxx::bridge]
mod ffi {
extern "Rust" {
type DoThingContext;
}
unsafe extern "C++" {
include!("path/to/bridge_shim.h");
fn shim_doThing(
arg: Arg,
done: fn(Box<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));
});
}
```

75
vendor/cxx/book/src/attributes.md vendored Normal file
View file

@ -0,0 +1,75 @@
{{#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.

120
vendor/cxx/book/src/binding/box.md vendored Normal file
View file

@ -0,0 +1,120 @@
{{#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");
}
```

140
vendor/cxx/book/src/binding/cxxstring.md vendored Normal file
View file

@ -0,0 +1,140 @@
{{#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", 2018.},
{"repository", json::null}});
}
```

View file

@ -0,0 +1,62 @@
{{#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);
}
```

34
vendor/cxx/book/src/binding/fn.md vendored Normal file
View file

@ -0,0 +1,34 @@
{{#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.

100
vendor/cxx/book/src/binding/rawptr.md vendored Normal file
View file

@ -0,0 +1,100 @@
{{#title *mut T, *const T — Rust ♡ C++}}
# *mut T,&ensp;*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.
}
```

148
vendor/cxx/book/src/binding/result.md vendored Normal file
View file

@ -0,0 +1,148 @@
{{#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,hidelines
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
```

View file

@ -0,0 +1,80 @@
{{#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>();
}
```

171
vendor/cxx/book/src/binding/slice.md vendored Normal file
View file

@ -0,0 +1,171 @@
{{#title rust::Slice<T> — Rust ♡ C++}}
# rust::Slice\<const T\>,&ensp;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;
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;
size_t length() const noexcept;
bool empty() const noexcept;
T &operator[](size_t n) const noexcept;
T &at(size_t n) const;
T &front() const noexcept;
T &back() const noexcept;
class iterator;
iterator begin() const noexcept;
iterator end() const noexcept;
void swap(Slice &) noexcept;
};
#
# template <typename T>
# class Slice<T>::iterator final {
# public:
# using iterator_category = std::random_access_iterator_tag;
# 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 &amp;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"
}
```

118
vendor/cxx/book/src/binding/str.md vendored Normal file
View file

@ -0,0 +1,118 @@
{{#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;
// Note: no null terminator.
const char *data() const noexcept;
size_t size() const noexcept;
size_t length() const noexcept;
bool empty() const noexcept;
using iterator = const char *;
using const_iterator = const char *;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
bool operator==(const Str &) const noexcept;
bool operator!=(const Str &) const noexcept;
bool operator<(const Str &) const noexcept;
bool operator<=(const Str &) const noexcept;
bool operator>(const Str &) const noexcept;
bool operator>=(const Str &) const noexcept;
void swap(Str &) noexcept;
};
std::ostream &operator<<(std::ostream &, const Str &);
#
# } // namespace rust
```
### Notes:
**Be aware that rust::Str behaves like &amp;str i.e. it is a borrow!**&ensp;C++
needs to be mindful of the lifetimes at play.
Just to reiterate: &amp;str is rust::Str. Do not try to write &amp;str as `const
rust::Str &`. A language-level C++ reference is not able to capture the fat
pointer nature of &amp;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++");
}
```

132
vendor/cxx/book/src/binding/string.md vendored Normal file
View file

@ -0,0 +1,132 @@
{{#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);
// Replaces invalid UTF-8 data with the replacement character (U+FFFD).
static String lossy(const std::string &) noexcept;
static String lossy(const char *) noexcept;
static String lossy(const char *, size_t) noexcept;
// Throws std::invalid_argument if not UTF-16.
String(const char16_t *);
String(const char16_t *, size_t);
// Replaces invalid UTF-16 data with the replacement character (U+FFFD).
static String lossy(const char16_t *) noexcept;
static String lossy(const char16_t *, size_t) noexcept;
String &operator=(const String &) noexcept;
String &operator=(String &&) noexcept;
explicit operator std::string() const;
// Note: no null terminator.
const char *data() const noexcept;
size_t size() const noexcept;
size_t length() const noexcept;
bool empty() const noexcept;
const char *c_str() noexcept;
size_t capacity() const noexcept;
void reserve(size_t new_cap) noexcept;
using iterator = char *;
iterator begin() noexcept;
iterator end() noexcept;
using const_iterator = const char *;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
bool operator==(const String &) const noexcept;
bool operator!=(const String &) const noexcept;
bool operator<(const String &) const noexcept;
bool operator<=(const String &) const noexcept;
bool operator>(const String &) const noexcept;
bool operator>=(const String &) const noexcept;
void swap(String &) noexcept;
};
std::ostream &operator<<(std::ostream &, const String &);
#
# } // namespace rust
```
### Restrictions:
None. Strings may be used as function arguments and function return values, by
value or by reference, as well as fields of shared structs.
## Example
```rust,noplayground
// src/main.rs
#[cxx::bridge]
mod ffi {
struct ConcatRequest {
fst: String,
snd: String,
}
unsafe extern "C++" {
include!("example/include/concat.h");
fn concat(r: ConcatRequest) -> String;
}
}
fn main() {
let concatenated = ffi::concat(ffi::ConcatRequest {
fst: "fearless".to_owned(),
snd: "concurrency".to_owned(),
});
println!("concatenated: {:?}", concatenated);
}
```
```cpp
// include/concat.h
#pragma once
#include "example/src/main.rs.h"
#include "rust/cxx.h"
rust::String concat(ConcatRequest r);
```
```cpp
// src/concat.cc
#include "example/include/concat.h"
rust::String concat(ConcatRequest r) {
// The full suite of operator overloads hasn't been added
// yet on rust::String, but we can get it done like this:
return std::string(r.fst) + std::string(r.snd);
}
```

View file

@ -0,0 +1,63 @@
{{#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>();
}
```

192
vendor/cxx/book/src/binding/vec.md vendored Normal file
View file

@ -0,0 +1,192 @@
{{#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:
# using iterator_category = std::random_access_iterator_tag;
# 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:
# using iterator_category = std::random_access_iterator_tag;
# 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());
}
```

56
vendor/cxx/book/src/bindings.md vendored Normal file
View file

@ -0,0 +1,56 @@
{{#title Built-in bindings — Rust ♡ C++}}
# Built-in bindings reference
In addition to all the primitive types (i32 &lt;=&gt; 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">&amp;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">&amp;[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;T&gt;</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">&amp;mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;T&gt;</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&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</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&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</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&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::shared_ptr&lt;T&gt;</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&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
<tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</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&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</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) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</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&lt;T&gt;</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&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
</table>

106
vendor/cxx/book/src/build/bazel.md vendored Normal file
View file

@ -0,0 +1,106 @@
{{#title Bazel, Buck — Rust ♡ C++}}
## Bazel, Buck, potentially other similar environments
Starlark-based build systems with the ability to compile a code generator and
invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge`
command line interface.
The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built
from the *gen/cmd/* directory of the CXX GitHub repo.
```console
$ cargo install cxxbridge-cmd
$ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
$ cxxbridge src/bridge.rs > path/to/bridge.rs.cc
```
The CXX repo maintains working Bazel `BUILD` and Buck `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.
```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
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"],
)
```

306
vendor/cxx/book/src/build/cargo.md vendored Normal file
View file

@ -0,0 +1,306 @@
{{#title Cargo-based setup — Rust ♡ C++}}
# Cargo-based builds
As one aspect of delivering a good Rust&ndash;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 = "2018"
[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")
.flag_if_supported("-std=c++11")
.compile("cxxbridge-demo");
println!("cargo:rerun-if-changed=src/main.rs");
println!("cargo:rerun-if-changed=src/demo.cc");
println!("cargo:rerun-if-changed=include/demo.h");
}
```
The `rerun-if-changed` lines are optional but make it so that Cargo does not
spend time recompiling your C++ code when only non-C++ code has changed since
the previous Cargo build. By default without any `rerun-if-changed`, Cargo will
re-execute the build script after *any* file changed in the project.
If stuck, try comparing what you have against the *demo/* directory of the CXX
GitHub repo, which maintains a working Cargo-based setup for the blobstore
tutorial (chapter 3).
## Header include paths
With cxx-build, by default your include paths always start with the crate name.
This applies to both `#include` within your C++ code, and `include!` in the
`extern "C++"` section of your Rust cxx::bridge.
Your crate name is determined by the `name` entry in Cargo.toml.
For example if your crate is named `yourcratename` and contains a C++ header
file `path/to/header.h` relative to Cargo.toml, that file will be includable as:
```cpp
#include "yourcratename/path/to/header.h"
```
A crate can choose a prefix for its headers that is different from the crate
name by modifying **[`CFG.include_prefix`][CFG]** from build.rs:
[CFG]: https://docs.rs/cxx-build/*/cxx_build/static.CFG.html
```rust,noplayground
// build.rs
use cxx_build::CFG;
fn main() {
CFG.include_prefix = "my/project";
cxx_build::bridge(...)...
}
```
Subsequently the header located at `path/to/header.h` would now be includable
as:
```cpp
#include "my/project/path/to/header.h"
```
The empty string `""` is a valid include prefix and will make it possible to
have `#include "path/to/header.h"`. However, if your crate is a library, be
considerate of possible name collisions that may occur in downstream crates. If
using an empty include prefix, you'll want to make sure your headers' local path
within the crate is sufficiently namespaced or unique.
## Including generated code
If your `#[cxx::bridge]` module contains an `extern "Rust"` block i.e. types or
functions exposed from Rust to C++, or any shared data structures, the
CXX-generated C++ header declaring those things is available using a `.rs.h`
extension on the Rust source file's name.
```cpp
// the header generated from path/to/lib.rs
#include "yourcratename/path/to/lib.rs.h"
```
For giggles, it's also available using just a plain `.rs` extension as if you
were including the Rust file directly. Use whichever you find more palatable.
```cpp
#include "yourcratename/path/to/lib.rs"
```
## Including headers from dependencies
You get to include headers from your dependencies, both handwritten ones
contained as `.h` files in their Cargo package, as well as CXX-generated ones.
It works the same as an include of a local header: use the crate name (or their
include\_prefix if their crate changed it) followed by the relative path of the
header within the crate.
```cpp
#include "dependencycratename/path/to/their/header.h`
```
Note that cross-crate imports are only made available between **direct
dependencies**. You must directly depend on the other crate in order to #include
its headers; a transitive dependency is not sufficient.
Additionally, headers from a direct dependency are only importable if the
dependency's Cargo.toml manifest contains a `links` key. If not, its headers
will not be importable from outside of the same crate. See *[the `links`
manifest key][links]* in the Cargo reference.
[links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
<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");
}
```

47
vendor/cxx/book/src/build/cmake.md vendored Normal file
View file

@ -0,0 +1,47 @@
{{#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
---

75
vendor/cxx/book/src/build/other.md vendored Normal file
View file

@ -0,0 +1,75 @@
{{#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.
### Producing the generated code
CXX's Rust code generation automatically happens when the `#[cxx::bridge]`
procedural macro is expanded during the normal Rust compilation process, so no
special build steps are required there.
But the C++ side of the bindings needs to be generated. Your options are:
- Use the `cxxbridge` command, which is a standalone command line interface to
the CXX C++ code generator. Wire up your build system to compile and invoke
this tool.
```console
$ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
$ cxxbridge src/bridge.rs > path/to/bridge.rs.cc
```
It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from
the *gen/cmd/* directory of the CXX GitHub repo.
- Or, build your own code generator frontend on top of the [cxx-gen] crate. This
is currently unofficial and unsupported.
[cxx-gen]: https://docs.rs/cxx-gen
### Compiling C++
However you like. We can provide no guidance.
### Linking the C++ and Rust together
When linking a binary which contains mixed Rust and C++ code, you will have to
choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you
may already have extensively tuned.
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

20
vendor/cxx/book/src/building.md vendored Normal file
View file

@ -0,0 +1,20 @@
{{#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.

85
vendor/cxx/book/src/concepts.md vendored Normal file
View file

@ -0,0 +1,85 @@
{{#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** &mdash; 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** &mdash; 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** &mdash; 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>

118
vendor/cxx/book/src/context.md vendored Normal file
View file

@ -0,0 +1,118 @@
{{#title Other RustC++ interop tools — Rust ♡ C++}}
# Context: other Rust&ndash;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
&mdash; 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&ndash;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&ndash;C edge always involves a
great deal of `unsafe` code, and the C++&ndash;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&ndash;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.

BIN
vendor/cxx/book/src/cxx.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

352
vendor/cxx/book/src/extern-c++.md vendored Normal file
View file

@ -0,0 +1,352 @@
{{#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.
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
}
```

165
vendor/cxx/book/src/extern-rust.md vendored Normal file
View file

@ -0,0 +1,165 @@
{{#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" {
struct 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);
}
# }
```
## 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.

83
vendor/cxx/book/src/index.md vendored Normal file
View file

@ -0,0 +1,83 @@
<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.*

444
vendor/cxx/book/src/overview.svg vendored Normal file
View file

@ -0,0 +1,444 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="541.903pt" height="142.287pt" viewBox="0 0 541.903 142.287" version="1.1">
<defs>
<g>
<symbol overflow="visible" id="glyph0-0">
<path style="stroke:none;" d=""/>
</symbol>
<symbol overflow="visible" id="glyph0-1">
<path style="stroke:none;" d="M 5.140625 -2.359375 L 6.234375 -2.359375 C 6.421875 -2.359375 6.890625 -2.359375 6.890625 -2.828125 C 6.890625 -3.296875 6.4375 -3.296875 6.234375 -3.296875 L 5.265625 -3.296875 L 5.515625 -5.46875 L 6.234375 -5.46875 C 6.421875 -5.46875 6.890625 -5.46875 6.890625 -5.921875 C 6.890625 -6.390625 6.4375 -6.390625 6.234375 -6.390625 L 5.65625 -6.390625 L 5.875 -8.125 C 5.9375 -8.59375 5.6875 -8.765625 5.421875 -8.765625 C 5.015625 -8.765625 4.984375 -8.390625 4.953125 -8.203125 L 4.71875 -6.390625 L 3.171875 -6.390625 L 3.40625 -8.125 C 3.453125 -8.59375 3.203125 -8.765625 2.9375 -8.765625 C 2.53125 -8.765625 2.5 -8.390625 2.46875 -8.203125 L 2.234375 -6.390625 L 1.140625 -6.390625 C 0.953125 -6.390625 0.484375 -6.390625 0.484375 -5.9375 C 0.484375 -5.46875 0.9375 -5.46875 1.140625 -5.46875 L 2.109375 -5.46875 L 1.84375 -3.296875 L 1.140625 -3.296875 C 0.953125 -3.296875 0.484375 -3.296875 0.484375 -2.84375 C 0.484375 -2.359375 0.9375 -2.359375 1.140625 -2.359375 L 1.71875 -2.359375 L 1.484375 -0.640625 C 1.40625 0 1.90625 0 1.953125 0 C 2.359375 0 2.390625 -0.375 2.421875 -0.5625 L 2.65625 -2.359375 L 4.203125 -2.359375 L 3.96875 -0.640625 C 3.890625 0 4.390625 0 4.4375 0 C 4.828125 0 4.875 -0.375 4.90625 -0.5625 Z M 3.046875 -5.46875 L 4.59375 -5.46875 L 4.328125 -3.296875 L 2.78125 -3.296875 Z M 3.046875 -5.46875 "/>
</symbol>
<symbol overflow="visible" id="glyph0-2">
<path style="stroke:none;" d="M 6.21875 -9.125 C 6.421875 -9.125 6.796875 -9.125 6.796875 -9.53125 C 6.796875 -9.953125 6.421875 -9.953125 6.21875 -9.953125 L 3.734375 -9.953125 C 3.25 -9.953125 3.15625 -9.828125 3.15625 -9.359375 L 3.15625 0.609375 C 3.15625 1.046875 3.234375 1.1875 3.734375 1.1875 L 6.21875 1.1875 C 6.421875 1.1875 6.796875 1.1875 6.796875 0.78125 C 6.796875 0.359375 6.421875 0.359375 6.21875 0.359375 L 4.09375 0.359375 L 4.09375 -9.125 Z M 6.21875 -9.125 "/>
</symbol>
<symbol overflow="visible" id="glyph0-3">
<path style="stroke:none;" d="M 4.21875 -9.359375 C 4.21875 -9.8125 4.125 -9.953125 3.640625 -9.953125 L 1.140625 -9.953125 C 0.953125 -9.953125 0.578125 -9.953125 0.578125 -9.53125 C 0.578125 -9.125 0.953125 -9.125 1.140625 -9.125 L 3.28125 -9.125 L 3.28125 0.359375 L 1.140625 0.359375 C 0.953125 0.359375 0.578125 0.359375 0.578125 0.78125 C 0.578125 1.1875 0.953125 1.1875 1.140625 1.1875 L 3.640625 1.1875 C 4.109375 1.1875 4.21875 1.0625 4.21875 0.609375 Z M 4.21875 -9.359375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-4">
<path style="stroke:none;" d="M 4.15625 -3.921875 L 6.203125 -3.921875 C 6.390625 -3.921875 6.84375 -3.921875 6.84375 -4.375 C 6.84375 -4.84375 6.390625 -4.84375 6.203125 -4.84375 L 4.15625 -4.84375 L 4.15625 -6.90625 C 4.15625 -7.078125 4.15625 -7.546875 3.703125 -7.546875 C 3.234375 -7.546875 3.234375 -7.09375 3.234375 -6.90625 L 3.234375 -4.84375 L 1.171875 -4.84375 C 0.984375 -4.84375 0.53125 -4.84375 0.53125 -4.390625 C 0.53125 -3.921875 0.96875 -3.921875 1.171875 -3.921875 L 3.234375 -3.921875 L 3.234375 -1.859375 C 3.234375 -1.671875 3.234375 -1.21875 3.6875 -1.21875 C 4.15625 -1.21875 4.15625 -1.65625 4.15625 -1.859375 Z M 4.15625 -3.921875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-0">
<path style="stroke:none;" d=""/>
</symbol>
<symbol overflow="visible" id="glyph1-1">
<path style="stroke:none;" d="M 5.75 -1.546875 C 5.09375 -1.015625 4.359375 -0.75 3.5625 -0.75 C 2.359375 -0.75 1.59375 -1.8125 1.59375 -3.203125 C 1.59375 -4.390625 2.171875 -5.6875 3.59375 -5.6875 C 4.5625 -5.6875 4.96875 -5.46875 5.578125 -5.046875 L 5.75 -5.984375 C 4.921875 -6.46875 4.453125 -6.578125 3.59375 -6.578125 C 1.625 -6.578125 0.5 -4.828125 0.5 -3.203125 C 0.5 -1.359375 1.828125 0.140625 3.546875 0.140625 C 4.25 0.140625 5.046875 -0.03125 5.84375 -0.609375 C 5.84375 -0.640625 5.796875 -1.09375 5.78125 -1.140625 Z M 5.75 -1.546875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-2">
<path style="stroke:none;" d="M 3.640625 -3.28125 L 6.1875 -6.375 L 4.984375 -6.375 L 3.171875 -4.046875 L 1.296875 -6.375 L 0.078125 -6.375 L 2.6875 -3.28125 L 0 0 L 1.1875 0 L 3.171875 -2.671875 L 5.203125 0 L 6.40625 0 Z M 3.640625 -3.28125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-3">
<path style="stroke:none;" d="M 2.53125 -6.375 L 1.359375 -6.375 L 1.359375 -5.203125 L 2.53125 -5.203125 Z M 1.359375 -1.15625 L 1.359375 0 L 2.53125 0 L 2.53125 -1.15625 Z M 1.359375 -1.15625 "/>
</symbol>
<symbol overflow="visible" id="glyph1-4">
<path style="stroke:none;" d="M 2.1875 -9.953125 L 1.125 -9.953125 L 1.125 0 L 2.203125 0 L 2.203125 -0.640625 C 2.875 -0.015625 3.578125 0.140625 4.078125 0.140625 C 5.4375 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.96875 5.734375 -6.515625 4.40625 -6.515625 C 3.984375 -6.515625 3.0625 -6.421875 2.1875 -5.703125 Z M 2.203125 -4.828125 C 2.46875 -5.234375 2.984375 -5.65625 3.6875 -5.65625 C 4.5625 -5.65625 5.59375 -4.984375 5.59375 -3.203125 C 5.59375 -1.328125 4.421875 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.265625 -1.359375 2.203125 -1.625 2.203125 -1.859375 Z M 2.203125 -4.828125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-5">
<path style="stroke:none;" d="M 2.1875 -3.140625 C 2.1875 -4.59375 3.265625 -5.53125 4.5625 -5.546875 L 4.5625 -6.515625 C 3.25 -6.5 2.5 -5.734375 2.109375 -5.171875 L 2.109375 -6.4375 L 1.125 -6.4375 L 1.125 0 L 2.1875 0 Z M 2.1875 -3.140625 "/>
</symbol>
<symbol overflow="visible" id="glyph1-6">
<path style="stroke:none;" d="M 2.265625 -9.734375 L 1.03125 -9.734375 L 1.03125 -8.5 L 2.265625 -8.5 Z M 2.1875 -6.375 L 1.125 -6.375 L 1.125 0 L 2.1875 0 Z M 2.1875 -6.375 "/>
</symbol>
<symbol overflow="visible" id="glyph1-7">
<path style="stroke:none;" d="M 6.0625 -9.953125 L 5 -9.953125 L 5 -5.765625 C 4.34375 -6.3125 3.59375 -6.515625 2.984375 -6.515625 C 1.625 -6.515625 0.5 -5.046875 0.5 -3.1875 C 0.5 -1.328125 1.5625 0.140625 2.921875 0.140625 C 3.453125 0.140625 4.265625 -0.03125 4.984375 -0.734375 L 4.984375 0 L 6.0625 0 Z M 4.984375 -1.6875 C 4.640625 -1.078125 4.125 -0.71875 3.5 -0.71875 C 2.625 -0.71875 1.59375 -1.390625 1.59375 -3.171875 C 1.59375 -5.078125 2.8125 -5.65625 3.640625 -5.65625 C 4.203125 -5.65625 4.65625 -5.359375 4.984375 -4.890625 Z M 4.984375 -1.6875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-8">
<path style="stroke:none;" d="M 4.890625 -5.65625 C 4.890625 -5.65625 4.921875 -5.625 4.9375 -5.59375 C 5.234375 -5.625 5.546875 -5.671875 6.078125 -5.671875 C 6.125 -5.671875 6.453125 -5.671875 6.8125 -5.640625 L 6.65625 -6.515625 C 6.390625 -6.515625 5.40625 -6.5 4.453125 -6.03125 C 3.984375 -6.4375 3.40625 -6.515625 3.125 -6.515625 C 1.875 -6.515625 0.875 -5.46875 0.875 -4.203125 C 0.875 -3.6875 1.03125 -3.21875 1.34375 -2.78125 C 1.015625 -2.328125 0.9375 -1.890625 0.9375 -1.546875 C 0.9375 -1.015625 1.140625 -0.65625 1.296875 -0.46875 C 0.5625 0 0.390625 0.609375 0.390625 1.015625 C 0.390625 2.0625 1.75 2.9375 3.5 2.9375 C 5.25 2.9375 6.625 2.09375 6.625 1 C 6.625 -1 4.296875 -1 3.71875 -1 L 2.5 -1 C 2.296875 -1 1.671875 -1 1.671875 -1.765625 C 1.671875 -2.078125 1.734375 -2.171875 1.828125 -2.296875 C 2.0625 -2.125 2.53125 -1.875 3.109375 -1.875 C 4.34375 -1.875 5.359375 -2.890625 5.359375 -4.203125 C 5.359375 -4.71875 5.171875 -5.25 4.875 -5.640625 Z M 3.125 -2.671875 C 2.5 -2.671875 1.859375 -3.09375 1.859375 -4.1875 C 1.859375 -5.46875 2.671875 -5.71875 3.109375 -5.71875 C 3.75 -5.71875 4.375 -5.296875 4.375 -4.203125 C 4.375 -2.921875 3.578125 -2.671875 3.125 -2.671875 Z M 3.734375 0.03125 C 4.046875 0.03125 5.625 0.03125 5.625 1.015625 C 5.625 1.671875 4.640625 2.15625 3.515625 2.15625 C 2.390625 2.15625 1.390625 1.703125 1.390625 1 C 1.390625 0.96875 1.390625 0.03125 2.484375 0.03125 Z M 3.734375 0.03125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-9">
<path style="stroke:none;" d="M 5.84375 -3.234375 C 5.84375 -3.84375 5.78125 -4.71875 5.328125 -5.484375 C 4.734375 -6.46875 3.734375 -6.578125 3.3125 -6.578125 C 1.765625 -6.578125 0.46875 -5.09375 0.46875 -3.234375 C 0.46875 -1.328125 1.84375 0.140625 3.515625 0.140625 C 4.171875 0.140625 4.96875 -0.046875 5.75 -0.609375 C 5.75 -0.671875 5.703125 -1.125 5.703125 -1.140625 C 5.6875 -1.15625 5.671875 -1.484375 5.671875 -1.53125 C 4.8125 -0.8125 3.96875 -0.71875 3.546875 -0.71875 C 2.4375 -0.71875 1.484375 -1.703125 1.46875 -3.234375 Z M 1.546875 -4 C 1.796875 -4.96875 2.46875 -5.71875 3.3125 -5.71875 C 3.765625 -5.71875 4.75 -5.515625 4.984375 -4 Z M 1.546875 -4 "/>
</symbol>
<symbol overflow="visible" id="glyph1-10">
<path style="stroke:none;" d="M 10 -4.3125 C 10 -5.3125 9.734375 -6.515625 8.0625 -6.515625 C 6.84375 -6.515625 6.171875 -5.671875 5.953125 -5.34375 C 5.6875 -6.25 4.90625 -6.515625 4.15625 -6.515625 C 2.984375 -6.515625 2.359375 -5.75 2.125 -5.453125 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.515625 2.5625 -5.65625 3.609375 -5.65625 C 4.9375 -5.65625 5 -4.75 5 -4.21875 L 5 0 L 6.09375 0 L 6.09375 -3.578125 C 6.09375 -4.515625 6.46875 -5.65625 7.515625 -5.65625 C 8.828125 -5.65625 8.90625 -4.75 8.90625 -4.21875 L 8.90625 0 L 10 0 Z M 10 -4.3125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-11">
<path style="stroke:none;" d="M 6.578125 -3.15625 C 6.578125 -5.09375 5.15625 -6.578125 3.515625 -6.578125 C 1.828125 -6.578125 0.4375 -5.0625 0.4375 -3.15625 C 0.4375 -1.28125 1.859375 0.140625 3.5 0.140625 C 5.1875 0.140625 6.578125 -1.3125 6.578125 -3.15625 Z M 3.515625 -0.75 C 2.484375 -0.75 1.515625 -1.609375 1.515625 -3.296875 C 1.515625 -5.03125 2.59375 -5.71875 3.5 -5.71875 C 4.484375 -5.71875 5.5 -4.984375 5.5 -3.296875 C 5.5 -1.53125 4.46875 -0.75 3.515625 -0.75 Z M 3.515625 -0.75 "/>
</symbol>
<symbol overflow="visible" id="glyph1-12">
<path style="stroke:none;" d="M 4.8125 -6.140625 C 3.90625 -6.5625 3.125 -6.578125 2.796875 -6.578125 C 2.46875 -6.578125 0.46875 -6.578125 0.46875 -4.71875 C 0.46875 -4.09375 0.8125 -3.65625 1.03125 -3.453125 C 1.546875 -3.015625 1.90625 -2.9375 2.75 -2.765625 C 3.234375 -2.671875 4.0625 -2.5 4.0625 -1.734375 C 4.0625 -0.75 2.9375 -0.75 2.734375 -0.75 C 2.171875 -0.75 1.328125 -0.90625 0.5625 -1.46875 L 0.390625 -0.484375 C 0.453125 -0.4375 1.4375 0.140625 2.75 0.140625 C 4.609375 0.140625 5.046875 -0.96875 5.046875 -1.828125 C 5.046875 -2.546875 4.609375 -3.015625 4.546875 -3.078125 C 4.015625 -3.625 3.578125 -3.71875 2.71875 -3.890625 C 2.1875 -3.984375 1.46875 -4.125 1.46875 -4.84375 C 1.46875 -5.734375 2.46875 -5.734375 2.65625 -5.734375 C 3.40625 -5.734375 4.015625 -5.5625 4.640625 -5.203125 Z M 4.8125 -6.140625 "/>
</symbol>
<symbol overflow="visible" id="glyph1-13">
<path style="stroke:none;" d="M 2.203125 -0.640625 C 2.703125 -0.203125 3.296875 0.140625 4.078125 0.140625 C 5.453125 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.9375 5.765625 -6.515625 4.4375 -6.515625 C 3.84375 -6.515625 2.921875 -6.328125 2.1875 -5.6875 L 2.1875 -6.375 L 1.125 -6.375 L 1.125 2.78125 L 2.203125 2.78125 Z M 2.203125 -4.8125 C 2.53125 -5.3125 3.078125 -5.625 3.671875 -5.625 C 4.734375 -5.625 5.59375 -4.546875 5.59375 -3.1875 C 5.59375 -1.75 4.609375 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.25 -1.375 2.203125 -1.640625 2.203125 -1.859375 Z M 2.203125 -4.8125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-14">
<path style="stroke:none;" d="M 2.453125 -5.53125 L 4.4375 -5.53125 L 4.4375 -6.375 L 2.453125 -6.375 L 2.453125 -8.1875 L 1.46875 -8.1875 L 1.46875 -6.375 L 0.265625 -6.375 L 0.265625 -5.53125 L 1.4375 -5.53125 L 1.4375 -1.671875 C 1.4375 -0.84375 1.625 0.140625 2.609375 0.140625 C 3.578125 0.140625 4.234375 -0.1875 4.671875 -0.421875 L 4.453125 -1.25 C 3.953125 -0.796875 3.421875 -0.75 3.171875 -0.75 C 2.53125 -0.75 2.453125 -1.421875 2.453125 -1.921875 Z M 2.453125 -5.53125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-15">
<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.359375 -6.515625 2.671875 -6.15625 2.125 -5.46875 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-16">
<path style="stroke:none;" d="M 2.484375 -5.53125 L 4.015625 -5.53125 L 4.015625 -6.375 L 2.453125 -6.375 L 2.453125 -8.09375 C 2.453125 -9.0625 3.265625 -9.234375 3.75 -9.234375 C 4.25 -9.234375 4.6875 -9.078125 4.859375 -9.015625 L 4.859375 -9.953125 C 4.765625 -9.984375 4.28125 -10.09375 3.765625 -10.09375 C 2.390625 -10.09375 1.421875 -9.046875 1.421875 -7.65625 L 1.421875 -6.375 L 0.375 -6.375 L 0.375 -5.53125 L 1.421875 -5.53125 L 1.421875 0 L 2.484375 0 Z M 2.484375 -5.53125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-17">
<path style="stroke:none;" d="M 6.078125 -6.375 L 4.984375 -6.375 L 4.984375 -2.265625 C 4.984375 -1.171875 4.234375 -0.640625 3.296875 -0.640625 C 2.296875 -0.640625 2.1875 -1.015625 2.1875 -1.65625 L 2.1875 -6.375 L 1.109375 -6.375 L 1.109375 -1.59375 C 1.109375 -0.5625 1.4375 0.140625 2.609375 0.140625 C 3.015625 0.140625 4.140625 0.078125 5.015625 -0.71875 L 5.015625 0 L 6.078125 0 Z M 6.078125 -6.375 "/>
</symbol>
<symbol overflow="visible" id="glyph1-18">
<path style="stroke:none;" d="M 5.609375 -4.203125 C 5.609375 -5.578125 4.625 -6.578125 3.28125 -6.578125 C 2.421875 -6.578125 1.78125 -6.390625 1.078125 -5.984375 L 1.15625 -5.03125 C 1.796875 -5.5 2.453125 -5.75 3.28125 -5.75 C 3.9375 -5.75 4.515625 -5.21875 4.515625 -4.171875 L 4.515625 -3.578125 C 3.875 -3.5625 3.015625 -3.515625 2.15625 -3.234375 C 1.1875 -2.890625 0.625 -2.359375 0.625 -1.65625 C 0.625 -1.015625 1 0.140625 2.21875 0.140625 C 3.015625 0.140625 4.015625 -0.09375 4.546875 -0.53125 L 4.546875 0 L 5.609375 0 Z M 4.515625 -1.921875 C 4.515625 -1.640625 4.515625 -1.296875 4.046875 -1 C 3.65625 -0.765625 3.171875 -0.71875 2.953125 -0.71875 C 2.1875 -0.71875 1.65625 -1.140625 1.65625 -1.65625 C 1.65625 -2.640625 3.640625 -2.859375 4.515625 -2.859375 Z M 4.515625 -1.921875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-19">
<path style="stroke:none;" d="M 6.203125 -6.375 L 5.140625 -6.375 C 4.46875 -4.671875 3.375 -1.859375 3.3125 -0.828125 L 3.296875 -0.828125 C 3.234375 -1.671875 2.46875 -3.578125 2.359375 -3.859375 L 1.328125 -6.375 L 0.203125 -6.375 L 2.875 0 L 2.359375 1.3125 C 2.046875 2.015625 1.84375 2.09375 1.578125 2.09375 C 1.375 2.09375 0.921875 2.046875 0.46875 1.875 L 0.5625 2.8125 C 0.640625 2.828125 1.125 2.921875 1.578125 2.921875 C 1.921875 2.921875 2.59375 2.921875 3.21875 1.34375 Z M 6.203125 -6.375 "/>
</symbol>
<symbol overflow="visible" id="glyph1-20">
<path style="stroke:none;" d="M 5.84375 -4.671875 C 7.40625 -5.125 8.25 -6.203125 8.25 -7.265625 C 8.25 -8.703125 6.71875 -9.953125 4.6875 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.515625 0 L 2.515625 -4.546875 L 4.75 -4.546875 L 7.40625 0 L 8.640625 0 Z M 2.515625 -5.40625 L 2.515625 -9.15625 L 4.53125 -9.15625 C 6.265625 -9.15625 7.109375 -8.234375 7.109375 -7.265625 C 7.109375 -6.390625 6.34375 -5.40625 4.53125 -5.40625 Z M 2.515625 -5.40625 "/>
</symbol>
<symbol overflow="visible" id="glyph1-21">
<path style="stroke:none;" d="M 8.171875 -1.65625 C 7.296875 -1 6.703125 -0.765625 5.453125 -0.765625 C 3.578125 -0.765625 2.171875 -2.703125 2.171875 -5 C 2.171875 -6.9375 3.328125 -9.21875 5.515625 -9.21875 C 6.453125 -9.21875 7.171875 -8.9375 7.890625 -8.453125 L 8.109375 -9.625 C 7.171875 -9.984375 6.46875 -10.109375 5.484375 -10.109375 C 3.046875 -10.109375 0.953125 -7.953125 0.953125 -4.984375 C 0.953125 -1.84375 3.25 0.125 5.34375 0.125 C 6.78125 0.125 7.09375 0.046875 8.265625 -0.65625 Z M 8.171875 -1.65625 "/>
</symbol>
<symbol overflow="visible" id="glyph1-22">
<path style="stroke:none;" d="M 3 -9.953125 L 1.359375 -9.953125 L 1.359375 0 L 2.46875 0 L 2.46875 -8.84375 L 2.484375 -8.84375 C 2.6875 -7.875 5 -1.734375 5.546875 -0.296875 L 6.59375 -0.296875 C 7.078125 -1.53125 9.4375 -7.78125 9.703125 -8.859375 L 9.703125 0 L 10.8125 0 L 10.8125 -9.953125 L 9.1875 -9.953125 L 7.546875 -5.53125 C 6.796875 -3.53125 6.234375 -2.015625 6.09375 -1.359375 L 6.078125 -1.359375 C 6.03125 -1.609375 5.859375 -2.140625 5.671875 -2.703125 C 5.40625 -3.46875 5.40625 -3.5 5.171875 -4.09375 Z M 3 -9.953125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-23">
<path style="stroke:none;" d="M 8.53125 -9.953125 L 7.296875 -9.953125 L 7.296875 -5.609375 L 2.53125 -5.609375 L 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 L 2.53125 -4.75 L 7.296875 -4.75 L 7.296875 0 L 8.53125 0 Z M 8.53125 -9.953125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-24">
<path style="stroke:none;" d="M 5.265625 -9.953125 L 4 -9.953125 L 0.390625 0 L 1.453125 0 L 2.5 -2.90625 L 6.546875 -2.90625 L 7.609375 0 L 8.875 0 Z M 4.515625 -8.921875 L 6.234375 -3.71875 L 2.8125 -3.71875 Z M 4.515625 -8.921875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-25">
<path style="stroke:none;" d="M 1.328125 -9.953125 L 1.328125 0 L 5.03125 0 C 7.0625 0 8.53125 -1.296875 8.53125 -2.703125 C 8.53125 -3.953125 7.28125 -4.984375 5.8125 -5.203125 C 7.484375 -5.671875 8.140625 -6.625 8.140625 -7.453125 C 8.140625 -8.75 6.671875 -9.953125 4.640625 -9.953125 Z M 2.5 -5.609375 L 2.5 -9.15625 L 4.265625 -9.15625 C 5.796875 -9.15625 7.03125 -8.390625 7.03125 -7.4375 C 7.03125 -6.4375 5.796875 -5.609375 4.28125 -5.609375 Z M 2.5 -0.796875 L 2.5 -4.75 L 4.40625 -4.75 C 6.25 -4.75 7.40625 -3.71875 7.40625 -2.71875 C 7.40625 -1.703125 6.234375 -0.796875 4.640625 -0.796875 Z M 2.5 -0.796875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-26">
<path style="stroke:none;" d="M 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 Z M 2.53125 -9.953125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-27">
<path style="stroke:none;" d="M 6.53125 -9.546875 C 5.9375 -9.875 5.21875 -10.25 3.9375 -10.25 C 2.015625 -10.25 0.78125 -8.875 0.78125 -7.4375 C 0.78125 -6.421875 1.390625 -5.765625 1.46875 -5.6875 C 2.171875 -4.984375 2.65625 -4.84375 3.578125 -4.625 C 4.796875 -4.3125 4.984375 -4.265625 5.453125 -3.78125 C 5.6875 -3.53125 5.90625 -3.0625 5.90625 -2.5625 C 5.90625 -1.578125 5.09375 -0.65625 3.859375 -0.65625 C 2.8125 -0.65625 1.6875 -1.078125 0.84375 -1.84375 L 0.625 -0.6875 C 1.9375 0.171875 3.203125 0.296875 3.859375 0.296875 C 5.703125 0.296875 7.015625 -1.125 7.015625 -2.71875 C 7.015625 -3.625 6.5625 -4.3125 6.25 -4.671875 C 5.59375 -5.375 5.0625 -5.515625 4.109375 -5.765625 C 3.125 -6.015625 2.765625 -6.09375 2.453125 -6.390625 C 2.265625 -6.59375 1.875 -6.953125 1.875 -7.609375 C 1.875 -8.484375 2.671875 -9.328125 3.9375 -9.328125 C 5.15625 -9.328125 5.796875 -8.84375 6.3125 -8.390625 Z M 6.53125 -9.546875 "/>
</symbol>
<symbol overflow="visible" id="glyph1-28">
<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.171875 -6.515625 2.515625 -5.953125 2.171875 -5.515625 L 2.171875 -9.953125 L 1.109375 -9.953125 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/>
</symbol>
<symbol overflow="visible" id="glyph1-29">
<path style="stroke:none;" d="M 9.328125 -6.375 L 8.28125 -6.375 L 7.421875 -3.453125 C 7.21875 -2.765625 6.8125 -1.421875 6.75 -0.796875 L 6.734375 -0.796875 C 6.703125 -1.140625 6.46875 -2.109375 6.171875 -3.125 L 5.21875 -6.375 L 4.234375 -6.375 L 3.40625 -3.5625 C 3.15625 -2.671875 2.8125 -1.4375 2.765625 -0.828125 L 2.75 -0.828125 C 2.734375 -1.109375 2.578125 -1.859375 2.3125 -2.828125 L 1.296875 -6.375 L 0.203125 -6.375 L 2.125 0 L 3.234375 0 C 3.765625 -1.8125 4.609375 -4.53125 4.6875 -5.53125 L 4.703125 -5.53125 C 4.734375 -4.953125 5.015625 -3.921875 5.125 -3.578125 L 6.140625 0 L 7.40625 0 Z M 9.328125 -6.375 "/>
</symbol>
<symbol overflow="visible" id="glyph1-30">
<path style="stroke:none;" d="M 4.8125 -4.140625 C 6.78125 -4.140625 8.140625 -5.5625 8.140625 -7.0625 C 8.140625 -8.578125 6.75 -9.953125 4.8125 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.53125 0 L 2.53125 -4.140625 Z M 4.5 -9.15625 C 6.1875 -9.15625 7.015625 -8.140625 7.015625 -7.078125 C 7.015625 -5.9375 6.140625 -4.984375 4.5 -4.984375 L 2.515625 -4.984375 L 2.515625 -9.15625 Z M 4.5 -9.15625 "/>
</symbol>
</g>
<clipPath id="clip1">
<path d="M 0 0 L 541.902344 0 L 541.902344 142.285156 L 0 142.285156 Z M 0 0 "/>
</clipPath>
<clipPath id="clip2">
<path d="M 102 92 L 245 92 L 245 142.285156 L 102 142.285156 Z M 102 92 "/>
</clipPath>
<clipPath id="clip3">
<path d="M 302 92 L 442 92 L 442 142.285156 L 302 142.285156 Z M 302 92 "/>
</clipPath>
<clipPath id="clip4">
<path d="M 17 101 L 67 101 L 67 142.285156 L 17 142.285156 Z M 17 101 "/>
</clipPath>
<clipPath id="clip5">
<path d="M 92 101 L 142 101 L 142 142.285156 L 92 142.285156 Z M 92 101 "/>
</clipPath>
<clipPath id="clip6">
<path d="M 205 101 L 255 101 L 255 142.285156 L 205 142.285156 Z M 205 101 "/>
</clipPath>
<clipPath id="clip7">
<path d="M 292 101 L 342 101 L 342 142.285156 L 292 142.285156 Z M 292 101 "/>
</clipPath>
<clipPath id="clip8">
<path d="M 402 101 L 452 101 L 452 142.285156 L 402 142.285156 Z M 402 101 "/>
</clipPath>
<clipPath id="clip9">
<path d="M 479 101 L 528 101 L 528 142.285156 L 479 142.285156 Z M 479 101 "/>
</clipPath>
</defs>
<g id="surface1">
<g clip-path="url(#clip1)" clip-rule="nonzero">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 142.285156 L 543.933594 142.285156 L 543.933594 -0.535156 L 0 -0.535156 Z M 0 142.285156 "/>
</g>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 93.618469 13.681906 L -93.619813 13.681906 C -96.369813 13.681906 -98.600281 11.451438 -98.600281 8.701438 L -98.600281 -17.204812 C -98.600281 -19.954812 -96.369813 -22.185281 -93.619813 -22.185281 L 93.618469 -22.185281 C 96.368469 -22.185281 98.598937 -19.954812 98.598937 -17.204812 L 98.598937 8.701438 C 98.598937 11.451438 96.368469 13.681906 93.618469 13.681906 Z M 93.618469 13.681906 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-1" x="215.699" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-2" x="222.091667" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-1" x="229.467" y="15.293"/>
<use xlink:href="#glyph1-2" x="235.710466" y="15.293"/>
<use xlink:href="#glyph1-2" x="242.136129" y="15.293"/>
<use xlink:href="#glyph1-3" x="248.561792" y="15.293"/>
<use xlink:href="#glyph1-3" x="252.463959" y="15.293"/>
<use xlink:href="#glyph1-4" x="256.366125" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="263.184874" y="15.293"/>
<use xlink:href="#glyph1-6" x="267.959289" y="15.293"/>
<use xlink:href="#glyph1-7" x="271.263219" y="15.293"/>
<use xlink:href="#glyph1-8" x="278.469315" y="15.293"/>
<use xlink:href="#glyph1-9" x="285.493215" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-3" x="291.733" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-10" x="303.797" y="15.293"/>
<use xlink:href="#glyph1-11" x="314.905263" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-7" x="322.31651" y="15.293"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-7" x="203.901" y="29.24"/>
<use xlink:href="#glyph1-9" x="211.107096" y="29.24"/>
<use xlink:href="#glyph1-12" x="217.350563" y="29.24"/>
<use xlink:href="#glyph1-1" x="222.734691" y="29.24"/>
<use xlink:href="#glyph1-5" x="228.978158" y="29.24"/>
<use xlink:href="#glyph1-6" x="233.752573" y="29.24"/>
<use xlink:href="#glyph1-13" x="237.056503" y="29.24"/>
<use xlink:href="#glyph1-14" x="244.262599" y="29.24"/>
<use xlink:href="#glyph1-6" x="249.335415" y="29.24"/>
<use xlink:href="#glyph1-11" x="252.639345" y="29.24"/>
<use xlink:href="#glyph1-15" x="259.663245" y="29.24"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-11" x="271.546202" y="29.24"/>
<use xlink:href="#glyph1-16" x="278.570102" y="29.24"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-4" x="287.553692" y="29.24"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-11" x="295.147136" y="29.24"/>
<use xlink:href="#glyph1-17" x="302.171035" y="29.24"/>
<use xlink:href="#glyph1-15" x="309.377132" y="29.24"/>
<use xlink:href="#glyph1-7" x="316.583228" y="29.24"/>
<use xlink:href="#glyph1-18" x="323.789324" y="29.24"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="330.126041" y="29.24"/>
<use xlink:href="#glyph1-19" x="334.900456" y="29.24"/>
</g>
<g clip-path="url(#clip2)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -53.619813 -99.095437 L -144.807313 -99.095437 C -147.006531 -99.095437 -148.791688 -100.880594 -148.791688 -103.079812 L -148.791688 -118.025125 C -148.791688 -120.22825 -147.006531 -122.0095 -144.807313 -122.0095 L -53.619813 -122.0095 C -51.420594 -122.0095 -49.635438 -120.22825 -49.635438 -118.025125 L -49.635438 -103.079812 C -49.635438 -100.880594 -51.420594 -99.095437 -53.619813 -99.095437 Z M -53.619813 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-20" x="133.785" y="129.463"/>
<use xlink:href="#glyph1-17" x="142.825975" y="129.463"/>
<use xlink:href="#glyph1-12" x="150.032072" y="129.463"/>
<use xlink:href="#glyph1-14" x="155.4162" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-4" x="165.165878" y="129.463"/>
<use xlink:href="#glyph1-6" x="172.371974" y="129.463"/>
<use xlink:href="#glyph1-15" x="175.675904" y="129.463"/>
<use xlink:href="#glyph1-7" x="182.882" y="129.463"/>
<use xlink:href="#glyph1-6" x="190.088097" y="129.463"/>
<use xlink:href="#glyph1-15" x="193.392026" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-8" x="200.612469" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-12" x="207.622022" y="129.463"/>
</g>
<g clip-path="url(#clip3)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 143.3255 -99.095437 L 55.102844 -99.095437 C 52.903625 -99.095437 51.118469 -100.880594 51.118469 -103.079812 L 51.118469 -118.025125 C 51.118469 -120.22825 52.903625 -122.0095 55.102844 -122.0095 L 143.3255 -122.0095 C 145.524719 -122.0095 147.309875 -120.22825 147.309875 -118.025125 L 147.309875 -103.079812 C 147.309875 -100.880594 145.524719 -99.095437 143.3255 -99.095437 Z M 143.3255 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-21" x="333.693" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-4" x="342.668" y="129.463"/>
<use xlink:href="#glyph0-4" x="350.050555" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-4" x="362.115" y="129.463"/>
<use xlink:href="#glyph1-6" x="369.321096" y="129.463"/>
<use xlink:href="#glyph1-15" x="372.625026" y="129.463"/>
<use xlink:href="#glyph1-7" x="379.831122" y="129.463"/>
<use xlink:href="#glyph1-6" x="387.037219" y="129.463"/>
<use xlink:href="#glyph1-15" x="390.341148" y="129.463"/>
<use xlink:href="#glyph1-8" x="397.547245" y="129.463"/>
<use xlink:href="#glyph1-12" x="404.571144" y="129.463"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-20" x="4.343" y="126.574"/>
<use xlink:href="#glyph1-17" x="13.383975" y="126.574"/>
<use xlink:href="#glyph1-12" x="20.590072" y="126.574"/>
<use xlink:href="#glyph1-14" x="25.9742" y="126.574"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-1" x="3.941" y="140.522"/>
<use xlink:href="#glyph1-11" x="10.184466" y="140.522"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-7" x="17.595713" y="140.522"/>
<use xlink:href="#glyph1-9" x="24.801809" y="140.522"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-21" x="514.177" y="126.574"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-4" x="523.151" y="126.574"/>
<use xlink:href="#glyph0-4" x="530.533555" y="126.574"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-1" x="514.177" y="140.522"/>
<use xlink:href="#glyph1-11" x="520.420466" y="140.522"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-7" x="527.831713" y="140.522"/>
<use xlink:href="#glyph1-9" x="535.037809" y="140.522"/>
</g>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00128125 -22.931375 L 0.00128125 -68.032937 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -99.213563 -89.1345 L -99.213563 -68.032937 L 99.212219 -68.032937 L 99.212219 -89.1345 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 0.0002575 C 5.539802 0.207289 2.129646 1.371351 0.00074 2.640882 L 0.00074 -2.640368 C 2.129646 -1.370836 5.539802 -0.206774 6.317146 0.0002575 Z M 6.317146 0.0002575 " transform="matrix(0,1,1,0,173.39818,103.56176)"/>
<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 -0.00160125 C 5.539802 0.20543 2.129646 1.373399 0.00074 2.639024 L 0.00074 -2.63832 C 2.129646 -1.372695 5.539802 -0.204726 6.317146 -0.00160125 Z M 6.317146 -0.00160125 " transform="matrix(0,1,1,0,371.82582,103.56176)"/>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -227.619813 -110.552469 L -158.752625 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 38.675781 124.980469 C 39.453125 125.1875 42.859375 126.351562 44.992188 127.621094 L 44.992188 122.339844 C 42.859375 123.609375 39.453125 124.777344 38.675781 124.980469 Z M 38.675781 124.980469 "/>
<g clip-path="url(#clip4)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.316149 -0.00123125 C 5.538805 0.2058 2.132555 1.369862 -0.0002575 2.639394 L -0.0002575 -2.641856 C 2.132555 -1.372325 5.538805 -0.204356 6.316149 -0.00123125 Z M 6.316149 -0.00123125 " transform="matrix(-1,0,0,1,44.99193,124.9817)"/>
</g>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 120.171875 124.980469 C 119.398438 124.777344 115.988281 123.609375 113.859375 122.339844 L 113.859375 127.621094 C 115.988281 126.351562 119.398438 125.1875 120.171875 124.980469 Z M 120.171875 124.980469 "/>
<g clip-path="url(#clip5)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313975 0.00123125 C 5.540537 0.204356 2.130381 1.372325 0.001475 2.641856 L 0.001475 -2.639394 C 2.130381 -1.369862 5.540537 -0.2058 6.313975 0.00123125 Z M 6.313975 0.00123125 " transform="matrix(1,0,0,-1,113.8579,124.9817)"/>
</g>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:7.97021,5.97766;stroke-miterlimit:10;" d="M -39.6745 -110.552469 L 41.157531 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 226.621094 124.980469 C 227.398438 125.1875 230.808594 126.351562 232.9375 127.621094 L 232.9375 122.339844 C 230.808594 123.609375 227.398438 124.777344 226.621094 124.980469 Z M 226.621094 124.980469 "/>
<g clip-path="url(#clip6)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317366 -0.00123125 C 5.540023 0.2058 2.129866 1.369862 0.00096 2.639394 L 0.00096 -2.641856 C 2.129866 -1.372325 5.540023 -0.204356 6.317366 -0.00123125 Z M 6.317366 -0.00123125 " transform="matrix(-1,0,0,1,232.93846,124.9817)"/>
</g>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 320.082031 124.980469 C 319.308594 124.777344 315.898438 123.609375 313.769531 122.339844 L 313.769531 127.621094 C 315.898438 126.351562 319.308594 125.1875 320.082031 124.980469 Z M 320.082031 124.980469 "/>
<g clip-path="url(#clip7)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313811 0.00123125 C 5.540374 0.204356 2.130217 1.372325 0.00131125 2.641856 L 0.00131125 -2.639394 C 2.130217 -1.369862 5.540374 -0.2058 6.313811 0.00123125 Z M 6.313811 0.00123125 " transform="matrix(1,0,0,-1,313.76822,124.9817)"/>
</g>
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.270812 -110.552469 L 227.618469 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 423.566406 124.980469 C 424.34375 125.1875 427.753906 126.351562 429.882812 127.621094 L 429.882812 122.339844 C 427.753906 123.609375 424.34375 124.777344 423.566406 124.980469 Z M 423.566406 124.980469 "/>
<g clip-path="url(#clip8)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317014 -0.00123125 C 5.53967 0.2058 2.129514 1.369862 0.0006075 2.639394 L 0.0006075 -2.641856 C 2.129514 -1.372325 5.53967 -0.204356 6.317014 -0.00123125 Z M 6.317014 -0.00123125 " transform="matrix(-1,0,0,1,429.88342,124.9817)"/>
</g>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 506.546875 124.980469 C 505.773438 124.777344 502.363281 123.609375 500.230469 122.339844 L 500.230469 127.621094 C 502.363281 126.351562 505.773438 125.1875 506.546875 124.980469 Z M 506.546875 124.980469 "/>
<g clip-path="url(#clip9)" clip-rule="nonzero">
<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.314805 0.00123125 C 5.541367 0.204356 2.131211 1.372325 -0.00160125 2.641856 L -0.00160125 -2.639394 C 2.131211 -1.369862 5.541367 -0.2058 6.314805 0.00123125 Z M 6.314805 0.00123125 " transform="matrix(1,0,0,-1,500.23207,124.9817)"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-22" x="148.925" y="75.603"/>
<use xlink:href="#glyph1-18" x="161.112097" y="75.603"/>
<use xlink:href="#glyph1-1" x="167.836161" y="75.603"/>
<use xlink:href="#glyph1-5" x="174.079627" y="75.603"/>
<use xlink:href="#glyph1-11" x="178.854042" y="75.603"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-9" x="190.554803" y="75.603"/>
<use xlink:href="#glyph1-2" x="196.798269" y="75.603"/>
<use xlink:href="#glyph1-13" x="203.223932" y="75.603"/>
<use xlink:href="#glyph1-18" x="210.430029" y="75.603"/>
<use xlink:href="#glyph1-15" x="217.154093" y="75.603"/>
<use xlink:href="#glyph1-12" x="224.360189" y="75.603"/>
<use xlink:href="#glyph1-6" x="229.744318" y="75.603"/>
<use xlink:href="#glyph1-11" x="233.048248" y="75.603"/>
<use xlink:href="#glyph1-15" x="240.072147" y="75.603"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-21" x="297.94" y="75.603"/>
<use xlink:href="#glyph1-11" x="306.914983" y="75.603"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-7" x="314.32623" y="75.603"/>
<use xlink:href="#glyph1-9" x="321.532326" y="75.603"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-8" x="332.452653" y="75.603"/>
<use xlink:href="#glyph1-9" x="339.476553" y="75.603"/>
<use xlink:href="#glyph1-15" x="345.720019" y="75.603"/>
<use xlink:href="#glyph1-9" x="352.926115" y="75.603"/>
<use xlink:href="#glyph1-5" x="359.169582" y="75.603"/>
<use xlink:href="#glyph1-18" x="363.943997" y="75.603"/>
<use xlink:href="#glyph1-14" x="370.668061" y="75.603"/>
<use xlink:href="#glyph1-6" x="375.740877" y="75.603"/>
<use xlink:href="#glyph1-11" x="379.044807" y="75.603"/>
<use xlink:href="#glyph1-15" x="386.068707" y="75.603"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-23" x="231.724" y="117.459"/>
<use xlink:href="#glyph1-6" x="241.569797" y="117.459"/>
<use xlink:href="#glyph1-7" x="244.873727" y="117.459"/>
<use xlink:href="#glyph1-7" x="252.079823" y="117.459"/>
<use xlink:href="#glyph1-9" x="259.285919" y="117.459"/>
<use xlink:href="#glyph1-15" x="265.529386" y="117.459"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-21" x="277.412343" y="117.459"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-24" x="291.078533" y="117.459"/>
<use xlink:href="#glyph1-25" x="300.360525" y="117.459"/>
<use xlink:href="#glyph1-26" x="309.68412" y="117.459"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-27" x="68.742" y="89.962"/>
<use xlink:href="#glyph1-18" x="76.546333" y="89.962"/>
<use xlink:href="#glyph1-16" x="83.270397" y="89.962"/>
<use xlink:href="#glyph1-9" x="87.56278" y="89.962"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-12" x="37.407" y="103.909"/>
<use xlink:href="#glyph1-14" x="42.791129" y="103.909"/>
<use xlink:href="#glyph1-5" x="47.863945" y="103.909"/>
<use xlink:href="#glyph1-18" x="52.638361" y="103.909"/>
<use xlink:href="#glyph1-6" x="59.362424" y="103.909"/>
<use xlink:href="#glyph1-8" x="62.666354" y="103.909"/>
<use xlink:href="#glyph1-28" x="69.690254" y="103.909"/>
<use xlink:href="#glyph1-14" x="76.89635" y="103.909"/>
<use xlink:href="#glyph1-16" x="81.969166" y="103.909"/>
<use xlink:href="#glyph1-11" x="86.261549" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="92.898102" y="103.909"/>
<use xlink:href="#glyph1-29" x="97.672517" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-18" x="106.832566" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="113.154936" y="103.909"/>
<use xlink:href="#glyph1-7" x="117.929351" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-20" x="51.871" y="117.857"/>
<use xlink:href="#glyph1-17" x="60.911975" y="117.857"/>
<use xlink:href="#glyph1-12" x="68.118072" y="117.857"/>
<use xlink:href="#glyph1-14" x="73.5022" y="117.857"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-24" x="83.251878" y="117.857"/>
<use xlink:href="#glyph1-30" x="92.533869" y="117.857"/>
<use xlink:href="#glyph1-26" x="101.467248" y="117.857"/>
<use xlink:href="#glyph1-12" x="105.286206" y="117.857"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-27" x="418.874" y="103.909"/>
<use xlink:href="#glyph1-14" x="426.678333" y="103.909"/>
<use xlink:href="#glyph1-5" x="431.751149" y="103.909"/>
<use xlink:href="#glyph1-18" x="436.525564" y="103.909"/>
<use xlink:href="#glyph1-6" x="443.249628" y="103.909"/>
<use xlink:href="#glyph1-8" x="446.553558" y="103.909"/>
<use xlink:href="#glyph1-28" x="453.577458" y="103.909"/>
<use xlink:href="#glyph1-14" x="460.783554" y="103.909"/>
<use xlink:href="#glyph1-16" x="465.85637" y="103.909"/>
<use xlink:href="#glyph1-11" x="470.148753" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="476.785306" y="103.909"/>
<use xlink:href="#glyph1-29" x="481.559721" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-18" x="490.705423" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-5" x="497.04214" y="103.909"/>
<use xlink:href="#glyph1-7" x="501.816555" y="103.909"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-21" x="436.031" y="117.857"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-4" x="445.005" y="117.857"/>
<use xlink:href="#glyph0-4" x="452.387555" y="117.857"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph1-24" x="464.452" y="117.857"/>
<use xlink:href="#glyph1-30" x="473.733991" y="117.857"/>
<use xlink:href="#glyph1-26" x="482.66737" y="117.857"/>
<use xlink:href="#glyph1-12" x="486.486329" y="117.857"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 42 KiB

29
vendor/cxx/book/src/reference.md vendored Normal file
View file

@ -0,0 +1,29 @@
{{#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)*** &mdash; exposing opaque Rust types, Rust
functions, Rust methods to C++; functions with lifetimes.
- ***[extern "C++"](extern-c++.md)*** &mdash; 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)*** &mdash; shared structs; shared enums; using
Rust as source of truth vs C++ as source of truth.
- ***[Attributes](attributes.md)*** &mdash; working with namespaces; giving
functions a different name in their non-native language.
- ***[Async functions](async.md)*** &mdash; integrating async C++ with async
Rust.
- ***[Error handling](binding/result.md)*** &mdash; 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.

246
vendor/cxx/book/src/shared.md vendored Normal file
View file

@ -0,0 +1,246 @@
{{#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`
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>=`
[hash]: https://en.cppreference.com/w/cpp/utility/hash

688
vendor/cxx/book/src/tutorial.md vendored Normal file
View file

@ -0,0 +1,688 @@
{{#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 = "2018"
[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 &mdash; 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 = "2018"
[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");
}
```
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")
.flag_if_supported("-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 blob.
void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {
impl->blobs[blobid].tags.emplace(tag);
}
// Retrieve metadata about a blob.
BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
BlobMetadata metadata{};
auto blob = impl->blobs.find(blobid);
if (blob != impl->blobs.end()) {
metadata.size = blob->second.data.size();
std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
[&](auto &t) { metadata.tags.emplace_back(t); });
}
return metadata;
}
#
# std::unique_ptr<BlobstoreClient> new_blobstore_client() {
# return std::make_unique<BlobstoreClient>();
# }
```
```console
cxx-demo$ cargo run
Running `target/debug/cxx-demo`
blobid = 9851996977040795552
tags = ["rust"]
```
*You've now seen all the code involved in the tutorial. It's available all
together in runnable form in the* demo *directory of
<https://github.com/dtolnay/cxx>. You can run it directly without stepping
through the steps above by running `cargo run` from that directory.*
<br>
# Takeaways
The key contribution of CXX is it gives you Rust&ndash;C++ interop in which
*all* of the Rust side of the code you write *really* looks like you are just
writing normal Rust, and the C++ side *really* looks like you are just writing
normal C++.
You've seen in this tutorial that none of the code involved feels like C or like
the usual perilous "FFI glue" prone to leaks or memory safety flaws.
An expressive system of opaque types, shared types, and key standard library
type bindings enables API design on the language boundary that captures the
proper ownership and borrowing contracts of the interface.
CXX plays to the strengths of the Rust type system *and* C++ type system *and*
the programmer's intuitions. An individual working on the C++ side without a
Rust background, or the Rust side without a C++ background, will be able to
apply all their usual intuitions and best practices about development in their
language to maintain a correct FFI.
<br><br>

7
vendor/cxx/book/theme/head.hbs vendored Normal file
View file

@ -0,0 +1,7 @@
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DG41MK6DDN"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-DG41MK6DDN', {'anonymize_ip': true});
</script>

55
vendor/cxx/build.rs vendored Normal file
View file

@ -0,0 +1,55 @@
use std::env;
use std::path::Path;
use std::process::Command;
fn main() {
cc::Build::new()
.file("src/cxx.cc")
.cpp(true)
.cpp_link_stdlib(None) // linked via link-cplusplus crate
.flag_if_supported(cxxbridge_flags::STD)
.warnings_into_errors(cfg!(deny_warnings))
.compile("cxxbridge1");
println!("cargo:rerun-if-changed=src/cxx.cc");
println!("cargo:rerun-if-changed=include/cxx.h");
println!("cargo:rustc-cfg=built_with_cargo");
if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
println!("cargo:HEADER={}", cxx_h.to_string_lossy());
}
if let Some(rustc) = rustc_version() {
if rustc.minor < 48 {
println!("cargo:warning=The cxx crate requires a rustc version 1.48.0 or newer.");
println!(
"cargo:warning=You appear to be building with: {}",
rustc.version,
);
}
if rustc.minor < 52 {
// #![deny(unsafe_op_in_unsafe_fn)].
// https://github.com/rust-lang/rust/issues/71668
println!("cargo:rustc-cfg=no_unsafe_op_in_unsafe_fn_lint");
}
}
}
struct RustVersion {
version: String,
minor: u32,
}
fn rustc_version() -> Option<RustVersion> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = String::from_utf8(output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let minor = pieces.next()?.parse().ok()?;
Some(RustVersion { version, minor })
}

1
vendor/cxx/compile_flags.txt vendored Normal file
View file

@ -0,0 +1 @@
-std=c++11

1111
vendor/cxx/include/cxx.h vendored Normal file

File diff suppressed because it is too large Load diff

69
vendor/cxx/src/c_char.rs vendored Normal file
View file

@ -0,0 +1,69 @@
#[allow(missing_docs)]
pub type c_char = c_char_definition::c_char;
// Validate that our definition is consistent with libstd's definition, without
// introducing a dependency on libstd in ordinary builds.
#[cfg(all(test, feature = "std"))]
const _: self::c_char = 0 as std::os::raw::c_char;
#[allow(dead_code)]
mod c_char_definition {
// These are the targets on which c_char is unsigned.
#[cfg(any(
all(
target_os = "linux",
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "hexagon",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "riscv64",
target_arch = "riscv32"
)
),
all(
target_os = "android",
any(target_arch = "aarch64", target_arch = "arm")
),
all(target_os = "l4re", target_arch = "x86_64"),
all(
target_os = "freebsd",
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "riscv64"
)
),
all(
target_os = "netbsd",
any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
),
all(target_os = "openbsd", target_arch = "aarch64"),
all(
target_os = "vxworks",
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc64",
target_arch = "powerpc"
)
),
all(target_os = "fuchsia", target_arch = "aarch64")
))]
pub use self::unsigned::c_char;
// On every other target, c_char is signed.
pub use self::signed::*;
mod unsigned {
pub type c_char = u8;
}
mod signed {
pub type c_char = i8;
}
}

792
vendor/cxx/src/cxx.cc vendored Normal file
View file

@ -0,0 +1,792 @@
#include "../include/cxx.h"
#include <cstring>
#include <iostream>
#include <memory>
extern "C" {
void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
std::size_t len) noexcept {
new (s) std::string(reinterpret_cast<const char *>(ptr), len);
}
void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
using std::string;
s->~string();
}
const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
return s.data();
}
std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
return s.length();
}
void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
void cxxbridge1$cxx_string$reserve_total(std::string &s,
size_t new_cap) noexcept {
s.reserve(new_cap);
}
void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
std::size_t len) noexcept {
s.append(reinterpret_cast<const char *>(ptr), len);
}
// rust::String
void cxxbridge1$string$new(rust::String *self) noexcept;
void cxxbridge1$string$clone(rust::String *self,
const rust::String &other) noexcept;
bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr,
std::size_t len) noexcept;
void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr,
std::size_t len) noexcept;
bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr,
std::size_t len) noexcept;
void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr,
std::size_t len) noexcept;
void cxxbridge1$string$drop(rust::String *self) noexcept;
const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
std::size_t cxxbridge1$string$capacity(const rust::String *self) noexcept;
void cxxbridge1$string$reserve_additional(rust::String *self,
size_t additional) noexcept;
void cxxbridge1$string$reserve_total(rust::String *self,
size_t new_cap) noexcept;
// rust::Str
void cxxbridge1$str$new(rust::Str *self) noexcept;
void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
std::size_t len) noexcept;
const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
// rust::Slice
void cxxbridge1$slice$new(void *self, const void *ptr,
std::size_t len) noexcept;
void *cxxbridge1$slice$ptr(const void *self) noexcept;
std::size_t cxxbridge1$slice$len(const void *self) noexcept;
} // extern "C"
namespace rust {
inline namespace cxxbridge1 {
template <typename Exception>
void panic [[noreturn]] (const char *msg) {
#if defined(RUST_CXX_NO_EXCEPTIONS)
std::cerr << "Error: " << msg << ". Aborting." << std::endl;
std::terminate();
#else
throw Exception(msg);
#endif
}
template void panic<std::out_of_range> [[noreturn]] (const char *msg);
template <typename T>
static bool is_aligned(const void *ptr) noexcept {
auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
return !(iptr % alignof(T));
}
String::String() noexcept { cxxbridge1$string$new(this); }
String::String(const String &other) noexcept {
cxxbridge1$string$clone(this, other);
}
String::String(String &&other) noexcept : repr(other.repr) {
cxxbridge1$string$new(&other);
}
String::~String() noexcept { cxxbridge1$string$drop(this); }
static void initString(String *self, const char *s, std::size_t len) {
if (!cxxbridge1$string$from_utf8(self, s, len)) {
panic<std::invalid_argument>("data for rust::String is not utf-8");
}
}
static void initString(String *self, const char16_t *s, std::size_t len) {
if (!cxxbridge1$string$from_utf16(self, s, len)) {
panic<std::invalid_argument>("data for rust::String is not utf-16");
}
}
String::String(const std::string &s) { initString(this, s.data(), s.length()); }
String::String(const char *s) {
assert(s != nullptr);
initString(this, s, std::strlen(s));
}
String::String(const char *s, std::size_t len) {
assert(s != nullptr || len == 0);
initString(this,
s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
len);
}
String::String(const char16_t *s) {
assert(s != nullptr);
assert(is_aligned<char16_t>(s));
initString(this, s, std::char_traits<char16_t>::length(s));
}
String::String(const char16_t *s, std::size_t len) {
assert(s != nullptr || len == 0);
assert(is_aligned<char16_t>(s));
initString(this,
s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2)
: s,
len);
}
struct String::lossy_t {};
String::String(lossy_t, const char *s, std::size_t len) noexcept {
cxxbridge1$string$from_utf8_lossy(
this, s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
len);
}
String::String(lossy_t, const char16_t *s, std::size_t len) noexcept {
cxxbridge1$string$from_utf16_lossy(
this,
s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s,
len);
}
String String::lossy(const std::string &s) noexcept {
return String::lossy(s.data(), s.length());
}
String String::lossy(const char *s) noexcept {
assert(s != nullptr);
return String::lossy(s, std::strlen(s));
}
String String::lossy(const char *s, std::size_t len) noexcept {
assert(s != nullptr || len == 0);
return String(lossy_t{}, s, len);
}
String String::lossy(const char16_t *s) noexcept {
assert(s != nullptr);
assert(is_aligned<char16_t>(s));
return String(lossy_t{}, s, std::char_traits<char16_t>::length(s));
}
String String::lossy(const char16_t *s, std::size_t len) noexcept {
assert(s != nullptr || len == 0);
assert(is_aligned<char16_t>(s));
return String(lossy_t{}, s, len);
}
String &String::operator=(const String &other) &noexcept {
if (this != &other) {
cxxbridge1$string$drop(this);
cxxbridge1$string$clone(this, other);
}
return *this;
}
String &String::operator=(String &&other) &noexcept {
cxxbridge1$string$drop(this);
this->repr = other.repr;
cxxbridge1$string$new(&other);
return *this;
}
String::operator std::string() const {
return std::string(this->data(), this->size());
}
const char *String::data() const noexcept {
return cxxbridge1$string$ptr(this);
}
std::size_t String::size() const noexcept {
return cxxbridge1$string$len(this);
}
std::size_t String::length() const noexcept {
return cxxbridge1$string$len(this);
}
bool String::empty() const noexcept { return this->size() == 0; }
const char *String::c_str() noexcept {
auto len = this->length();
cxxbridge1$string$reserve_additional(this, 1);
auto ptr = this->data();
const_cast<char *>(ptr)[len] = '\0';
return ptr;
}
std::size_t String::capacity() const noexcept {
return cxxbridge1$string$capacity(this);
}
void String::reserve(std::size_t new_cap) noexcept {
cxxbridge1$string$reserve_total(this, new_cap);
}
String::iterator String::begin() noexcept {
return const_cast<char *>(this->data());
}
String::iterator String::end() noexcept {
return const_cast<char *>(this->data()) + this->size();
}
String::const_iterator String::begin() const noexcept { return this->cbegin(); }
String::const_iterator String::end() const noexcept { return this->cend(); }
String::const_iterator String::cbegin() const noexcept { return this->data(); }
String::const_iterator String::cend() const noexcept {
return this->data() + this->size();
}
bool String::operator==(const String &rhs) const noexcept {
return rust::Str(*this) == rust::Str(rhs);
}
bool String::operator!=(const String &rhs) const noexcept {
return rust::Str(*this) != rust::Str(rhs);
}
bool String::operator<(const String &rhs) const noexcept {
return rust::Str(*this) < rust::Str(rhs);
}
bool String::operator<=(const String &rhs) const noexcept {
return rust::Str(*this) <= rust::Str(rhs);
}
bool String::operator>(const String &rhs) const noexcept {
return rust::Str(*this) > rust::Str(rhs);
}
bool String::operator>=(const String &rhs) const noexcept {
return rust::Str(*this) >= rust::Str(rhs);
}
void String::swap(String &rhs) noexcept {
using std::swap;
swap(this->repr, rhs.repr);
}
String::String(unsafe_bitcopy_t, const String &bits) noexcept
: repr(bits.repr) {}
std::ostream &operator<<(std::ostream &os, const String &s) {
os.write(s.data(), s.size());
return os;
}
Str::Str() noexcept { cxxbridge1$str$new(this); }
Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
static void initStr(Str *self, const char *ptr, std::size_t len) {
if (!cxxbridge1$str$from(self, ptr, len)) {
panic<std::invalid_argument>("data for rust::Str is not utf-8");
}
}
Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
Str::Str(const char *s) {
assert(s != nullptr);
initStr(this, s, std::strlen(s));
}
Str::Str(const char *s, std::size_t len) {
assert(s != nullptr || len == 0);
initStr(this,
s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
len);
}
Str::operator std::string() const {
return std::string(this->data(), this->size());
}
const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
std::size_t Str::length() const noexcept { return this->size(); }
bool Str::empty() const noexcept { return this->size() == 0; }
Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
Str::const_iterator Str::end() const noexcept { return this->cend(); }
Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
Str::const_iterator Str::cend() const noexcept {
return this->data() + this->size();
}
bool Str::operator==(const Str &rhs) const noexcept {
return this->size() == rhs.size() &&
std::equal(this->begin(), this->end(), rhs.begin());
}
bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
bool Str::operator<(const Str &rhs) const noexcept {
return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
rhs.end());
}
bool Str::operator<=(const Str &rhs) const noexcept {
// std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
// without Undefined Behavior on C++11 if rhs is shorter than *this.
const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
rend = rhs.end();
while (liter != lend && riter != rend && *liter == *riter) {
++liter, ++riter;
}
if (liter == lend) {
return true; // equal or *this is a prefix of rhs
} else if (riter == rend) {
return false; // rhs is a prefix of *this
} else {
return *liter <= *riter;
}
}
bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
void Str::swap(Str &rhs) noexcept {
using std::swap;
swap(this->repr, rhs.repr);
}
std::ostream &operator<<(std::ostream &os, const Str &s) {
os.write(s.data(), s.size());
return os;
}
void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
cxxbridge1$slice$new(self, ptr, len);
}
void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
std::size_t sliceLen(const void *self) noexcept {
return cxxbridge1$slice$len(self);
}
// Rust specifies that usize is ABI compatible with C's uintptr_t.
// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
// However there is no direct Rust equivalent for size_t. C does not guarantee
// that size_t and uintptr_t are compatible. In practice though, on all
// platforms supported by Rust, they are identical for ABI purposes. See the
// libc crate which unconditionally defines libc::size_t = usize. We expect the
// same here and these assertions are just here to explicitly document that.
// *Note that no assumption is made about C++ name mangling of signatures
// containing these types, not here nor anywhere in CXX.*
static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
"unsupported size_t size");
static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
"unsupported size_t alignment");
static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
"unsupported ssize_t size");
static_assert(alignof(rust::isize) == alignof(std::intptr_t),
"unsupported ssize_t alignment");
static_assert(std::is_trivially_copy_constructible<Str>::value,
"trivial Str(const Str &)");
static_assert(std::is_trivially_copy_assignable<Str>::value,
"trivial operator=(const Str &)");
static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
static_assert(
std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
"trivial Slice(const Slice &)");
static_assert(
std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
"trivial Slice(Slice &&)");
static_assert(
std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
"trivial Slice::operator=(const Slice &) for const slices");
static_assert(
std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
"trivial Slice::operator=(Slice &&)");
static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
"trivial ~Slice()");
static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
"trivial Slice(const Slice &)");
static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
"trivial Slice(Slice &&)");
static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
"delete Slice::operator=(const Slice &) for mut slices");
static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
"trivial Slice::operator=(Slice &&)");
static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
"trivial ~Slice()");
static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
Vec<const std::uint8_t>::iterator>::value,
"Vec<T>::const_iterator == Vec<const T>::iterator");
static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
Vec<const std::uint8_t>::iterator>::value,
"Vec<const T>::const_iterator == Vec<const T>::iterator");
static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
Vec<std::uint8_t>::iterator>::value,
"Vec<T>::const_iterator != Vec<T>::iterator");
static const char *errorCopy(const char *ptr, std::size_t len) {
char *copy = new char[len];
std::memcpy(copy, ptr, len);
return copy;
}
extern "C" {
const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
return errorCopy(ptr, len);
}
} // extern "C"
Error::Error(const Error &other)
: std::exception(other),
msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
len(other.len) {}
Error::Error(Error &&other) noexcept
: std::exception(std::move(other)), msg(other.msg), len(other.len) {
other.msg = nullptr;
other.len = 0;
}
Error::~Error() noexcept { delete[] this->msg; }
Error &Error::operator=(const Error &other) & {
if (this != &other) {
std::exception::operator=(other);
delete[] this->msg;
this->msg = nullptr;
if (other.msg) {
this->msg = errorCopy(other.msg, other.len);
this->len = other.len;
}
}
return *this;
}
Error &Error::operator=(Error &&other) &noexcept {
std::exception::operator=(std::move(other));
this->msg = other.msg;
this->len = other.len;
other.msg = nullptr;
other.len = 0;
return *this;
}
const char *Error::what() const noexcept { return this->msg; }
namespace {
template <typename T>
union MaybeUninit {
T value;
MaybeUninit() {}
~MaybeUninit() {}
};
} // namespace
namespace repr {
struct PtrLen final {
void *ptr;
std::size_t len;
};
} // namespace repr
extern "C" {
repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept;
}
namespace detail {
// On some platforms size_t is the same C++ type as one of the sized integer
// types; on others it is a distinct type. Only in the latter case do we need to
// define a specialized impl of rust::Vec<size_t>, because in the former case it
// would collide with one of the other specializations.
using usize_if_unique =
typename std::conditional<std::is_same<size_t, uint64_t>::value ||
std::is_same<size_t, uint32_t>::value,
struct usize_ignore, size_t>::type;
using isize_if_unique =
typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
std::is_same<rust::isize, int32_t>::value,
struct isize_ignore, rust::isize>::type;
class Fail final {
repr::PtrLen &throw$;
public:
Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
void operator()(const char *) noexcept;
void operator()(const std::string &) noexcept;
};
void Fail::operator()(const char *catch$) noexcept {
throw$ = cxxbridge1$exception(catch$, std::strlen(catch$));
}
void Fail::operator()(const std::string &catch$) noexcept {
throw$ = cxxbridge1$exception(catch$.data(), catch$.length());
}
} // namespace detail
} // namespace cxxbridge1
} // namespace rust
namespace {
template <typename T>
void destroy(T *ptr) {
ptr->~T();
}
} // namespace
extern "C" {
void cxxbridge1$unique_ptr$std$string$null(
std::unique_ptr<std::string> *ptr) noexcept {
new (ptr) std::unique_ptr<std::string>();
}
void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
std::string *raw) noexcept {
new (ptr) std::unique_ptr<std::string>(raw);
}
const std::string *cxxbridge1$unique_ptr$std$string$get(
const std::unique_ptr<std::string> &ptr) noexcept {
return ptr.get();
}
std::string *cxxbridge1$unique_ptr$std$string$release(
std::unique_ptr<std::string> &ptr) noexcept {
return ptr.release();
}
void cxxbridge1$unique_ptr$std$string$drop(
std::unique_ptr<std::string> *ptr) noexcept {
ptr->~unique_ptr();
}
} // extern "C"
namespace {
const std::size_t kMaxExpectedWordsInString = 8;
static_assert(alignof(std::string) <= alignof(void *),
"unexpectedly large std::string alignment");
static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
"unexpectedly large std::string size");
} // namespace
#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
const std::vector<CXX_TYPE> &s) noexcept { \
return s.size(); \
} \
CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
return &(*s)[pos]; \
} \
void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
} \
void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
std::vector<CXX_TYPE> *raw) noexcept { \
new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
} \
const std::vector<CXX_TYPE> \
*cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
return ptr.get(); \
} \
std::vector<CXX_TYPE> \
*cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
return ptr.release(); \
} \
void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
ptr->~unique_ptr(); \
}
#define STD_VECTOR_TRIVIAL_OPS(RUST_TYPE, CXX_TYPE) \
void cxxbridge1$std$vector$##RUST_TYPE##$push_back( \
std::vector<CXX_TYPE> *v, CXX_TYPE *value) noexcept { \
v->push_back(std::move(*value)); \
destroy(value); \
} \
void cxxbridge1$std$vector$##RUST_TYPE##$pop_back(std::vector<CXX_TYPE> *v, \
CXX_TYPE *out) noexcept { \
new (out) CXX_TYPE(std::move(v->back())); \
v->pop_back(); \
}
#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
rust::Vec<CXX_TYPE> *ptr) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
rust::Vec<CXX_TYPE> *ptr) noexcept; \
std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
const rust::Vec<CXX_TYPE> *ptr) noexcept; \
std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
const rust::Vec<CXX_TYPE> *ptr) noexcept; \
const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
const rust::Vec<CXX_TYPE> *ptr) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
std::size_t len) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \
std::size_t len) noexcept;
#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
template <> \
Vec<CXX_TYPE>::Vec() noexcept { \
cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
} \
template <> \
void Vec<CXX_TYPE>::drop() noexcept { \
return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
} \
template <> \
std::size_t Vec<CXX_TYPE>::size() const noexcept { \
return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
} \
template <> \
std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
} \
template <> \
const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
} \
template <> \
void Vec<CXX_TYPE>::reserve_total(std::size_t new_cap) noexcept { \
cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, new_cap); \
} \
template <> \
void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
} \
template <> \
void Vec<CXX_TYPE>::truncate(std::size_t len) { \
cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \
}
#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
new (ptr) std::shared_ptr<CXX_TYPE>(); \
} \
CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
CXX_TYPE *uninit = \
reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
return uninit; \
} \
void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
const std::shared_ptr<CXX_TYPE> &self, \
std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
new (ptr) std::shared_ptr<CXX_TYPE>(self); \
} \
const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
const std::shared_ptr<CXX_TYPE> &self) noexcept { \
return self.get(); \
} \
void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
const std::shared_ptr<CXX_TYPE> *self) noexcept { \
self->~shared_ptr(); \
} \
static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
new (ptr) std::weak_ptr<CXX_TYPE>(); \
} \
void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
const std::weak_ptr<CXX_TYPE> &self, \
std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
new (ptr) std::weak_ptr<CXX_TYPE>(self); \
} \
void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
const std::shared_ptr<CXX_TYPE> &shared, \
std::weak_ptr<CXX_TYPE> *weak) noexcept { \
new (weak) std::weak_ptr<CXX_TYPE>(shared); \
} \
void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
const std::weak_ptr<CXX_TYPE> &weak, \
std::shared_ptr<CXX_TYPE> *shared) noexcept { \
new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
} \
void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
const std::weak_ptr<CXX_TYPE> *self) noexcept { \
self->~weak_ptr(); \
}
// Usize and isize are the same type as one of the below.
#define FOR_EACH_NUMERIC(MACRO) \
MACRO(u8, std::uint8_t) \
MACRO(u16, std::uint16_t) \
MACRO(u32, std::uint32_t) \
MACRO(u64, std::uint64_t) \
MACRO(i8, std::int8_t) \
MACRO(i16, std::int16_t) \
MACRO(i32, std::int32_t) \
MACRO(i64, std::int64_t) \
MACRO(f32, float) \
MACRO(f64, double)
#define FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
FOR_EACH_NUMERIC(MACRO) \
MACRO(usize, std::size_t) \
MACRO(isize, rust::isize)
#define FOR_EACH_STD_VECTOR(MACRO) \
FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
MACRO(string, std::string)
#define FOR_EACH_RUST_VEC(MACRO) \
FOR_EACH_NUMERIC(MACRO) \
MACRO(bool, bool) \
MACRO(char, char) \
MACRO(usize, rust::detail::usize_if_unique) \
MACRO(isize, rust::detail::isize_if_unique) \
MACRO(string, rust::String) \
MACRO(str, rust::Str)
#define FOR_EACH_SHARED_PTR(MACRO) \
FOR_EACH_NUMERIC(MACRO) \
MACRO(bool, bool) \
MACRO(usize, std::size_t) \
MACRO(isize, rust::isize) \
MACRO(string, std::string)
extern "C" {
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS)
FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
} // extern "C"
namespace rust {
inline namespace cxxbridge1 {
FOR_EACH_RUST_VEC(RUST_VEC_OPS)
} // namespace cxxbridge1
} // namespace rust

293
vendor/cxx/src/cxx_string.rs vendored Normal file
View file

@ -0,0 +1,293 @@
use crate::actually_private::Private;
use crate::lossy;
#[cfg(feature = "alloc")]
use alloc::borrow::Cow;
#[cfg(feature = "alloc")]
use alloc::string::String;
use core::cmp::Ordering;
use core::fmt::{self, Debug, Display};
use core::hash::{Hash, Hasher};
use core::marker::{PhantomData, PhantomPinned};
use core::mem::MaybeUninit;
use core::pin::Pin;
use core::slice;
use core::str::{self, Utf8Error};
extern "C" {
#[link_name = "cxxbridge1$cxx_string$init"]
fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
#[link_name = "cxxbridge1$cxx_string$destroy"]
fn string_destroy(this: &mut MaybeUninit<CxxString>);
#[link_name = "cxxbridge1$cxx_string$data"]
fn string_data(this: &CxxString) -> *const u8;
#[link_name = "cxxbridge1$cxx_string$length"]
fn string_length(this: &CxxString) -> usize;
#[link_name = "cxxbridge1$cxx_string$clear"]
fn string_clear(this: Pin<&mut CxxString>);
#[link_name = "cxxbridge1$cxx_string$reserve_total"]
fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize);
#[link_name = "cxxbridge1$cxx_string$push"]
fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
}
/// Binding to C++ `std::string`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we 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 `UniquePtr<CxxString>`.
#[repr(C)]
pub struct CxxString {
_private: [u8; 0],
_pinned: PhantomData<PhantomPinned>,
}
/// Construct a C++ std::string on the Rust stack.
///
/// # Syntax
///
/// In statement position:
///
/// ```
/// # use cxx::let_cxx_string;
/// # let expression = "";
/// let_cxx_string!(var = expression);
/// ```
///
/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
/// it will be a string literal, but for example `&[u8]` and `String` would work
/// as well.
///
/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
///
/// # Example
///
/// ```
/// use cxx::{let_cxx_string, CxxString};
///
/// fn f(s: &CxxString) {/* ... */}
///
/// fn main() {
/// let_cxx_string!(s = "example");
/// f(&s);
/// }
/// ```
#[macro_export]
macro_rules! let_cxx_string {
($var:ident = $value:expr $(,)?) => {
let mut cxx_stack_string = $crate::private::StackString::new();
#[allow(unused_mut, unused_unsafe)]
let mut $var = match $value {
let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) },
};
};
}
impl CxxString {
/// `CxxString` is not constructible via `new`. Instead, use the
/// [`let_cxx_string!`] macro.
pub fn new<T: Private>() -> Self {
unreachable!()
}
/// Returns the length of the string in bytes.
///
/// Matches the behavior of C++ [std::string::size][size].
///
/// [size]: https://en.cppreference.com/w/cpp/string/basic_string/size
pub fn len(&self) -> usize {
unsafe { string_length(self) }
}
/// Returns true if `self` has a length of zero bytes.
///
/// Matches the behavior of C++ [std::string::empty][empty].
///
/// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns a byte slice of this string's contents.
pub fn as_bytes(&self) -> &[u8] {
let data = self.as_ptr();
let len = self.len();
unsafe { slice::from_raw_parts(data, len) }
}
/// Produces a pointer to the first character of the string.
///
/// Matches the behavior of C++ [std::string::data][data].
///
/// Note that the return type may look like `const char *` but is not a
/// `const char *` in the typical C sense, as C++ strings may contain
/// internal null bytes. As such, the returned pointer only makes sense as a
/// string in combination with the length returned by [`len()`][len].
///
/// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data
/// [len]: #method.len
pub fn as_ptr(&self) -> *const u8 {
unsafe { string_data(self) }
}
/// Validates that the C++ string contains UTF-8 data and produces a view of
/// it as a Rust &amp;str, otherwise an error.
pub fn to_str(&self) -> Result<&str, Utf8Error> {
str::from_utf8(self.as_bytes())
}
/// If the contents of the C++ string are valid UTF-8, this function returns
/// a view as a Cow::Borrowed &amp;str. Otherwise replaces any invalid UTF-8
/// sequences with the U+FFFD [replacement character] and returns a
/// Cow::Owned String.
///
/// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.as_bytes())
}
/// Removes all characters from the string.
///
/// Matches the behavior of C++ [std::string::clear][clear].
///
/// Note: **unlike** the guarantee of Rust's `std::string::String::clear`,
/// the C++ standard does not require that capacity is unchanged by this
/// operation. In practice existing implementations do not change the
/// capacity but all pointers, references, and iterators into the string
/// contents are nevertheless invalidated.
///
/// [clear]: https://en.cppreference.com/w/cpp/string/basic_string/clear
pub fn clear(self: Pin<&mut Self>) {
unsafe { string_clear(self) }
}
/// Ensures that this string's capacity is at least `additional` bytes
/// larger than its length.
///
/// The capacity may be increased by more than `additional` bytes if it
/// chooses, to amortize the cost of frequent reallocations.
///
/// **The meaning of the argument is not the same as
/// [std::string::reserve][reserve] in C++.** The C++ standard library and
/// Rust standard library both have a `reserve` method on strings, but in
/// C++ code the argument always refers to total capacity, whereas in Rust
/// code it always refers to additional capacity. This API on `CxxString`
/// follows the Rust convention, the same way that for the length accessor
/// we use the Rust conventional `len()` naming and not C++ `size()` or
/// `length()`.
///
/// # Panics
///
/// Panics if the new capacity overflows usize.
///
/// [reserve]: https://en.cppreference.com/w/cpp/string/basic_string/reserve
pub fn reserve(self: Pin<&mut Self>, additional: usize) {
let new_cap = self
.len()
.checked_add(additional)
.expect("CxxString capacity overflow");
unsafe { string_reserve_total(self, new_cap) }
}
/// Appends a given string slice onto the end of this C++ string.
pub fn push_str(self: Pin<&mut Self>, s: &str) {
self.push_bytes(s.as_bytes());
}
/// Appends arbitrary bytes onto the end of this C++ string.
pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
}
}
impl Display for CxxString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
lossy::display(self.as_bytes(), f)
}
}
impl Debug for CxxString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
lossy::debug(self.as_bytes(), f)
}
}
impl PartialEq for CxxString {
fn eq(&self, other: &Self) -> bool {
self.as_bytes() == other.as_bytes()
}
}
impl PartialEq<CxxString> for str {
fn eq(&self, other: &CxxString) -> bool {
self.as_bytes() == other.as_bytes()
}
}
impl PartialEq<str> for CxxString {
fn eq(&self, other: &str) -> bool {
self.as_bytes() == other.as_bytes()
}
}
impl Eq for CxxString {}
impl PartialOrd for CxxString {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_bytes().partial_cmp(other.as_bytes())
}
}
impl Ord for CxxString {
fn cmp(&self, other: &Self) -> Ordering {
self.as_bytes().cmp(other.as_bytes())
}
}
impl Hash for CxxString {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_bytes().hash(state);
}
}
#[doc(hidden)]
#[repr(C)]
pub struct StackString {
// Static assertions in cxx.cc validate that this is large enough and
// aligned enough.
space: MaybeUninit<[usize; 8]>,
}
#[allow(missing_docs)]
impl StackString {
pub fn new() -> Self {
StackString {
space: MaybeUninit::uninit(),
}
}
pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
let value = value.as_ref();
unsafe {
let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
string_init(this, value.as_ptr(), value.len());
Pin::new_unchecked(&mut *this.as_mut_ptr())
}
}
}
impl Drop for StackString {
fn drop(&mut self) {
unsafe {
let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
string_destroy(this);
}
}
}

492
vendor/cxx/src/cxx_vector.rs vendored Normal file
View file

@ -0,0 +1,492 @@
//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
//! itself is exposed at the crate root.
use crate::extern_type::ExternType;
use crate::kind::Trivial;
use crate::string::CxxString;
use core::ffi::c_void;
use core::fmt::{self, Debug};
use core::iter::FusedIterator;
use core::marker::{PhantomData, PhantomPinned};
use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::pin::Pin;
use core::slice;
/// Binding to C++ `std::vector<T, std::allocator<T>>`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we 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>>`.
#[repr(C, packed)]
pub struct CxxVector<T> {
// A thing, because repr(C) structs are not allowed to consist exclusively
// of PhantomData fields.
_void: [c_void; 0],
// The conceptual vector elements to ensure that autotraits are propagated
// correctly, e.g. CxxVector is UnwindSafe iff T is.
_elements: PhantomData<[T]>,
// Prevent unpin operation from Pin<&mut CxxVector<T>> to &mut CxxVector<T>.
_pinned: PhantomData<PhantomPinned>,
}
impl<T> CxxVector<T>
where
T: VectorElement,
{
/// Returns the number of elements in the vector.
///
/// Matches the behavior of C++ [std::vector\<T\>::size][size].
///
/// [size]: https://en.cppreference.com/w/cpp/container/vector/size
pub fn len(&self) -> usize {
T::__vector_size(self)
}
/// Returns true if the vector contains no elements.
///
/// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
///
/// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns a reference to an element at the given position, or `None` if
/// out of bounds.
pub fn get(&self, pos: usize) -> Option<&T> {
if pos < self.len() {
Some(unsafe { self.get_unchecked(pos) })
} else {
None
}
}
/// Returns a pinned mutable reference to an element at the given position,
/// or `None` if out of bounds.
pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
if pos < self.len() {
Some(unsafe { self.index_unchecked_mut(pos) })
} else {
None
}
}
/// Returns a reference to an element without doing bounds checking.
///
/// This is generally not recommended, use with caution! Calling this method
/// with an out-of-bounds index is undefined behavior even if the resulting
/// reference is not used.
///
/// Matches the behavior of C++
/// [std::vector\<T\>::operator\[\] const][operator_at].
///
/// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
let this = self as *const CxxVector<T> as *mut CxxVector<T>;
unsafe {
let ptr = T::__get_unchecked(this, pos) as *const T;
&*ptr
}
}
/// Returns a pinned mutable reference to an element without doing bounds
/// checking.
///
/// This is generally not recommended, use with caution! Calling this method
/// with an out-of-bounds index is undefined behavior even if the resulting
/// reference is not used.
///
/// Matches the behavior of C++
/// [std::vector\<T\>::operator\[\]][operator_at].
///
/// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
unsafe {
let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos);
Pin::new_unchecked(&mut *ptr)
}
}
/// Returns a slice to the underlying contiguous array of elements.
pub fn as_slice(&self) -> &[T]
where
T: ExternType<Kind = Trivial>,
{
let len = self.len();
if len == 0 {
// The slice::from_raw_parts in the other branch requires a nonnull
// and properly aligned data ptr. C++ standard does not guarantee
// that data() on a vector with size 0 would return a nonnull
// pointer or sufficiently aligned pointer, so using it would be
// undefined behavior. Create our own empty slice in Rust instead
// which upholds the invariants.
&[]
} else {
let this = self as *const CxxVector<T> as *mut CxxVector<T>;
let ptr = unsafe { T::__get_unchecked(this, 0) };
unsafe { slice::from_raw_parts(ptr, len) }
}
}
/// Returns a slice to the underlying contiguous array of elements by
/// mutable reference.
pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
where
T: ExternType<Kind = Trivial>,
{
let len = self.len();
if len == 0 {
&mut []
} else {
let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) };
unsafe { slice::from_raw_parts_mut(ptr, len) }
}
}
/// Returns an iterator over elements of type `&T`.
pub fn iter(&self) -> Iter<T> {
Iter { v: self, index: 0 }
}
/// Returns an iterator over elements of type `Pin<&mut T>`.
pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
IterMut { v: self, index: 0 }
}
/// Appends an element to the back of the vector.
///
/// Matches the behavior of C++ [std::vector\<T\>::push_back][push_back].
///
/// [push_back]: https://en.cppreference.com/w/cpp/container/vector/push_back
pub fn push(self: Pin<&mut Self>, value: T)
where
T: ExternType<Kind = Trivial>,
{
let mut value = ManuallyDrop::new(value);
unsafe {
// C++ calls move constructor followed by destructor on `value`.
T::__push_back(self, &mut value);
}
}
/// Removes the last element from a vector and returns it, or `None` if the
/// vector is empty.
pub fn pop(self: Pin<&mut Self>) -> Option<T>
where
T: ExternType<Kind = Trivial>,
{
if self.is_empty() {
None
} else {
let mut value = MaybeUninit::uninit();
Some(unsafe {
T::__pop_back(self, &mut value);
value.assume_init()
})
}
}
}
/// Iterator over elements of a `CxxVector` by shared reference.
///
/// The iterator element type is `&'a T`.
pub struct Iter<'a, T> {
v: &'a CxxVector<T>,
index: usize,
}
impl<'a, T> IntoIterator for &'a CxxVector<T>
where
T: VectorElement,
{
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> Iterator for Iter<'a, T>
where
T: VectorElement,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let next = self.v.get(self.index)?;
self.index += 1;
Some(next)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<'a, T> ExactSizeIterator for Iter<'a, T>
where
T: VectorElement,
{
fn len(&self) -> usize {
self.v.len() - self.index
}
}
impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
/// Iterator over elements of a `CxxVector` by pinned mutable reference.
///
/// The iterator element type is `Pin<&'a mut T>`.
pub struct IterMut<'a, T> {
v: Pin<&'a mut CxxVector<T>>,
index: usize,
}
impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>>
where
T: VectorElement,
{
type Item = Pin<&'a mut T>;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<'a, T> Iterator for IterMut<'a, T>
where
T: VectorElement,
{
type Item = Pin<&'a mut T>;
fn next(&mut self) -> Option<Self::Item> {
let next = self.v.as_mut().index_mut(self.index)?;
self.index += 1;
// Extend lifetime to allow simultaneous holding of nonoverlapping
// elements, analogous to slice::split_first_mut.
unsafe {
let ptr = Pin::into_inner_unchecked(next) as *mut T;
Some(Pin::new_unchecked(&mut *ptr))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<'a, T> ExactSizeIterator for IterMut<'a, T>
where
T: VectorElement,
{
fn len(&self) -> usize {
self.v.len() - self.index
}
}
impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
impl<T> Debug for CxxVector<T>
where
T: VectorElement + Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_list().entries(self).finish()
}
}
/// Trait bound for types which may be used as the `T` inside of a
/// `CxxVector<T>` in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
///
/// # Example
///
/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
/// in generic code.
///
/// ```
/// use cxx::vector::{CxxVector, VectorElement};
/// use std::fmt::Display;
///
/// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
/// where
/// T: VectorElement + Display,
/// {
/// println!("the vector elements are:");
/// for element in vector {
/// println!(" • {}", element);
/// }
/// }
/// ```
///
/// Writing the same generic function without a `VectorElement` trait bound
/// would not compile.
pub unsafe trait VectorElement: Sized {
#[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
#[doc(hidden)]
fn __vector_size(v: &CxxVector<Self>) -> usize;
#[doc(hidden)]
unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
#[doc(hidden)]
unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut ManuallyDrop<Self>) {
// Opaque C type vector elements do not get this method because they can
// never exist by value on the Rust side of the bridge.
let _ = v;
let _ = value;
unreachable!()
}
#[doc(hidden)]
unsafe fn __pop_back(v: Pin<&mut CxxVector<Self>>, out: &mut MaybeUninit<Self>) {
// Opaque C type vector elements do not get this method because they can
// never exist by value on the Rust side of the bridge.
let _ = v;
let _ = out;
unreachable!()
}
#[doc(hidden)]
fn __unique_ptr_null() -> MaybeUninit<*mut c_void>;
#[doc(hidden)]
unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void>;
#[doc(hidden)]
unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self>;
#[doc(hidden)]
unsafe fn __unique_ptr_release(repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self>;
#[doc(hidden)]
unsafe fn __unique_ptr_drop(repr: MaybeUninit<*mut c_void>);
}
macro_rules! vector_element_by_value_methods {
(opaque, $segment:expr, $ty:ty) => {};
(trivial, $segment:expr, $ty:ty) => {
unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")]
fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>);
}
}
unsafe { __push_back(v, value) }
}
unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")]
fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>);
}
}
unsafe { __pop_back(v, out) }
}
};
}
macro_rules! impl_vector_element {
($kind:ident, $segment:expr, $name:expr, $ty:ty) => {
const_assert_eq!(0, mem::size_of::<CxxVector<$ty>>());
const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
unsafe impl VectorElement for $ty {
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
fn __vector_size(v: &CxxVector<$ty>) -> usize {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
fn __vector_size(_: &CxxVector<$ty>) -> usize;
}
}
unsafe { __vector_size(v) }
}
unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
}
}
unsafe { __get_unchecked(v, pos) }
}
vector_element_by_value_methods!($kind, $segment, $ty);
fn __unique_ptr_null() -> MaybeUninit<*mut c_void> {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>);
}
}
let mut repr = MaybeUninit::uninit();
unsafe { __unique_ptr_null(&mut repr) }
repr
}
unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>);
}
}
let mut repr = MaybeUninit::uninit();
unsafe { __unique_ptr_raw(&mut repr, raw) }
repr
}
unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>;
}
}
unsafe { __unique_ptr_get(&repr) }
}
unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>;
}
}
unsafe { __unique_ptr_release(&mut repr) }
}
unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>);
}
}
unsafe { __unique_ptr_drop(&mut repr) }
}
}
};
}
macro_rules! impl_vector_element_for_primitive {
($ty:ident) => {
impl_vector_element!(trivial, stringify!($ty), stringify!($ty), $ty);
};
}
impl_vector_element_for_primitive!(u8);
impl_vector_element_for_primitive!(u16);
impl_vector_element_for_primitive!(u32);
impl_vector_element_for_primitive!(u64);
impl_vector_element_for_primitive!(usize);
impl_vector_element_for_primitive!(i8);
impl_vector_element_for_primitive!(i16);
impl_vector_element_for_primitive!(i32);
impl_vector_element_for_primitive!(i64);
impl_vector_element_for_primitive!(isize);
impl_vector_element_for_primitive!(f32);
impl_vector_element_for_primitive!(f64);
impl_vector_element!(opaque, "string", "CxxString", CxxString);

28
vendor/cxx/src/exception.rs vendored Normal file
View file

@ -0,0 +1,28 @@
#![cfg(feature = "alloc")]
use alloc::boxed::Box;
use core::fmt::{self, Display};
/// Exception thrown from an `extern "C++"` function.
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
#[derive(Debug)]
pub struct Exception {
pub(crate) what: Box<str>,
}
impl Display for Exception {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.what)
}
}
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
impl std::error::Error for Exception {}
impl Exception {
#[allow(missing_docs)]
pub fn what(&self) -> &str {
&self.what
}
}

225
vendor/cxx/src/extern_type.rs vendored Normal file
View file

@ -0,0 +1,225 @@
use self::kind::{Kind, Opaque, Trivial};
use crate::CxxString;
#[cfg(feature = "alloc")]
use alloc::string::String;
/// A type for which the layout is determined by its C++ definition.
///
/// This trait serves the following two related purposes.
///
/// <br>
///
/// ## Safely unifying occurrences of the same extern type
///
/// `ExternType` makes it possible for CXX to safely share a consistent Rust
/// type across multiple #\[cxx::bridge\] invocations that refer to a common
/// extern C++ type.
///
/// 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. The CXX code generator will use an automatically
/// generated `ExternType` impl emitted in file1 to statically verify that in
/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
/// `example::Demo` as expected in file2.
///
/// ```no_run
/// // file1.rs
/// # mod file1 {
/// #[cxx::bridge(namespace = "example")]
/// pub mod ffi {
/// unsafe extern "C++" {
/// type Demo;
///
/// fn create_demo() -> UniquePtr<Demo>;
/// }
/// }
/// # }
///
/// // file2.rs
/// #[cxx::bridge(namespace = "example")]
/// pub mod ffi {
/// unsafe extern "C++" {
/// type Demo = crate::file1::ffi::Demo;
///
/// fn take_ref_demo(demo: &Demo);
/// }
/// }
/// #
/// # fn main() {}
/// ```
///
/// <br><br>
///
/// ## Integrating with bindgen-generated types
///
/// 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.
///
/// ```no_run
/// # const _: &str = stringify! {
/// mod folly_sys; // the bindgen-generated bindings
/// # };
/// # mod folly_sys {
/// # #[repr(transparent)]
/// # pub struct StringPiece([usize; 2]);
/// # }
///
/// 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.
/// #
/// # fn main() {}
/// ```
pub unsafe trait ExternType {
/// A type-level representation of the type's C++ namespace and type name.
///
/// This will always be defined using `type_id!` in the following form:
///
/// ```
/// # struct TypeName;
/// # unsafe impl cxx::ExternType for TypeName {
/// type Id = cxx::type_id!("name::space::of::TypeName");
/// # type Kind = cxx::kind::Opaque;
/// # }
/// ```
type Id;
/// Either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`].
///
/// [`cxx::kind::Opaque`]: kind::Opaque
/// [`cxx::kind::Trivial`]: kind::Trivial
///
/// 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.
///
/// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
///
/// If you believe your C++ type reflected by this ExternType impl is indeed
/// fine to hold by value and move in Rust, you can specify:
///
/// ```
/// # struct TypeName;
/// # 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.
type Kind: Kind;
}
/// Marker types identifying Rust's knowledge about an extern C++ type.
///
/// These markers are used in the [`Kind`][ExternType::Kind] associated type in
/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
/// overview of their purpose.
pub mod kind {
use super::private;
/// An opaque type which cannot be passed or held by value within Rust.
///
/// Rust's move semantics are such that every move is equivalent to a
/// memcpy. This is incompatible in general with C++'s constructor-based
/// move semantics, so a C++ type which has a destructor or nontrivial move
/// constructor must never exist by value in Rust. In CXX, such types are
/// called opaque C++ types.
///
/// When passed across an FFI boundary, an opaque C++ type must be behind an
/// indirection such as a reference or UniquePtr.
pub enum Opaque {}
/// A type with trivial move constructor and no destructor, which can
/// therefore be owned and moved around in Rust code without requiring
/// indirection.
pub enum Trivial {}
#[allow(missing_docs)]
pub trait Kind: private::Sealed {}
impl Kind for Opaque {}
impl Kind for Trivial {}
}
mod private {
pub trait Sealed {}
impl Sealed for super::Opaque {}
impl Sealed for super::Trivial {}
}
#[doc(hidden)]
pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
#[doc(hidden)]
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
macro_rules! impl_extern_type {
($([$kind:ident] $($(#[$($attr:tt)*])* $ty:path = $cxxpath:literal)*)*) => {
$($(
$(#[$($attr)*])*
unsafe impl ExternType for $ty {
#[allow(unused_attributes)] // incorrect lint; this doc(hidden) attr *is* respected by rustdoc
#[doc(hidden)]
type Id = crate::type_id!($cxxpath);
type Kind = $kind;
}
)*)*
};
}
impl_extern_type! {
[Trivial]
bool = "bool"
u8 = "std::uint8_t"
u16 = "std::uint16_t"
u32 = "std::uint32_t"
u64 = "std::uint64_t"
usize = "size_t"
i8 = "std::int8_t"
i16 = "std::int16_t"
i32 = "std::int32_t"
i64 = "std::int64_t"
isize = "rust::isize"
f32 = "float"
f64 = "double"
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
String = "rust::String"
[Opaque]
CxxString = "std::string"
}

16
vendor/cxx/src/fmt.rs vendored Normal file
View file

@ -0,0 +1,16 @@
use core::fmt::{self, Display};
pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display {
DisplayInvoke(fmt)
}
struct DisplayInvoke<T>(T);
impl<T> Display for DisplayInvoke<T>
where
T: Fn(&mut fmt::Formatter) -> fmt::Result,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
(self.0)(formatter)
}
}

9
vendor/cxx/src/function.rs vendored Normal file
View file

@ -0,0 +1,9 @@
#![allow(missing_docs)]
use core::ffi::c_void;
#[repr(C)]
pub struct FatFunction {
pub trampoline: *const c_void,
pub ptr: *const c_void,
}

12
vendor/cxx/src/hash.rs vendored Normal file
View file

@ -0,0 +1,12 @@
use core::hash::{Hash, Hasher};
#[doc(hidden)]
pub fn hash<V: Hash>(value: &V) -> usize {
#[cfg(feature = "std")]
let mut hasher = std::collections::hash_map::DefaultHasher::new();
#[cfg(not(feature = "std"))]
let mut hasher = crate::sip::SipHasher13::new();
Hash::hash(value, &mut hasher);
Hasher::finish(&hasher) as usize
}

538
vendor/cxx/src/lib.rs vendored Normal file
View file

@ -0,0 +1,538 @@
//! [![github]](https://github.com/dtolnay/cxx)&ensp;[![crates-io]](https://crates.io/crates/cxx)&ensp;[![docs-rs]](https://docs.rs/cxx)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
//! 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.
//!
//! <br>
//!
//! *Compiler support: requires rustc 1.48+ 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 manipulation 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
//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
//! directory.
//!
//! ```no_run
//! #[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;
//! }
//! }
//! #
//! # pub struct MultiBuf;
//! #
//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] {
//! # unimplemented!()
//! # }
//! #
//! # fn main() {}
//! ```
//!
//! 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](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.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)
//!
//! 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** &mdash; their fields are made visible to both
//! languages. The definition written within cxx::bridge is the single source
//! of truth.
//!
//! - **Opaque types** &mdash; 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** &mdash; 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"
//! ```
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//! cxx_build::bridge("src/main.rs") // returns a cc::Build
//! .file("src/demo.cc")
//! .flag_if_supported("-std=c++11")
//! .compile("cxxbridge-demo");
//!
//! println!("cargo:rerun-if-changed=src/main.rs");
//! println!("cargo:rerun-if-changed=src/demo.cc");
//! println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! <br><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 <https://github.com/dtolnay/cxx>.
//!
//! ```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 &lt;=&gt; 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>&amp;str</td><td>rust::Str</td><td></td></tr>
//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
//! <tr><td><a href="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&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
//! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
//! <tr><td><a href="struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
//! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</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) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
//! <tr><td>Result&lt;T&gt;</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 <https://github.com/dtolnay/cxx>. 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&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
//! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
//! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
//! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
//! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
//! </table>
#![no_std]
#![doc(html_root_url = "https://docs.rs/cxx/1.0.85")]
#![deny(improper_ctypes, improper_ctypes_definitions, missing_docs)]
#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
#![allow(
clippy::cognitive_complexity,
clippy::declare_interior_mutable_const,
clippy::doc_markdown,
clippy::empty_enum,
clippy::inherent_to_string,
clippy::items_after_statements,
clippy::large_enum_variant,
clippy::len_without_is_empty,
clippy::missing_errors_doc,
clippy::missing_safety_doc,
clippy::module_inception,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::needless_doctest_main,
clippy::new_without_default,
clippy::or_fun_call,
clippy::ptr_arg,
clippy::toplevel_ref_arg,
clippy::transmute_undefined_repr, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8417
clippy::useless_let_if_seq,
clippy::wrong_self_convention
)]
#[cfg(built_with_cargo)]
extern crate link_cplusplus;
extern crate self as cxx;
#[doc(hidden)]
pub extern crate core;
#[cfg(feature = "alloc")]
#[doc(hidden)]
pub extern crate alloc;
#[cfg(not(feature = "alloc"))]
extern crate core as alloc;
#[cfg(feature = "std")]
#[doc(hidden)]
pub extern crate std;
// Block inadvertent use of items from libstd, which does not otherwise produce
// a compile-time error on edition 2018+.
#[cfg(not(feature = "std"))]
extern crate core as std;
#[cfg(not(any(feature = "alloc", cxx_experimental_no_alloc)))]
compile_error! {
r#"cxx support for no_alloc is incomplete and semver exempt; you must build with at least one of feature="std", feature="alloc", or RUSTFLAGS='--cfg cxx_experimental_no_alloc'"#
}
#[cfg(all(compile_error_if_alloc, feature = "alloc"))]
compile_error! {
r#"feature="alloc" is unexpectedly enabled"#
}
#[cfg(all(compile_error_if_std, feature = "std"))]
compile_error! {
r#"feature="std" is unexpectedly enabled"#
}
#[macro_use]
mod macros;
mod c_char;
mod cxx_vector;
mod exception;
mod extern_type;
mod fmt;
mod function;
mod hash;
mod lossy;
pub mod memory;
mod opaque;
mod result;
mod rust_slice;
mod rust_str;
mod rust_string;
mod rust_type;
mod rust_vec;
mod shared_ptr;
mod sip;
#[path = "cxx_string.rs"]
mod string;
mod symbols;
mod type_id;
mod unique_ptr;
mod unwind;
pub mod vector;
mod weak_ptr;
pub use crate::cxx_vector::CxxVector;
#[cfg(feature = "alloc")]
pub use crate::exception::Exception;
pub use crate::extern_type::{kind, ExternType};
pub use crate::shared_ptr::SharedPtr;
pub use crate::string::CxxString;
pub use crate::unique_ptr::UniquePtr;
pub use crate::weak_ptr::WeakPtr;
pub use cxxbridge_macro::bridge;
/// Synonym for `CxxString`.
///
/// To avoid confusion with Rust's standard library string you probably
/// shouldn't import this type with `use`. Instead, write `cxx::String`, or
/// import and use `CxxString`.
pub type String = CxxString;
/// Synonym for `CxxVector`.
///
/// To avoid confusion with Rust's standard library vector you probably
/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or
/// import and use `CxxVector`.
pub type Vector<T> = CxxVector<T>;
// Not public API.
#[doc(hidden)]
pub mod private {
pub use crate::c_char::c_char;
pub use crate::cxx_vector::VectorElement;
pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
pub use crate::function::FatFunction;
pub use crate::hash::hash;
pub use crate::opaque::Opaque;
#[cfg(feature = "alloc")]
pub use crate::result::{r#try, Result};
pub use crate::rust_slice::RustSlice;
pub use crate::rust_str::RustStr;
#[cfg(feature = "alloc")]
pub use crate::rust_string::RustString;
pub use crate::rust_type::{ImplBox, ImplVec, RustType};
#[cfg(feature = "alloc")]
pub use crate::rust_vec::RustVec;
pub use crate::shared_ptr::SharedPtrTarget;
pub use crate::string::StackString;
pub use crate::unique_ptr::UniquePtrTarget;
pub use crate::unwind::prevent_unwind;
pub use crate::weak_ptr::WeakPtrTarget;
pub use core::{concat, module_path};
pub use cxxbridge_macro::type_id;
}
mod actually_private {
pub trait Private {}
}
macro_rules! chars {
($($ch:ident)*) => {
$(
#[doc(hidden)]
pub enum $ch {}
)*
};
}
chars! {
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
__ // underscore
}
#[repr(transparent)]
struct void(core::ffi::c_void);

67
vendor/cxx/src/lossy.rs vendored Normal file
View file

@ -0,0 +1,67 @@
use core::char;
use core::fmt::{self, Write as _};
use core::str;
pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
loop {
match str::from_utf8(bytes) {
Ok(valid) => return f.write_str(valid),
Err(utf8_error) => {
let valid_up_to = utf8_error.valid_up_to();
let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) };
f.write_str(valid)?;
f.write_char(char::REPLACEMENT_CHARACTER)?;
if let Some(error_len) = utf8_error.error_len() {
bytes = &bytes[valid_up_to + error_len..];
} else {
return Ok(());
}
}
}
}
}
pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
f.write_char('"')?;
while !bytes.is_empty() {
let from_utf8_result = str::from_utf8(bytes);
let valid = match from_utf8_result {
Ok(valid) => valid,
Err(utf8_error) => {
let valid_up_to = utf8_error.valid_up_to();
unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }
}
};
let mut written = 0;
for (i, ch) in valid.char_indices() {
let esc = ch.escape_debug();
if esc.len() != 1 {
f.write_str(&valid[written..i])?;
for ch in esc {
f.write_char(ch)?;
}
written = i + ch.len_utf8();
}
}
f.write_str(&valid[written..])?;
match from_utf8_result {
Ok(_valid) => break,
Err(utf8_error) => {
let end_of_broken = if let Some(error_len) = utf8_error.error_len() {
valid.len() + error_len
} else {
bytes.len()
};
for b in &bytes[valid.len()..end_of_broken] {
write!(f, "\\x{:02x}", b)?;
}
bytes = &bytes[end_of_broken..];
}
}
}
f.write_char('"')
}

7
vendor/cxx/src/macros/assert.rs vendored Normal file
View file

@ -0,0 +1,7 @@
#[macro_export]
#[doc(hidden)]
macro_rules! const_assert_eq {
($left:expr, $right:expr $(,)?) => {
const _: [(); $left] = [(); $right];
};
}

8
vendor/cxx/src/macros/concat.rs vendored Normal file
View file

@ -0,0 +1,8 @@
#[macro_export]
#[doc(hidden)]
macro_rules! attr {
(#[$name:ident = $value:expr] $($rest:tt)*) => {
#[$name = $value]
$($rest)*
};
}

4
vendor/cxx/src/macros/mod.rs vendored Normal file
View file

@ -0,0 +1,4 @@
#[macro_use]
mod assert;
#[macro_use]
mod concat;

9
vendor/cxx/src/memory.rs vendored Normal file
View file

@ -0,0 +1,9 @@
//! Less used details of `UniquePtr` and `SharedPtr`.
//!
//! The pointer types themselves are exposed at the crate root.
pub use crate::shared_ptr::SharedPtrTarget;
pub use crate::unique_ptr::UniquePtrTarget;
pub use crate::weak_ptr::WeakPtrTarget;
#[doc(no_inline)]
pub use cxx::{SharedPtr, UniquePtr};

20
vendor/cxx/src/opaque.rs vendored Normal file
View file

@ -0,0 +1,20 @@
#![allow(missing_docs)]
use crate::void;
use core::marker::{PhantomData, PhantomPinned};
use core::mem;
// . size = 0
// . align = 1
// . ffi-safe
// . !Send
// . !Sync
// . !Unpin
#[repr(C, packed)]
pub struct Opaque {
_private: [*const void; 0],
_pinned: PhantomData<PhantomPinned>,
}
const_assert_eq!(0, mem::size_of::<Opaque>());
const_assert_eq!(1, mem::align_of::<Opaque>());

70
vendor/cxx/src/result.rs vendored Normal file
View file

@ -0,0 +1,70 @@
#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use crate::exception::Exception;
use alloc::boxed::Box;
use alloc::string::{String, ToString};
use core::fmt::Display;
use core::ptr::{self, NonNull};
use core::result::Result as StdResult;
use core::slice;
use core::str;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PtrLen {
pub ptr: NonNull<u8>,
pub len: usize,
}
#[repr(C)]
pub union Result {
err: PtrLen,
ok: *const u8, // null
}
pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
where
E: Display,
{
match result {
Ok(ok) => {
unsafe { ptr::write(ret, ok) }
Result { ok: ptr::null() }
}
Err(err) => unsafe { to_c_error(err.to_string()) },
}
}
unsafe fn to_c_error(msg: String) -> Result {
let mut msg = msg;
unsafe { msg.as_mut_vec() }.push(b'\0');
let ptr = msg.as_ptr();
let len = msg.len();
extern "C" {
#[link_name = "cxxbridge1$error"]
fn error(ptr: *const u8, len: usize) -> NonNull<u8>;
}
let copy = unsafe { error(ptr, len) };
let err = PtrLen { ptr: copy, len };
Result { err }
}
impl Result {
pub unsafe fn exception(self) -> StdResult<(), Exception> {
unsafe {
if self.ok.is_null() {
Ok(())
} else {
let err = self.err;
let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
let s = str::from_utf8_unchecked_mut(slice);
Err(Exception {
what: Box::from_raw(s),
})
}
}
}
}

66
vendor/cxx/src/rust_slice.rs vendored Normal file
View file

@ -0,0 +1,66 @@
#![allow(missing_docs)]
use core::mem::{self, MaybeUninit};
use core::ptr::{self, NonNull};
use core::slice;
// ABI compatible with C++ rust::Slice<T> (not necessarily &[T]).
#[repr(C)]
pub struct RustSlice {
repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()],
}
impl RustSlice {
pub fn from_ref<T>(slice: &[T]) -> Self {
let ptr = NonNull::from(slice).cast::<T>();
let len = slice.len();
Self::from_raw_parts(ptr, len)
}
pub fn from_mut<T>(slice: &mut [T]) -> Self {
let ptr = NonNull::from(&mut *slice).cast::<T>();
let len = slice.len();
Self::from_raw_parts(ptr, len)
}
pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
let ptr = self.as_non_null_ptr().as_ptr();
let len = self.len();
unsafe { slice::from_raw_parts(ptr, len) }
}
pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
let ptr = self.as_non_null_ptr().as_ptr();
let len = self.len();
unsafe { slice::from_raw_parts_mut(ptr, len) }
}
pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
// TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable.
// https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts
// https://github.com/rust-lang/rust/issues/81513
let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len);
unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) }
}
pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> {
let rust_slice = RustSlice { repr: self.repr };
let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
repr.cast()
}
pub(crate) fn len(&self) -> usize {
let rust_slice = RustSlice { repr: self.repr };
let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) };
// TODO: use repr.len() when stable.
// https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len
// https://github.com/rust-lang/rust/issues/71146
unsafe { repr.as_ref() }.len()
}
}
const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>());
const_assert_eq!(
mem::align_of::<NonNull<[()]>>(),
mem::align_of::<RustSlice>(),
);

28
vendor/cxx/src/rust_str.rs vendored Normal file
View file

@ -0,0 +1,28 @@
#![allow(missing_docs)]
use core::mem::{self, MaybeUninit};
use core::ptr::NonNull;
use core::str;
// ABI compatible with C++ rust::Str (not necessarily &str).
#[repr(C)]
pub struct RustStr {
repr: [MaybeUninit<usize>; mem::size_of::<NonNull<str>>() / mem::size_of::<usize>()],
}
impl RustStr {
pub fn from(repr: &str) -> Self {
let repr = NonNull::from(repr);
unsafe { mem::transmute::<NonNull<str>, RustStr>(repr) }
}
pub unsafe fn as_str<'a>(self) -> &'a str {
unsafe {
let repr = mem::transmute::<RustStr, NonNull<str>>(self);
&*repr.as_ptr()
}
}
}
const_assert_eq!(mem::size_of::<NonNull<str>>(), mem::size_of::<RustStr>());
const_assert_eq!(mem::align_of::<NonNull<str>>(), mem::align_of::<RustStr>());

48
vendor/cxx/src/rust_string.rs vendored Normal file
View file

@ -0,0 +1,48 @@
#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use alloc::string::String;
use core::mem::{self, MaybeUninit};
use core::ptr;
// ABI compatible with C++ rust::String (not necessarily alloc::string::String).
#[repr(C)]
pub struct RustString {
repr: [MaybeUninit<usize>; mem::size_of::<String>() / mem::size_of::<usize>()],
}
impl RustString {
pub fn from(s: String) -> Self {
unsafe { mem::transmute::<String, RustString>(s) }
}
pub fn from_ref(s: &String) -> &Self {
unsafe { &*(s as *const String as *const RustString) }
}
pub fn from_mut(s: &mut String) -> &mut Self {
unsafe { &mut *(s as *mut String as *mut RustString) }
}
pub fn into_string(self) -> String {
unsafe { mem::transmute::<RustString, String>(self) }
}
pub fn as_string(&self) -> &String {
unsafe { &*(self as *const RustString as *const String) }
}
pub fn as_mut_string(&mut self) -> &mut String {
unsafe { &mut *(self as *mut RustString as *mut String) }
}
}
impl Drop for RustString {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.as_mut_string()) }
}
}
const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<RustString>());
const_assert_eq!(mem::size_of::<String>(), mem::size_of::<RustString>());
const_assert_eq!(mem::align_of::<String>(), mem::align_of::<RustString>());

5
vendor/cxx/src/rust_type.rs vendored Normal file
View file

@ -0,0 +1,5 @@
#![allow(missing_docs)]
pub unsafe trait RustType {}
pub unsafe trait ImplBox {}
pub unsafe trait ImplVec {}

115
vendor/cxx/src/rust_vec.rs vendored Normal file
View file

@ -0,0 +1,115 @@
#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use crate::rust_string::RustString;
use alloc::string::String;
use alloc::vec::Vec;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::ptr;
// ABI compatible with C++ rust::Vec<T> (not necessarily alloc::vec::Vec<T>).
#[repr(C)]
pub struct RustVec<T> {
repr: [MaybeUninit<usize>; mem::size_of::<Vec<c_void>>() / mem::size_of::<usize>()],
marker: PhantomData<Vec<T>>,
}
impl<T> RustVec<T> {
pub fn new() -> Self {
Self::from(Vec::new())
}
pub fn from(v: Vec<T>) -> Self {
unsafe { mem::transmute::<Vec<T>, RustVec<T>>(v) }
}
pub fn from_ref(v: &Vec<T>) -> &Self {
unsafe { &*(v as *const Vec<T> as *const RustVec<T>) }
}
pub fn from_mut(v: &mut Vec<T>) -> &mut Self {
unsafe { &mut *(v as *mut Vec<T> as *mut RustVec<T>) }
}
pub fn into_vec(self) -> Vec<T> {
unsafe { mem::transmute::<RustVec<T>, Vec<T>>(self) }
}
pub fn as_vec(&self) -> &Vec<T> {
unsafe { &*(self as *const RustVec<T> as *const Vec<T>) }
}
pub fn as_mut_vec(&mut self) -> &mut Vec<T> {
unsafe { &mut *(self as *mut RustVec<T> as *mut Vec<T>) }
}
pub fn len(&self) -> usize {
self.as_vec().len()
}
pub fn capacity(&self) -> usize {
self.as_vec().capacity()
}
pub fn as_ptr(&self) -> *const T {
self.as_vec().as_ptr()
}
pub fn reserve_total(&mut self, new_cap: usize) {
let vec = self.as_mut_vec();
if new_cap > vec.capacity() {
let additional = new_cap - vec.len();
vec.reserve(additional);
}
}
pub unsafe fn set_len(&mut self, len: usize) {
unsafe { self.as_mut_vec().set_len(len) }
}
pub fn truncate(&mut self, len: usize) {
self.as_mut_vec().truncate(len);
}
}
impl RustVec<RustString> {
pub fn from_vec_string(v: Vec<String>) -> Self {
let mut v = ManuallyDrop::new(v);
let ptr = v.as_mut_ptr().cast::<RustString>();
let len = v.len();
let cap = v.capacity();
Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) })
}
pub fn from_ref_vec_string(v: &Vec<String>) -> &Self {
Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) })
}
pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self {
Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) })
}
pub fn into_vec_string(self) -> Vec<String> {
let mut v = ManuallyDrop::new(self.into_vec());
let ptr = v.as_mut_ptr().cast::<String>();
let len = v.len();
let cap = v.capacity();
unsafe { Vec::from_raw_parts(ptr, len, cap) }
}
pub fn as_vec_string(&self) -> &Vec<String> {
unsafe { &*(self as *const RustVec<RustString> as *const Vec<String>) }
}
pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> {
unsafe { &mut *(self as *mut RustVec<RustString> as *mut Vec<String>) }
}
}
impl<T> Drop for RustVec<T> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.as_mut_vec()) }
}
}

283
vendor/cxx/src/shared_ptr.rs vendored Normal file
View file

@ -0,0 +1,283 @@
use crate::fmt::display;
use crate::kind::Trivial;
use crate::string::CxxString;
use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
use crate::ExternType;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ops::Deref;
/// Binding to C++ `std::shared_ptr<T>`.
#[repr(C)]
pub struct SharedPtr<T>
where
T: SharedPtrTarget,
{
repr: [MaybeUninit<*mut c_void>; 2],
ty: PhantomData<T>,
}
impl<T> SharedPtr<T>
where
T: SharedPtrTarget,
{
/// Makes a new SharedPtr wrapping a null pointer.
///
/// Matches the behavior of default-constructing a std::shared\_ptr.
pub fn null() -> Self {
let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
let new = shared_ptr.as_mut_ptr().cast();
unsafe {
T::__null(new);
shared_ptr.assume_init()
}
}
/// Allocates memory on the heap and makes a SharedPtr owner for it.
pub fn new(value: T) -> Self
where
T: ExternType<Kind = Trivial>,
{
let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
let new = shared_ptr.as_mut_ptr().cast();
unsafe {
T::__new(value, new);
shared_ptr.assume_init()
}
}
/// Checks whether the SharedPtr does not own an object.
///
/// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
pub fn is_null(&self) -> bool {
let this = self as *const Self as *const c_void;
let ptr = unsafe { T::__get(this) };
ptr.is_null()
}
/// Returns a reference to the object owned by this SharedPtr if any,
/// otherwise None.
pub fn as_ref(&self) -> Option<&T> {
let this = self as *const Self as *const c_void;
unsafe { T::__get(this).as_ref() }
}
/// Constructs new WeakPtr as a non-owning reference to the object managed
/// by `self`. If `self` manages no object, the WeakPtr manages no object
/// too.
///
/// Matches the behavior of [std::weak_ptr\<T\>::weak_ptr(const std::shared_ptr\<T\> \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr).
pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T>
where
T: WeakPtrTarget,
{
let this = self as *const Self as *const c_void;
let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
let new = weak_ptr.as_mut_ptr().cast();
unsafe {
T::__downgrade(this, new);
weak_ptr.assume_init()
}
}
}
unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
unsafe impl<T> Sync for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
impl<T> Clone for SharedPtr<T>
where
T: SharedPtrTarget,
{
fn clone(&self) -> Self {
let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
let new = shared_ptr.as_mut_ptr().cast();
let this = self as *const Self as *mut c_void;
unsafe {
T::__clone(this, new);
shared_ptr.assume_init()
}
}
}
// SharedPtr is not a self-referential type and is safe to move out of a Pin,
// regardless whether the pointer's target is Unpin.
impl<T> Unpin for SharedPtr<T> where T: SharedPtrTarget {}
impl<T> Drop for SharedPtr<T>
where
T: SharedPtrTarget,
{
fn drop(&mut self) {
let this = self as *mut Self as *mut c_void;
unsafe { T::__drop(this) }
}
}
impl<T> Deref for SharedPtr<T>
where
T: SharedPtrTarget,
{
type Target = T;
fn deref(&self) -> &Self::Target {
match self.as_ref() {
Some(target) => target,
None => panic!(
"called deref on a null SharedPtr<{}>",
display(T::__typename),
),
}
}
}
impl<T> Debug for SharedPtr<T>
where
T: Debug + SharedPtrTarget,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.as_ref() {
None => formatter.write_str("nullptr"),
Some(value) => Debug::fmt(value, formatter),
}
}
}
impl<T> Display for SharedPtr<T>
where
T: Display + SharedPtrTarget,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.as_ref() {
None => formatter.write_str("nullptr"),
Some(value) => Display::fmt(value, formatter),
}
}
}
/// Trait bound for types which may be used as the `T` inside of a
/// `SharedPtr<T>` in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
///
/// # Example
///
/// A bound `T: SharedPtrTarget` may be necessary when manipulating
/// [`SharedPtr`] in generic code.
///
/// ```
/// use cxx::memory::{SharedPtr, SharedPtrTarget};
/// use std::fmt::Display;
///
/// pub fn take_generic_ptr<T>(ptr: SharedPtr<T>)
/// where
/// T: SharedPtrTarget + Display,
/// {
/// println!("the shared_ptr points to: {}", *ptr);
/// }
/// ```
///
/// Writing the same generic function without a `SharedPtrTarget` trait bound
/// would not compile.
pub unsafe trait SharedPtrTarget {
#[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
#[doc(hidden)]
unsafe fn __null(new: *mut c_void);
#[doc(hidden)]
unsafe fn __new(value: Self, new: *mut c_void)
where
Self: Sized,
{
// Opoaque C types do not get this method because they can never exist
// by value on the Rust side of the bridge.
let _ = value;
let _ = new;
unreachable!()
}
#[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void);
#[doc(hidden)]
unsafe fn __get(this: *const c_void) -> *const Self;
#[doc(hidden)]
unsafe fn __drop(this: *mut c_void);
}
macro_rules! impl_shared_ptr_target {
($segment:expr, $name:expr, $ty:ty) => {
unsafe impl SharedPtrTarget for $ty {
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
unsafe fn __null(new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")]
fn __null(new: *mut c_void);
}
}
unsafe { __null(new) }
}
unsafe fn __new(value: Self, new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")]
fn __uninit(new: *mut c_void) -> *mut c_void;
}
}
unsafe { __uninit(new).cast::<$ty>().write(value) }
}
unsafe fn __clone(this: *const c_void, new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")]
fn __clone(this: *const c_void, new: *mut c_void);
}
}
unsafe { __clone(this, new) }
}
unsafe fn __get(this: *const c_void) -> *const Self {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")]
fn __get(this: *const c_void) -> *const c_void;
}
}
unsafe { __get(this) }.cast()
}
unsafe fn __drop(this: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")]
fn __drop(this: *mut c_void);
}
}
unsafe { __drop(this) }
}
}
};
}
macro_rules! impl_shared_ptr_target_for_primitive {
($ty:ident) => {
impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty);
};
}
impl_shared_ptr_target_for_primitive!(bool);
impl_shared_ptr_target_for_primitive!(u8);
impl_shared_ptr_target_for_primitive!(u16);
impl_shared_ptr_target_for_primitive!(u32);
impl_shared_ptr_target_for_primitive!(u64);
impl_shared_ptr_target_for_primitive!(usize);
impl_shared_ptr_target_for_primitive!(i8);
impl_shared_ptr_target_for_primitive!(i16);
impl_shared_ptr_target_for_primitive!(i32);
impl_shared_ptr_target_for_primitive!(i64);
impl_shared_ptr_target_for_primitive!(isize);
impl_shared_ptr_target_for_primitive!(f32);
impl_shared_ptr_target_for_primitive!(f64);
impl_shared_ptr_target!("string", "CxxString", CxxString);

228
vendor/cxx/src/sip.rs vendored Normal file
View file

@ -0,0 +1,228 @@
// Vendored from libstd:
// https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/hash/sip.rs
//
// TODO: maybe depend on a hasher from crates.io if this becomes annoying to
// maintain, or change this to a simpler one.
#![cfg(not(feature = "std"))]
use core::cmp;
use core::hash::Hasher;
use core::mem;
use core::ptr;
/// An implementation of SipHash 1-3.
///
/// This is currently the default hashing function used by standard library
/// (e.g., `collections::HashMap` uses it by default).
///
/// See: <https://131002.net/siphash>
pub struct SipHasher13 {
k0: u64,
k1: u64,
length: usize, // how many bytes we've processed
state: State, // hash State
tail: u64, // unprocessed bytes le
ntail: usize, // how many bytes in tail are valid
}
#[derive(Clone, Copy)]
#[repr(C)]
struct State {
// v0, v2 and v1, v3 show up in pairs in the algorithm,
// and simd implementations of SipHash will use vectors
// of v02 and v13. By placing them in this order in the struct,
// the compiler can pick up on just a few simd optimizations by itself.
v0: u64,
v2: u64,
v1: u64,
v3: u64,
}
macro_rules! compress {
($state:expr) => {
compress!($state.v0, $state.v1, $state.v2, $state.v3)
};
($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {
$v0 = $v0.wrapping_add($v1);
$v1 = $v1.rotate_left(13);
$v1 ^= $v0;
$v0 = $v0.rotate_left(32);
$v2 = $v2.wrapping_add($v3);
$v3 = $v3.rotate_left(16);
$v3 ^= $v2;
$v0 = $v0.wrapping_add($v3);
$v3 = $v3.rotate_left(21);
$v3 ^= $v0;
$v2 = $v2.wrapping_add($v1);
$v1 = $v1.rotate_left(17);
$v1 ^= $v2;
$v2 = $v2.rotate_left(32);
};
}
/// Loads an integer of the desired type from a byte stream, in LE order. Uses
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load it from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
macro_rules! load_int_le {
($buf:expr, $i:expr, $int_ty:ident) => {{
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
let mut data = 0 as $int_ty;
ptr::copy_nonoverlapping(
$buf.as_ptr().add($i),
&mut data as *mut _ as *mut u8,
mem::size_of::<$int_ty>(),
);
data.to_le()
}};
}
/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the
/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed
/// sizes and avoid calling `memcpy`, which is good for speed.
///
/// Unsafe because: unchecked indexing at start..start+len
unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
debug_assert!(len < 8);
let mut i = 0; // current byte index (from LSB) in the output u64
let mut out = 0;
if i + 3 < len {
// SAFETY: `i` cannot be greater than `len`, and the caller must guarantee
// that the index start..start+len is in bounds.
out = unsafe { load_int_le!(buf, start + i, u32) } as u64;
i += 4;
}
if i + 1 < len {
// SAFETY: same as above.
out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8);
i += 2
}
if i < len {
// SAFETY: same as above.
out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8);
i += 1;
}
debug_assert_eq!(i, len);
out
}
impl SipHasher13 {
/// Creates a new `SipHasher13` with the two initial keys set to 0.
pub fn new() -> Self {
Self::new_with_keys(0, 0)
}
/// Creates a `SipHasher13` that is keyed off the provided keys.
fn new_with_keys(key0: u64, key1: u64) -> Self {
let mut state = SipHasher13 {
k0: key0,
k1: key1,
length: 0,
state: State {
v0: 0,
v1: 0,
v2: 0,
v3: 0,
},
tail: 0,
ntail: 0,
};
state.reset();
state
}
fn reset(&mut self) {
self.length = 0;
self.state.v0 = self.k0 ^ 0x736f6d6570736575;
self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
self.state.v2 = self.k0 ^ 0x6c7967656e657261;
self.state.v3 = self.k1 ^ 0x7465646279746573;
self.ntail = 0;
}
}
impl Hasher for SipHasher13 {
// Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
// for this type. We could add them, copy the `short_write` implementation
// in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
// methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would
// greatly speed up integer hashing by those hashers, at the cost of
// slightly slowing down compile speeds on some benchmarks. See #69152 for
// details.
fn write(&mut self, msg: &[u8]) {
let length = msg.len();
self.length += length;
let mut needed = 0;
if self.ntail != 0 {
needed = 8 - self.ntail;
// SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length`
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
if length < needed {
self.ntail += length;
return;
} else {
self.state.v3 ^= self.tail;
Sip13Rounds::c_rounds(&mut self.state);
self.state.v0 ^= self.tail;
self.ntail = 0;
}
}
// Buffered tail is now flushed, process new input.
let len = length - needed;
let left = len & 0x7; // len % 8
let mut i = needed;
while i < len - left {
// SAFETY: because `len - left` is the biggest multiple of 8 under
// `len`, and because `i` starts at `needed` where `len` is `length - needed`,
// `i + 8` is guaranteed to be less than or equal to `length`.
let mi = unsafe { load_int_le!(msg, i, u64) };
self.state.v3 ^= mi;
Sip13Rounds::c_rounds(&mut self.state);
self.state.v0 ^= mi;
i += 8;
}
// SAFETY: `i` is now `needed + len.div_euclid(8) * 8`,
// so `i + left` = `needed + len` = `length`, which is by
// definition equal to `msg.len()`.
self.tail = unsafe { u8to64_le(msg, i, left) };
self.ntail = left;
}
fn finish(&self) -> u64 {
let mut state = self.state;
let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
state.v3 ^= b;
Sip13Rounds::c_rounds(&mut state);
state.v0 ^= b;
state.v2 ^= 0xff;
Sip13Rounds::d_rounds(&mut state);
state.v0 ^ state.v1 ^ state.v2 ^ state.v3
}
}
struct Sip13Rounds;
impl Sip13Rounds {
fn c_rounds(state: &mut State) {
compress!(state);
}
fn d_rounds(state: &mut State) {
compress!(state);
compress!(state);
compress!(state);
}
}

18
vendor/cxx/src/symbols/exception.rs vendored Normal file
View file

@ -0,0 +1,18 @@
#![cfg(feature = "alloc")]
use crate::result::PtrLen;
use alloc::boxed::Box;
use alloc::string::String;
use core::ptr::NonNull;
use core::slice;
#[export_name = "cxxbridge1$exception"]
unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
let string = String::from_utf8_lossy(slice);
let len = string.len();
let raw_str = Box::into_raw(string.into_owned().into_boxed_str());
let raw_u8 = raw_str.cast::<u8>();
let nonnull = unsafe { NonNull::new_unchecked(raw_u8) };
PtrLen { ptr: nonnull, len }
}

5
vendor/cxx/src/symbols/mod.rs vendored Normal file
View file

@ -0,0 +1,5 @@
mod exception;
mod rust_slice;
mod rust_str;
mod rust_string;
mod rust_vec;

20
vendor/cxx/src/symbols/rust_slice.rs vendored Normal file
View file

@ -0,0 +1,20 @@
use crate::rust_slice::RustSlice;
use core::mem::MaybeUninit;
use core::ptr::{self, NonNull};
#[export_name = "cxxbridge1$slice$new"]
unsafe extern "C" fn slice_new(this: &mut MaybeUninit<RustSlice>, ptr: NonNull<()>, len: usize) {
let this = this.as_mut_ptr();
let rust_slice = RustSlice::from_raw_parts(ptr, len);
unsafe { ptr::write(this, rust_slice) }
}
#[export_name = "cxxbridge1$slice$ptr"]
unsafe extern "C" fn slice_ptr(this: &RustSlice) -> NonNull<()> {
this.as_non_null_ptr()
}
#[export_name = "cxxbridge1$slice$len"]
unsafe extern "C" fn slice_len(this: &RustSlice) -> usize {
this.len()
}

43
vendor/cxx/src/symbols/rust_str.rs vendored Normal file
View file

@ -0,0 +1,43 @@
#[cfg(feature = "alloc")]
use alloc::string::String;
use core::mem::MaybeUninit;
use core::ptr;
use core::slice;
use core::str;
#[export_name = "cxxbridge1$str$new"]
unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) {
let this = this.as_mut_ptr();
unsafe { ptr::write(this, "") }
}
#[cfg(feature = "alloc")]
#[export_name = "cxxbridge1$str$ref"]
unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) {
let this = this.as_mut_ptr();
let s = string.as_str();
unsafe { ptr::write(this, s) }
}
#[export_name = "cxxbridge1$str$from"]
unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: usize) -> bool {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
match str::from_utf8(slice) {
Ok(s) => {
let this = this.as_mut_ptr();
unsafe { ptr::write(this, s) }
true
}
Err(_) => false,
}
}
#[export_name = "cxxbridge1$str$ptr"]
unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 {
this.as_ptr()
}
#[export_name = "cxxbridge1$str$len"]
unsafe extern "C" fn str_len(this: &&str) -> usize {
this.len()
}

114
vendor/cxx/src/symbols/rust_string.rs vendored Normal file
View file

@ -0,0 +1,114 @@
#![cfg(feature = "alloc")]
use alloc::borrow::ToOwned;
use alloc::string::String;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ptr;
use core::slice;
use core::str;
#[export_name = "cxxbridge1$string$new"]
unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
let this = this.as_mut_ptr();
let new = String::new();
unsafe { ptr::write(this, new) }
}
#[export_name = "cxxbridge1$string$clone"]
unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
let this = this.as_mut_ptr();
let clone = other.clone();
unsafe { ptr::write(this, clone) }
}
#[export_name = "cxxbridge1$string$from_utf8"]
unsafe extern "C" fn string_from_utf8(
this: &mut MaybeUninit<String>,
ptr: *const u8,
len: usize,
) -> bool {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
match str::from_utf8(slice) {
Ok(s) => {
let this = this.as_mut_ptr();
let owned = s.to_owned();
unsafe { ptr::write(this, owned) }
true
}
Err(_) => false,
}
}
#[export_name = "cxxbridge1$string$from_utf8_lossy"]
unsafe extern "C" fn string_from_utf8_lossy(
this: &mut MaybeUninit<String>,
ptr: *const u8,
len: usize,
) {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
let owned = String::from_utf8_lossy(slice).into_owned();
let this = this.as_mut_ptr();
unsafe { ptr::write(this, owned) }
}
#[export_name = "cxxbridge1$string$from_utf16"]
unsafe extern "C" fn string_from_utf16(
this: &mut MaybeUninit<String>,
ptr: *const u16,
len: usize,
) -> bool {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
match String::from_utf16(slice) {
Ok(s) => {
let this = this.as_mut_ptr();
unsafe { ptr::write(this, s) }
true
}
Err(_) => false,
}
}
#[export_name = "cxxbridge1$string$from_utf16_lossy"]
unsafe extern "C" fn string_from_utf16_lossy(
this: &mut MaybeUninit<String>,
ptr: *const u16,
len: usize,
) {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
let owned = String::from_utf16_lossy(slice);
let this = this.as_mut_ptr();
unsafe { ptr::write(this, owned) }
}
#[export_name = "cxxbridge1$string$drop"]
unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
unsafe { ManuallyDrop::drop(this) }
}
#[export_name = "cxxbridge1$string$ptr"]
unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
this.as_ptr()
}
#[export_name = "cxxbridge1$string$len"]
unsafe extern "C" fn string_len(this: &String) -> usize {
this.len()
}
#[export_name = "cxxbridge1$string$capacity"]
unsafe extern "C" fn string_capacity(this: &String) -> usize {
this.capacity()
}
#[export_name = "cxxbridge1$string$reserve_additional"]
unsafe extern "C" fn string_reserve_additional(this: &mut String, additional: usize) {
this.reserve(additional);
}
#[export_name = "cxxbridge1$string$reserve_total"]
unsafe extern "C" fn string_reserve_total(this: &mut String, new_cap: usize) {
if new_cap > this.capacity() {
let additional = new_cap - this.len();
this.reserve(additional);
}
}

91
vendor/cxx/src/symbols/rust_vec.rs vendored Normal file
View file

@ -0,0 +1,91 @@
#![cfg(feature = "alloc")]
use crate::c_char::c_char;
use crate::rust_string::RustString;
use crate::rust_vec::RustVec;
use alloc::vec::Vec;
use core::mem;
use core::ptr;
macro_rules! rust_vec_shims {
($segment:expr, $ty:ty) => {
const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<RustVec<$ty>>());
const_assert_eq!(mem::size_of::<Vec<$ty>>(), mem::size_of::<RustVec<$ty>>());
const_assert_eq!(mem::align_of::<Vec<$ty>>(), mem::align_of::<RustVec<$ty>>());
const _: () = {
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$new")]
unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
unsafe { ptr::write(this, RustVec::new()) }
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$drop")]
unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
unsafe { ptr::drop_in_place(this) }
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$len")]
unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
unsafe { &*this }.len()
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity")]
unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize {
unsafe { &*this }.capacity()
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")]
unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
unsafe { &*this }.as_ptr()
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$reserve_total")]
unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, new_cap: usize) {
unsafe { &mut *this }.reserve_total(new_cap);
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$set_len")]
unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) {
unsafe { (*this).set_len(len) }
}
}
attr! {
#[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$truncate")]
unsafe extern "C" fn __truncate(this: *mut RustVec<$ty>, len: usize) {
unsafe { (*this).truncate(len) }
}
}
};
};
}
macro_rules! rust_vec_shims_for_primitive {
($ty:ident) => {
rust_vec_shims!(stringify!($ty), $ty);
};
}
rust_vec_shims_for_primitive!(bool);
rust_vec_shims_for_primitive!(u8);
rust_vec_shims_for_primitive!(u16);
rust_vec_shims_for_primitive!(u32);
rust_vec_shims_for_primitive!(u64);
rust_vec_shims_for_primitive!(usize);
rust_vec_shims_for_primitive!(i8);
rust_vec_shims_for_primitive!(i16);
rust_vec_shims_for_primitive!(i32);
rust_vec_shims_for_primitive!(i64);
rust_vec_shims_for_primitive!(isize);
rust_vec_shims_for_primitive!(f32);
rust_vec_shims_for_primitive!(f64);
rust_vec_shims!("char", c_char);
rust_vec_shims!("string", RustString);
rust_vec_shims!("str", &str);

9
vendor/cxx/src/type_id.rs vendored Normal file
View file

@ -0,0 +1,9 @@
/// For use in impls of the `ExternType` trait. See [`ExternType`].
///
/// [`ExternType`]: trait.ExternType.html
#[macro_export]
macro_rules! type_id {
($($path:tt)*) => {
$crate::private::type_id! { $crate $($path)* }
};
}

296
vendor/cxx/src/unique_ptr.rs vendored Normal file
View file

@ -0,0 +1,296 @@
use crate::cxx_vector::{CxxVector, VectorElement};
use crate::fmt::display;
use crate::kind::Trivial;
use crate::string::CxxString;
use crate::ExternType;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::marker::PhantomData;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
T: UniquePtrTarget,
{
repr: MaybeUninit<*mut c_void>,
ty: PhantomData<T>,
}
impl<T> UniquePtr<T>
where
T: UniquePtrTarget,
{
/// Makes a new UniquePtr wrapping a null pointer.
///
/// Matches the behavior of default-constructing a std::unique\_ptr.
pub fn null() -> Self {
UniquePtr {
repr: T::__null(),
ty: PhantomData,
}
}
/// Allocates memory on the heap and makes a UniquePtr pointing to it.
pub fn new(value: T) -> Self
where
T: ExternType<Kind = Trivial>,
{
UniquePtr {
repr: T::__new(value),
ty: PhantomData,
}
}
/// Checks whether the UniquePtr does not own an object.
///
/// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
pub fn is_null(&self) -> bool {
let ptr = unsafe { T::__get(self.repr) };
ptr.is_null()
}
/// Returns a reference to the object owned by this UniquePtr if any,
/// otherwise None.
pub fn as_ref(&self) -> Option<&T> {
unsafe { T::__get(self.repr).as_ref() }
}
/// Returns a mutable pinned reference to the object owned by this UniquePtr
/// if any, otherwise None.
pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
unsafe {
let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
Some(Pin::new_unchecked(mut_reference))
}
}
/// Returns a mutable pinned reference to the object owned by this
/// UniquePtr.
///
/// # Panics
///
/// Panics if the UniquePtr holds a null pointer.
pub fn pin_mut(&mut self) -> Pin<&mut T> {
match self.as_mut() {
Some(target) => target,
None => panic!(
"called pin_mut on a null UniquePtr<{}>",
display(T::__typename),
),
}
}
/// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
///
/// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
pub fn into_raw(self) -> *mut T {
let ptr = unsafe { T::__release(self.repr) };
mem::forget(self);
ptr
}
/// Constructs a UniquePtr retaking ownership of a pointer previously
/// obtained from `into_raw`.
///
/// # Safety
///
/// This function is unsafe because improper use may lead to memory
/// problems. For example a double-free may occur if the function is called
/// twice on the same raw pointer.
pub unsafe fn from_raw(raw: *mut T) -> Self {
UniquePtr {
repr: unsafe { T::__raw(raw) },
ty: PhantomData,
}
}
}
unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
// UniquePtr is not a self-referential type and is safe to move out of a Pin,
// regardless whether the pointer's target is Unpin.
impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}
impl<T> Drop for UniquePtr<T>
where
T: UniquePtrTarget,
{
fn drop(&mut self) {
unsafe { T::__drop(self.repr) }
}
}
impl<T> Deref for UniquePtr<T>
where
T: UniquePtrTarget,
{
type Target = T;
fn deref(&self) -> &Self::Target {
match self.as_ref() {
Some(target) => target,
None => panic!(
"called deref on a null UniquePtr<{}>",
display(T::__typename),
),
}
}
}
impl<T> DerefMut for UniquePtr<T>
where
T: UniquePtrTarget + Unpin,
{
fn deref_mut(&mut self) -> &mut Self::Target {
match self.as_mut() {
Some(target) => Pin::into_inner(target),
None => panic!(
"called deref_mut on a null UniquePtr<{}>",
display(T::__typename),
),
}
}
}
impl<T> Debug for UniquePtr<T>
where
T: Debug + UniquePtrTarget,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.as_ref() {
None => formatter.write_str("nullptr"),
Some(value) => Debug::fmt(value, formatter),
}
}
}
impl<T> Display for UniquePtr<T>
where
T: Display + UniquePtrTarget,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.as_ref() {
None => formatter.write_str("nullptr"),
Some(value) => Display::fmt(value, formatter),
}
}
}
/// Trait bound for types which may be used as the `T` inside of a
/// `UniquePtr<T>` in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
///
/// # Example
///
/// A bound `T: UniquePtrTarget` may be necessary when manipulating
/// [`UniquePtr`] in generic code.
///
/// ```
/// use cxx::memory::{UniquePtr, UniquePtrTarget};
/// use std::fmt::Display;
///
/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
/// where
/// T: UniquePtrTarget + Display,
/// {
/// println!("the unique_ptr points to: {}", *ptr);
/// }
/// ```
///
/// Writing the same generic function without a `UniquePtrTarget` trait bound
/// would not compile.
pub unsafe trait UniquePtrTarget {
#[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
#[doc(hidden)]
fn __null() -> MaybeUninit<*mut c_void>;
#[doc(hidden)]
fn __new(value: Self) -> MaybeUninit<*mut c_void>
where
Self: Sized,
{
// Opaque C types do not get this method because they can never exist by
// value on the Rust side of the bridge.
let _ = value;
unreachable!()
}
#[doc(hidden)]
unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
#[doc(hidden)]
unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
#[doc(hidden)]
unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
#[doc(hidden)]
unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
}
extern "C" {
#[link_name = "cxxbridge1$unique_ptr$std$string$null"]
fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
#[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString);
#[link_name = "cxxbridge1$unique_ptr$std$string$get"]
fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
#[link_name = "cxxbridge1$unique_ptr$std$string$release"]
fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
#[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
}
unsafe impl UniquePtrTarget for CxxString {
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("CxxString")
}
fn __null() -> MaybeUninit<*mut c_void> {
let mut repr = MaybeUninit::uninit();
unsafe {
unique_ptr_std_string_null(&mut repr);
}
repr
}
unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
let mut repr = MaybeUninit::uninit();
unsafe { unique_ptr_std_string_raw(&mut repr, raw) }
repr
}
unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
unsafe { unique_ptr_std_string_get(&repr) }
}
unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
unsafe { unique_ptr_std_string_release(&mut repr) }
}
unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
unsafe { unique_ptr_std_string_drop(&mut repr) }
}
}
unsafe impl<T> UniquePtrTarget for CxxVector<T>
where
T: VectorElement,
{
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CxxVector<{}>", display(T::__typename))
}
fn __null() -> MaybeUninit<*mut c_void> {
T::__unique_ptr_null()
}
unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
unsafe { T::__unique_ptr_raw(raw) }
}
unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
unsafe { T::__unique_ptr_get(repr) }
}
unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
unsafe { T::__unique_ptr_release(repr) }
}
unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
unsafe { T::__unique_ptr_drop(repr) }
}
}

39
vendor/cxx/src/unwind.rs vendored Normal file
View file

@ -0,0 +1,39 @@
#![allow(missing_docs)]
use core::mem;
pub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R
where
F: FnOnce() -> R,
{
// Goal is to make it impossible to propagate a panic across the C interface
// of an extern "Rust" function, which would be Undefined Behavior. We
// transform such panicks into a deterministic abort instead. When cxx is
// built in an application using panic=abort, this guard object is compiled
// out because its destructor is statically unreachable. When built with
// panic=unwind, an unwind from the foreign call will attempt to drop the
// guard object leading to a double panic, which is defined by Rust to
// abort. In no_std programs, on most platforms the current mechanism for
// this is for core::intrinsics::abort to invoke an invalid instruction. On
// Unix, the process will probably terminate with a signal like SIGABRT,
// SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise behaviour is not
// guaranteed and not stable, but is safe.
let guard = Guard { label };
let ret = foreign_call();
// If we made it here, no uncaught panic occurred during the foreign call.
mem::forget(guard);
ret
}
struct Guard {
label: &'static str,
}
impl Drop for Guard {
#[cold]
fn drop(&mut self) {
panic!("panic in ffi function {}, aborting.", self.label);
}
}

9
vendor/cxx/src/vector.rs vendored Normal file
View file

@ -0,0 +1,9 @@
//! Less used details of `CxxVector`.
//!
//! `CxxVector` itself is exposed at the crate root.
pub use crate::cxx_vector::{Iter, IterMut, VectorElement};
#[doc(inline)]
pub use crate::Vector;
#[doc(no_inline)]
pub use cxx::CxxVector;

189
vendor/cxx/src/weak_ptr.rs vendored Normal file
View file

@ -0,0 +1,189 @@
use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
use crate::string::CxxString;
use core::ffi::c_void;
use core::fmt::{self, Debug};
use core::marker::PhantomData;
use core::mem::MaybeUninit;
/// Binding to C++ `std::weak_ptr<T>`.
///
/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a
/// SharedPtr.
///
/// [downgrading]: crate::SharedPtr::downgrade
#[repr(C)]
pub struct WeakPtr<T>
where
T: WeakPtrTarget,
{
repr: [MaybeUninit<*mut c_void>; 2],
ty: PhantomData<T>,
}
impl<T> WeakPtr<T>
where
T: WeakPtrTarget,
{
/// Makes a new WeakPtr wrapping a null pointer.
///
/// Matches the behavior of default-constructing a std::weak\_ptr.
pub fn null() -> Self {
let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
let new = weak_ptr.as_mut_ptr().cast();
unsafe {
T::__null(new);
weak_ptr.assume_init()
}
}
/// Upgrades a non-owning reference into an owning reference if possible,
/// otherwise to a null reference.
///
/// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock).
pub fn upgrade(&self) -> SharedPtr<T>
where
T: SharedPtrTarget,
{
let this = self as *const Self as *const c_void;
let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
let new = shared_ptr.as_mut_ptr().cast();
unsafe {
T::__upgrade(this, new);
shared_ptr.assume_init()
}
}
}
unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
impl<T> Clone for WeakPtr<T>
where
T: WeakPtrTarget,
{
fn clone(&self) -> Self {
let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
let new = weak_ptr.as_mut_ptr().cast();
let this = self as *const Self as *mut c_void;
unsafe {
T::__clone(this, new);
weak_ptr.assume_init()
}
}
}
impl<T> Drop for WeakPtr<T>
where
T: WeakPtrTarget,
{
fn drop(&mut self) {
let this = self as *mut Self as *mut c_void;
unsafe { T::__drop(this) }
}
}
impl<T> Debug for WeakPtr<T>
where
T: Debug + WeakPtrTarget + SharedPtrTarget,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.upgrade(), formatter)
}
}
/// Trait bound for types which may be used as the `T` inside of a `WeakPtr<T>`
/// in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
pub unsafe trait WeakPtrTarget {
#[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
#[doc(hidden)]
unsafe fn __null(new: *mut c_void);
#[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void);
#[doc(hidden)]
unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
#[doc(hidden)]
unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
#[doc(hidden)]
unsafe fn __drop(this: *mut c_void);
}
macro_rules! impl_weak_ptr_target {
($segment:expr, $name:expr, $ty:ty) => {
unsafe impl WeakPtrTarget for $ty {
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
unsafe fn __null(new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
fn __null(new: *mut c_void);
}
}
unsafe { __null(new) }
}
unsafe fn __clone(this: *const c_void, new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
fn __clone(this: *const c_void, new: *mut c_void);
}
}
unsafe { __clone(this, new) }
}
unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
fn __downgrade(shared: *const c_void, weak: *mut c_void);
}
}
unsafe { __downgrade(shared, weak) }
}
unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")]
fn __upgrade(weak: *const c_void, shared: *mut c_void);
}
}
unsafe { __upgrade(weak, shared) }
}
unsafe fn __drop(this: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
fn __drop(this: *mut c_void);
}
}
unsafe { __drop(this) }
}
}
};
}
macro_rules! impl_weak_ptr_target_for_primitive {
($ty:ident) => {
impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
};
}
impl_weak_ptr_target_for_primitive!(bool);
impl_weak_ptr_target_for_primitive!(u8);
impl_weak_ptr_target_for_primitive!(u16);
impl_weak_ptr_target_for_primitive!(u32);
impl_weak_ptr_target_for_primitive!(u64);
impl_weak_ptr_target_for_primitive!(usize);
impl_weak_ptr_target_for_primitive!(i8);
impl_weak_ptr_target_for_primitive!(i16);
impl_weak_ptr_target_for_primitive!(i32);
impl_weak_ptr_target_for_primitive!(i64);
impl_weak_ptr_target_for_primitive!(isize);
impl_weak_ptr_target_for_primitive!(f32);
impl_weak_ptr_target_for_primitive!(f64);
impl_weak_ptr_target!("string", "CxxString", CxxString);

57
vendor/cxx/tests/BUCK vendored Normal file
View file

@ -0,0 +1,57 @@
load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
rust_test(
name = "test",
srcs = ["test.rs"],
edition = "2018",
deps = [
":ffi",
"//:cxx",
],
)
rust_library(
name = "ffi",
srcs = [
"ffi/cast.rs",
"ffi/lib.rs",
"ffi/module.rs",
],
crate = "cxx_test_suite",
edition = "2018",
deps = [
":impl",
"//:cxx",
],
)
cxx_library(
name = "impl",
srcs = [
"ffi/tests.cc",
":bridge/source",
":module/source",
],
exported_deps = ["//:core"],
exported_headers = {
"ffi/lib.rs.h": ":bridge/header",
"ffi/module.rs.h": ":module/header",
"ffi/tests.h": "ffi/tests.h",
},
)
rust_cxx_bridge(
name = "bridge",
src = "ffi/lib.rs",
deps = [
":impl",
],
)
rust_cxx_bridge(
name = "module",
src = "ffi/module.rs",
deps = [
":impl",
],
)

55
vendor/cxx/tests/BUILD vendored Normal file
View file

@ -0,0 +1,55 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
rust_test(
name = "test",
size = "small",
srcs = ["test.rs"],
edition = "2018",
deps = [
":cxx_test_suite",
"//:cxx",
],
)
rust_library(
name = "cxx_test_suite",
srcs = [
"ffi/cast.rs",
"ffi/lib.rs",
"ffi/module.rs",
],
edition = "2018",
deps = [
":impl",
"//:cxx",
],
)
cc_library(
name = "impl",
srcs = [
"ffi/tests.cc",
":bridge/source",
":module/source",
],
hdrs = ["ffi/tests.h"],
deps = [
":bridge/include",
":module/include",
"//:core",
],
)
rust_cxx_bridge(
name = "bridge",
src = "ffi/lib.rs",
deps = [":impl"],
)
rust_cxx_bridge(
name = "module",
src = "ffi/module.rs",
deps = [":impl"],
)

9
vendor/cxx/tests/compiletest.rs vendored Normal file
View file

@ -0,0 +1,9 @@
#[allow(unused_attributes)]
#[rustversion::attr(not(nightly), ignore)]
#[cfg_attr(skip_ui_tests, ignore)]
#[cfg_attr(miri, ignore)]
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}

34
vendor/cxx/tests/cxx_gen.rs vendored Normal file
View file

@ -0,0 +1,34 @@
#![allow(clippy::field_reassign_with_default)]
use cxx_gen::{generate_header_and_cc, Opt};
use std::str;
const BRIDGE0: &str = r#"
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
pub fn do_cpp_thing(foo: &str);
}
}
"#;
#[test]
fn test_extern_c_function() {
let opt = Opt::default();
let source = BRIDGE0.parse().unwrap();
let generated = generate_header_and_cc(source, &opt).unwrap();
let output = str::from_utf8(&generated.implementation).unwrap();
// To avoid continual breakage we won't test every byte.
// Let's look for the major features.
assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
}
#[test]
fn test_impl_annotation() {
let mut opt = Opt::default();
opt.cxx_impl_annotations = Some("ANNOTATION".to_owned());
let source = BRIDGE0.parse().unwrap();
let generated = generate_header_and_cc(source, &opt).unwrap();
let output = str::from_utf8(&generated.implementation).unwrap();
assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
}

15
vendor/cxx/tests/cxx_string.rs vendored Normal file
View file

@ -0,0 +1,15 @@
use cxx::{let_cxx_string, CxxString};
#[test]
fn test_async_cxx_string() {
async fn f() {
let_cxx_string!(s = "...");
async fn g(_: &CxxString) {}
g(&s).await;
}
// https://github.com/dtolnay/cxx/issues/693
fn assert_send(_: impl Send) {}
assert_send(f());
}

380
vendor/cxx/tests/test.rs vendored Normal file
View file

@ -0,0 +1,380 @@
#![allow(
clippy::assertions_on_constants,
clippy::assertions_on_result_states,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::float_cmp,
clippy::needless_pass_by_value,
clippy::unit_cmp,
clippy::unseparated_literal_suffix
)]
use cxx::SharedPtr;
use cxx_test_suite::module::ffi2;
use cxx_test_suite::{cast, ffi, R};
use std::cell::Cell;
use std::ffi::CStr;
thread_local! {
static CORRECT: Cell<bool> = Cell::new(false);
}
#[no_mangle]
extern "C" fn cxx_test_suite_set_correct() {
CORRECT.with(|correct| correct.set(true));
}
macro_rules! check {
($run:expr) => {{
CORRECT.with(|correct| correct.set(false));
$run;
assert!(CORRECT.with(Cell::get), "{}", stringify!($run));
}};
}
#[test]
fn test_c_return() {
let shared = ffi::Shared { z: 2020 };
let ns_shared = ffi::AShared { z: 2020 };
let nested_ns_shared = ffi::ABShared { z: 2020 };
assert_eq!(2020, ffi::c_return_primitive());
assert_eq!(2020, ffi::c_return_shared().z);
assert_eq!(2020, ffi::c_return_box().0);
ffi::c_return_unique_ptr();
ffi2::c_return_ns_unique_ptr();
assert_eq!(2020, *ffi::c_return_ref(&shared));
assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
assert_eq!("2020", ffi::c_return_str(&shared));
assert_eq!(
b"2020\0",
cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)),
);
assert_eq!("2020", ffi::c_return_rust_string());
assert_eq!("Hello \u{fffd}World", ffi::c_return_rust_string_lossy());
assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len());
assert_eq!(
200_u8,
ffi::c_return_unique_ptr_vector_u8().into_iter().sum(),
);
assert_eq!(
200.5_f64,
ffi::c_return_unique_ptr_vector_f64().into_iter().sum(),
);
assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len());
assert_eq!(
2021_usize,
ffi::c_return_unique_ptr_vector_shared()
.into_iter()
.map(|o| o.z)
.sum(),
);
assert_eq!(b"\x02\0\x02\0"[..], ffi::c_return_rust_vec_u8());
assert_eq!([true, true, false][..], ffi::c_return_rust_vec_bool());
assert_eq!(2020, ffi::c_return_identity(2020));
assert_eq!(2021, ffi::c_return_sum(2020, 1));
match ffi::c_return_enum(0) {
enm @ ffi::Enum::AVal => assert_eq!(0, enm.repr),
_ => assert!(false),
}
match ffi::c_return_enum(1) {
enm @ ffi::Enum::BVal => assert_eq!(2020, enm.repr),
_ => assert!(false),
}
match ffi::c_return_enum(2021) {
enm @ ffi::Enum::LastVal => assert_eq!(2021, enm.repr),
_ => assert!(false),
}
match ffi::c_return_ns_enum(0) {
enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr),
_ => assert!(false),
}
match ffi::c_return_nested_ns_enum(0) {
enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr),
_ => assert!(false),
}
}
#[test]
fn test_c_try_return() {
assert_eq!((), ffi::c_try_return_void().unwrap());
assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
assert_eq!(
"logic error",
ffi::c_fail_return_primitive().unwrap_err().what(),
);
assert_eq!(2020, ffi::c_try_return_box().unwrap().0);
assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap());
}
#[test]
fn test_c_take() {
let unique_ptr = ffi::c_return_unique_ptr();
let unique_ptr_ns = ffi2::c_return_ns_unique_ptr();
check!(ffi::c_take_primitive(2020));
check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 }));
check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 }));
check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
check!(ffi::c_take_box(Box::new(R(2020))));
check!(ffi::c_take_ref_c(&unique_ptr));
check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
check!(ffi::c_take_str("2020"));
check!(ffi::c_take_slice_char(cast::unsigned_to_c_char(b"2020")));
check!(ffi::c_take_slice_shared(&[
ffi::Shared { z: 2020 },
ffi::Shared { z: 2021 },
]));
let shared_sort_slice = &mut [
ffi::Shared { z: 2 },
ffi::Shared { z: 0 },
ffi::Shared { z: 7 },
ffi::Shared { z: 4 },
];
check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
assert_eq!(shared_sort_slice[0].z, 0);
assert_eq!(shared_sort_slice[1].z, 2);
assert_eq!(shared_sort_slice[2].z, 4);
assert_eq!(shared_sort_slice[3].z, 7);
let r_sort_slice = &mut [R(2020), R(2050), R(2021)];
check!(ffi::c_take_slice_r(r_sort_slice));
check!(ffi::c_take_slice_r_sort(r_sort_slice));
assert_eq!(r_sort_slice[0].0, 2020);
assert_eq!(r_sort_slice[1].0, 2021);
assert_eq!(r_sort_slice[2].0, 2050);
check!(ffi::c_take_rust_string("2020".to_owned()));
check!(ffi::c_take_unique_ptr_string(
ffi::c_return_unique_ptr_string()
));
let mut vector = ffi::c_return_unique_ptr_vector_u8();
assert_eq!(vector.pin_mut().pop(), Some(9));
check!(ffi::c_take_unique_ptr_vector_u8(vector));
let mut vector = ffi::c_return_unique_ptr_vector_f64();
vector.pin_mut().push(9.0);
check!(ffi::c_take_unique_ptr_vector_f64(vector));
let mut vector = ffi::c_return_unique_ptr_vector_shared();
vector.pin_mut().push(ffi::Shared { z: 9 });
check!(ffi::c_take_unique_ptr_vector_shared(vector));
check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
check!(ffi::c_take_rust_vec(test_vec.clone()));
check!(ffi::c_take_rust_vec_index(test_vec.clone()));
let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }];
check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_truncate(
shared_test_vec.clone()
));
check!(ffi::c_take_rust_vec_shared_clear(shared_test_vec.clone()));
check!(ffi::c_take_rust_vec_shared_forward_iterator(
shared_test_vec,
));
let shared_sort_vec = vec![
ffi::Shared { z: 2 },
ffi::Shared { z: 0 },
ffi::Shared { z: 7 },
ffi::Shared { z: 4 },
];
check!(ffi::c_take_rust_vec_shared_sort(shared_sort_vec));
check!(ffi::c_take_ref_rust_vec(&test_vec));
check!(ffi::c_take_ref_rust_vec_index(&test_vec));
check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
check!(ffi::c_take_ref_shared_string(&ffi::SharedString {
msg: "2020".to_owned()
}));
let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }];
check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec));
let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }];
check!(ffi::c_take_rust_vec_nested_ns_shared(
nested_ns_shared_test_vec
));
check!(ffi::c_take_enum(ffi::Enum::AVal));
check!(ffi::c_take_ns_enum(ffi::AEnum::AAVal));
check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
}
#[test]
fn test_c_callback() {
fn callback(s: String) -> usize {
if s == "2020" {
cxx_test_suite_set_correct();
}
0
}
#[allow(clippy::ptr_arg)]
fn callback_ref(s: &String) {
if s == "2020" {
cxx_test_suite_set_correct();
}
}
fn callback_mut(s: &mut String) {
if s == "2020" {
cxx_test_suite_set_correct();
}
}
check!(ffi::c_take_callback(callback));
check!(ffi::c_take_callback_ref(callback_ref));
check!(ffi::c_take_callback_ref_lifetime(callback_ref));
check!(ffi::c_take_callback_mut(callback_mut));
}
#[test]
fn test_c_call_r() {
fn cxx_run_test() {
extern "C" {
fn cxx_run_test() -> *const i8;
}
let failure = unsafe { cxx_run_test() };
if !failure.is_null() {
let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) };
eprintln!("{}", msg.to_string_lossy());
}
}
check!(cxx_run_test());
}
#[test]
fn test_c_method_calls() {
let mut unique_ptr = ffi::c_return_unique_ptr();
let old_value = unique_ptr.get();
assert_eq!(2020, old_value);
assert_eq!(2021, unique_ptr.pin_mut().set(2021));
assert_eq!(2021, unique_ptr.get());
assert_eq!(2021, unique_ptr.get2());
assert_eq!(2021, *unique_ptr.getRef());
assert_eq!(2021, *unique_ptr.pin_mut().getMut());
assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap());
assert!(unique_ptr.pin_mut().get_fail().is_err());
assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared());
assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared());
let val = 42;
let mut array = ffi::Array {
a: [0, 0, 0, 0],
b: ffi::Buffer::default(),
};
array.c_set_array(val);
assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum());
}
#[test]
fn test_shared_ptr_weak_ptr() {
let shared_ptr = ffi::c_return_shared_ptr();
let weak_ptr = SharedPtr::downgrade(&shared_ptr);
assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
assert!(!weak_ptr.upgrade().is_null());
assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
drop(shared_ptr);
assert_eq!(0, ffi::c_get_use_count(&weak_ptr));
assert!(weak_ptr.upgrade().is_null());
}
#[test]
fn test_c_ns_method_calls() {
let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
let old_value = unique_ptr.get();
assert_eq!(1000, old_value);
}
#[test]
fn test_enum_representations() {
assert_eq!(0, ffi::Enum::AVal.repr);
assert_eq!(2020, ffi::Enum::BVal.repr);
assert_eq!(2021, ffi::Enum::LastVal.repr);
}
#[test]
fn test_debug() {
assert_eq!("Shared { z: 1 }", format!("{:?}", ffi::Shared { z: 1 }));
assert_eq!("BVal", format!("{:?}", ffi::Enum::BVal));
assert_eq!("Enum(9)", format!("{:?}", ffi::Enum { repr: 9 }));
}
#[no_mangle]
extern "C" fn cxx_test_suite_get_box() -> *mut R {
Box::into_raw(Box::new(R(2020usize)))
}
#[no_mangle]
unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool {
(*r).0 == 2020
}
#[test]
fn test_rust_name_attribute() {
assert_eq!("2020", ffi::i32_overloaded_function(2020));
assert_eq!("2020", ffi::str_overloaded_function("2020"));
let unique_ptr = ffi::c_return_unique_ptr();
assert_eq!("2020", unique_ptr.i32_overloaded_method(2020));
assert_eq!("2020", unique_ptr.str_overloaded_method("2020"));
}
#[test]
fn test_extern_trivial() {
let mut d = ffi2::c_return_trivial();
check!(ffi2::c_take_trivial_ref(&d));
check!(d.c_take_trivial_ref_method());
check!(d.c_take_trivial_mut_ref_method());
check!(ffi2::c_take_trivial(d));
let mut d = ffi2::c_return_trivial_ptr();
check!(d.c_take_trivial_ref_method());
check!(d.c_take_trivial_mut_ref_method());
check!(ffi2::c_take_trivial_ptr(d));
cxx::UniquePtr::new(ffi2::D { d: 42 });
let d = ffi2::ns_c_return_trivial();
check!(ffi2::ns_c_take_trivial(d));
let g = ffi2::c_return_trivial_ns();
check!(ffi2::c_take_trivial_ns_ref(&g));
check!(ffi2::c_take_trivial_ns(g));
let g = ffi2::c_return_trivial_ns_ptr();
check!(ffi2::c_take_trivial_ns_ptr(g));
cxx::UniquePtr::new(ffi2::G { g: 42 });
}
#[test]
fn test_extern_opaque() {
let mut e = ffi2::c_return_opaque_ptr();
check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
check!(e.c_take_opaque_ref_method());
check!(e.pin_mut().c_take_opaque_mut_ref_method());
check!(ffi2::c_take_opaque_ptr(e));
let f = ffi2::c_return_ns_opaque_ptr();
check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap()));
check!(ffi2::c_take_opaque_ns_ptr(f));
}
#[test]
fn test_raw_ptr() {
let c = ffi::c_return_mut_ptr(2023);
let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) };
assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap());
// c will be dropped as it's now in a UniquePtr
let c2 = ffi::c_return_mut_ptr(2024);
assert_eq!(2024, unsafe { ffi::c_take_const_ptr(c2) });
assert_eq!(2024, unsafe { ffi::c_take_mut_ptr(c2) }); // deletes c2
let c3 = ffi::c_return_const_ptr(2025);
assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) });
assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3
}

10
vendor/cxx/tests/ui/array_len_expr.rs vendored Normal file
View file

@ -0,0 +1,10 @@
#[cxx::bridge]
mod ffi {
struct Shared {
arraystr: [String; "13"],
arraysub: [String; 15 - 1],
arrayzero: [String; 0],
}
}
fn main() {}

View file

@ -0,0 +1,17 @@
error: array length must be an integer literal
--> tests/ui/array_len_expr.rs:4:28
|
4 | arraystr: [String; "13"],
| ^^^^
error: unsupported expression, array length must be an integer literal
--> tests/ui/array_len_expr.rs:5:28
|
5 | arraysub: [String; 15 - 1],
| ^^^^^^
error: array with zero size is not supported
--> tests/ui/array_len_expr.rs:6:20
|
6 | arrayzero: [String; 0],
| ^^^^^^^^^^^

View file

@ -0,0 +1,8 @@
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
fn array() -> [String; 12u16];
}
}
fn main() {}

View file

@ -0,0 +1,10 @@
error[E0308]: mismatched types
--> tests/ui/array_len_suffix.rs:4:32
|
4 | fn array() -> [String; 12u16];
| ^^^^^ expected `usize`, found `u16`
|
help: change the type of the numeric literal from `u16` to `usize`
|
4 | fn array() -> [String; 12usize];
| ~~~~~

14
vendor/cxx/tests/ui/async_fn.rs vendored Normal file
View file

@ -0,0 +1,14 @@
#[cxx::bridge]
mod ffi {
extern "Rust" {
async fn f();
}
extern "C++" {
async fn g();
}
}
async fn f() {}
fn main() {}

11
vendor/cxx/tests/ui/async_fn.stderr vendored Normal file
View file

@ -0,0 +1,11 @@
error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet
--> tests/ui/async_fn.rs:4:9
|
4 | async fn f();
| ^^^^^^^^^^^^^
error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet
--> tests/ui/async_fn.rs:8:9
|
8 | async fn g();
| ^^^^^^^^^^^^^

Some files were not shown because too many files have changed in this diff Show more