133d722a9Sopenharmony_ci{{#title rust::Slice<T> — Rust ♡ C++}}
233d722a9Sopenharmony_ci# rust::Slice\<const T\>,&ensp;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 &amp;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