Skip to content

feat: add Rust crate import support#18

Closed
kdroidFilter wants to merge 94 commits into
mainfrom
feat/rust-import-support
Closed

feat: add Rust crate import support#18
kdroidFilter wants to merge 94 commits into
mainfrom
feat/rust-import-support

Conversation

@kdroidFilter
Copy link
Copy Markdown
Collaborator

Summary

  • Add rustImport { } DSL to import any Rust crate as a Kotlin library via FFM
  • Parse public API automatically via cargo rustdoc --output-format json — no crate modification needed
  • Generate Rust FFI bridges (#[no_mangle] extern "C" fn) and reuse FfmProxyGenerator for JVM proxies
  • Full pipeline: rustdoc JSON → parse → bridge codegen → cargo build → bundle .so in JAR
  • Include rust-calculator example with Compose Desktop UI powered by Rust

New files

  • RustdocJsonParser — rustdoc JSON → KneModule (structs, enums, methods, all primitive types, String, Option, Vec, HashMap)
  • RustBridgeGenerator — KneModule → Rust #[no_mangle] extern "C" fn wrappers
  • RustWorkAction — orchestrates parse + codegen + bridge injection into crate
  • GenerateRustBindingsTask + CargoBuildTask — Gradle tasks
  • RustImportExtension — DSL (crate(), cratePath(), crateGit())

Supported in v1

  • pub struct with methods → KneClass
  • pub enum (fieldless variants) → KneEnum
  • impl methods (&self, &mut self) → instance methods
  • Top-level pub fn → module-level functions
  • All primitive types, String, Option, Vec, HashMap, Point (object handles)

Test plan

  • 58 unit tests (parser + bridge generator) — all green
  • Rust calculator compiles with generated bridges (cargo build)
  • JVM proxies compile with generated code
  • Compose Desktop UI runs and calls Rust functions via FFM
  • End-to-end parity tests (Rust vs Kotlin results)
  • Tantivy integration test (stretch goal)

kdroidFilter and others added 30 commits March 31, 2026 16:39
Import any Rust crate as a Kotlin library using the new `rustImport { }` DSL.
The plugin parses the crate's public API via `cargo rustdoc --output-format json`,
generates Rust FFI bridges (#[no_mangle] extern "C" fn), and reuses the existing
FfmProxyGenerator to produce JVM proxy classes — zero changes to the Rust crate required.

Pipeline: rustdoc JSON → RustdocJsonParser → KneModule → RustBridgeGenerator + FfmProxyGenerator → cargo build → bundled .so in JAR

Includes:
- RustdocJsonParser: parses rustdoc JSON into KneModule (structs, enums, functions)
- RustBridgeGenerator: generates Rust #[no_mangle] extern "C" fn wrappers
- RustWorkAction: orchestrates parse → codegen → bridge injection
- GenerateRustBindingsTask + CargoBuildTask: Gradle tasks
- RustImportExtension: DSL for crate configuration
- Example rust-calculator with Compose Desktop UI powered by Rust via FFM
- 58 unit tests (parser + bridge generator)
…traction

- Track isBorrowed on KneParam (borrowed_ref vs resolved_path in rustdoc JSON)
- Track isMutating on KneFunction (&self vs &mut self)
- Extract get_X/set_X patterns as KneProperty (label, scale, enabled, current)
- Bridge generator uses &str for borrowed params, String for owned
- Bridge generator uses &* for immutable methods, &mut * for mutating
- Dynamic fqName from crate name instead of hardcoded
- Update UI to use property syntax (calc.current instead of calc.get_current())
- Parser: handle 'slice' type in rustdoc JSON (borrowed_ref → slice → primitive)
- Bridge generator: expand BYTE_ARRAY/LIST params to pointer+length pair in C ABI
- Bridge generator: reconstruct Rust slice via std::slice::from_raw_parts
- Restore sum_bytes, reverse_bytes, sum_all, find_max in rust-calculator example
- 5 new tests for slice parsing and bridge generation
…evel functions

- buildTopLevelDescriptor: expand LIST/BYTE_ARRAY params to ADDRESS + JAVA_INT
- generateFunctionObject: call appendCollectionParamAlloc for collection params
- buildTopLevelInvokeArgs: expand LIST/BYTE_ARRAY to segment + size pair
- sum_all and find_max now compile and are callable from JVM
Data classes:
- Detect all-pub-field structs without methods as KneDataClass (Point, NamedValue)
- Bridge generator: field-expanded params/returns for DATA_CLASS types
- Parser: resolve DATA_CLASS type references in method signatures
- Add NamedValue struct + get_named_value/set_from_named to Rust calculator

Build system:
- Bridge code now lives in Gradle build dir, not in crate src/
- Generated build.rs copies bridge from build dir to Cargo OUT_DIR
- lib.rs uses include!(concat!(env!("OUT_DIR"), "/kne_bridges.rs"))
- Filter out generated bridge functions from rustdoc parsing
Same algorithms (fib, pi, sum, sort, string, allocation), same parameters.
Enables direct Rust vs KN vs JVM comparison.

Key results:
- Rust faster on heavy compute (fib_recursive: 0.76x, string_concat: 0.01x)
- JVM faster on small frequent calls (FFM overhead: 7.6x)
- Tie on iterative compute (fib_iterative, pi_leibniz: 1.00x)
- Bridge generator: NULLABLE param conversion (sentinel encoding)
  - Option<i32> → i64 param, i64::MIN = None
  - Option<String> → *const c_char, null pointer = None
  - Option<bool> → i32 param, -1 = None
  - Option<&Object> → i64 handle, 0 = None
- Add add_optional, set_nickname, get_nickname, add_point_or_null to Rust calculator
- 5 new tests (3 parser + 2 bridge generator)
- Fix Rust test compilation (echo/greet String params)
Compose Desktop UI showing system info powered by Rust sysinfo crate:
- Hostname, OS name/version, kernel version, uptime
- CPU model, core count, frequency
- Memory total/available/used/swap
- Process count, disk count
- Auto-detected properties from get_*/set_* pattern
- Data classes: MemoryInfo, DiskInfo, ProcessInfo
Mirrors the Kotlin/Native calculator test suite:
- CoreTest (35): constructor, arithmetic, strings, unicode, all primitives, properties, exceptions
- NullableTest (15): Option<T> returns (Int, String, Bool, Long, Double) + Option<T> params
- CollectionTest (13): Vec<i32> return, ByteArray return/param, top-level sum_all/find_max
- DataClassTest (10): Point get/add roundtrip, NamedValue with String field, set_from_named
- EnumTest (6): entries, ordinals, enum as param
- TopLevelFunctionTest (6): compute, greet with unicode

All 85 tests pass — every call crosses JVM → FFM → Rust → FFM → JVM.
- Parser: detect @kne:suspend in rustdoc docs → isSuspend = true
- Bridge generator: spawn std::thread, call cont_ptr/exc_ptr callbacks
  - cancelJob: AtomicBool flag for JVM cancellation
  - disposeRef: Box cleanup for result handles
  - readStringRef: read String from boxed handle
- Supported return types: Int, Long, Double, Float, Boolean, Byte, Short, String, Unit
- Error propagation: catch_unwind → exc_ptr callback → KotlinNativeException on JVM
- 5 suspend integration tests + 11 parser/bridge unit tests
- 90 total end-to-end tests, all passing
- Parser: detect @kne:flow(Int|String|...) in rustdoc docs → FLOW(T) return type
- Bridge generator: spawn thread, iterate Vec, call next_fn/complete_fn/error_fn
- Element encoding: Int, Long, Boolean, String, Double, Float
- Cancellation: AtomicBool flag checked between emissions
- 4 Flow integration tests + 6 parser/bridge unit tests
- 94 total end-to-end tests, all passing
…ble)

- Parse trait definitions from rustdoc JSON format 56
- Detect trait impl blocks via 'trait' field in JSON (inherent vs trait impls)
- Generate KneInterface from public traits with method contracts
- Track trait implementations on Calculator via interfaces field
- Generate FFM proxy interfaces with override methods
- Fix constructor visibility issue: maintain private constructor despite interfaces
- Add InterfaceTest.kt with 8 comprehensive trait tests
- Add parser tests for trait detection and interface validation
- 102 tests passing (94 original + 8 new interface tests)
Support Rust enums with data variants (tuple, struct, and unit) as
Kotlin sealed classes. CalcResult(Value/Error/Partial/Nothing) is
the reference example covering all three variant kinds.

- Add KneSealedEnum/KneSealedVariant IR types with isTuple flag
- Add KneType.SEALED_ENUM for type resolution (opaque handle)
- Parser: classify enums with data variants as sealed, parse fields
- RustBridgeGenerator: generate tag/dispose/constructors/field getters
- FfmProxyGenerator: generate sealed class with variant subclasses
- 12 new end-to-end tests, 8 new parser tests (220 total)
Parse function_pointer and dyn_trait(Fn/FnMut/FnOnce) from rustdoc
JSON format 56. Generate Rust bridge transmute from i64 to fn() with
direct pointer cast for primitive-only signatures. Add callback stub
allocation for suspend methods with FUNCTION params.

- Parser: resolve function_pointer → KneType.FUNCTION
- Parser: resolve &dyn Fn(T) → KneType.FUNCTION via dyn_trait
- RustBridgeGenerator: transmute i64 → fn() for callback params
- RustBridgeGenerator: closure wrapper for bool/String type conversion
- FfmProxyGenerator: add appendCallbackStubAlloc to suspend methods
- 7 new E2E tests (sync + suspend callbacks), 3 new parser tests
- 230 total tests passing (121 E2E + 109 plugin)
- Added complete Compose UI for sysinfo example with reactive Flow-based updates
- Implemented dynamic system monitoring: CPU usage, memory, disk I/O refreshing every 2s
- Fixed unsafe JSON casts in rustdoc parser (unit variants, generics, path resolution)
- Improved sealed class handling: each concrete class gets its own factory methods
- Added proper data class flattening for companion method returns (LoadAvg, out-parameters)
- Implemented type-specific list serialization: handles, strings (null-terminated), primitives
- Added OsStr/OsString support with lossy string conversion
- Implemented unsupported return type filtering to prevent broken code generation
- Added comprehensive limitations documentation in README
- Added RustWorkAction tests for rustdoc target resolution and manifest discovery
- Removed generated Rust bridge files from version control (now code-generated)
…idge generation. Extended Compose dynamic state and UI with network and process monitoring. Updated README to reflect MAP enhancements.
…eration

- Implemented serialization for SET types, backed by deduplicated lists in JVM.
- Enabled nullable DataClass support with out-parameters and presence flags.
- Updated README to reflect new return type support and their mappings.
Cover object/interface/sealed returns, all LIST/MAP/SET element types,
property getter/setter bridges, companion methods, canFail/Result,
unsafe methods, OWNED/BORROWED receivers, BYTE_ARRAY return,
all nullable types, DataClass field diversity, struct literal and
canFail constructors.
- Create CargoResolver utility for shared cargo executable discovery
- Add nullable DataClass parameter handling in Rust C function signatures
- Expand calculator example with division operator and error handling
- Add JSON type safety check in RustdocJsonParser
- Ignore generated build.rs artifacts
…tion

Types that are `pub` in their module but not explicitly re-exported from the
crate root (e.g., sysinfo::windows::sid::Sid on Windows with pub(crate) visibility)
were incorrectly included in bridge generation. This caused compilation failures
when the generated bridge tried to reference types not in scope after `pub use`.

Filter by traversing the root module's exports instead of scanning the flat index.
Build rootExportedIds by collecting directly defined types and explicit re-exports,
with support for glob re-exports (one level deep). This matches exactly what's
in scope after `pub use crate_name::*`.

Fixes Windows-only build failure on rust-sysinfo example.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add support for SET and MAP collection fields in sealed enum variants.
Updates Rust bridge generation to use dual buffers for MAP fields, and
updates FFM proxy generation to properly deserialize collection fields.
…ess details

Add new tabs for Sensors (hardware temps) and Users. Expand Processes with disk
I/O, exe path, working dir. Add disk kind, read-only status, and I/O to Disks tab.
Support Option<Vec<T>>, Option<HashSet<T>>, Option<HashMap<K,V>> as return
types via dual-buffer approach with -1 sentinel for None. Handles all three
contexts: methods, companion methods, and top-level functions.
…and parent PID

After regenerating bridges with nullable collection support, expose Process.tasks(),
accumulated_cpu_time(), open_files(), open_files_limit(), parent(), and cmd().
Add Component.id() and System.distribution_id_like(). Enhance Processes tab with
command line, parent PID, CPU time, open file descriptors, and thread count.
Prevent stale native library cache by comparing content in addition to file
size. Fixes UnsatisfiedLinkError when DLL content changes but file size
remains the same.
Optimize Rust bridge code generation by switching to borrowed handles, introducing buffer resizing for collections, and refining null-terminated string handling. Update FFM proxy generation to align with ownership semantics and improve automatic cleanup behavior.
Functions returning `!` (never) are now properly bridged:
- Parser accepts both "!" and "never" primitive types
- RustBridgeGenerator returns () via catch_unwind for C ABI compatibility
- FfmProxyGenerator throws RuntimeException for Never-returning functions
- NativeBridgeGenerator handles Never type correctly
- Add e2e tests for panic_always() function
Add support for callbacks that return or take sealed enum, object, and interface
types. Callbacks can now use impl FnOnce to accept both function pointers and
closures, with proper handle lifecycle management through Boxing for sealed
enums/objects and trait registry for interfaces.

- Extend RustBridgeGenerator to recognize OBJECT, INTERFACE, SEALED_ENUM as
  C-ABI friendly and handle their conversion in callback contexts
- Add handle conversion helpers for callback parameters and return values
- Support upcall stubs that wrap Kotlin callbacks for Rust closures
- Add 20 new comprehensive tests: sealed enum callbacks, object callbacks,
  edge cases (MAX_VALUE, MIN_VALUE), load tests (1K iterations), and
  concurrency tests (10 threads x 1K iterations)
- Update README with handle-backed callback types in feature table
Enable passing trait objects as parameters to constructors and methods
via registry-based handle transmission. Previously only `Box<dyn Trait>`
returns were supported; now `&dyn Trait` and `&mut dyn Trait` params work
for constructors, methods, and top-level functions.

Changes:
- RustBridgeGenerator: INTERFACE params use registry-based reconstruction
  (KNE_TRAIT_REGISTRY + transmute) instead of Box::from_raw
- FfmProxyGenerator: Remove INTERFACE skip in constructor filter; use
  DynWrapper type names in all param signatures (constructor, methods, etc.)
- Add TraitConsumer struct (new Rust type) with constructor taking
  &dyn Describable and methods accepting &dyn Describable/&dyn Measurable
- Add 11 comprehensive tests: edge cases (boundary values), load tests
  (100K calls), and concurrency tests (10 threads)

All 38 InterfaceTest tests pass, covering both existing dyn Trait returns
and new param support.
…hods

When a Rust function returns `impl Trait` where Trait is a known crate-local trait,
it is now bridged as a DynXxx wrapper object — the same pattern as dyn Trait returns.

Changes:
- Parser: resolveImplTrait detects known crate traits and resolves to INTERFACE type
- Bridge generator: appendValueReturnFromBinding adds boxing step for impl Trait returns
- isDynTraitFunction excludes impl dyn from registry-based handling

This enables code like `fn get_thing() -> impl MyTrait` to be fully bridged to Kotlin,
with automatic DynMyTrait wrapper generation and FFM proxy support.
Create a comprehensive camera example demonstrating the full nokhwa API:
- Live video preview with FPS counter
- Camera device info (name, description, capabilities)
- Format configuration (resolution, frame rate, pixel format)
- Compatible formats browser grouped by resolution
- Camera controls with value ranges and descriptions

Follows sysinfo's architecture: dark theme, sidebar navigation (5 tabs),
data flows, reusable components, and clean separation of concerns.
Showcases: frame capture/decode, device querying, format selection,
control inspection, and real-time streaming.
…M redirect

Parser: scan rootExportedIds (which traverses pub use submodules) for
functions, not just root items. This discovers entry points like
cpal::default_host() and symphonia::default::get_probe() that live in
submodules but are accessible at the crate root.

Also include function items in buildRootExportedIds and expandGlobModule
so they are collected during module traversal.

FfmProxyGenerator: apply OBJECT→ENUM redirect consistently in:
- buildTopLevelDescriptor (FFM layout)
- buildJvmInvokeArg (param conversion)
- buildNullableJvmInvokeArg (nullable param)
- appendCallAndReturn nullable OBJECT return path
- effectiveReturn computation for descriptors

This fixes compilation errors in rust-camera where ApiBackend (an enum)
was resolved as OBJECT from cross-crate rustdoc, causing calls to
fromNativeHandle/_consumeHandle on an enum class.
Demonstrates the rfd (Rusty File Dialogs) crate v0.17.2 via FFM bridge:
- File picker: single, multi, file-or-folder, files-or-folders
- Folder picker: single and multi with starting directory
- Save file: with preset filenames and directories
- Message dialogs: 3 levels (Info/Warning/Error), 7 button configs
  including custom labels (OkCustom, OkCancelCustom, YesNoCancelCustom)
- Dialog history with stats and timeline

Same dark theme and sidebar architecture as rust-sysinfo/rust-camera.
Plugin changes:
- Skip synthetic generic params (is_synthetic: true) in resolveGenericMappings
  and hasUnsupportedGenerics, unblocking methods with impl Trait params
- Add Future trait to resolveImplTrait: extracts Output associated type and
  marks the return as isFuture for bridge generation
- Add isAsync field to KneFunction, set from header.is_async or isFuture
- Generate pollster::block_on() wrapper for async method calls in Rust bridges
- Add pollster dependency to generated Cargo.toml
- Fix convertedParamName for borrowed LIST(STRING) params (&[&str]):
  use &name_vec instead of name_ptr

Example updates:
- rust-rfd: use add_filter() with file extension filters in FilePickerTab
  and SaveFileTab now that impl ToString params are supported
- Fix CrossCrateReexportTest: get_resolution/get_camera_format are now
  properties (get_ prefix stripped), update lookups accordingly
- Fix RustCalculatorParserTest: get_point/get_named_value are properties
- Fix unsupported-signature tests: tuples and fn pointers as params are
  now supported, use unbounded generic T as the unsupported type instead
- Add tests for async fn (is_async flag), impl Future return resolution,
  and synthetic impl Trait param skipping (is_synthetic: true)
- Update README with impl Future and impl ToString param documentation
Four categories of bridge generator bugs fixed:

1. Box<dyn Trait> param reconstruction: appendParamConversion now checks
   rustType for "Box<dyn" and generates ownership-transfer code (remove
   from registry + transmute to Box) instead of always generating &dyn.

2. Callback generic types: callbackNativeParamType/ReturnType and
   appendCallbackParamCleanup now use objectRustTypeNames lookup to
   resolve full generic type names (e.g. AudioPlanesMut<u24>).

3. fn pointer rustType: parser now builds full "fn(Type1, Type2) -> Ret"
   rustType string instead of bare "fn", enabling the existing
   hasUnbridgeableParam check to correctly filter fn pointers with
   dyn Trait in their signature.

4. ZST enum transmute: single-variant enums (like cpal::HostId) are now
   constructed directly instead of using transmute from u8.

Additionally, callbacks with unresolved generic template params
(e.g. AudioPlanesMut without concrete type arg) are now correctly
detected as unbridgeable via monomorphisedBaseNames check.
FfmProxyGenerator now emits suspend fun with withContext(Dispatchers.IO)
for methods with isAsync=true. The pattern generates a private _blocking
sync method (with the actual FFM invoke) and a public suspend fun wrapper.

- Add appendAsyncMethodProxy to FfmProxyGenerator
- Route isAsync methods through the new async proxy generator
- Add Dispatchers/withContext imports when class has async methods
- Update interface proxy to declare suspend for async methods
- Update rust-rfd example: remove manual withContext wrapping from
  RfdActions.kt since the generated proxies now handle it
- Update README to document suspend fun generation
- README.md: global presentation with links to specialized guides
- README-KOTLIN-NATIVE.md: complete Kotlin/Native bridge documentation (experimental)
- README-RUST.md: Rust bridge documentation (proof of concept)

Status badges added to clarify the maturity level of each bridge.
Add a new rust-tray-icon example demonstrating the local wrapper crate pattern
to work around Rust bridge limitations. Includes:

- Local wrapper crate (tray-icon 0.19) with macOS dispatch_sync main-thread
  dispatching, context menus, and event polling
- Compose Desktop UI with tabbed interface (Tray Control, Info, Event Log)
- Multiple plugin fixes:
  * RustdocJsonParser: propagate generic args in qualifiedRustType
  * RustWorkAction: traverse glob re-exports, detect module re-exports
  * FfmProxyGenerator: handle KneType.INTERFACE in list params,
    detect nullable function params for _companionCallbackArena
  * RustBridgeGenerator: detect NULLABLE(LIST/SET/MAP/FUNCTION) params
    as unbridgeable
- Documentation: add tray-icon limitations and lessons learned to README-RUST.md
- settings.gradle.kts: include :examples:rust-tray-icon
Enable `Option<impl Fn(T) -> R>` parameters in Rust functions bridged to Kotlin.
Nullable closures are bridged as nullable function pointers with FFM upcall stubs:
- 0 (null) → None, otherwise transmute to fn and wrap in Some
- Kotlin can pass null to clear the handler, or a lambda to receive callbacks

Changes:
- RustdocJsonParser: handle Fn/FnMut/FnOnce in resolveImplTrait()
- RustBridgeGenerator: remove blanket NULLABLE(FUNCTION) rejection, add C ABI check
  * appendNullableParamConversion: new FUNCTION case
  * appendFunctionParamConversion: add move to closure for stored callbacks
- FfmProxyGenerator: detect nullable functions in classHasCallbacks/objectHasCallbacks

rust-tray-icon: replace event polling with callbacks
- on_tray_event(Option<impl Fn(String)>) / on_menu_event(Option<impl Fn(String)>)
- Remove LaunchedEffect polling loop, events delivered via Kotlin lambdas directly
- Eliminates 100ms polling overhead

rust-calculator: add nullable callback test coverage
- maybe_transform(Option<impl Fn(i32) -> i32>) / maybe_for_each / compute_with_observer
- Edge cases: null/non-null alternation, MAX/MIN values
- Load tests: 100K calls with alternating null/Some
- Concurrency tests: 10 threads x 10K operations
- Fix opaque dispose: was no-op (memory leak), now properly Box::from_raw + drop
- Add use imports for opaque external types in generated Rust preamble
- Smart path resolution: non-std crates use crate::SimpleName for public re-exports
- Update rust-tray-icon example to expose Icon as opaque type parameter
- Add Kotlin UI demonstrating both flat API (RGB) and opaque Icon handle API
- Update README-RUST.md to reflect improved opaque type support
Implement MenuItem as an opaque type following the Icon pattern. The bridge
now handles external types with qualified rustTypeName paths (e.g.,
tray_icon::menu::MenuItem) by using fully qualified casts and giving priority
to objectRustTypeNames mapping over simple type unwrapping.

Changes:

1. RustdocJsonParser: Prefer public function signature paths over internal
   rustdoc paths (e.g., tray_icon::menu::MenuItem not muda::items::MenuItem)

2. RustBridgeGenerator:
   - Use full qualified paths in opaque dispose (no need for `use` imports)
   - Include opaque types with qualified paths in objectRustTypeNames
   - Check objectRustTypeNames BEFORE unwrapping borrowed types

3. Rust wrapper (lib.rs): Add MenuItem functions:
   - create_menu_item(label, enabled) -> MenuItem
   - add_menu_item, remove_menu_item, add_separator
   - get/set_menu_item_text, is/set_menu_item_enabled

4. TrayIconManager.kt: Add MenuItem management methods

5. TrayControlTab.kt: Add dynamic MenuItem UI section demonstrating:
   - Creating individual menu items
   - Adding/removing items from the tray menu
   - Modifying text and enabled state
   - Full opaque type lifecycle (create → use → close)

6. README-RUST.md: Remove MenuItem::new limitation; update to show opaque
   type wrapper pattern supports both Icon and MenuItem bridging

All examples (tray-icon, sysinfo, calculator) build and tests pass.
…attern

Update limitations table to show wrapper solutions for each blocker, making clear that the local wrapper crate solves all limitations including Box<dyn Trait> params (which stay on the Rust side while Kotlin works with opaque handles).
… traits

Support impl Trait parameters (impl ToString, impl Into<T>, impl AsRef<str>)
by resolving them to concrete KneTypes at the bridge level. Trait bounds are
satisfied at the Rust call site (e.g., String: ToString).

Support Box<dyn Trait> parameters for external traits by monomorphizing
functions to concrete implementors. For local traits, enable ownership
transfer via registry-based fat pointer reconstruction.

Updates:
- RustdocJsonParser: dyn_trait resolution falls back to traitImpls for
  external traits; single-implementor traits resolve directly to concrete type
- RustBridgeGenerator: hasUnbridgeableParam allows OBJECT with Box<dyn>;
  appendParamConversion handles Box<dyn> for both INTERFACE and OBJECT types;
  appendDynTraitTopLevelFunction applies full param conversions to all params
- rust-calculator: Add impl Trait param test functions (greet_impl, into_upper,
  count_chars, consume_describable) with end-to-end tests

README-RUST.md: Update limitations table and lessons to reflect that impl Trait
params and external trait objects are now bridged.
Types from transitive dependencies (e.g. bytes::bytes::Bytes) with no bridgeable
content (methods, properties, constructor) can't be resolved in the wrapper scope.
Skip generating empty wrapper classes for these types.
Implement full support for Map<K, Vec<T>> and other nested collection types
in HashMap returns and properties. Fixes generation of get_metadata() and
get_with_metadata_map() which return Map<String, Vec<i32>>.

Changes:
- FfmProxyGenerator: MAP properties now use direct out-params (no StableRef)
  instead of non-functional StableRef handle pattern. Added readBoxedList*
  helpers in KneRuntime to read boxed Vecs via handles. Fixed
  appendMapElementRead to call KneRuntime.readBoxedList* for LIST/SET values.
- RustBridgeGenerator: Extended isSupportedMapElementType to accept LIST/SET,
  added isSupportedCollectionElementForBridge recursive cases. Generated
  appendBoxedListHelpers for 8 types. Fixed v.clone() for boxing nested Vecs.
  Fixed appendMapPropertyGetter triple-call bug (now stores result in local var).
- TupleTest: Added 10 tests covering edge cases (negative, MAX_VALUE, unicode),
  load (100K calls), and concurrency (10 threads x 10K calls) for both
  metadata and get_with_metadata_map functions.
- README-RUST.md: Updated Map support documentation to reflect nested
  collection capability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant