summaryrefslogtreecommitdiffstats
path: root/vendor/cxx/book/src/binding
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/cxx/book/src/binding
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/cxx/book/src/binding')
-rw-r--r--vendor/cxx/book/src/binding/box.md120
-rw-r--r--vendor/cxx/book/src/binding/cxxstring.md140
-rw-r--r--vendor/cxx/book/src/binding/cxxvector.md62
-rw-r--r--vendor/cxx/book/src/binding/fn.md34
-rw-r--r--vendor/cxx/book/src/binding/rawptr.md100
-rw-r--r--vendor/cxx/book/src/binding/result.md148
-rw-r--r--vendor/cxx/book/src/binding/sharedptr.md80
-rw-r--r--vendor/cxx/book/src/binding/slice.md171
-rw-r--r--vendor/cxx/book/src/binding/str.md118
-rw-r--r--vendor/cxx/book/src/binding/string.md132
-rw-r--r--vendor/cxx/book/src/binding/uniqueptr.md63
-rw-r--r--vendor/cxx/book/src/binding/vec.md192
12 files changed, 1360 insertions, 0 deletions
diff --git a/vendor/cxx/book/src/binding/box.md b/vendor/cxx/book/src/binding/box.md
new file mode 100644
index 000000000..7df195974
--- /dev/null
+++ b/vendor/cxx/book/src/binding/box.md
@@ -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");
+}
+```
diff --git a/vendor/cxx/book/src/binding/cxxstring.md b/vendor/cxx/book/src/binding/cxxstring.md
new file mode 100644
index 000000000..cfe707f21
--- /dev/null
+++ b/vendor/cxx/book/src/binding/cxxstring.md
@@ -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}});
+}
+```
diff --git a/vendor/cxx/book/src/binding/cxxvector.md b/vendor/cxx/book/src/binding/cxxvector.md
new file mode 100644
index 000000000..fd95a2dbd
--- /dev/null
+++ b/vendor/cxx/book/src/binding/cxxvector.md
@@ -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);
+}
+```
diff --git a/vendor/cxx/book/src/binding/fn.md b/vendor/cxx/book/src/binding/fn.md
new file mode 100644
index 000000000..2934b0695
--- /dev/null
+++ b/vendor/cxx/book/src/binding/fn.md
@@ -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.
diff --git a/vendor/cxx/book/src/binding/rawptr.md b/vendor/cxx/book/src/binding/rawptr.md
new file mode 100644
index 000000000..179421127
--- /dev/null
+++ b/vendor/cxx/book/src/binding/rawptr.md
@@ -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.
+}
+```
diff --git a/vendor/cxx/book/src/binding/result.md b/vendor/cxx/book/src/binding/result.md
new file mode 100644
index 000000000..e49dcf4de
--- /dev/null
+++ b/vendor/cxx/book/src/binding/result.md
@@ -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
+```
diff --git a/vendor/cxx/book/src/binding/sharedptr.md b/vendor/cxx/book/src/binding/sharedptr.md
new file mode 100644
index 000000000..a3b707008
--- /dev/null
+++ b/vendor/cxx/book/src/binding/sharedptr.md
@@ -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>();
+}
+```
diff --git a/vendor/cxx/book/src/binding/slice.md b/vendor/cxx/book/src/binding/slice.md
new file mode 100644
index 000000000..803277ba9
--- /dev/null
+++ b/vendor/cxx/book/src/binding/slice.md
@@ -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"
+}
+```
diff --git a/vendor/cxx/book/src/binding/str.md b/vendor/cxx/book/src/binding/str.md
new file mode 100644
index 000000000..9c1e0a773
--- /dev/null
+++ b/vendor/cxx/book/src/binding/str.md
@@ -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++");
+}
+```
diff --git a/vendor/cxx/book/src/binding/string.md b/vendor/cxx/book/src/binding/string.md
new file mode 100644
index 000000000..1e4827812
--- /dev/null
+++ b/vendor/cxx/book/src/binding/string.md
@@ -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);
+}
+```
diff --git a/vendor/cxx/book/src/binding/uniqueptr.md b/vendor/cxx/book/src/binding/uniqueptr.md
new file mode 100644
index 000000000..eefbc34a3
--- /dev/null
+++ b/vendor/cxx/book/src/binding/uniqueptr.md
@@ -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>();
+}
+```
diff --git a/vendor/cxx/book/src/binding/vec.md b/vendor/cxx/book/src/binding/vec.md
new file mode 100644
index 000000000..4d6587ab1
--- /dev/null
+++ b/vendor/cxx/book/src/binding/vec.md
@@ -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());
+}
+```