|
19 | 19 |
|
20 | 20 | (Experimental) Rust support for the `tvm-ffi` ABI. |
21 | 21 | Currently, the rust support is in an experimental stage. |
| 22 | +The workspace requires Rust 1.85 or newer. |
22 | 23 | This workspace contains three crates: |
23 | 24 |
|
24 | 25 | - `tvm-ffi`: Safe, ergonomic Rust bindings over the ABI. |
@@ -70,3 +71,60 @@ cargo run --example load_library --features example |
70 | 71 | ``` |
71 | 72 |
|
72 | 73 | Check out the [load_library.rs](tvm-ffi/examples/load_library.rs) for details. |
| 74 | + |
| 75 | +## Ordered Type Matching |
| 76 | + |
| 77 | +`match_any!` matches an erased value against `AnyPattern` implementations in |
| 78 | +source order. A matcher is evaluated before its guard, a false guard continues |
| 79 | +with the next arm, and a final `_` fallback is required. The current phase-1 |
| 80 | +implementation deliberately uses ordered conditional dispatch; it does not |
| 81 | +build an index table or apply an index-space heuristic. |
| 82 | + |
| 83 | +```rust |
| 84 | +use tvm_ffi::{match_any, Any, AnyPattern, AnyView}; |
| 85 | + |
| 86 | +struct Integer; |
| 87 | + |
| 88 | +impl AnyPattern for Integer { |
| 89 | + type Bound<'a> = i64; |
| 90 | + |
| 91 | + fn try_match<'a>(value: AnyView<'a>) -> Option<Self::Bound<'a>> { |
| 92 | + value.try_as::<i64>() |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +let value = Any::from(42_i64); |
| 97 | +let result = match_any! { |
| 98 | + value { |
| 99 | + Integer(integer) if integer > 0 => integer, |
| 100 | + _ => 0, |
| 101 | + } |
| 102 | +}; |
| 103 | +assert_eq!(result, 42); |
| 104 | +``` |
| 105 | + |
| 106 | +## Object Layout Contracts |
| 107 | + |
| 108 | +Types using `#[derive(Object)]` must use `#[repr(C)]` and place their registered |
| 109 | +base object in the first field. The declared type key and type index must |
| 110 | +identify a registered TVM-FFI object whose direct parent is that base type. The |
| 111 | +derive validates these properties when its type index is first used and rejects |
| 112 | +conflicting Rust layout claims for the same runtime index. |
| 113 | + |
| 114 | +Because registry metadata cannot prove every foreign field offset and Rust |
| 115 | +validity invariant, deriving also requires a separate |
| 116 | +`unsafe impl ObjectLayout for MyObject`. That explicit implementation asserts |
| 117 | +that the complete Rust field ABI matches every foreign allocation registered |
| 118 | +under the type key; it must be reviewed like any other unsafe FFI declaration. |
| 119 | + |
| 120 | +Registration and type lookup use the process-wide TVM-FFI type table. Type |
| 121 | +registration must finish before concurrent lookup begins, unless the caller |
| 122 | +provides external synchronization. Manual `unsafe impl ObjectCore` |
| 123 | +implementations remain responsible for the same header, prefix-layout, |
| 124 | +registration, and foreign-ABI compatibility requirements. |
| 125 | + |
| 126 | +Rust-owned `ObjectArc` allocations do not currently support foreign weak |
| 127 | +owners. Releasing the final strong owner through Rust or C++ while a foreign |
| 128 | +weak owner remains aborts the process rather than permitting access to an |
| 129 | +already-dropped embedded reference-count header. Cloning an `ObjectArc` also |
| 130 | +aborts before the ABI's 32-bit strong-count field can overflow. |
0 commit comments