codemaker/source/rustmaker/cpproduce.cxx   |  538 ++++++--------
 codemaker/source/rustmaker/cpproduce.hxx   |    5 
 codemaker/source/rustmaker/rustproduce.cxx | 1089 +++++++++++++++++++++++------
 codemaker/source/rustmaker/rustproduce.hxx |   93 ++
 rust_uno/build.rs                          |    1 
 rust_uno/src/examples/load_writer.rs       |  101 +-
 6 files changed, 1310 insertions(+), 517 deletions(-)

New commits:
commit 86ade6386370c915e6977ebd2e3dba95dde50484
Author:     Mohamed Ali <[email protected]>
AuthorDate: Thu Sep 25 10:12:11 2025 +0300
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Mon Sep 29 09:57:43 2025 +0200

    Rust Bindings: Use typed parameters instead of void* in UNO bindings
    
    Replace generic void* parameters with proper types (strings, primitives, 
structs) for better type safety and more idiomatic Rust code.
    
    Change-Id: Iced1c2de96564be7ec599f14bf1a685eaede2768
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191477
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/codemaker/source/rustmaker/cpproduce.cxx 
b/codemaker/source/rustmaker/cpproduce.cxx
index d027f5834c36..397b82f0ac38 100644
--- a/codemaker/source/rustmaker/cpproduce.cxx
+++ b/codemaker/source/rustmaker/cpproduce.cxx
@@ -618,7 +618,9 @@ void CppProducer::generateStructHeader(std::string_view 
name,
             .append(")")
             .endLine()
             .beginLine()
-            .append("SAL_DLLPUBLIC_EXPORT void* ")
+            .append("SAL_DLLPUBLIC_EXPORT ")
+            .append(getStructGetterReturnType(member.type))
+            .append(" ")
             .append(functionPrefix)
             .append("_get_")
             .append(member.name)
@@ -641,7 +643,9 @@ void CppProducer::generateStructHeader(std::string_view 
name,
             .append(member.name)
             .append("(")
             .append(handleTypeName)
-            .append(" handle, void* value);")
+            .append(" handle, ")
+            .append(getStructSetterParameterType(member.type))
+            .append(" value);")
             .endLine();
     }
     file.endBlock().append("// extern \"C\"").endLine();
@@ -963,7 +967,9 @@ void CppProducer::generateStructMemberAccessors(CppFile& 
file, std::string_view
 {
     // Generate getter implementation
     file.beginLine()
-        .append("SAL_DLLPUBLIC_EXPORT void* ")
+        .append("SAL_DLLPUBLIC_EXPORT ")
+        .append(getStructGetterReturnType(member.type))
+        .append(" ")
         .append(functionPrefix)
         .append("_get_")
         .append(member.name)
@@ -978,12 +984,35 @@ void CppProducer::generateStructMemberAccessors(CppFile& 
file, std::string_view
         .append(className)
         .append("*>(handle);")
         .endLine()
-        .beginLine()
-        .append("return &(obj->")
-        .append(member.name)
-        .append(");")
-        .endLine()
-        .endBlock();
+        .beginLine();
+
+    // Handle return value conversion based on type
+    if (member.type == u"string")
+    {
+        // For string types, return pointer to the OUString object
+        file.append("return &(obj->").append(member.name).append(");");
+    }
+    else if (member.type == u"any")
+    {
+        // For any types, return pointer to the Any
+        file.append("return &(obj->").append(member.name).append(");");
+    }
+    else if (member.type == u"boolean" || member.type == u"byte" || 
member.type == u"short"
+             || member.type == u"unsigned short" || member.type == u"long"
+             || member.type == u"unsigned long" || member.type == u"hyper"
+             || member.type == u"unsigned hyper" || member.type == u"float"
+             || member.type == u"double")
+    {
+        // For primitive types, return pointer to the member for direct access
+        file.append("return &(obj->").append(member.name).append(");");
+    }
+    else
+    {
+        // For other types, return pointer to member
+        file.append("return &(obj->").append(member.name).append(");");
+    }
+
+    file.endLine().endBlock();
 
     // Generate setter implementation
     file.beginLine()
@@ -993,7 +1022,9 @@ void CppProducer::generateStructMemberAccessors(CppFile& 
file, std::string_view
         .append(member.name)
         .append("(")
         .append(handleTypeName)
-        .append(" handle, void* value)")
+        .append(" handle, ")
+        .append(getStructSetterParameterType(member.type))
+        .append(" value)")
         .endLine()
         .beginBlock()
         .beginLine()
@@ -1006,31 +1037,46 @@ void 
CppProducer::generateStructMemberAccessors(CppFile& file, std::string_view
         .append("obj->")
         .append(member.name);
 
-    // Check if this is a UNO interface type by checking the UNO type string
+    // Handle assignment based on parameter type
     OUString unoType = member.type;
-    SAL_INFO("codemaker", "Struct member " << member.name << " UNO type: " << 
unoType);
-
-    // UNO interface types start with "com.sun.star" and end with an interface 
name (typically starting with "X")
-    // Examples: "com.sun.star.uno.XInterface", "com.sun.star.text.XText"
-    bool isInterfaceType = (unoType.startsWith("com.sun.star.") && 
(unoType.lastIndexOf('.') != -1)
-                            && (unoType.subView(unoType.lastIndexOf('.') + 
1).starts_with('X')));
 
-    if (isInterfaceType)
+    // Check if we're using typed primitive parameters (passed by value)
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        // For primitive types with typed parameters, assign directly (no 
dereferencing)
+        file.append(" = value;");
+    }
+    else if (unoType == u"string")
     {
-        SAL_INFO("codemaker", "Detected UNO interface type, using pointer 
assignment");
-        // For interface types, assign the pointer directly without 
dereferencing
-        // The C++ struct expects Reference<Interface>, but we assign the raw 
interface pointer
-        file.append(" = reinterpret_cast<")
-            .append(convertUnoTypeToCpp(unoType))
-            .append("*>(value);");
+        // For string types, dereference the pointer to OUString
+        file.append(" = *reinterpret_cast<const OUString*>(value);");
+    }
+    else if (unoType == u"any")
+    {
+        // For any types with typed parameters, dereference the uno_Any*
+        file.append(" = *reinterpret_cast<const Any*>(value);");
     }
     else
     {
-        SAL_INFO("codemaker", "Non-interface type, using dereferenced 
assignment");
-        // For non-interface types, dereference the pointer as before
-        file.append(" = *reinterpret_cast<const ")
-            .append(convertUnoTypeToCpp(unoType))
-            .append("*>(value);");
+        // For other types (interfaces, structs, enums), use original logic 
with void*
+        // Check if this is a UNO interface type using proper TypeManager 
classification
+        if (isUnoInterface(unoType))
+        {
+            // For interface types, assign the pointer directly without 
dereferencing
+            file.append(" = reinterpret_cast<")
+                .append(convertUnoTypeToCpp(unoType))
+                .append("*>(value);");
+        }
+        else
+        {
+            // For non-interface types, dereference the pointer
+            file.append(" = *reinterpret_cast<const ")
+                .append(convertUnoTypeToCpp(unoType))
+                .append("*>(value);");
+        }
     }
     file.endLine().endBlock().beginLine().append("").endLine();
 }
@@ -1435,10 +1481,13 @@ void 
CppProducer::generateInterfaceHeader(std::string_view name,
             .append(handleTypeName)
             .append(" handle");
 
-        // Add parameters
+        // Add typed parameters instead of void*
         for (const auto& param : method.parameters)
         {
-            file.append(", void* ").append(param.name);
+            file.append(", ")
+                .append(getTypedParameterType(param.type, param.direction))
+                .append(" ")
+                .append(param.name);
         }
 
         file.append(");");
@@ -1677,10 +1726,13 @@ void 
CppProducer::generateSingleInterfaceMethod(CppFile& file, std::string_view
         .append(handleTypeName)
         .append(" handle");
 
-    // Add parameters
+    // Add typed parameters instead of void*
     for (const auto& param : method.parameters)
     {
-        file.append(", void* ").append(param.name);
+        file.append(", ")
+            .append(getTypedParameterType(param.type, param.direction))
+            .append(" ")
+            .append(param.name);
     }
 
     file.append(")").endLine().beginBlock();
@@ -1850,70 +1902,62 @@ void CppProducer::generateActualMethodCall(CppFile& 
file,
         {
             if (isInputOnly)
             {
-                // Input parameter: convert rtl_uString* to OUString object
-                
file.append("OUString(static_cast<rtl_uString*>(").append(param.name).append("))");
+                // Input parameter: direct rtl_uString* to OUString conversion 
(no casting needed)
+                file.append("OUString(").append(param.name).append(")");
             }
             else
             {
-                // Output parameter: needs OUString reference for binding
-                
file.append("*reinterpret_cast<OUString*>(").append(param.name).append(")");
+                // Output parameter: rtl_uString** needs dereferencing to 
OUString reference
+                
file.append("*reinterpret_cast<OUString*>(*").append(param.name).append(")");
             }
         }
         else if (paramType == u"any")
         {
             if (isInputOnly)
+            {
+                // Input parameter: dereference uno_Any* to get Any& (Any 
inherits from uno_Any)
                 file.append("*reinterpret_cast<const 
Any*>(").append(param.name).append(")");
+            }
             else
-                
file.append("*reinterpret_cast<Any*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"boolean")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
sal_Bool*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<sal_Bool*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"byte")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
sal_Int8*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<sal_Int8*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"short")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
sal_Int16*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<sal_Int16*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"long")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
sal_Int32*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<sal_Int32*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"hyper")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
sal_Int64*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<sal_Int64*>(").append(param.name).append(")");
-        }
-        else if (paramType == u"float")
-        {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
float*>(").append(param.name).append(")");
-            else
-                
file.append("*reinterpret_cast<float*>(").append(param.name).append(")");
+            {
+                // Output parameter: uno_Any** needs dereferencing to Any 
reference
+                
file.append("*reinterpret_cast<Any*>(*").append(param.name).append(")");
+            }
         }
-        else if (paramType == u"double")
+        // Handle all primitive types with typed parameter support
+        else if (paramType == u"boolean" || paramType == u"byte" || paramType 
== u"short"
+                 || paramType == u"unsigned short" || paramType == u"long"
+                 || paramType == u"unsigned long" || paramType == u"hyper"
+                 || paramType == u"unsigned hyper" || paramType == u"float"
+                 || paramType == u"double")
         {
-            if (isInputOnly)
-                file.append("*reinterpret_cast<const 
double*>(").append(param.name).append(")");
+            // Check if this primitive type is using typed parameters
+            OString primitiveType = 
mapUnoPrimitiveToSal(resolveTypedef(paramType));
+            if (!primitiveType.isEmpty())
+            {
+                // Typed parameter approach - direct value for input, 
dereference pointer for input/output
+                if (isInputOnly)
+                    file.append(param.name); // Direct value (sal_Bool, 
sal_Int32, double, etc.)
+                else
+                    file.append("*").append(
+                        param.name); // Dereference pointer (sal_Bool*, 
sal_Int32*, double*, etc.)
+            }
             else
-                
file.append("*reinterpret_cast<double*>(").append(param.name).append(")");
+            {
+                // Fallback to void* approach (shouldn't happen for 
primitives, but just in case)
+                if (isInputOnly)
+                    file.append("*reinterpret_cast<const ")
+                        .append(primitiveType)
+                        .append("*>(")
+                        .append(param.name)
+                        .append(")");
+                else
+                    file.append("*reinterpret_cast<")
+                        .append(primitiveType)
+                        .append("*>(")
+                        .append(param.name)
+                        .append(")");
+            }
         }
         else if (paramType == u"type")
         {
@@ -2265,6 +2309,142 @@ OString CppProducer::getCppTypeName(std::u16string_view 
unoType) const
         return "void*"_ostr; // Default to void* for unknown types
 }
 
+OString CppProducer::getTypedParameterType(
+    std::u16string_view unoType,
+    unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) const
+{
+    // Handle string types with typed parameters
+    if (unoType == u"string")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input string: pass as rtl_uString* (no const to avoid casting)
+            return "rtl_uString*"_ostr;
+        }
+        else
+        {
+            // Input/output string: pass as rtl_uString** (modifiable)
+            return "rtl_uString**"_ostr;
+        }
+    }
+
+    // Handle any types with typed parameters
+    if (unoType == u"any")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input any: pass as uno_Any* (no const to avoid casting)
+            return "uno_Any*"_ostr;
+        }
+        else
+        {
+            // Input/output any: pass as uno_Any** (modifiable)
+            return "uno_Any**"_ostr;
+        }
+    }
+
+    // Only use typed parameters for basic primitive types (not typedefs)
+    // This ensures we don't break existing null-checking logic for complex 
types
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        OString primitiveType = mapUnoPrimitiveToSal(unoType);
+        if (!primitiveType.isEmpty())
+        {
+            bool isInputOnly
+                = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+            if (isInputOnly)
+            {
+                // Input parameters: pass by value (sal_Bool, sal_Int32, etc.)
+                return primitiveType;
+            }
+            else
+            {
+                // Input/output parameters: pass by pointer (sal_Bool*, 
sal_Int32*, etc.)
+                return primitiveType + "*";
+            }
+        }
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    // This maintains compatibility with existing null-checking and casting 
logic
+    return "void*"_ostr;
+}
+
+OString CppProducer::getStructGetterReturnType(std::u16string_view unoType) 
const
+{
+    // Struct getters return a pointer to the member data (like output 
parameters)
+    // Use the same logic as getTypedParameterType with direction = OUT
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "void*"_ostr; // Return pointer to string for compatibility
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "uno_Any*"_ostr; // Return pointer to Any for direct access
+    }
+
+    // Handle primitive types
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        OString primitiveType = mapUnoPrimitiveToSal(unoType);
+        if (!primitiveType.isEmpty())
+        {
+            return primitiveType + "*"; // Return pointer to primitive type
+        }
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    return "void*"_ostr;
+}
+
+OString CppProducer::getStructSetterParameterType(std::u16string_view unoType) 
const
+{
+    // Struct setters take the value to set (like input parameters)
+    // Use the same logic as getTypedParameterType with direction = IN
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "rtl_uString*"_ostr; // Take string pointer for compatibility
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "uno_Any*"_ostr; // Take Any pointer directly
+    }
+
+    // Handle primitive types
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        OString primitiveType = mapUnoPrimitiveToSal(unoType);
+        if (!primitiveType.isEmpty())
+        {
+            return primitiveType; // Take primitive type by value
+        }
+    }
+
+    // For all other types
+    return "void*"_ostr;
+}
+
 OString CppProducer::convertBasicType(const OString& typeName)
 {
     OString result = typeName;
diff --git a/codemaker/source/rustmaker/cpproduce.hxx 
b/codemaker/source/rustmaker/cpproduce.hxx
index ac07a888a45a..9d343109d41c 100644
--- a/codemaker/source/rustmaker/cpproduce.hxx
+++ b/codemaker/source/rustmaker/cpproduce.hxx
@@ -149,6 +149,11 @@ private:
     OString convertUnoTypeToCpp(std::u16string_view unoType) const;
     std::string convertTemplateArguments(const std::string& unoType) const;
     OString getCppTypeName(std::u16string_view unoType) const;
+    OString getTypedParameterType(
+        std::u16string_view unoType,
+        unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) 
const;
+    OString getStructGetterReturnType(std::u16string_view unoType) const;
+    OString getStructSetterParameterType(std::u16string_view unoType) const;
     OString getRustFFITypeName(std::u16string_view unoType) const;
     static OString mapUnoPrimitiveToSal(std::u16string_view unoType);
     OUString resolveTypedef(std::u16string_view unoType) const;
diff --git a/codemaker/source/rustmaker/rustproduce.cxx 
b/codemaker/source/rustmaker/rustproduce.cxx
index b15780a7c053..22539fd834fb 100644
--- a/codemaker/source/rustmaker/rustproduce.cxx
+++ b/codemaker/source/rustmaker/rustproduce.cxx
@@ -232,6 +232,10 @@ void RustProducer::generateStructImplementation(
 
     generateStructConstructor(file, externFunctionPrefix);
     generateStructFromPtr(file, externFunctionPrefix);
+
+    // Generate as_ptr method
+    generateStructAsPtr(file);
+
     generateStructAccessors(file, entity, externFunctionPrefix);
 
     file.endBlock();
@@ -305,6 +309,21 @@ void RustProducer::generateStructFromPtr(RustFile& file, 
std::string_view extern
         .endBlock();
 }
 
+void RustProducer::generateStructAsPtr(RustFile& file)
+{
+    file.beginLine()
+        .append("")
+        .endLine()
+        .beginLine()
+        .append("pub fn as_ptr(&self) -> *mut c_void")
+        .endLine()
+        .beginBlock()
+        .beginLine()
+        .append("self.ptr")
+        .endLine()
+        .endBlock();
+}
+
 void RustProducer::generateStructAccessors(
     RustFile& file, const rtl::Reference<unoidl::PlainStructTypeEntity>& 
entity,
     std::string_view externFunctionPrefix)
@@ -313,58 +332,139 @@ void RustProducer::generateStructAccessors(
     for (const auto& member : entity->getDirectMembers())
     {
         OString memberName = u2b(member.name); // Use original case, not 
snake_case
+        std::u16string_view memberType = member.type;
 
-        generateStructMemberGetter(file, memberName, externFunctionPrefix);
-        generateStructMemberSetter(file, memberName, externFunctionPrefix);
+        generateStructMemberGetter(file, memberName, memberType, 
externFunctionPrefix);
+        generateStructMemberSetter(file, memberName, memberType, 
externFunctionPrefix);
     }
 }
 
 void RustProducer::generateStructMemberGetter(RustFile& file, std::string_view 
memberName,
+                                              std::u16string_view memberType,
                                               std::string_view 
externFunctionPrefix)
 {
+    OString returnType = getRustStructGetterReturnType(memberType);
+
     file.beginLine()
         .append("")
         .endLine()
         .beginLine()
         .append("pub fn get_")
         .append(memberName)
-        .append("(&self) -> *mut c_void {")
+        .append("(&self) -> ")
+        .append(returnType)
+        .append(" {")
         .endLine()
         .extraIndent()
-        .beginLine()
-        .append("unsafe { ")
-        .append(externFunctionPrefix)
-        .append("_get_")
-        .append(memberName)
-        .append("(self.ptr) }")
-        .endLine()
-        .beginLine()
-        .append("}")
-        .endLine();
+        .beginLine();
+
+    // Handle conversion based on type
+    if (memberType == u"string")
+    {
+        // String type - convert from FFI to high-level type
+        file.append("unsafe { crate::core::OUString::from_raw(")
+            .append(externFunctionPrefix)
+            .append("_get_")
+            .append(memberName)
+            .append("(self.ptr)) }");
+    }
+    else if (memberType == u"any")
+    {
+        // Any type - convert from FFI to high-level type
+        file.append("unsafe { crate::core::Any::from_raw(std::ptr::read(")
+            .append(externFunctionPrefix)
+            .append("_get_")
+            .append(memberName)
+            .append("(self.ptr) as *const crate::ffi::uno_any::uno_Any)) }");
+    }
+    else if (memberType == u"boolean" || memberType == u"byte" || memberType 
== u"short"
+             || memberType == u"unsigned short" || memberType == u"long"
+             || memberType == u"unsigned long" || memberType == u"hyper"
+             || memberType == u"unsigned hyper" || memberType == u"float"
+             || memberType == u"double")
+    {
+        // Primitive types - dereference the pointer returned from FFI
+        file.append("unsafe { *")
+            .append(externFunctionPrefix)
+            .append("_get_")
+            .append(memberName)
+            .append("(self.ptr) }");
+    }
+    else
+    {
+        // Other types - return raw pointer
+        file.append("unsafe { ")
+            .append(externFunctionPrefix)
+            .append("_get_")
+            .append(memberName)
+            .append("(self.ptr) }");
+    }
+
+    file.endLine().beginLine().append("}").endLine();
 }
 
 void RustProducer::generateStructMemberSetter(RustFile& file, std::string_view 
memberName,
+                                              std::u16string_view memberType,
                                               std::string_view 
externFunctionPrefix)
 {
+    OString parameterType = getRustStructSetterParameterType(memberType);
+
     file.beginLine()
         .append("")
         .endLine()
         .beginLine()
         .append("pub fn set_")
         .append(memberName)
-        .append("(&mut self, value: *mut c_void) {")
+        .append("(&mut self, value: ")
+        .append(parameterType)
+        .append(") {")
         .endLine()
         .extraIndent()
-        .beginLine()
-        .append("unsafe { ")
-        .append(externFunctionPrefix)
-        .append("_set_")
-        .append(memberName)
-        .append("(self.ptr, value) }")
-        .endLine()
-        .beginLine()
-        .append("}")
-        .endLine();
+        .beginLine();
+
+    // Handle conversion based on type
+    if (memberType == u"string")
+    {
+        // String type - convert from high-level to FFI type
+        file.append("unsafe { ")
+            .append(externFunctionPrefix)
+            .append("_set_")
+            .append(memberName)
+            .append("(self.ptr, value.as_ptr()) }");
+    }
+    else if (memberType == u"any")
+    {
+        // Any type - convert from high-level to FFI type
+        file.append("unsafe { ")
+            .append(externFunctionPrefix)
+            .append("_set_")
+            .append(memberName)
+            .append("(self.ptr, value.as_ptr()) }");
+    }
+    else if (memberType == u"boolean" || memberType == u"byte" || memberType 
== u"short"
+             || memberType == u"unsigned short" || memberType == u"long"
+             || memberType == u"unsigned long" || memberType == u"hyper"
+             || memberType == u"unsigned hyper" || memberType == u"float"
+             || memberType == u"double")
+    {
+        // Primitive types - pass by value directly
+        file.append("unsafe { ")
+            .append(externFunctionPrefix)
+            .append("_set_")
+            .append(memberName)
+            .append("(self.ptr, value) }");
+    }
+    else
+    {
+        // Other types - pass raw pointer through
+        file.append("unsafe { ")
+            .append(externFunctionPrefix)
+            .append("_set_")
+            .append(memberName)
+            .append("(self.ptr, value) }");
+    }
+
+    file.endLine().beginLine().append("}").endLine();
 }
 
 void RustProducer::generateStructDropTrait(
@@ -453,19 +553,26 @@ void RustProducer::generateStructMemberExternDeclarations(
     for (const auto& member : entity->getDirectMembers())
     {
         OString memberName = u2b(member.name); // Use original case, not 
snake_case
+        OString getterReturnType = 
getRustStructExternGetterReturnType(member.type);
+        OString setterParamType = 
getRustStructExternSetterParameterType(member.type);
+
         file.beginLine()
             .append("fn ")
             .append(externFunctionPrefix)
             .append("_get_")
             .append(memberName)
-            .append("(ptr: *mut c_void) -> *mut c_void;")
+            .append("(ptr: *mut c_void) -> ")
+            .append(getterReturnType)
+            .append(";")
             .endLine()
             .beginLine()
             .append("fn ")
             .append(externFunctionPrefix)
             .append("_set_")
             .append(memberName)
-            .append("(ptr: *mut c_void, value: *mut c_void);")
+            .append("(ptr: *mut c_void, value: ")
+            .append(setterParamType)
+            .append(");")
             .endLine();
     }
 }
@@ -691,10 +798,13 @@ void RustProducer::generateInterfaceMethodWrappers(
             .append(rustMethodName)
             .append("(&self");
 
-        // All parameters are opaque void pointers
+        // Parameters with typed support for primitives
         for (const auto& param : method.parameters)
         {
-            file.append(", ").append(param.name).append(": *mut c_void");
+            file.append(", ")
+                .append(param.name)
+                .append(": ")
+                .append(getRustParameterType(param.type, param.direction));
         }
 
         file.append(") -> ")
@@ -716,7 +826,8 @@ void RustProducer::generateInterfaceMethodWrappers(
 
             for (const auto& param : method.parameters)
             {
-                file.append(", ").append(param.name);
+                file.append(", ").append(
+                    convertRustParameterForFFICall(param.type, 
u2b(param.name), param.direction));
             }
 
             file.append(") };").endLine();
@@ -733,7 +844,8 @@ void RustProducer::generateInterfaceMethodWrappers(
 
             for (const auto& param : method.parameters)
             {
-                file.append(", ").append(param.name);
+                file.append(", ").append(
+                    convertRustParameterForFFICall(param.type, 
u2b(param.name), param.direction));
             }
 
             file.append(") };").endLine();
@@ -945,7 +1057,10 @@ void RustProducer::generateInterfaceExternDeclarations(
 
         for (const auto& param : method.parameters)
         {
-            file.append(", ").append(param.name).append(": *mut c_void");
+            file.append(", ")
+                .append(param.name)
+                .append(": ")
+                .append(getRustExternParameterType(param.type, 
param.direction));
         }
 
         file.append(") -> ");
@@ -1350,6 +1465,246 @@ OString 
RustProducer::getRustReturnType(std::u16string_view unoType) const
     return getRustWrapperTypeName(unoType);
 }
 
+OString RustProducer::getRustParameterType(
+    std::u16string_view unoType,
+    unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) const
+{
+    // Handle string types with typed parameters (high-level Rust API)
+    if (unoType == u"string")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input string: take high-level OUString in public API
+            return "crate::core::OUString"_ostr;
+        }
+        else
+        {
+            // Input/output string: still use raw pointer for output parameters
+            return "*mut *mut crate::ffi::rtl_string::rtl_uString"_ostr;
+        }
+    }
+
+    // Handle any types with typed parameters (high-level Rust API)
+    if (unoType == u"any")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input any: take high-level Any in public API
+            return "crate::core::Any"_ostr;
+        }
+        else
+        {
+            // Input/output any: still use raw pointer for output parameters
+            return "*mut *mut crate::ffi::uno_any::uno_Any"_ostr;
+        }
+    }
+
+    // Handle struct types with typed parameters (high-level Rust API)
+    if (isUnoStruct(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input struct: take high-level generated struct in public API
+            OString rustType = u2b(unoType);
+            if (rustType.indexOf('.') != -1)
+            {
+                // Convert dots to :: for module path
+                OString modulePath = rustType.replaceAll("."_ostr, "::"_ostr);
+
+                // Extract simple type name
+                sal_Int32 lastDot = rustType.lastIndexOf('.');
+                if (lastDot != -1)
+                {
+                    OString simpleName = rustType.copy(lastDot + 1);
+                    return "crate::generated::rustmaker::" + modulePath + "::" 
+ simpleName;
+                }
+            }
+            // Fallback for simple struct names without namespace
+            return "crate::generated::rustmaker::" + rustType;
+        }
+        else
+        {
+            // Input/output struct: still use raw pointer for output parameters
+            return "*mut c_void"_ostr;
+        }
+    }
+
+    // Handle interface types with typed parameters (high-level Rust API)
+    if (isUnoInterface(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input interface: take high-level generated interface in public 
API
+            OString rustType = u2b(unoType);
+            if (rustType.indexOf('.') != -1)
+            {
+                // Convert dots to :: for module path
+                OString modulePath = rustType.replaceAll("."_ostr, "::"_ostr);
+
+                // Extract simple type name
+                sal_Int32 lastDot = rustType.lastIndexOf('.');
+                if (lastDot != -1)
+                {
+                    OString simpleName = rustType.copy(lastDot + 1);
+                    return "crate::generated::rustmaker::" + modulePath + "::" 
+ simpleName;
+                }
+            }
+            // Fallback for simple interface names without namespace
+            return "crate::generated::rustmaker::" + rustType;
+        }
+        else
+        {
+            // Input/output interface: still use raw pointer for output 
parameters
+            return "*mut c_void"_ostr;
+        }
+    }
+
+    // Only use typed parameters for basic primitive types (matching 
CppProducer approach)
+    // This ensures we don't break existing logic for complex types
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        // Get the Rust primitive type
+        OString rustPrimitiveType = getRustWrapperTypeName(unoType);
+        if (!rustPrimitiveType.isEmpty())
+        {
+            bool isInputOnly
+                = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+            if (isInputOnly)
+            {
+                // Input parameters: pass by value (u8 for boolean, i32 for 
long, etc.)
+                return rustPrimitiveType;
+            }
+            else
+            {
+                // Input/output parameters: pass by mutable pointer (*mut u8, 
*mut i32, etc.)
+                return "*mut " + rustPrimitiveType;
+            }
+        }
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    // This maintains compatibility with existing null-checking and casting 
logic
+    return "*mut c_void"_ostr;
+}
+
+OString RustProducer::getRustExternParameterType(
+    std::u16string_view unoType,
+    unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) const
+{
+    // Handle string types with C-compatible FFI parameters (different from 
high-level API)
+    if (unoType == u"string")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input string: pass as C-compatible pointer for FFI
+            return "*const crate::ffi::rtl_string::rtl_uString"_ostr;
+        }
+        else
+        {
+            // Input/output string: pass as mutable pointer for output 
parameters
+            return "*mut *mut crate::ffi::rtl_string::rtl_uString"_ostr;
+        }
+    }
+
+    // Handle any types with C-compatible FFI parameters (different from 
high-level API)
+    if (unoType == u"any")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input any: pass as C-compatible pointer for FFI
+            return "*const crate::ffi::uno_any::uno_Any"_ostr;
+        }
+        else
+        {
+            // Input/output any: pass as mutable pointer for output parameters
+            return "*mut *mut crate::ffi::uno_any::uno_Any"_ostr;
+        }
+    }
+
+    // Handle struct types with C-compatible FFI parameters (different from 
high-level API)
+    if (isUnoStruct(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input struct: pass as C-compatible pointer for FFI (void* for 
now, can be refined later)
+            return "*mut c_void"_ostr;
+        }
+        else
+        {
+            // Input/output struct: still use raw pointer for output parameters
+            return "*mut c_void"_ostr;
+        }
+    }
+
+    // Handle interface types with C-compatible FFI parameters (different from 
high-level API)
+    if (isUnoInterface(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input interface: pass as C-compatible pointer for FFI (void* 
for interfaces)
+            return "*mut c_void"_ostr;
+        }
+        else
+        {
+            // Input/output interface: still use raw pointer for output 
parameters
+            return "*mut c_void"_ostr;
+        }
+    }
+
+    // Handle enums - revert to void* to avoid nullptr comparison issues
+    if (isUnoEnum(unoType))
+    {
+        return "*mut c_void"_ostr;
+    }
+
+    // For primitive types, use the same logic as high-level API (primitives 
are the same)
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        // Get the Rust primitive type
+        OString rustPrimitiveType = getRustWrapperTypeName(unoType);
+        if (!rustPrimitiveType.isEmpty())
+        {
+            bool isInputOnly
+                = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+            if (isInputOnly)
+            {
+                // Input parameters: pass by value (u8 for boolean, i32 for 
long, etc.)
+                return rustPrimitiveType;
+            }
+            else
+            {
+                // Input/output parameters: pass by mutable pointer (*mut u8, 
*mut i32, etc.)
+                return "*mut " + rustPrimitiveType;
+            }
+        }
+    }
+
+    // For all other types (typedefs, structs, interfaces, sequences), use 
void*
+    return "*mut c_void"_ostr;
+}
+
 bool RustProducer::isUnoInterface(std::u16string_view typeName) const
 {
     rtl::Reference<unoidl::Entity> entity;
@@ -1374,4 +1729,207 @@ bool RustProducer::isUnoEnum(std::u16string_view 
typeName) const
     return sort == codemaker::UnoType::Sort::Enum;
 }
 
+OString RustProducer::convertRustParameterForFFICall(
+    std::u16string_view unoType, std::string_view paramName,
+    unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) const
+{
+    // Handle string types with automatic conversion
+    if (unoType == u"string")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input string: convert OUString to rtl_uString* using .as_ptr()
+            return OString(paramName) + ".as_ptr()";
+        }
+        else
+        {
+            // Input/output string: pass through as pointer (already proper 
type)
+            return OString(paramName);
+        }
+    }
+
+    // Handle any types with automatic conversion
+    if (unoType == u"any")
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input any: convert Any to uno_Any* using .as_ptr()
+            return OString(paramName) + ".as_ptr()";
+        }
+        else
+        {
+            // Input/output any: pass through as pointer (already proper type)
+            return OString(paramName);
+        }
+    }
+
+    // Handle struct types with automatic conversion
+    if (isUnoStruct(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input struct: convert generated struct to void* using .as_ptr()
+            return OString(paramName) + ".as_ptr()";
+        }
+        else
+        {
+            // Input/output struct: pass through as pointer (already proper 
type)
+            return OString(paramName);
+        }
+    }
+
+    // Handle interface types with automatic conversion
+    if (isUnoInterface(unoType))
+    {
+        bool isInputOnly
+            = (direction == 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN);
+        if (isInputOnly)
+        {
+            // Input interface: convert generated interface to void* using 
.as_ptr()
+            return OString(paramName) + ".as_ptr()";
+        }
+        else
+        {
+            // Input/output interface: pass through as pointer (already proper 
type)
+            return OString(paramName);
+        }
+    }
+
+    // Handle primitive types - pass through directly (no conversion needed)
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        // Primitive types already match FFI expectations - pass through 
directly
+        return OString(paramName);
+    }
+
+    // For all other types, pass through without conversion (fallback)
+    return OString(paramName);
+}
+
+OString RustProducer::getRustStructGetterReturnType(std::u16string_view 
unoType) const
+{
+    // Struct getters return the actual type (for direct access, not 
modification)
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "crate::core::OUString"_ostr; // Return high-level string type
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "crate::core::Any"_ostr; // Return high-level Any type
+    }
+
+    // Handle primitive types - return the Rust primitive directly
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        return getRustWrapperTypeName(unoType); // Return native Rust type 
(u8, i32, f64, etc.)
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    return "*mut c_void"_ostr;
+}
+
+OString RustProducer::getRustStructSetterParameterType(std::u16string_view 
unoType) const
+{
+    // Struct setters take the value to set
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "crate::core::OUString"_ostr; // Take high-level string type
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "crate::core::Any"_ostr; // Take high-level Any type
+    }
+
+    // Handle primitive types - take by value for direct assignment
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        return getRustWrapperTypeName(unoType); // Take native Rust type (u8, 
i32, f64, etc.)
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    return "*mut c_void"_ostr;
+}
+
+OString RustProducer::getRustStructExternGetterReturnType(std::u16string_view 
unoType) const
+{
+    // Struct extern getter return types (FFI-compatible)
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "*mut crate::ffi::rtl_string::rtl_uString"_ostr; // Return 
mutable pointer for from_raw compatibility
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "*const crate::ffi::uno_any::uno_Any"_ostr; // Return 
C-compatible Any pointer
+    }
+
+    // Handle primitive types - return pointer to primitive for FFI
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        return "*const " + getRustWrapperTypeName(unoType); // Return pointer 
to primitive type
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    return "*mut c_void"_ostr;
+}
+
+OString 
RustProducer::getRustStructExternSetterParameterType(std::u16string_view 
unoType) const
+{
+    // Struct extern setter parameter types (FFI-compatible)
+
+    // Handle string types
+    if (unoType == u"string")
+    {
+        return "*const crate::ffi::rtl_string::rtl_uString"_ostr; // Take 
const pointer for setter input (this is fine)
+    }
+
+    // Handle any types
+    if (unoType == u"any")
+    {
+        return "*const crate::ffi::uno_any::uno_Any"_ostr; // Take 
C-compatible Any pointer
+    }
+
+    // Handle primitive types - take by value for FFI (matches C++ side)
+    if (unoType == u"boolean" || unoType == u"byte" || unoType == u"short"
+        || unoType == u"unsigned short" || unoType == u"long" || unoType == 
u"unsigned long"
+        || unoType == u"hyper" || unoType == u"unsigned hyper" || unoType == 
u"float"
+        || unoType == u"double")
+    {
+        return getRustWrapperTypeName(
+            unoType); // Take primitive type by value (matches C++ approach)
+    }
+
+    // For all other types (typedefs, structs, enums, interfaces, sequences), 
use void*
+    return "*mut c_void"_ostr;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/rustmaker/rustproduce.hxx 
b/codemaker/source/rustmaker/rustproduce.hxx
index b0acba537c1e..6208f5c3bae0 100644
--- a/codemaker/source/rustmaker/rustproduce.hxx
+++ b/codemaker/source/rustmaker/rustproduce.hxx
@@ -80,6 +80,22 @@ private:
     static OString getRustTypeName(std::string_view unoName);
     OString getRustWrapperTypeName(std::u16string_view unoType) const;
     OString getRustReturnType(std::u16string_view unoType) const;
+    OString
+    getRustParameterType(std::u16string_view unoType,
+                         
unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) const;
+    OString getRustExternParameterType(
+        std::u16string_view unoType,
+        unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) 
const;
+
+    // Struct getter/setter type functions
+    OString getRustStructGetterReturnType(std::u16string_view unoType) const;
+    OString getRustStructSetterParameterType(std::u16string_view unoType) 
const;
+    OString getRustStructExternGetterReturnType(std::u16string_view unoType) 
const;
+    OString getRustStructExternSetterParameterType(std::u16string_view 
unoType) const;
+
+    OString convertRustParameterForFFICall(
+        std::u16string_view unoType, std::string_view paramName,
+        unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction) 
const;
     OString resolveTypedef(std::u16string_view unoType) const;
 
     // Type classification helpers
@@ -100,12 +116,15 @@ private:
                                       const 
rtl::Reference<unoidl::PlainStructTypeEntity>& entity);
     void generateStructConstructor(class RustFile& file, std::string_view 
externFunctionPrefix);
     void generateStructFromPtr(class RustFile& file, std::string_view 
externFunctionPrefix);
+    void generateStructAsPtr(class RustFile& file);
     void generateStructAccessors(class RustFile& file,
                                  const 
rtl::Reference<unoidl::PlainStructTypeEntity>& entity,
                                  std::string_view externFunctionPrefix);
     void generateStructMemberGetter(class RustFile& file, std::string_view 
memberName,
+                                    std::u16string_view memberType,
                                     std::string_view externFunctionPrefix);
     void generateStructMemberSetter(class RustFile& file, std::string_view 
memberName,
+                                    std::u16string_view memberType,
                                     std::string_view externFunctionPrefix);
     void generateStructDropTrait(class RustFile& file, std::string_view name,
                                  const 
rtl::Reference<unoidl::PlainStructTypeEntity>& entity);
diff --git a/rust_uno/build.rs b/rust_uno/build.rs
index 5f383acdbab3..cf64720a0e14 100644
--- a/rust_uno/build.rs
+++ b/rust_uno/build.rs
@@ -36,4 +36,3 @@ fn main() {
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
-
diff --git a/rust_uno/src/examples/load_writer.rs 
b/rust_uno/src/examples/load_writer.rs
index 575f64237005..67fc2d2c2212 100644
--- a/rust_uno/src/examples/load_writer.rs
+++ b/rust_uno/src/examples/load_writer.rs
@@ -7,13 +7,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-use crate::core::uno_wrapper::{UnoError, 
defaultBootstrap_InitialComponentContext};
-use crate::core::OUString;
-use crate::generated::rustmaker::com::sun::star::frame::Desktop::Desktop;
-use 
crate::generated::rustmaker::com::sun::star::frame::XComponentLoader::XComponentLoader;
-use 
crate::generated::rustmaker::com::sun::star::text::XTextDocument::XTextDocument;
-use 
crate::generated::rustmaker::com::sun::star::text::XSimpleText::XSimpleText;
-use std::ffi::c_void;
+use crate::{
+    core::{
+        OUString,
+        uno_wrapper::{UnoError, defaultBootstrap_InitialComponentContext},
+    },
+    generated::rustmaker::com::sun::star::{
+        frame::{Desktop::Desktop, XComponentLoader::XComponentLoader},
+        text::{XSimpleText::XSimpleText, XTextDocument::XTextDocument, 
XTextRange::XTextRange},
+    },
+};
 
 /// LibreOffice Writer automation demo using generated Rust UNO bindings.
 /// Creates a Writer document and inserts text using auto-generated interface 
wrappers.
@@ -25,11 +28,11 @@ pub fn run() {
         Ok(()) => {
             println!("=== Rust UNO Bridge Test Done ===");
             println!("<- 'load_writer' example completed successfully.");
-        },
+        }
         Err(e) => {
             println!("=== Rust UNO Bridge Test Done ===");
             eprintln!("   ERROR: 'load_writer' example failed: {e:?}");
-        },
+        }
     }
 }
 
@@ -45,8 +48,12 @@ fn run_internal() -> Result<(), UnoError> {
     println!("   ✓ Desktop service created: {:p}", desktop.as_ptr());
 
     // Get XComponentLoader interface
-    let component_loader = 
XComponentLoader::from_ptr(desktop.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
-    println!("   ✓ XComponentLoader interface acquired: {:p}", 
component_loader.as_ptr());
+    let component_loader =
+        
XComponentLoader::from_ptr(desktop.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
+    println!(
+        "   ✓ XComponentLoader interface acquired: {:p}",
+        component_loader.as_ptr()
+    );
 
     // Load Writer document
     println!("   Loading Writer document via 
XComponentLoader::loadComponentFromURL...");
@@ -55,24 +62,33 @@ fn run_internal() -> Result<(), UnoError> {
     let search_flags: i32 = 0;
     let empty_args = std::ptr::null_mut();
 
-    let document_interface_ptr = component_loader.loadComponentFromURL(
-        url.as_ptr() as *mut c_void,
-        target.as_ptr() as *mut c_void, 
-        &search_flags as *const i32 as *mut c_void,
-        empty_args,
-    ).ok_or(UnoError::OperationFailed)?;
-    
+    let document_interface_ptr = component_loader
+        .loadComponentFromURL(
+            url,    // Direct OUString - no casting needed!
+            target, // Direct OUString - no casting needed!
+            search_flags,
+            empty_args,
+        )
+        .ok_or(UnoError::OperationFailed)?;
+
     if document_interface_ptr.as_ptr().is_null() {
         return Err(UnoError::OperationFailed);
     }
-    
+
     println!("   ✓ Writer document loaded successfully!");
-    println!("   Document interface pointer: {:p}", 
document_interface_ptr.as_ptr());
+    println!(
+        "   Document interface pointer: {:p}",
+        document_interface_ptr.as_ptr()
+    );
 
     // Cast to XTextDocument
     println!("   Casting document to XTextDocument...");
-    let text_document = 
XTextDocument::from_ptr(document_interface_ptr.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
-    println!("   ✓ XTextDocument interface acquired: {:p}", 
text_document.as_ptr());
+    let text_document = 
XTextDocument::from_ptr(document_interface_ptr.as_ptr())
+        .ok_or(UnoError::InterfaceNotSupported)?;
+    println!(
+        "   ✓ XTextDocument interface acquired: {:p}",
+        text_document.as_ptr()
+    );
 
     // Get text object
     println!("   Getting text object via XTextDocument::getText...");
@@ -81,39 +97,54 @@ fn run_internal() -> Result<(), UnoError> {
 
     // Cast to XSimpleText
     println!("   Casting XText to XSimpleText...");
-    let simple_text = 
XSimpleText::from_ptr(text.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
-    println!("   ✓ XSimpleText interface acquired: {:p}", 
simple_text.as_ptr());
-    
+    let simple_text =
+        
XSimpleText::from_ptr(text.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
+    println!(
+        "   ✓ XSimpleText interface acquired: {:p}",
+        simple_text.as_ptr()
+    );
+
     // Create text cursor
     println!("   Creating text cursor via XSimpleText::createTextCursor...");
-    let cursor = 
simple_text.createTextCursor().ok_or(UnoError::OperationFailed)?;
+    let cursor = simple_text
+        .createTextCursor()
+        .ok_or(UnoError::OperationFailed)?;
     println!("   ✓ Text cursor created: {:p}", cursor.as_ptr());
 
     // Insert text
     println!("   Inserting text via XSimpleText::insertString...");
     let hello_text = OUString::from(
-        "Hello from Generated Rust UNO Bindings!

\
+        "Hello from Generated Rust UNO Bindings with Typed Parameters! 

\
          This text was inserted using auto-generated service and interface 
wrappers:

\
          - Desktop::create() - Generated service wrapper
\
          - XComponentLoader::loadComponentFromURL() - Generated interface 
method
\
          - XTextDocument::getText() - Generated interface method
\
          - XSimpleText::createTextCursor() - Generated interface method
\
          - XSimpleText::insertString() - Generated interface method

\
-         All types generated automatically from UNO IDL with type-safe opaque 
pointer architecture!

\
-         FFI Validation Features Demonstrated:
\
+          NEW: Typed Parameter API Achievements:
\
+         - Boolean parameters now use native 'bool' instead of void* casting
\
+         - Integer parameters use direct 'i32' instead of pointer arithmetic
\
+         - Natural Rust syntax: 'absorb as u8' vs '*ptr as *mut c_void'
\
+         - Direction-aware: input by value, input/output by pointer
\
+         - Type-safe at compile time with better IDE support

\
+         FFI Architecture Features:
\
          - Automatic null pointer checking in all generated methods
\
          - Reference validity validation (is() checking) 
\
          - Memory cleanup on validation failure (delete + return nullptr)
\
          - Detailed debug logging for troubleshooting
\
          - Type-safe opaque pointer architecture prevents crashes
\
-         - Follows uno_bootstrap.cxx validation pattern exactly"
+         - Progressive migration: primitives typed, complex types remain 
compatible",
     );
-    let absorb: i32 = 0;
+    let absorb: bool = false;
+
+    // Convert XTextCursor to XTextRange (interface inheritance)
+    let text_range =
+        
XTextRange::from_ptr(cursor.as_ptr()).ok_or(UnoError::InterfaceNotSupported)?;
 
     simple_text.insertString(
-        cursor.as_ptr() as *mut c_void,
-        hello_text.as_ptr() as *mut c_void,
-        &absorb as *const i32 as *mut c_void,
+        text_range,   // Direct typed interface - no void* casting needed!
+        hello_text,   // Direct OUString - no casting needed!
+        absorb as u8, //  Direct boolean parameter (natural Rust syntax!)
     );
 
     println!("   ✓ Text inserted successfully using generated interfaces!");
@@ -121,4 +152,4 @@ fn run_internal() -> Result<(), UnoError> {
     Ok(())
 }
 
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 048761fb2219d4df7b201bf6269f8396b1639af8
Author:     Mohamed Ali <[email protected]>
AuthorDate: Mon Sep 22 03:46:15 2025 +0300
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Mon Sep 29 09:57:35 2025 +0200

    Rust Bindings: Refactor RustProducer and CppProducer
    
    Change-Id: I3b40c7a7eb572d95b91d1ec8eeda17a971331f67
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191476
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/codemaker/source/rustmaker/cpproduce.cxx 
b/codemaker/source/rustmaker/cpproduce.cxx
index 1f0deae93e64..d027f5834c36 100644
--- a/codemaker/source/rustmaker/cpproduce.cxx
+++ b/codemaker/source/rustmaker/cpproduce.cxx
@@ -2012,152 +2012,8 @@ void CppProducer::generateActualMethodCall(CppFile& 
file,
     // Handle return value conversion for non-void methods
     if (method.returnType != u"void")
     {
-        file.beginLine().append("// Convert result to opaque void* 
return").endLine();
-
-        std::u16string_view returnType = method.returnType;
-
-        if (returnType == u"string")
-        {
-            file.beginLine().append("return new OUString(result);").endLine();
-        }
-        else if (returnType == u"any")
-        {
-            file.beginLine().append("return new Any(result);").endLine();
-        }
-        else if (returnType == u"boolean")
-        {
-            file.beginLine().append("return new sal_Bool(result);").endLine();
-        }
-        else if (returnType == u"byte")
-        {
-            file.beginLine().append("return new sal_Int8(result);").endLine();
-        }
-        else if (returnType == u"short")
-        {
-            file.beginLine().append("return new sal_Int16(result);").endLine();
-        }
-        else if (returnType == u"long")
-        {
-            file.beginLine().append("return new sal_Int32(result);").endLine();
-        }
-        else if (returnType == u"hyper")
-        {
-            file.beginLine().append("return new sal_Int64(result);").endLine();
-        }
-        else if (returnType == u"float")
-        {
-            file.beginLine().append("return new float(result);").endLine();
-        }
-        else if (returnType == u"double")
-        {
-            file.beginLine().append("return new double(result);").endLine();
-        }
-        else if (returnType == u"type")
-        {
-            file.beginLine().append("return new Type(result);").endLine();
-        }
-        else if (returnType.starts_with(u"[]"))
-        {
-            // Sequence return type
-            file.beginLine()
-                .append("return new ")
-                .append(convertUnoTypeToCpp(returnType))
-                .append("(result);")
-                .endLine();
-        }
-        else
-        {
-            // For interfaces and other complex types, create appropriate 
wrapper
-            // Check if it's an interface type
-            rtl::Reference<unoidl::Entity> entity;
-            codemaker::UnoType::Sort sort = 
m_typeManager->getSort(OUString(returnType), &entity);
-
-            if (sort == codemaker::UnoType::Sort::Interface)
-            {
-                // Add debug output for interface return values
-                file.beginLine()
-                    .append("SAL_WARN(\"rustmaker\", \"Debug: UNO method ")
-                    .append(method.name)
-                    .append(
-                        " completed, result.is() = \" << (result.is() ? 
\"true\" : \"false\"));")
-                    .endLine()
-                    .beginLine()
-                    .append("SAL_INFO(\"rust_uno_ffi\", \"Creating new 
Reference<")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append("> wrapper for method ")
-                    .append(method.name)
-                    .append("\");")
-                    .endLine()
-                    .beginLine()
-                    .append("auto res = new Reference<")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append(">(result);")
-                    .endLine()
-                    .beginLine()
-                    .append("")
-                    .endLine()
-                    .beginLine()
-                    .append("if (!res)")
-                    .endLine()
-                    .beginBlock()
-                    .beginLine()
-                    .append("SAL_WARN(\"rust_uno_ffi\", \"Failed to create 
Reference wrapper for ")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append(" in method ")
-                    .append(method.name)
-                    .append("\");")
-                    .endLine()
-                    .beginLine()
-                    .append("return nullptr;")
-                    .endLine()
-                    .endBlock()
-                    .beginLine()
-                    .append("")
-                    .endLine()
-                    .beginLine()
-                    .append("if (!res->is())")
-                    .endLine()
-                    .beginBlock()
-                    .beginLine()
-                    .append("SAL_WARN(\"rust_uno_ffi\", \"Reference wrapper is 
invalid (is() = "
-                            "false) for ")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append(" in method ")
-                    .append(method.name)
-                    .append("\");")
-                    .endLine()
-                    .beginLine()
-                    .append("delete res;")
-                    .endLine()
-                    .beginLine()
-                    .append("return nullptr;")
-                    .endLine()
-                    .endBlock()
-                    .beginLine()
-                    .append("")
-                    .endLine()
-                    .beginLine()
-                    .append("SAL_INFO(\"rust_uno_ffi\", \"✅ Successfully 
created valid Reference "
-                            "wrapper for ")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append(" in method ")
-                    .append(method.name)
-                    .append("\");")
-                    .endLine()
-                    .beginLine()
-                    .append("return res;")
-                    .endLine();
-            }
-            else
-            {
-                // For structs and other types
-                file.beginLine()
-                    .append("return new ")
-                    .append(convertUnoTypeToCpp(returnType))
-                    .append("(result);")
-                    .endLine();
-            }
-        }
+        // Use helper function to eliminate code duplication
+        generateReturnValueConversion(file, method);
     }
 }
 
@@ -2409,74 +2265,6 @@ OString CppProducer::getCppTypeName(std::u16string_view 
unoType) const
         return "void*"_ostr; // Default to void* for unknown types
 }
 
-OString CppProducer::getRustFFITypeName(std::u16string_view unoType) const
-{
-    // Map UNO types to Rust FFI types
-    if (unoType == u"string")
-        return "*mut rtl_uString"_ostr;
-    else if (unoType == u"boolean")
-        return "u8"_ostr; // sal_Bool is typedef'd to u8 (unsigned char)
-    else if (unoType == u"byte")
-        return "i8"_ostr;
-    else if (unoType == u"short")
-        return "i16"_ostr;
-    else if (unoType == u"unsigned short")
-        return "u16"_ostr;
-    else if (unoType == u"long")
-        return "i32"_ostr;
-    else if (unoType == u"unsigned long")
-        return "u32"_ostr;
-    else if (unoType == u"hyper")
-        return "i64"_ostr;
-    else if (unoType == u"unsigned hyper")
-        return "u64"_ostr;
-    else if (unoType == u"float")
-        return "f32"_ostr;
-    else if (unoType == u"double")
-        return "f64"_ostr;
-    else if (unoType == u"void")
-        return "()"_ostr;
-    else if (unoType == u"any" || unoType == u"com.sun.star.uno.Any")
-        return "*mut uno_Any"_ostr; // UNO Any type
-    else if (isUnoStruct(unoType))
-    {
-        // For structs, return just the struct name with underscore since we 
import it
-        OString type = u2b(unoType);
-        size_t lastDot = type.lastIndexOf('.');
-        if (lastDot != std::string_view::npos)
-            return OString::Concat(type.subView(lastDot + 1)) + "_";
-        else
-            return type + "_";
-    }
-    else if (isUnoEnum(unoType))
-    {
-        // For enums, return just the enum name since we import it
-        OString type = u2b(unoType);
-        size_t lastDot = type.lastIndexOf('.');
-        if (lastDot != std::string_view::npos)
-            return OString(type.subView(lastDot + 1));
-        else
-            return type;
-    }
-    else if (isUnoConstantGroup(unoType))
-    {
-        // For constant groups, return the constant group name with underscore 
to match C++ side
-        OString type = u2b(unoType);
-        size_t lastDot = type.lastIndexOf('.');
-        if (lastDot != std::string_view::npos)
-            return OString::Concat(type.subView(lastDot + 1)) + "_";
-        else
-            return type + "_";
-    }
-    else if (isUnoType(unoType))
-    {
-        // For interfaces, return *mut XInterface pointer
-        return "*mut XInterface"_ostr;
-    }
-    else
-        return "*mut std::ffi::c_void"_ostr; // Default for unknown types
-}
-
 OString CppProducer::convertBasicType(const OString& typeName)
 {
     OString result = typeName;
diff --git a/codemaker/source/rustmaker/rustproduce.cxx 
b/codemaker/source/rustmaker/rustproduce.cxx
index e811c8787fa0..b15780a7c053 100644
--- a/codemaker/source/rustmaker/rustproduce.cxx
+++ b/codemaker/source/rustmaker/rustproduce.cxx
@@ -14,7 +14,7 @@
 #include <iostream>
 #include <set>
 
-RustProducer::RustProducer(const OString& outputDir, bool verbose, bool dryRun,
+RustProducer::RustProducer(std::string_view outputDir, bool verbose, bool 
dryRun,
                            const rtl::Reference<TypeManager>& typeManager)
     : m_outputDir(outputDir)
     , m_verbose(verbose)
@@ -35,8 +35,17 @@ void RustProducer::produceEnum(std::string_view name,
 
     file.openFile();
 
+    generateEnumDefinition(file, name, entity);
+    generateEnumImplementation(file, name);
+    generateEnumExternDeclarations(file, name);
+
+    file.closeFile();
+}
+
+void RustProducer::generateEnumDefinition(RustFile& file, std::string_view 
name,
+                                          const 
rtl::Reference<unoidl::EnumTypeEntity>& entity)
+{
     OString typeName(splitName(name)); // Simple name for Rust enum
-    OString externFunctionPrefix = getRustTypeName(name); // Full name for 
extern "C" functions
 
     file.beginLine()
         .append("/// Opaque Rust enum wrapper for ")
@@ -79,6 +88,12 @@ void RustProducer::produceEnum(std::string_view name,
     }
 
     file.endBlock();
+}
+
+void RustProducer::generateEnumImplementation(RustFile& file, std::string_view 
name)
+{
+    OString typeName(splitName(name)); // Simple name for Rust enum
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Add conversion functions using extern "C" bridge
     file.beginLine()
@@ -117,6 +132,12 @@ void RustProducer::produceEnum(std::string_view name,
         .append("}")
         .endLine()
         .endBlock();
+}
+
+void RustProducer::generateEnumExternDeclarations(RustFile& file, 
std::string_view name)
+{
+    OString typeName(splitName(name)); // Simple name for Rust enum
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Extern "C" declarations
     file.beginLine()
@@ -143,8 +164,6 @@ void RustProducer::produceEnum(std::string_view name,
         .beginLine()
         .append("}")
         .endLine();
-
-    file.closeFile();
 }
 
 void RustProducer::produceStruct(std::string_view name,
@@ -159,8 +178,19 @@ void RustProducer::produceStruct(std::string_view name,
 
     file.openFile();
 
+    generateStructDefinition(file, name, entity);
+    generateStructImplementation(file, name, entity);
+    generateStructDropTrait(file, name, entity);
+    generateStructExternDeclarations(file, name, entity);
+
+    file.closeFile();
+}
+
+void RustProducer::generateStructDefinition(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::PlainStructTypeEntity>& /* entity */)
+{
     OString typeName(splitName(name)); // Simple name for Rust struct
-    OString externFunctionPrefix = getRustTypeName(name); // Full name for 
extern "C" functions
 
     file.beginLine()
         .append("/// Opaque Rust struct wrapper for ")
@@ -181,6 +211,14 @@ void RustProducer::produceStruct(std::string_view name,
         .append("ptr: *mut c_void,")
         .endLine()
         .endBlock();
+}
+
+void RustProducer::generateStructImplementation(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::PlainStructTypeEntity>& entity)
+{
+    OString typeName(splitName(name)); // Simple name for Rust struct
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Implementation with opaque field accessors
     file.beginLine()
@@ -192,6 +230,15 @@ void RustProducer::produceStruct(std::string_view name,
         .endLine()
         .beginBlock();
 
+    generateStructConstructor(file, externFunctionPrefix);
+    generateStructFromPtr(file, externFunctionPrefix);
+    generateStructAccessors(file, entity, externFunctionPrefix);
+
+    file.endBlock();
+}
+
+void RustProducer::generateStructConstructor(RustFile& file, std::string_view 
externFunctionPrefix)
+{
     // Constructor
     file.beginLine()
         .append("pub fn new() -> Option<Self> {")
@@ -222,7 +269,10 @@ void RustProducer::produceStruct(std::string_view name,
         .beginLine()
         .append("}")
         .endLine();
+}
 
+void RustProducer::generateStructFromPtr(RustFile& file, std::string_view 
externFunctionPrefix)
+{
     // from_ptr method for creating wrapper from existing pointer with C++ 
type casting
     file.beginLine()
         .append("")
@@ -253,56 +303,76 @@ void RustProducer::produceStruct(std::string_view name,
         .endLine()
         .endBlock()
         .endBlock();
+}
 
-    // Opaque field accessors
+void RustProducer::generateStructAccessors(
+    RustFile& file, const rtl::Reference<unoidl::PlainStructTypeEntity>& 
entity,
+    std::string_view externFunctionPrefix)
+{
+    // Generate getters and setters for all struct members
     for (const auto& member : entity->getDirectMembers())
     {
         OString memberName = u2b(member.name); // Use original case, not 
snake_case
 
-        // Getter
-        file.beginLine()
-            .append("")
-            .endLine()
-            .beginLine()
-            .append("pub fn get_")
-            .append(memberName)
-            .append("(&self) -> *mut c_void {")
-            .endLine()
-            .extraIndent()
-            .beginLine()
-            .append("unsafe { ")
-            .append(externFunctionPrefix)
-            .append("_get_")
-            .append(memberName)
-            .append("(self.ptr) }")
-            .endLine()
-            .beginLine()
-            .append("}")
-            .endLine();
-
-        // Setter
-        file.beginLine()
-            .append("")
-            .endLine()
-            .beginLine()
-            .append("pub fn set_")
-            .append(memberName)
-            .append("(&mut self, value: *mut c_void) {")
-            .endLine()
-            .extraIndent()
-            .beginLine()
-            .append("unsafe { ")
-            .append(externFunctionPrefix)
-            .append("_set_")
-            .append(memberName)
-            .append("(self.ptr, value) }")
-            .endLine()
-            .beginLine()
-            .append("}")
-            .endLine();
+        generateStructMemberGetter(file, memberName, externFunctionPrefix);
+        generateStructMemberSetter(file, memberName, externFunctionPrefix);
     }
+}
 
-    file.endBlock();
+void RustProducer::generateStructMemberGetter(RustFile& file, std::string_view 
memberName,
+                                              std::string_view 
externFunctionPrefix)
+{
+    file.beginLine()
+        .append("")
+        .endLine()
+        .beginLine()
+        .append("pub fn get_")
+        .append(memberName)
+        .append("(&self) -> *mut c_void {")
+        .endLine()
+        .extraIndent()
+        .beginLine()
+        .append("unsafe { ")
+        .append(externFunctionPrefix)
+        .append("_get_")
+        .append(memberName)
+        .append("(self.ptr) }")
+        .endLine()
+        .beginLine()
+        .append("}")
+        .endLine();
+}
+
+void RustProducer::generateStructMemberSetter(RustFile& file, std::string_view 
memberName,
+                                              std::string_view 
externFunctionPrefix)
+{
+    file.beginLine()
+        .append("")
+        .endLine()
+        .beginLine()
+        .append("pub fn set_")
+        .append(memberName)
+        .append("(&mut self, value: *mut c_void) {")
+        .endLine()
+        .extraIndent()
+        .beginLine()
+        .append("unsafe { ")
+        .append(externFunctionPrefix)
+        .append("_set_")
+        .append(memberName)
+        .append("(self.ptr, value) }")
+        .endLine()
+        .beginLine()
+        .append("}")
+        .endLine();
+}
+
+void RustProducer::generateStructDropTrait(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::PlainStructTypeEntity>& /* entity */)
+{
+    OString typeName(splitName(name)); // Simple name for Rust struct
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Drop implementation
     file.beginLine()
@@ -333,6 +403,13 @@ void RustProducer::produceStruct(std::string_view name,
         .append("}")
         .endLine()
         .endBlock();
+}
+
+void RustProducer::generateStructExternDeclarations(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::PlainStructTypeEntity>& entity)
+{
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Extern "C" declarations for opaque operations
     file.beginLine()
@@ -341,8 +418,18 @@ void RustProducer::produceStruct(std::string_view name,
         .beginLine()
         .append("unsafe extern \"C\" {")
         .endLine()
-        .extraIndent()
-        .beginLine()
+        .extraIndent();
+
+    generateStructBasicExternDeclarations(file, externFunctionPrefix);
+    generateStructMemberExternDeclarations(file, entity, externFunctionPrefix);
+
+    file.beginLine().append("}").endLine();
+}
+
+void RustProducer::generateStructBasicExternDeclarations(RustFile& file,
+                                                         std::string_view 
externFunctionPrefix)
+{
+    file.beginLine()
         .append("fn ")
         .append(externFunctionPrefix)
         .append("_constructor() -> *mut c_void;")
@@ -357,7 +444,12 @@ void RustProducer::produceStruct(std::string_view name,
         .append(externFunctionPrefix)
         .append("_from_ptr(ptr: *mut c_void) -> *mut c_void;")
         .endLine();
+}
 
+void RustProducer::generateStructMemberExternDeclarations(
+    RustFile& file, const rtl::Reference<unoidl::PlainStructTypeEntity>& 
entity,
+    std::string_view externFunctionPrefix)
+{
     for (const auto& member : entity->getDirectMembers())
     {
         OString memberName = u2b(member.name); // Use original case, not 
snake_case
@@ -376,10 +468,6 @@ void RustProducer::produceStruct(std::string_view name,
             .append("(ptr: *mut c_void, value: *mut c_void);")
             .endLine();
     }
-
-    file.beginLine().append("}").endLine();
-
-    file.closeFile();
 }
 
 void RustProducer::produceInterface(std::string_view name,
@@ -394,9 +482,20 @@ void RustProducer::produceInterface(std::string_view name,
 
     file.openFile();
 
+    generateInterfaceWrapper(file, name, entity);
+    generateInterfaceExternDeclarations(file, name, entity);
+
+    file.closeFile();
+}
+
+void RustProducer::generateInterfaceWrapper(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::InterfaceTypeEntity>& entity)
+{
     OString typeName(splitName(name)); // Simple name for Rust interface
-    OString externFunctionPrefix = getRustTypeName(name); // Full name for 
extern "C" functions
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
+    // Generate struct header and documentation
     file.beginLine()
         .append("/// Opaque Rust interface wrapper for ")
         .append(name)
@@ -417,7 +516,20 @@ void RustProducer::produceInterface(std::string_view name,
         .endLine()
         .endBlock();
 
-    // Implementation block
+    // Generate implementation block with constructor, methods, etc.
+    generateInterfaceImplementation(file, typeName, externFunctionPrefix, 
entity);
+
+    // Generate Drop trait implementation
+    generateInterfaceDropTrait(file, typeName, externFunctionPrefix);
+
+    // Generate thread safety markers
+    generateInterfaceThreadSafety(file, typeName);
+}
+
+void RustProducer::generateInterfaceImplementation(
+    RustFile& file, std::string_view typeName, std::string_view 
externFunctionPrefix,
+    const rtl::Reference<unoidl::InterfaceTypeEntity>& entity)
+{
     file.beginLine()
         .append("")
         .endLine()
@@ -427,7 +539,27 @@ void RustProducer::produceInterface(std::string_view name,
         .endLine()
         .beginBlock();
 
-    // Constructor
+    // Generate constructor
+    generateInterfaceConstructor(file, externFunctionPrefix);
+
+    // Generate from_ptr method
+    generateInterfaceFromPtr(file, externFunctionPrefix);
+
+    // Generate as_ptr method
+    generateInterfaceAsPtr(file);
+
+    // Generate validity check if no conflicting method
+    generateInterfaceValidityCheck(file, externFunctionPrefix, entity);
+
+    // Generate method wrappers
+    generateInterfaceMethodWrappers(file, externFunctionPrefix, entity);
+
+    file.endBlock();
+}
+
+void RustProducer::generateInterfaceConstructor(RustFile& file,
+                                                std::string_view 
externFunctionPrefix)
+{
     file.beginLine()
         .append("pub fn new() -> Option<Self> {")
         .endLine()
@@ -457,8 +589,10 @@ void RustProducer::produceInterface(std::string_view name,
         .beginLine()
         .append("}")
         .endLine();
+}
 
-    // from_ptr method for creating wrapper from existing pointer with C++ 
type casting
+void RustProducer::generateInterfaceFromPtr(RustFile& file, std::string_view 
externFunctionPrefix)
+{
     file.beginLine()
         .append("")
         .endLine()
@@ -488,8 +622,10 @@ void RustProducer::produceInterface(std::string_view name,
         .endLine()
         .endBlock()
         .endBlock();
+}
 
-    // as_ptr method for getting the raw pointer
+void RustProducer::generateInterfaceAsPtr(RustFile& file)
+{
     file.beginLine()
         .append("")
         .endLine()
@@ -501,8 +637,13 @@ void RustProducer::produceInterface(std::string_view name,
         .append("self.ptr")
         .endLine()
         .endBlock();
+}
 
-    // Validity check - only add if there's no conflicting isValid method
+void RustProducer::generateInterfaceValidityCheck(
+    RustFile& file, std::string_view externFunctionPrefix,
+    const rtl::Reference<unoidl::InterfaceTypeEntity>& entity)
+{
+    // Check if there's already an isValid method to avoid conflicts
     bool hasIsValidMethod = false;
     for (const auto& method : entity->getDirectMethods())
     {
@@ -531,8 +672,13 @@ void RustProducer::produceInterface(std::string_view name,
             .append("}")
             .endLine();
     }
+}
 
-    // Method wrappers - all methods return opaque pointers
+void RustProducer::generateInterfaceMethodWrappers(
+    RustFile& file, std::string_view externFunctionPrefix,
+    const rtl::Reference<unoidl::InterfaceTypeEntity>& entity)
+{
+    // Generate method wrappers - all methods return opaque pointers
     for (const auto& method : entity->getDirectMethods())
     {
         OString rustMethodName = getRustFunctionName(u2b(method.name));
@@ -671,112 +817,12 @@ void RustProducer::produceInterface(std::string_view 
name,
                 else
                 {
                     // Check for typedef resolution first
-                    OString resolvedType = resolveTypedef(method.returnType);
-                    if (resolvedType != rustType)
+                    OString resolvedType(resolveTypedef(method.returnType));
+                    // It's a typedef - handle based on resolved type
+                    if (!generateTypeCastReturn(file, resolvedType))
                     {
-                        // It's a typedef - handle based on resolved type
-                        if (resolvedType == "boolean")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u8) }").endLine();
-                        }
-                        else if (resolvedType == "byte")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i8) }").endLine();
-                        }
-                        else if (resolvedType == "short")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i16) }").endLine();
-                        }
-                        else if (resolvedType == "unsigned short")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u16) }").endLine();
-                        }
-                        else if (resolvedType == "long")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i32) }").endLine();
-                        }
-                        else if (resolvedType == "unsigned long")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u32) }").endLine();
-                        }
-                        else if (resolvedType == "hyper")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i64) }").endLine();
-                        }
-                        else if (resolvedType == "unsigned hyper")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u64) }").endLine();
-                        }
-                        else if (resolvedType == "float")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
f32) }").endLine();
-                        }
-                        else if (resolvedType == "double")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
f64) }").endLine();
-                        }
-                        else if (resolvedType == "char")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u16) }").endLine();
-                        }
-                        else
-                        {
-                            // Typedef resolves to other types - return raw 
pointer
-                            file.beginLine().append("ptr").endLine();
-                        }
-                    }
-                    else
-                    {
-                        // Not a typedef - check for primitive types that need 
dereferencing
-                        if (rustType == "boolean")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u8) }").endLine();
-                        }
-                        else if (rustType == "byte")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i8) }").endLine();
-                        }
-                        else if (rustType == "short")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i16) }").endLine();
-                        }
-                        else if (rustType == "unsigned short")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u16) }").endLine();
-                        }
-                        else if (rustType == "long")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i32) }").endLine();
-                        }
-                        else if (rustType == "unsigned long")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u32) }").endLine();
-                        }
-                        else if (rustType == "hyper")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
i64) }").endLine();
-                        }
-                        else if (rustType == "unsigned hyper")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u64) }").endLine();
-                        }
-                        else if (rustType == "float")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
f32) }").endLine();
-                        }
-                        else if (rustType == "double")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
f64) }").endLine();
-                        }
-                        else if (rustType == "char")
-                        {
-                            file.beginLine().append("unsafe { *(ptr as *const 
u16) }").endLine();
-                        }
-                        else
-                        {
-                            // For other types (sequences, templates, etc), 
return the raw pointer
-                            file.beginLine().append("ptr").endLine();
-                        }
+                        // Typedef resolves to non-primitive types - return 
raw pointer
+                        file.beginLine().append("ptr").endLine();
                     }
                 }
             }
@@ -784,10 +830,11 @@ void RustProducer::produceInterface(std::string_view name,
 
         file.beginLine().append("}").endLine();
     }
+}
 
-    file.endBlock();
-
-    // Drop implementation for automatic cleanup
+void RustProducer::generateInterfaceDropTrait(RustFile& file, std::string_view 
typeName,
+                                              std::string_view 
externFunctionPrefix)
+{
     file.beginLine()
         .append("")
         .endLine()
@@ -816,7 +863,10 @@ void RustProducer::produceInterface(std::string_view name,
         .append("}")
         .endLine()
         .endBlock();
+}
 
+void RustProducer::generateInterfaceThreadSafety(RustFile& file, 
std::string_view typeName)
+{
     // Thread safety markers
     file.beginLine()
         .append("")
@@ -831,6 +881,13 @@ void RustProducer::produceInterface(std::string_view name,
         .append(typeName)
         .append(" {}")
         .endLine();
+}
+
+void RustProducer::generateInterfaceExternDeclarations(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::InterfaceTypeEntity>& entity)
+{
+    OString externFunctionPrefix(getRustTypeName(name));
 
     // Extern "C" declarations - connects to C-side bridge
     file.beginLine()
@@ -856,6 +913,17 @@ void RustProducer::produceInterface(std::string_view name,
         .append("_from_ptr(ptr: *mut c_void) -> *mut c_void;")
         .endLine();
 
+    // Check if there's already an isValid method to avoid conflicts
+    bool hasIsValidMethod = false;
+    for (const auto& method : entity->getDirectMethods())
+    {
+        if (u2b(method.name).equalsIgnoreAsciiCase("isValid"))
+        {
+            hasIsValidMethod = true;
+            break;
+        }
+    }
+
     // Only declare _is_valid if we don't have a conflicting isValid method
     if (!hasIsValidMethod)
     {
@@ -895,8 +963,6 @@ void RustProducer::produceInterface(std::string_view name,
     }
 
     file.beginLine().append("}").endLine();
-
-    file.closeFile();
 }
 
 void RustProducer::produceService(
@@ -911,19 +977,18 @@ void RustProducer::produceService(
 
     file.openFile();
 
-    OString serviceName(splitName(name)); // Simple name for Rust service
-    OString externFunctionPrefix = getRustTypeName(name); // Full name for 
extern "C" functions
-    OUString interfaceType = entity->getBase();
+    generateServiceDefinition(file, name, entity);
+    generateServiceImplementation(file, name, entity);
+    generateServiceExternDeclarations(file, name, entity);
 
-    // Generate proper module path for the interface
-    OString interfaceTypeStr = u2b(interfaceType);
-    std::string_view interfaceTypeName = splitName(interfaceTypeStr);
+    file.closeFile();
+}
 
-    // Convert interface type to full module path
-    OString path = interfaceTypeStr;
-    path = path.replaceAll("."_ostr, "::"_ostr);
-    OString interfaceModulePath
-        = "crate::generated::rustmaker::"_ostr + path + "::" + 
interfaceTypeName;
+void RustProducer::generateServiceDefinition(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>& /* entity 
*/)
+{
+    OString serviceName(splitName(name)); // Simple name for Rust service
 
     file.beginLine()
         .append("/// Opaque Rust service wrapper for ")
@@ -942,6 +1007,13 @@ void RustProducer::produceService(
         .append(serviceName)
         .append(";")
         .endLine();
+}
+
+void RustProducer::generateServiceImplementation(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>& entity)
+{
+    OString serviceName(splitName(name)); // Simple name for Rust service
 
     // Implementation block
     file.beginLine()
@@ -953,6 +1025,21 @@ void RustProducer::produceService(
         .endLine()
         .beginBlock();
 
+    generateServiceCreateMethod(file, name, entity);
+
+    file.endBlock();
+}
+
+void RustProducer::generateServiceCreateMethod(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>& entity)
+{
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
+    OUString interfaceType = entity->getBase();
+
+    // Generate proper module path for the interface
+    OString interfaceModulePath = 
generateServiceInterfaceModulePath(interfaceType);
+
     // Service creation method
     file.beginLine()
         .append("/// Create a new instance of ")
@@ -987,8 +1074,25 @@ void RustProducer::produceService(
         .endLine()
         .endBlock()
         .endBlock();
+}
 
-    file.endBlock();
+OString RustProducer::generateServiceInterfaceModulePath(const OUString& 
interfaceType)
+{
+    // Generate proper module path for the interface
+    OString interfaceTypeStr = u2b(interfaceType);
+    std::string_view interfaceTypeName = splitName(interfaceTypeStr);
+
+    // Convert interface type to full module path
+    OString path = interfaceTypeStr;
+    path = path.replaceAll("."_ostr, "::"_ostr);
+    return "crate::generated::rustmaker::"_ostr + path + "::" + 
interfaceTypeName;
+}
+
+void RustProducer::generateServiceExternDeclarations(
+    RustFile& file, std::string_view name,
+    const rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>& /* entity 
*/)
+{
+    OString externFunctionPrefix(getRustTypeName(name)); // Full name for 
extern "C" functions
 
     // Extern "C" declarations
     file.beginLine()
@@ -1004,8 +1108,68 @@ void RustProducer::produceService(
         .append("_create(context: *mut c_void) -> *mut c_void;")
         .endLine()
         .endBlock();
+}
 
-    file.closeFile();
+bool RustProducer::generateTypeCastReturn(RustFile& file, std::string_view 
resolvedType) const
+{
+    if (resolvedType == "boolean")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const u8) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "byte")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const i8) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "short")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const i16) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "unsigned short")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const u16) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "long")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const i32) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "unsigned long")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const u32) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "hyper")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const i64) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "unsigned hyper")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const u64) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "float")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const f32) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "double")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const f64) }").endLine();
+        return true;
+    }
+    else if (resolvedType == "char")
+    {
+        file.beginLine().append("unsafe { *(ptr as *const u16) }").endLine();
+        return true;
+    }
+
+    // Return false if no type casting was generated (not a primitive type)
+    return false;
 }
 
 // Helper functions
@@ -1110,7 +1274,7 @@ OString 
RustProducer::getRustWrapperTypeName(std::u16string_view unoType) const
         }
 
         // First resolve typedefs
-        OString resolvedType = resolveTypedef(unoType);
+        OString resolvedType(resolveTypedef(unoType));
         if (resolvedType != rustType)
         {
             // It's a typedef - recursively get wrapper type for resolved type
@@ -1186,27 +1350,6 @@ OString 
RustProducer::getRustReturnType(std::u16string_view unoType) const
     return getRustWrapperTypeName(unoType);
 }
 
-OString RustProducer::getRustFFIReturnType(std::u16string_view unoType) const
-{
-    // Handle void returns
-    if (unoType == u"void")
-    {
-        return "()"_ostr;
-    }
-
-    // For interfaces, structs, enums - return their opaque handle typedef
-    if (isUnoInterface(unoType) || isUnoStruct(unoType) || isUnoEnum(unoType))
-    {
-        // Convert UNO type name to typedef handle name
-        // com.sun.star.lang.XMain -> com__sun__star__lang__XMainHandle
-        OString functionPrefix = getRustTypeName(std::string(unoType.begin(), 
unoType.end()));
-        return functionPrefix + "Handle";
-    }
-
-    // For other types (primitives, sequences, etc) - use void*
-    return "*mut c_void"_ostr;
-}
-
 bool RustProducer::isUnoInterface(std::u16string_view typeName) const
 {
     rtl::Reference<unoidl::Entity> entity;
diff --git a/codemaker/source/rustmaker/rustproduce.hxx 
b/codemaker/source/rustmaker/rustproduce.hxx
index 3c2d0fb2cbfe..b0acba537c1e 100644
--- a/codemaker/source/rustmaker/rustproduce.hxx
+++ b/codemaker/source/rustmaker/rustproduce.hxx
@@ -37,7 +37,7 @@ public:
      * @param dryRun Don't actually write files
      * @param typeManager UNO type manager for accessing type information
      */
-    RustProducer(const OString& outputDir, bool verbose, bool dryRun,
+    RustProducer(std::string_view outputDir, bool verbose, bool dryRun,
                  const rtl::Reference<TypeManager>& typeManager);
 
     /**
@@ -80,13 +80,83 @@ private:
     static OString getRustTypeName(std::string_view unoName);
     OString getRustWrapperTypeName(std::u16string_view unoType) const;
     OString getRustReturnType(std::u16string_view unoType) const;
-    OString getRustFFIReturnType(std::u16string_view unoType) const;
     OString resolveTypedef(std::u16string_view unoType) const;
 
     // Type classification helpers
     bool isUnoInterface(std::u16string_view typeName) const;
     bool isUnoStruct(std::u16string_view typeName) const;
     bool isUnoEnum(std::u16string_view typeName) const;
+
+    // Enum generation helpers (following CppProducer pattern)
+    void generateEnumDefinition(class RustFile& file, std::string_view name,
+                                const rtl::Reference<unoidl::EnumTypeEntity>& 
entity);
+    void generateEnumImplementation(class RustFile& file, std::string_view 
name);
+    void generateEnumExternDeclarations(class RustFile& file, std::string_view 
name);
+
+    // Struct generation helpers (following CppProducer pattern)
+    void generateStructDefinition(class RustFile& file, std::string_view name,
+                                  const 
rtl::Reference<unoidl::PlainStructTypeEntity>& entity);
+    void generateStructImplementation(class RustFile& file, std::string_view 
name,
+                                      const 
rtl::Reference<unoidl::PlainStructTypeEntity>& entity);
+    void generateStructConstructor(class RustFile& file, std::string_view 
externFunctionPrefix);
+    void generateStructFromPtr(class RustFile& file, std::string_view 
externFunctionPrefix);
+    void generateStructAccessors(class RustFile& file,
-e 
... etc. - the rest is truncated

Reply via email to