diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/cxx/book/src/binding/cxxstring.md | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/cxx/book/src/binding/cxxstring.md')
-rw-r--r-- | vendor/cxx/book/src/binding/cxxstring.md | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/vendor/cxx/book/src/binding/cxxstring.md b/vendor/cxx/book/src/binding/cxxstring.md new file mode 100644 index 000000000..cfe707f21 --- /dev/null +++ b/vendor/cxx/book/src/binding/cxxstring.md @@ -0,0 +1,140 @@ +{{#title std::string — Rust ♡ C++}} +# std::string + +The Rust binding of std::string is called **[`CxxString`]**. See the link for +documentation of the Rust API. + +[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html + +### Restrictions: + +Rust code can never obtain a CxxString by value. C++'s string requires a move +constructor and may hold internal pointers, which is not compatible with Rust's +move behavior. Instead in Rust code we will only ever look at a CxxString +through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\> +or UniquePtr\<CxxString\>. + +In order to construct a CxxString on the stack from Rust, you must use the +[`let_cxx_string!`] macro which will pin the string properly. The code below +uses this in one place, and the link covers the syntax. + +[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html + +## Example + +This example uses C++17's std::variant to build a toy JSON type. JSON can hold +various types including strings, and JSON's object type is a map with string +keys. The example demonstrates Rust indexing into one of those maps. + +```rust,noplayground +// src/main.rs + +use cxx::let_cxx_string; + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("example/include/json.h"); + + #[cxx_name = "json"] + type Json; + #[cxx_name = "object"] + type Object; + + fn isNull(self: &Json) -> bool; + fn isNumber(self: &Json) -> bool; + fn isString(self: &Json) -> bool; + fn isArray(self: &Json) -> bool; + fn isObject(self: &Json) -> bool; + + fn getNumber(self: &Json) -> f64; + fn getString(self: &Json) -> &CxxString; + fn getArray(self: &Json) -> &CxxVector<Json>; + fn getObject(self: &Json) -> &Object; + + #[cxx_name = "at"] + fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; + + fn load_config() -> UniquePtr<Json>; + } +} + +fn main() { + let config = ffi::load_config(); + + let_cxx_string!(key = "name"); + println!("{}", config.getObject().get(&key).getString()); +} +``` + +```cpp +// include/json.h + +#pragma once +#include <map> +#include <memory> +#include <string> +#include <variant> +#include <vector> + +class json final { +public: + static const json null; + using number = double; + using string = std::string; + using array = std::vector<json>; + using object = std::map<string, json>; + + json() noexcept = default; + json(const json &) = default; + json(json &&) = default; + template <typename... T> + json(T &&...value) : value(std::forward<T>(value)...) {} + + bool isNull() const; + bool isNumber() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + number getNumber() const; + const string &getString() const; + const array &getArray() const; + const object &getObject() const; + +private: + std::variant<std::monostate, number, string, array, object> value; +}; + +using object = json::object; + +std::unique_ptr<json> load_config(); +``` + +```cpp +// include/json.cc + +#include "example/include/json.h" +#include <initializer_list> +#include <utility> + +const json json::null{}; +bool json::isNull() const { return std::holds_alternative<std::monostate>(value); } +bool json::isNumber() const { return std::holds_alternative<number>(value); } +bool json::isString() const { return std::holds_alternative<string>(value); } +bool json::isArray() const { return std::holds_alternative<array>(value); } +bool json::isObject() const { return std::holds_alternative<object>(value); } +json::number json::getNumber() const { return std::get<number>(value); } +const json::string &json::getString() const { return std::get<string>(value); } +const json::array &json::getArray() const { return std::get<array>(value); } +const json::object &json::getObject() const { return std::get<object>(value); } + +std::unique_ptr<json> load_config() { + return std::make_unique<json>( + std::in_place_type<json::object>, + std::initializer_list<std::pair<const std::string, json>>{ + {"name", "cxx-example"}, + {"edition", 2018.}, + {"repository", json::null}}); +} +``` |