diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/cxx/book/src/binding | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.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.md | 120 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/cxxstring.md | 140 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/cxxvector.md | 62 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/fn.md | 34 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/rawptr.md | 100 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/result.md | 148 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/sharedptr.md | 80 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/slice.md | 171 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/str.md | 118 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/string.md | 132 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/uniqueptr.md | 63 | ||||
-rw-r--r-- | vendor/cxx/book/src/binding/vec.md | 192 |
12 files changed, 0 insertions, 1360 deletions
diff --git a/vendor/cxx/book/src/binding/box.md b/vendor/cxx/book/src/binding/box.md deleted file mode 100644 index 7df195974..000000000 --- a/vendor/cxx/book/src/binding/box.md +++ /dev/null @@ -1,120 +0,0 @@ -{{#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 deleted file mode 100644 index cfe707f21..000000000 --- a/vendor/cxx/book/src/binding/cxxstring.md +++ /dev/null @@ -1,140 +0,0 @@ -{{#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 deleted file mode 100644 index fd95a2dbd..000000000 --- a/vendor/cxx/book/src/binding/cxxvector.md +++ /dev/null @@ -1,62 +0,0 @@ -{{#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 deleted file mode 100644 index 2934b0695..000000000 --- a/vendor/cxx/book/src/binding/fn.md +++ /dev/null @@ -1,34 +0,0 @@ -{{#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 deleted file mode 100644 index 179421127..000000000 --- a/vendor/cxx/book/src/binding/rawptr.md +++ /dev/null @@ -1,100 +0,0 @@ -{{#title *mut T, *const T — Rust ♡ C++}} -# *mut T, *const T - -Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>] -where possible over raw pointers, but raw pointers are available too as an -unsafe fallback option. - -[std::unique_ptr\<T\>]: uniqueptr.md - -### Restrictions: - -Extern functions and function pointers taking a raw pointer as an argument must -be declared `unsafe fn` i.e. unsafe to call. The same does not apply to -functions which only *return* a raw pointer, though presumably doing anything -useful with the returned pointer is going to involve unsafe code elsewhere -anyway. - -## Example - -This example illustrates making a Rust call to a canonical C-style `main` -signature involving `char *argv[]`. - -```cpp -// include/args.h - -#pragma once - -void parseArgs(int argc, char *argv[]); -``` - -```cpp -// src/args.cc - -#include "example/include/args.h" -#include <iostream> - -void parseArgs(int argc, char *argv[]) { - std::cout << argc << std::endl; - for (int i = 0; i < argc; i++) { - std::cout << '"' << argv[i] << '"' << std::endl; - } -} -``` - -```rust,noplayground -// src/main.rs - -use std::env; -use std::ffi::CString; -use std::os::raw::c_char; -use std::os::unix::ffi::OsStrExt; -use std::ptr; - -#[cxx::bridge] -mod ffi { - extern "C++" { - include!("example/include/args.h"); - - unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char); - } -} - -fn main() { - // Convert from OsString to nul-terminated CString, truncating each argument - // at the first inner nul byte if present. - let args: Vec<CString> = env::args_os() - .map(|os_str| { - let bytes = os_str.as_bytes(); - CString::new(bytes).unwrap_or_else(|nul_error| { - let nul_position = nul_error.nul_position(); - let mut bytes = nul_error.into_vec(); - bytes.truncate(nul_position); - CString::new(bytes).unwrap() - }) - }) - .collect(); - - // Convert from Vec<CString> of owned strings to Vec<*mut c_char> of - // borrowed string pointers. - // - // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467) - // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258 - // is implemented, and CStr pointers become thin, we can sidestep this step - // by accumulating the args as Vec<Box<CStr>> up front, then simply casting - // from *mut [Box<CStr>] to *mut [*mut CStr] to *mut *mut c_char. - let argc = args.len(); - let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1); - for arg in &args { - argv.push(arg.as_ptr() as *mut c_char); - } - argv.push(ptr::null_mut()); // Nul terminator. - - unsafe { - ffi::parseArgs(argc as i32, argv.as_mut_ptr()); - } - - // The CStrings go out of scope here. C function must not have held on to - // the pointers beyond this point. -} -``` diff --git a/vendor/cxx/book/src/binding/result.md b/vendor/cxx/book/src/binding/result.md deleted file mode 100644 index e49dcf4de..000000000 --- a/vendor/cxx/book/src/binding/result.md +++ /dev/null @@ -1,148 +0,0 @@ -{{#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 deleted file mode 100644 index a3b707008..000000000 --- a/vendor/cxx/book/src/binding/sharedptr.md +++ /dev/null @@ -1,80 +0,0 @@ -{{#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 deleted file mode 100644 index 803277ba9..000000000 --- a/vendor/cxx/book/src/binding/slice.md +++ /dev/null @@ -1,171 +0,0 @@ -{{#title rust::Slice<T> — Rust ♡ C++}} -# rust::Slice\<const T\>, rust::Slice\<T\> - -- Rust `&[T]` is written `rust::Slice<const T>` in C++ -- Rust `&mut [T]` is written `rust::Slice<T>` in C++ - -### Public API: - -```cpp,hidelines -// rust/cxx.h -# -# #include <iterator> -# #include <type_traits> -# -# namespace rust { - -template <typename T> -class Slice final { -public: - using value_type = T; - - Slice() noexcept; - Slice(const Slice<T> &) noexcept; - Slice(T *, size_t count) noexcept; - - 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 &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 deleted file mode 100644 index 9c1e0a773..000000000 --- a/vendor/cxx/book/src/binding/str.md +++ /dev/null @@ -1,118 +0,0 @@ -{{#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 &str i.e. it is a borrow!** C++ -needs to be mindful of the lifetimes at play. - -Just to reiterate: &str is rust::Str. Do not try to write &str as `const -rust::Str &`. A language-level C++ reference is not able to capture the fat -pointer nature of &str. - -### Restrictions: - -Allowed as function argument or return value. Not supported in shared structs -yet. `&mut str` is not supported yet, but is also extremely obscure so this is -fine. - -## Example - -```rust,noplayground -// src/main.rs - -#[cxx::bridge] -mod ffi { - extern "Rust" { - fn r(greeting: &str); - } - - unsafe extern "C++" { - include!("example/include/greeting.h"); - fn c(greeting: &str); - } -} - -fn r(greeting: &str) { - println!("{}", greeting); -} - -fn main() { - ffi::c("hello from Rust"); -} -``` - -```cpp -// include/greeting.h - -#pragma once -#include "example/src/main.rs.h" -#include "rust/cxx.h" - -void c(rust::Str greeting); -``` - -```cpp -// src/greeting.cc - -#include "example/include/greeting.h" -#include <iostream> - -void c(rust::Str greeting) { - std::cout << greeting << std::endl; - r("hello from C++"); -} -``` diff --git a/vendor/cxx/book/src/binding/string.md b/vendor/cxx/book/src/binding/string.md deleted file mode 100644 index 1e4827812..000000000 --- a/vendor/cxx/book/src/binding/string.md +++ /dev/null @@ -1,132 +0,0 @@ -{{#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 deleted file mode 100644 index eefbc34a3..000000000 --- a/vendor/cxx/book/src/binding/uniqueptr.md +++ /dev/null @@ -1,63 +0,0 @@ -{{#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 deleted file mode 100644 index 4d6587ab1..000000000 --- a/vendor/cxx/book/src/binding/vec.md +++ /dev/null @@ -1,192 +0,0 @@ -{{#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()); -} -``` |