Files
odfstudio/rust_uno/doc/Rust_UNO_Developer_Guide.md
Mohamed Ali a7ef6f04e9 Rust Bindings: Add initial documentation for Rust UNO bindings
Change-Id: Ibb2978ebf1bbca8afddd13bdf8fba5e070c9037f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198115
Reviewed-by: Stephan Bergmann <stephan.bergmann@collabora.com>
Tested-by: Jenkins
2026-01-27 08:53:19 +01:00

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

  1. Project Overview
  2. Codebase Structure
  3. The Rustmaker Generator
  4. Development Workflow
  5. Testing Strategy

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:

  1. Rust Wrappers: Safe, idiomatic Rust structs.
  2. 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, exports generated modules.
  • src/generated/: Destination for generated Rust code.
  • src/core/: Handwritten core utilities (OUString wrapper, 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_void in Rust, pointing to a Ref<Interface> in C++.
  • Memory Management: The Drop trait 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, try make rust_uno.clean first 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 of Option<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.