From 11a4063825c40ef584557e1be55190d4bbdbd7aa Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Wed, 4 Mar 2026 10:16:15 -0800 Subject: [PATCH] Example of constructing `TuplePayload` variants of `enum`s. PiperOrigin-RevId: 878549100 --- docs/rust/enums.md | 19 ++- examples/rust/enum_with_payload/BUILD | 39 ++++++ examples/rust/enum_with_payload/example.rs | 13 ++ .../enum_with_payload/example_generated.h | 131 ++++++++++++++++++ examples/rust/enum_with_payload/main.cc | 18 +++ 5 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 examples/rust/enum_with_payload/BUILD create mode 100644 examples/rust/enum_with_payload/example.rs create mode 100644 examples/rust/enum_with_payload/example_generated.h create mode 100644 examples/rust/enum_with_payload/main.cc diff --git a/docs/rust/enums.md b/docs/rust/enums.md index 96549e1fb..01e3abd0e 100644 --- a/docs/rust/enums.md +++ b/docs/rust/enums.md @@ -56,7 +56,24 @@ with the corresponding variant. ### Example -TODO(b/489757240): Add an example. +Given the following Rust crate: + +``` +{{ #include ../../examples/rust/enum_with_payload/example.rs }} +``` + + + +Crubit will generate the following bindings: + + + +``` +{{ #include ../../examples/rust/enum_with_payload/example_generated.h }} +``` + + ## Known issues diff --git a/examples/rust/enum_with_payload/BUILD b/examples/rust/enum_with_payload/BUILD new file mode 100644 index 000000000..1b247d95a --- /dev/null +++ b/examples/rust/enum_with_payload/BUILD @@ -0,0 +1,39 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load( + "@rules_rust//rust:defs.bzl", + "rust_library", +) +load( + "//cc_bindings_from_rs/bazel_support:cc_bindings_from_rust_rule.bzl", + "cc_bindings_from_rust", +) +load( + "//cc_bindings_from_rs/test/golden:golden_test.bzl", + "golden_test", +) + +package(default_applicable_licenses = ["//:license"]) + +licenses(["notice"]) + +rust_library( + name = "example_crate", + srcs = ["example.rs"], +) + +cc_bindings_from_rust( + name = "example_crate_cc_api", + crate = ":example_crate", +) + +cc_binary( + name = "main", + srcs = ["main.cc"], + deps = [":example_crate_cc_api"], +) + +golden_test( + name = "example_golden_test", + golden_h = "example_generated.h", + rust_library = "example_crate", +) diff --git a/examples/rust/enum_with_payload/example.rs b/examples/rust/enum_with_payload/example.rs new file mode 100644 index 000000000..b95bdc066 --- /dev/null +++ b/examples/rust/enum_with_payload/example.rs @@ -0,0 +1,13 @@ +// Part of the Crubit project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#[derive(Copy, Clone)] +pub enum Color { + /// A completely transparent color (no payload) + Transparent, + /// A grayscale value from 0 to 255 + Grayscale(u8), + /// Red, Green, and Blue values from 0 to 255 + Rgb(u8, u8, u8), +} diff --git a/examples/rust/enum_with_payload/example_generated.h b/examples/rust/enum_with_payload/example_generated.h new file mode 100644 index 000000000..d69a0224c --- /dev/null +++ b/examples/rust/enum_with_payload/example_generated.h @@ -0,0 +1,131 @@ +// Part of the Crubit project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Automatically @generated C++ bindings for the following Rust crate: +// example_crate_golden +// Features: supported + +// clang-format off +#ifndef THIRD_PARTY_CRUBIT_EXAMPLES_RUST_ENUM_WITH_PAYLOAD_EXAMPLE_CRATE_GOLDEN +#define THIRD_PARTY_CRUBIT_EXAMPLES_RUST_ENUM_WITH_PAYLOAD_EXAMPLE_CRATE_GOLDEN + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +#pragma clang diagnostic ignored "-Wunused-private-field" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#include "support/annotations_internal.h" +#include "support/internal/slot.h" + +#include +#include +#include +#include +#include + +namespace example_crate { + +// Generated from: +// examples/rust/enum_with_payload/example.rs;l=6 +struct CRUBIT_INTERNAL_RUST_TYPE(":: example_crate_golden :: Color") alignas(1) + [[clang::trivial_abi]] Color final { + public: + // `example_crate_golden::Color` doesn't implement the `Default` trait + Color() = delete; + + // A completely transparent color (no payload) + // + // Generated from: + // examples/rust/enum_with_payload/example.rs;l=8 + static constexpr Color MakeTransparent(); + + // A grayscale value from 0 to 255 + // + // Generated from: + // examples/rust/enum_with_payload/example.rs;l=10 + static ::example_crate::Color MakeGrayscale(std::uint8_t __param_0); + + // Red, Green, and Blue values from 0 to 255 + // + // Generated from: + // examples/rust/enum_with_payload/example.rs;l=12 + static ::example_crate::Color MakeRgb(std::uint8_t __param_0, + std::uint8_t __param_1, + std::uint8_t __param_2); + + // No custom `Drop` impl and no custom "drop glue" required + ~Color() = default; + Color(Color&&) = default; + ::example_crate::Color& operator=(Color&&) = default; + + // Rust types that are `Copy` get trivial, `default` C++ copy constructor and + // assignment operator. + Color(const Color&) = default; + ::example_crate::Color& operator=(const Color&) = default; + Color(::crubit::UnsafeRelocateTag, Color&& value) { + memcpy(this, &value, sizeof(value)); + } + + private: + // Field type has been replaced with a blob of bytes: No support for bindings + // of individual non-repr(C) `enum`s + std::array __opaque_blob_of_bytes; + + private: + struct PrivateBytesTag {}; + constexpr Color(PrivateBytesTag, std::array bytes) + : __opaque_blob_of_bytes(bytes) {} + + private: + static void __crubit_field_offset_assertions(); +}; + +static_assert( + sizeof(Color) == 4, + "Verify that ADT layout didn't change since this header got generated"); +static_assert( + alignof(Color) == 1, + "Verify that ADT layout didn't change since this header got generated"); + +// `static` constructor +inline constexpr Color Color::MakeTransparent() { + return Color(PrivateBytesTag{}, {0, 0, 0, 0}); +} + +namespace __crubit_internal { +extern "C" void __crubit_thunk_Grayscale(std::uint8_t, + ::example_crate::Color* __ret_ptr); +} +inline ::example_crate::Color Color::MakeGrayscale(std::uint8_t __param_0) { + crubit::Slot<::example_crate::Color> __return_value_ret_val_holder; + auto* __return_value_storage = __return_value_ret_val_holder.Get(); + __crubit_internal::__crubit_thunk_Grayscale(__param_0, + __return_value_storage); + return std::move(__return_value_ret_val_holder).AssumeInitAndTakeValue(); +} + +namespace __crubit_internal { +extern "C" void __crubit_thunk_Rgb(std::uint8_t, std::uint8_t, std::uint8_t, + ::example_crate::Color* __ret_ptr); +} +inline ::example_crate::Color Color::MakeRgb(std::uint8_t __param_0, + std::uint8_t __param_1, + std::uint8_t __param_2) { + crubit::Slot<::example_crate::Color> __return_value_ret_val_holder; + auto* __return_value_storage = __return_value_ret_val_holder.Get(); + __crubit_internal::__crubit_thunk_Rgb(__param_0, __param_1, __param_2, + __return_value_storage); + return std::move(__return_value_ret_val_holder).AssumeInitAndTakeValue(); +} +static_assert(std::is_trivially_destructible_v); +static_assert(std::is_trivially_move_constructible_v<::example_crate::Color>); +static_assert(std::is_trivially_move_assignable_v<::example_crate::Color>); +static_assert(std::is_trivially_copy_constructible_v<::example_crate::Color>); +static_assert(std::is_trivially_copy_assignable_v<::example_crate::Color>); +inline void Color::__crubit_field_offset_assertions() { + static_assert(0 == offsetof(Color, __opaque_blob_of_bytes)); +} +} // namespace example_crate + +#pragma clang diagnostic pop +#endif // THIRD_PARTY_CRUBIT_EXAMPLES_RUST_ENUM_WITH_PAYLOAD_EXAMPLE_CRATE_GOLDEN diff --git a/examples/rust/enum_with_payload/main.cc b/examples/rust/enum_with_payload/main.cc new file mode 100644 index 000000000..435d005be --- /dev/null +++ b/examples/rust/enum_with_payload/main.cc @@ -0,0 +1,18 @@ +// Part of the Crubit project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#include "examples/rust/enum_with_payload/example_crate.h" + +int main(int argc, char* argv[]) { + example_crate::Color transparent_color = + example_crate::Color::MakeTransparent(); + + example_crate::Color red_color = example_crate::Color::MakeRgb(255, 0, 0); + + std::ignore = transparent_color; + std::ignore = red_color; + return 0; +}