Change-Id: Ibb2978ebf1bbca8afddd13bdf8fba5e070c9037f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198115 Reviewed-by: Stephan Bergmann <stephan.bergmann@collabora.com> Tested-by: Jenkins
7.8 KiB
Rust UNO Developer Guide
This guide is intended for contributors working on the Rust UNO bindings implementation itself. If you are a user looking to use the bindings, please see the User Guide.
Table of Contents
Project Overview
The Rust UNO project enables LibreOffice to be scripted and extended using Rust. It works by inspecting the UNO IDL (Interface Definition Language) types and generating:
- Rust Wrappers: Safe, idiomatic Rust structs.
- C++ Bridges:
extern "C"functions that handle the raw UNO C++ API.
The system is fully integrated into the LibreOffice build system via autogen.sh and make.
Codebase Structure
The project is split across the core LibreOffice codebase:
Code Generator (codemaker)
Located in codemaker/source/rustmaker/. This tool reads the binary type library (RDB files) and outputs source code.
| File | Purpose |
|---|---|
rustproduce.cxx |
Generates Rust source files (structs, enums, interfaces). |
cpproduce.cxx |
Generates the C++ side of the bridge. |
unoproduce.cxx |
Coordinator that drives the generation process. |
rustfile.cxx |
Helper for writing Rust source files (indentation, imports). |
Runtime Library (rust_uno)
Located in rust_uno/. This is the crate that users depend on.
src/lib.rs: Crate root, exportsgeneratedmodules.src/generated/: Destination for generated Rust code.src/core/: Handwritten core utilities (OUStringwrapper, primitive types).
The Rustmaker Generator
The heart of the project is the rustmaker binary. It runs during the build process to produce the bindings.
Generation Flow
graph LR
IDL["UNO IDL Files"] -->|idlc| RDB["Binary RDB"]
RDB -->|read by| RustMaker["rustmaker (codemaker)"]
RustMaker -->|writes| RustFiles["Rust Wrappers (.rs)"]
RustMaker -->|writes| CppFiles["C++ Bridge (.cxx)"]
RustFiles -->|compiled by| Rustc["rustc"]
CppFiles -->|compiled by| Gxx["g++"]
Rustc -->|links| SharedLib["lib_rust_uno.so"]
Gxx -->|links| SharedLib
Key Implementation Details
- Typed Parameters: Methods are generated with native types (e.g.
i32,bool) where possible. - Opaque Pointers: All UNO objects are held as
*mut c_voidin Rust, pointing to aRef<Interface>in C++. - Memory Management: The
Droptrait implementation calls the C++ destructor, which releases the UNO reference.
Development Workflow
Prerequisites
Ensure you have a full LibreOffice build environment and have run ./autogen.sh --enable-rust-uno.
Rebuilding Bindings
When you modify codemaker, you need to regenerate the bindings:
# Rebuild the generator
make codemaker
# Regenerate the source files
make rust_uno
# Rebuild the final library
make
Tip
If you see bizarre errors after changing
rustmaker, trymake rust_uno.cleanfirst to force a fresh generation.
Testing Strategy
Testing is integrated into the LibreOffice startup sequence for basic sanity checks.
Integration Tests
The entry point run_rust_uno_test in rust_uno/src/lib.rs is called by soffice on startup.
It runs scenarios defined in rust_uno/src/examples/.
To run the tests:
./instdir/program/soffice --norestore
Watch the console output for === Rust UNO Bridge Test ===.
Unit Tests
Pure Rust unit tests (for OUString logic, etc.) can be run via Cargo:
cd rust_uno
cargo test
Future Work: Embindtest
We plan to integrate with embindtest, the comprehensive UNO test suite. This is a high-priority task to ensure full coverage of generated types.
Roadmap and Missing Features
This section details the current implementation status and future development tasks, ordered by architectural dependency and impact.
Implementation Status
The following table summarizes the generation status of UNO types in codemaker.
| UNO Type | Status | Generator Function | Notes |
|---|---|---|---|
| Module | Implemented | produceModule() |
Generates directory structure and mod.rs files. |
| Enum | Implemented | produceEnum() |
Full support including validation and bridge functions. |
| Struct | Implemented | produceStruct() |
Generates PlainStructs with getters, setters, and constructors. |
| Interface | Implemented | produceInterface() |
Generates traits, wrappers, and reference-counting logic. |
| Service | Partial | produceService() |
Supports single-interface services; accumulation-based services are deprecated. |
| Sequence | Partial | rustproduce.cxx |
Currently handled as void* in FFI; lacks safe Rust wrappers. |
| ConstantGroup | Not Implemented | produceConstantGroup() |
Function exists but body contains only a log message; content is skipped. |
| Exception | Not Implemented | produceException() |
Function exists but body contains only a log message; code generation is missing. |
Development Tasks
The following tasks are ordered by their foundational importance to the binding quality.
1. ConstantGroup Generation
Goal: Generate Rust constants for UNO ConstantGroups (e.g., com.sun.star.awt.FontWeight).
Files: codemaker/source/rustmaker/rustproduce.cxx, cpproduce.cxx
Details: Currently, produceConstantGroup prints a skipping message. This needs to look up the constants in the IDL entity and generate a Rust module with const items.
2. Exception Mapping
Goal: Integrate UNO exceptions with Rust's Result type.
Files: codemaker/source/rustmaker/
Details:
- Generate structs for UNO Exception types (
produceException). - Update method signatures to return
Result<T, UnoError>instead ofOption<T>. - The C++ bridge currently catches exceptions but does not fully propagate type information to Rust.
3. Typedef Resolution
Goal: Resolve UNO typedefs to their concrete Rust types.
Files: codemaker/source/rustmaker/unoproduce.cxx
Details: produceTypedef currently prints a log message. It should resolve the aliased type and generate a type Alias = ConcreteType; definition in Rust.
4. Singleton Generation
Goal: Generate accessors for UNO singletons.
Files: codemaker/source/rustmaker/rustproduce.cxx
Details: produceSingleton is currently a placeholder. It should generate helper methods to retrieve the singleton instance (typically via component context), avoiding manual createInstance calls.
5. Type-Safe Sequences
Goal: Replace void* usage for Sequences with a proper Sequence<T> wrapper.
Files: codemaker/source/rustmaker/rustproduce.cxx, rust_uno/src/core/
Details: Implement a Sequence struct that manages the memory layout compatible with UNO sequences and implements Iterator.