• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1{{#title rust::Slice<T> — Rust ♡ C++}}
2# rust::Slice\<const T\>,&ensp;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 &amp;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