1{{#title rust::Slice<T> — Rust ♡ C++}} 2# rust::Slice\<const T\>, rust::Slice\<T\> 3 4- Rust `&[T]` is written `rust::Slice<const T>` in C++ 5- Rust `&mut [T]` is written `rust::Slice<T>` in C++ 6 7### Public API: 8 9```cpp,hidelines 10// rust/cxx.h 11# 12# #include <iterator> 13# #include <type_traits> 14# 15# namespace rust { 16 17template <typename T> 18class Slice final { 19public: 20 using value_type = T; 21 22 Slice() noexcept; 23 Slice(const Slice<T> &) noexcept; 24 Slice(T *, size_t count) noexcept; 25 26 Slice &operator=(Slice<T> &&) noexcept; 27 Slice &operator=(const Slice<T> &) noexcept 28 requires std::is_const_v<T>; 29 30 T *data() const noexcept; 31 size_t size() const noexcept; 32 size_t length() const noexcept; 33 bool empty() const noexcept; 34 35 T &operator[](size_t n) const noexcept; 36 T &at(size_t n) const; 37 T &front() const noexcept; 38 T &back() const noexcept; 39 40 class iterator; 41 iterator begin() const noexcept; 42 iterator end() const noexcept; 43 44 void swap(Slice &) noexcept; 45}; 46# 47# template <typename T> 48# class Slice<T>::iterator final { 49# public: 50# using iterator_category = std::random_access_iterator_tag; 51# using value_type = T; 52# using pointer = T *; 53# using reference = T &; 54# 55# T &operator*() const noexcept; 56# T *operator->() const noexcept; 57# T &operator[](ptrdiff_t) const noexcept; 58# 59# iterator &operator++() noexcept; 60# iterator operator++(int) noexcept; 61# iterator &operator--() noexcept; 62# iterator operator--(int) noexcept; 63# 64# iterator &operator+=(ptrdiff_t) noexcept; 65# iterator &operator-=(ptrdiff_t) noexcept; 66# iterator operator+(ptrdiff_t) const noexcept; 67# iterator operator-(ptrdiff_t) const noexcept; 68# ptrdiff_t operator-(const iterator &) const noexcept; 69# 70# bool operator==(const iterator &) const noexcept; 71# bool operator!=(const iterator &) const noexcept; 72# bool operator<(const iterator &) const noexcept; 73# bool operator>(const iterator &) const noexcept; 74# bool operator<=(const iterator &) const noexcept; 75# bool operator>=(const iterator &) const noexcept; 76# }; 77# 78# } // namespace rust 79``` 80 81### Restrictions: 82 83T must not be an opaque Rust type or opaque C++ type. Support for opaque Rust 84types in slices is coming. 85 86Allowed as function argument or return value. Not supported in shared structs. 87 88Only rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are 89move-assignable.) You'll need to write std::move occasionally as a reminder that 90accidentally exposing overlapping &mut \[T\] to Rust is UB. 91 92## Example 93 94This example is a C++ program that constructs a slice containing JSON data (by 95reading from stdin, but it could be from anywhere), then calls into Rust to 96pretty-print that JSON data into a std::string via the [serde_json] and 97[serde_transcode] crates. 98 99[serde_json]: https://github.com/serde-rs/json 100[serde_transcode]: https://github.com/sfackler/serde-transcode 101 102```rust,noplayground 103// src/main.rs 104 105#![no_main] // main defined in C++ by main.cc 106 107use cxx::CxxString; 108use std::io::{self, Write}; 109use std::pin::Pin; 110 111#[cxx::bridge] 112mod ffi { 113 extern "Rust" { 114 fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>; 115 } 116} 117 118struct WriteToCxxString<'a>(Pin<&'a mut CxxString>); 119 120impl<'a> Write for WriteToCxxString<'a> { 121 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 122 self.0.as_mut().push_bytes(buf); 123 Ok(buf.len()) 124 } 125 fn flush(&mut self) -> io::Result<()> { 126 Ok(()) 127 } 128} 129 130fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> { 131 let writer = WriteToCxxString(output); 132 let mut deserializer = serde_json::Deserializer::from_slice(input); 133 let mut serializer = serde_json::Serializer::pretty(writer); 134 serde_transcode::transcode(&mut deserializer, &mut serializer) 135} 136``` 137 138```cpp 139// src/main.cc 140 141#include "example/src/main.rs.h" 142#include <iostream> 143#include <iterator> 144#include <string> 145#include <vector> 146 147int main() { 148 // Read json from stdin. 149 std::istreambuf_iterator<char> begin{std::cin}, end; 150 std::vector<unsigned char> input{begin, end}; 151 rust::Slice<const uint8_t> slice{input.data(), input.size()}; 152 153 // Prettify using serde_json and serde_transcode. 154 std::string output; 155 prettify_json(slice, output); 156 157 // Write to stdout. 158 std::cout << output << std::endl; 159} 160``` 161 162Testing the example: 163 164```console 165$ echo '{"fearless":"concurrency"}' | cargo run 166 Finished dev [unoptimized + debuginfo] target(s) in 0.02s 167 Running `target/debug/example` 168{ 169 "fearless": "concurrency" 170} 171``` 172