Skip to content

Provide Rust interface for libResult - #403

Open
eclipse-impl wants to merge 4 commits into
eclipse-score:mainfrom
eclipse-impl:swp-271152
Open

Provide Rust interface for libResult#403
eclipse-impl wants to merge 4 commits into
eclipse-score:mainfrom
eclipse-impl:swp-271152

Conversation

@eclipse-impl

Copy link
Copy Markdown
Contributor

With this interface, Rust code can convert C++ score::Result objects to Rust's own std::Result<T, E> transparently.

Note: The PR is on draft state because it's overriding @score_crates until it's officially released. Due to this overriding, also @score_tooling had to be overridden.

@github-project-automation github-project-automation Bot moved this to In Progress in BAS - Baselibs FT Jul 22, 2026
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 23, 2026 14:30 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval July 23, 2026 14:30 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown

The created documentation from the pull request is available at: docu-html

@github-actions github-actions Bot added comp-result Related to score/result component c++ C++ code rust Rust code bazel Bazel and Starlark build files labels Aug 3, 2026
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 14:00 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 14:00 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 14:00 — with GitHub Actions Inactive
@eclipse-impl
eclipse-impl temporarily deployed to workflow-approval August 3, 2026 14:00 — with GitHub Actions Inactive
@4og
4og requested a review from Copilot August 3, 2026 15:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces Rust-side bindings to interoperate with the C++ score::Result<T> / score::result::Error API across the FFI boundary, including cxx integration helpers and supporting “ABI-aware” Rust representations of selected C++ standard library types.

Changes:

  • Add a new result_rs Rust crate implementing an FFI-compatible Expected<T, Error> / Result<T> wrapper plus cxx import macros.
  • Add a new libcpp + libcpp_derive Rust crates to model ABI-dependent C++ stdlib types (currently std::string_view and std::variant) and provide layout tests.
  • Wire everything into Bazel and the Cargo workspace, including C++ test helpers and a cxx bridge example.

Reviewed changes

Copilot reviewed 25 out of 27 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
score/result/rust/result.rs Core Rust FFI types for score::Result + cxx integration macros + tests.
score/result/rust/result_example.rs cxx-bridge example demonstrating passing score::Result<T>-like values into Rust.
score/result/rust/result_example_cpp.h C++ declarations for the cxx example.
score/result/rust/result_example_cpp.cpp C++ implementation for the cxx example.
score/result/rust/result_cxx.h cxx relocatability traits for score::Result with smart pointers.
score/result/rust/README.md Documentation for the Rust result bindings and how to build/test them.
score/result/rust/plantuml/sequence.puml Sequence diagram describing the ABI flow for returning Result across FFI.
score/result/rust/ffi_test_helpers.cpp C++ helpers used by Rust tests to validate layout/behavior across FFI.
score/result/rust/Cargo.toml Cargo crate definition for result_rs with ABI-layout feature flags.
score/result/rust/BUILD Bazel targets for result_rs, docs, unit tests, and examples.
score/language/rust/libcpp/string_view.rs ABI-dependent std::string_view representation + layout tests.
score/language/rust/libcpp/README.md Rationale and strategy notes for ABI-dependent bindings.
score/language/rust/libcpp/libcpp_test.rs Simple Rust-side usage tests for imported std::variant.
score/language/rust/libcpp/lib.rs libcpp crate root exporting CStringView and the import macro.
score/language/rust/libcpp/ffi_test_helpers.cpp C++ helpers for std::string_view layout validation tests.
score/language/rust/libcpp/Cargo.toml Cargo crate definition for libcpp.
score/language/rust/libcpp/BUILD Bazel targets for libcpp + C++ helpers + tests/docs.
score/language/rust/libcpp_derive/unit_test.rs Rust tests validating libcpp_derive::import against C++ variants.
score/language/rust/libcpp_derive/unit_test_helpers.cpp C++ helpers for libcpp_derive variant tests.
score/language/rust/libcpp_derive/lib.rs Procedural macro generating Rust layouts/APIs for imported std::variant.
score/language/rust/libcpp_derive/Cargo.toml Cargo crate definition for libcpp_derive.
score/language/rust/libcpp_derive/BUILD Bazel build rules for proc-macro crate and tests.
MODULE.bazel Adds/updates Bazel module deps needed for the Rust/cxx integration.
Cargo.toml Adds new crates to the workspace members/default-members and deps.
Cargo.lock Locks new Rust dependencies introduced by the new crates.
.bazelrc Adjusts test config filters (notably around Rust doc tests).
Suppressed comments (2)

score/result/rust/result.rs:482

  • Same issue as above: fixed-size array + transmute for the error case is size/layout fragile. Copy bytes into MaybeUninit<Expected<...>> instead.
                let mut error_result_array = [0u8; MAX_SIZE];
                error_result_array
                    .copy_from_slice(&cpp_error_result_slice[..std::mem::size_of::<Expected<i32, Error>>()]);
                let rust_error_result: Expected<i32, Error> = std::mem::transmute(error_result_array);

score/result/rust/result.rs:759

  • In main_module_tests, the helper functions are also missing #[test], so none of these conversions/round-trip checks are executed in CI.
    #[cfg(all(test, not(miri)))]
    fn test_cpp_result_to_std_result_success() {
        unsafe {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread score/result/rust/ffi_test_helpers.cpp Outdated
Comment on lines +279 to +282
std::size_t create_result_int32_error_for_layout_test(int32_t error_code,
score::Result<std::int32_t>* out_result,
std::size_t bufsize)
{

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines +130 to +154
try
{
if (should_have_value)
{
if (!cpp_result->has_value())
{
return false;
}
return cpp_result->value() == expected_value_or_error_code;
}
else
{
if (cpp_result->has_value())
{
return false;
}
// For error case, just check if we can access the error and it matches
return *cpp_result->error() == expected_value_or_error_code;
}
}
catch (...)
{
// If any exception occurs during C++ access, the layout is incompatible
return false;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the current repository does not use exceptions, the library can be included on other modules. We cannot control their environment, so it's foreseeable that some of them might have exceptions active. In that case, the lack of the try/catch would be a problem. So, although it's not extrictly necessary for this repository itself, it does not cause any harm for it, while also protecting potential future use-cases. Therefore, we choose to keep it.

Comment on lines +198 to +206
pub fn #fn_get(&self) -> &#generic {
assert_eq!(self.discriminant, #discriminant);
unsafe { &self.storage.#value_name }
}

pub fn #fn_get_mut(&mut self) ->&mut std::mem::ManuallyDrop<#generic> {
assert_eq!(self.discriminant, #discriminant);
unsafe { &mut self.storage.#value_name }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code does compile. The gist is that C++ does the clean-up, therefore it's not a problem to have a ManuallyDrop<T> here. False positive.

Comment on lines +226 to +228
fn get_index(&self) -> usize {
self.discriminant as usize
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean-up is performed on C++ side. False positive.

Comment thread score/result/rust/result.rs Outdated
Comment on lines +14 to +18
//! This module provides FFI-compatible types and functions to interoperate with bmw::Result and
//! associated types.
//!
//! It also offers integration with cxx, allowing type aliases of bmw::Result to be used as types
//! of arguments or return values of C++ functions and methods. See the documentation of

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines +359 to +361
#[cfg(all(test, not(miri)))]
fn test_binary_compatibility_sizes() {
unsafe {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False positive, it's marked as test, but not under miri.

Comment on lines +3 to +12
This directory contains Rust FFI bindings that enable seamless interoperability
between C++ and Rust components using BMW's result types.

## Overview

The Rust bindings provide type-safe, zero-cost abstractions for working with:

- **`bmw::Result<T>`** - C++ result type with error handling
- **`bmw::result::Error`** - Error objects with domain and error codes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment thread score/result/rust/README.md Outdated
Comment on lines +30 to +32
A detailed sequence diagram illustrating the complete FFI flow is available in [sequence.puml](plantuml/sequence.puml), and depicted bellow:

![Result C++ to Rust Integration](plantuml/Result_CppToRust_Integration.svg)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines +62 to +77
```bash
# Basic Result example
bazel run --config=spp_host_gcc //platform/aas/lib/result/rust:result_rs_example

# SafeResult integration
bazel run --config=spp_host_gcc //platform/aas/lib/result/rust:safe_result_integration_example

# Type mismatch detection
bazel run --config=spp_host_gcc //platform/aas/lib/result/rust:safe_result_type_mismatch_example
```

### Run Tests

```bash
bazel test --config=spp_host_gcc //platform/aas/lib/result/rust:...
```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines +42 to +45
score::result::Error MakeError(ConversionErrorCode code, std::string_view user_message = {}) noexcept
{
return {static_cast<score::result::ErrorCode>(code), conversion_error_domain, user_message};
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False positive. This is needed by result.h. The reason why it's being provided on an example is that client code using he lib should provide it, as does the example.

With this interface, Rust code can convert C++ `score::Result` objects to Rust's own `std::Result<T, E>` transparently.
This type of target creates a shell script, intended to run on host.
However, the target configuration tries to run the script on target,
which fails to run.

As agreed with component management, it's fine to excluse these tests
from the target runs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bazel Bazel and Starlark build files c++ C++ code comp-result Related to score/result component rust Rust code

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants