133d722a9Sopenharmony_ci{{#title rust::Slice<T> — Rust ♡ C++}} 233d722a9Sopenharmony_ci# rust::Slice\<const T\>, rust::Slice\<T\> 333d722a9Sopenharmony_ci 433d722a9Sopenharmony_ci- Rust `&[T]` is written `rust::Slice<const T>` in C++ 533d722a9Sopenharmony_ci- Rust `&mut [T]` is written `rust::Slice<T>` in C++ 633d722a9Sopenharmony_ci 733d722a9Sopenharmony_ci### Public API: 833d722a9Sopenharmony_ci 933d722a9Sopenharmony_ci```cpp,hidelines 1033d722a9Sopenharmony_ci// rust/cxx.h 1133d722a9Sopenharmony_ci# 1233d722a9Sopenharmony_ci# #include <iterator> 1333d722a9Sopenharmony_ci# #include <type_traits> 1433d722a9Sopenharmony_ci# 1533d722a9Sopenharmony_ci# namespace rust { 1633d722a9Sopenharmony_ci 1733d722a9Sopenharmony_citemplate <typename T> 1833d722a9Sopenharmony_ciclass Slice final { 1933d722a9Sopenharmony_cipublic: 2033d722a9Sopenharmony_ci using value_type = T; 2133d722a9Sopenharmony_ci 2233d722a9Sopenharmony_ci Slice() noexcept; 2333d722a9Sopenharmony_ci Slice(const Slice<T> &) noexcept; 2433d722a9Sopenharmony_ci Slice(T *, size_t count) noexcept; 2533d722a9Sopenharmony_ci 2633d722a9Sopenharmony_ci Slice &operator=(Slice<T> &&) noexcept; 2733d722a9Sopenharmony_ci Slice &operator=(const Slice<T> &) noexcept 2833d722a9Sopenharmony_ci requires std::is_const_v<T>; 2933d722a9Sopenharmony_ci 3033d722a9Sopenharmony_ci T *data() const noexcept; 3133d722a9Sopenharmony_ci size_t size() const noexcept; 3233d722a9Sopenharmony_ci size_t length() const noexcept; 3333d722a9Sopenharmony_ci bool empty() const noexcept; 3433d722a9Sopenharmony_ci 3533d722a9Sopenharmony_ci T &operator[](size_t n) const noexcept; 3633d722a9Sopenharmony_ci T &at(size_t n) const; 3733d722a9Sopenharmony_ci T &front() const noexcept; 3833d722a9Sopenharmony_ci T &back() const noexcept; 3933d722a9Sopenharmony_ci 4033d722a9Sopenharmony_ci class iterator; 4133d722a9Sopenharmony_ci iterator begin() const noexcept; 4233d722a9Sopenharmony_ci iterator end() const noexcept; 4333d722a9Sopenharmony_ci 4433d722a9Sopenharmony_ci void swap(Slice &) noexcept; 4533d722a9Sopenharmony_ci}; 4633d722a9Sopenharmony_ci# 4733d722a9Sopenharmony_ci# template <typename T> 4833d722a9Sopenharmony_ci# class Slice<T>::iterator final { 4933d722a9Sopenharmony_ci# public: 5033d722a9Sopenharmony_ci# using iterator_category = std::random_access_iterator_tag; 5133d722a9Sopenharmony_ci# using value_type = T; 5233d722a9Sopenharmony_ci# using pointer = T *; 5333d722a9Sopenharmony_ci# using reference = T &; 5433d722a9Sopenharmony_ci# 5533d722a9Sopenharmony_ci# T &operator*() const noexcept; 5633d722a9Sopenharmony_ci# T *operator->() const noexcept; 5733d722a9Sopenharmony_ci# T &operator[](ptrdiff_t) const noexcept; 5833d722a9Sopenharmony_ci# 5933d722a9Sopenharmony_ci# iterator &operator++() noexcept; 6033d722a9Sopenharmony_ci# iterator operator++(int) noexcept; 6133d722a9Sopenharmony_ci# iterator &operator--() noexcept; 6233d722a9Sopenharmony_ci# iterator operator--(int) noexcept; 6333d722a9Sopenharmony_ci# 6433d722a9Sopenharmony_ci# iterator &operator+=(ptrdiff_t) noexcept; 6533d722a9Sopenharmony_ci# iterator &operator-=(ptrdiff_t) noexcept; 6633d722a9Sopenharmony_ci# iterator operator+(ptrdiff_t) const noexcept; 6733d722a9Sopenharmony_ci# iterator operator-(ptrdiff_t) const noexcept; 6833d722a9Sopenharmony_ci# ptrdiff_t operator-(const iterator &) const noexcept; 6933d722a9Sopenharmony_ci# 7033d722a9Sopenharmony_ci# bool operator==(const iterator &) const noexcept; 7133d722a9Sopenharmony_ci# bool operator!=(const iterator &) const noexcept; 7233d722a9Sopenharmony_ci# bool operator<(const iterator &) const noexcept; 7333d722a9Sopenharmony_ci# bool operator>(const iterator &) const noexcept; 7433d722a9Sopenharmony_ci# bool operator<=(const iterator &) const noexcept; 7533d722a9Sopenharmony_ci# bool operator>=(const iterator &) const noexcept; 7633d722a9Sopenharmony_ci# }; 7733d722a9Sopenharmony_ci# 7833d722a9Sopenharmony_ci# } // namespace rust 7933d722a9Sopenharmony_ci``` 8033d722a9Sopenharmony_ci 8133d722a9Sopenharmony_ci### Restrictions: 8233d722a9Sopenharmony_ci 8333d722a9Sopenharmony_ciT must not be an opaque Rust type or opaque C++ type. Support for opaque Rust 8433d722a9Sopenharmony_citypes in slices is coming. 8533d722a9Sopenharmony_ci 8633d722a9Sopenharmony_ciAllowed as function argument or return value. Not supported in shared structs. 8733d722a9Sopenharmony_ci 8833d722a9Sopenharmony_ciOnly rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are 8933d722a9Sopenharmony_cimove-assignable.) You'll need to write std::move occasionally as a reminder that 9033d722a9Sopenharmony_ciaccidentally exposing overlapping &mut \[T\] to Rust is UB. 9133d722a9Sopenharmony_ci 9233d722a9Sopenharmony_ci## Example 9333d722a9Sopenharmony_ci 9433d722a9Sopenharmony_ciThis example is a C++ program that constructs a slice containing JSON data (by 9533d722a9Sopenharmony_cireading from stdin, but it could be from anywhere), then calls into Rust to 9633d722a9Sopenharmony_cipretty-print that JSON data into a std::string via the [serde_json] and 9733d722a9Sopenharmony_ci[serde_transcode] crates. 9833d722a9Sopenharmony_ci 9933d722a9Sopenharmony_ci[serde_json]: https://github.com/serde-rs/json 10033d722a9Sopenharmony_ci[serde_transcode]: https://github.com/sfackler/serde-transcode 10133d722a9Sopenharmony_ci 10233d722a9Sopenharmony_ci```rust,noplayground 10333d722a9Sopenharmony_ci// src/main.rs 10433d722a9Sopenharmony_ci 10533d722a9Sopenharmony_ci#![no_main] // main defined in C++ by main.cc 10633d722a9Sopenharmony_ci 10733d722a9Sopenharmony_ciuse cxx::CxxString; 10833d722a9Sopenharmony_ciuse std::io::{self, Write}; 10933d722a9Sopenharmony_ciuse std::pin::Pin; 11033d722a9Sopenharmony_ci 11133d722a9Sopenharmony_ci#[cxx::bridge] 11233d722a9Sopenharmony_cimod ffi { 11333d722a9Sopenharmony_ci extern "Rust" { 11433d722a9Sopenharmony_ci fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>; 11533d722a9Sopenharmony_ci } 11633d722a9Sopenharmony_ci} 11733d722a9Sopenharmony_ci 11833d722a9Sopenharmony_cistruct WriteToCxxString<'a>(Pin<&'a mut CxxString>); 11933d722a9Sopenharmony_ci 12033d722a9Sopenharmony_ciimpl<'a> Write for WriteToCxxString<'a> { 12133d722a9Sopenharmony_ci fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 12233d722a9Sopenharmony_ci self.0.as_mut().push_bytes(buf); 12333d722a9Sopenharmony_ci Ok(buf.len()) 12433d722a9Sopenharmony_ci } 12533d722a9Sopenharmony_ci fn flush(&mut self) -> io::Result<()> { 12633d722a9Sopenharmony_ci Ok(()) 12733d722a9Sopenharmony_ci } 12833d722a9Sopenharmony_ci} 12933d722a9Sopenharmony_ci 13033d722a9Sopenharmony_cifn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> { 13133d722a9Sopenharmony_ci let writer = WriteToCxxString(output); 13233d722a9Sopenharmony_ci let mut deserializer = serde_json::Deserializer::from_slice(input); 13333d722a9Sopenharmony_ci let mut serializer = serde_json::Serializer::pretty(writer); 13433d722a9Sopenharmony_ci serde_transcode::transcode(&mut deserializer, &mut serializer) 13533d722a9Sopenharmony_ci} 13633d722a9Sopenharmony_ci``` 13733d722a9Sopenharmony_ci 13833d722a9Sopenharmony_ci```cpp 13933d722a9Sopenharmony_ci// src/main.cc 14033d722a9Sopenharmony_ci 14133d722a9Sopenharmony_ci#include "example/src/main.rs.h" 14233d722a9Sopenharmony_ci#include <iostream> 14333d722a9Sopenharmony_ci#include <iterator> 14433d722a9Sopenharmony_ci#include <string> 14533d722a9Sopenharmony_ci#include <vector> 14633d722a9Sopenharmony_ci 14733d722a9Sopenharmony_ciint main() { 14833d722a9Sopenharmony_ci // Read json from stdin. 14933d722a9Sopenharmony_ci std::istreambuf_iterator<char> begin{std::cin}, end; 15033d722a9Sopenharmony_ci std::vector<unsigned char> input{begin, end}; 15133d722a9Sopenharmony_ci rust::Slice<const uint8_t> slice{input.data(), input.size()}; 15233d722a9Sopenharmony_ci 15333d722a9Sopenharmony_ci // Prettify using serde_json and serde_transcode. 15433d722a9Sopenharmony_ci std::string output; 15533d722a9Sopenharmony_ci prettify_json(slice, output); 15633d722a9Sopenharmony_ci 15733d722a9Sopenharmony_ci // Write to stdout. 15833d722a9Sopenharmony_ci std::cout << output << std::endl; 15933d722a9Sopenharmony_ci} 16033d722a9Sopenharmony_ci``` 16133d722a9Sopenharmony_ci 16233d722a9Sopenharmony_ciTesting the example: 16333d722a9Sopenharmony_ci 16433d722a9Sopenharmony_ci```console 16533d722a9Sopenharmony_ci$ echo '{"fearless":"concurrency"}' | cargo run 16633d722a9Sopenharmony_ci Finished dev [unoptimized + debuginfo] target(s) in 0.02s 16733d722a9Sopenharmony_ci Running `target/debug/example` 16833d722a9Sopenharmony_ci{ 16933d722a9Sopenharmony_ci "fearless": "concurrency" 17033d722a9Sopenharmony_ci} 17133d722a9Sopenharmony_ci``` 172