Start customizing Rust bindings for `absl::flat_hash_map`

The Rust methods are designed to look familiar to Rust users while accurately describing the underlying behavior and imposing minimal overhead.

This change provides three basic getters and two insert methods:

- `len`, which calls C++ `size`
- `capacity`, which calls C++ `capacity`
- `is_empty`, which calls C++ `empty`
- `try_insert` for `!Unpin` key and value types, which accepts a key and value and passes them as rvalue references to C++ `try_emplace`. The overall effect is to Rust-move and then C++-move or C++-copy them. When an equivalent key already exists, they are Rust-moved into the error.
- `try_insert_mov`, which accepts a (pinned if necessary) key and value by `RvalueReference` and passes them to C++ `try_emplace`. The overall effect is to C++-move or C++-copy them without performing any Rust-moves.

This is incomplete and further changes will fill in the API. The `try_insert` methods will likely generate broken code if lifetime parameters are involved; that's left for follow-up. There may also need to be checks to exclude unworkable cases like a key or value type that can't be moved or copied, if such a thing is well-formed enough to get bindings in the first place.

PiperOrigin-RevId: 954891745
14 files changed
tree: 195c52cd60b17163291d463dde267de3e3ac1f90
  1. .github/
  2. assets/
  3. bazel/
  4. buildenv/
  5. cargo/
  6. cc_bindings_from_rs/
  7. common/
  8. crubit_explorer/
  9. docs/
  10. doxygen/
  11. examples/
  12. features/
  13. lifetime_analysis/
  14. lifetime_annotations/
  15. migrator/
  16. nullability/
  17. patches/
  18. rs_bindings_from_cc/
  19. support/
  20. theme/
  21. .bazelignore
  22. .bazelrc
  23. .bazelversion
  24. .gitignore
  25. book.toml
  26. BUILD
  27. BUILD.gn
  28. Cargo.Bazel.lock
  29. Cargo.lock
  30. Cargo.toml
  31. CMakeLists.txt
  32. CODE_OF_CONDUCT
  33. CONTRIBUTING.md
  34. crubit.gni
  35. LICENSE
  36. MODULE.bazel
  37. MODULE.bazel.lock
  38. README.md
  39. rust-toolchain.toml
README.md

Crubit: C++/Rust Bidirectional Interop Tool

rust workflow GitHub

Crubit is a bidirectional bindings generator for C++ and Rust, with the goal of integrating the C++ and Rust ecosystems.

Status

See the status page for an overview of the current supported features.

Example

{}

{{#tab name=“Calling Rust from C++”}}

Consider the following Rust library:

pub struct Account {
    pub id: u64,
    pub balance: f64,
}

impl std::fmt::Display for Account { ... }

// Takes shared references, mapped to const references in C++.
pub fn calculate_interest(account: &Account, rate: f64) -> f64 { ... }

// Takes a string slice, mapped to rs_std::StrRef in C++.
pub fn is_valid_username(username: &str) -> bool { ... }

You can call these Rust functions from C++:

#include "path/to/account.h"
#include <iostream>

void demo() {
  account::Account my_account{.id = 123, .balance = 1000.0};
  double interest = account::calculate_interest(my_account, 0.05);

  // my_account is printable because Account implements Display in Rust!
  std::cout << my_account << std::endl;

  if (account::is_valid_username("bob")) {
    std::cout << "Valid user" << std::endl;
  }
}

{}

{{#tab name=“Calling C++ from Rust”}}

Consider the following C++ header:

#include <string_view>
#include <optional>
#include <memory>

struct User {
  int id;
  double balance;
};

std::optional<User> FindUser(int id);
std::unique_ptr<User> CreateUser(std::string_view name, int id);

You can call these C++ functions from Rust:

use cpp_std::unique_ptr;
use ffi_11::{c_double, c_int};
use user_api::{CreateUser, FindUser, User};

let id: c_int = 123;
let user: Option<User> = FindUser(id);
if let Some(u) = user {
    let balance: c_double = u.balance;
    println!("User {} has balance {}", u.id, balance);
}

let new_user: unique_ptr<User> = CreateUser("Alice".into(), 456);

{}

{}

Getting Started

We have detailed walkthroughs on how to use C++ from Rust, or Rust from C++, using Crubit, as well as copy-pastable example code. The example code also includes spanshots of what the generated bindings look like.

Test Matrix

NightlyStable
nightly-0stable-0
nightly-1stable-1
nightly-2
nightly-3
nightly-4
nightly-5
nightly-6