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

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>