# ABI ## Value ABI At its core, the Giterated Runtime uses the `extern "C"` ABI. What that means is likely platform specific, and doesn't matter. You are intended to compile the Giterated Runtime and Plugins for your local machine, all with a similar idea of what your "local machine" is. Values are passed using the `FFI` type. There are four categories of value that the `FFI` type enables you to pass: | `FFI` Type Category | Placed Backing? | Owned? | |---------------------|-----------------|--------| | Slice | Heap/Stack | No | | Referenced Slice | Stack | No | | Referenced Value | No | No | | Owned Value | Heap | Yes | For an FFI type to have a "placed backing" is for it to have some data structure beyond the data it represents, placed somewhere in memory. Some types only require stack placement while some offer both stack and heap placement. Stack-placed values can be shared by `PinnedRef` and `PinnedMut`, and thus can only be owned by the caller. Heap-placed values can be shared by `Owned`, `PinnedRef`, and `PinnedMut`. They can be owned by any one consumer, When the handle with ownership is `Drop`'d by the sole consumer, it will free the object using the associated `Drop` callback. ### Safety Intents This API is designed to simplify interaction with FFI values, and provide a static ABI for those values to be passed. It is key to enabling ownership across FFI while ensuring associated dropping and allocation freeing logic is ran. The contract the developer has to follow is made simpler by this system, and it allows for generic code to be written to interact with FFI-given values and pass values using FFI. ### Stability Guarantees There are no plans to guarantee stability until 1.0.0. At that point you can expect the ABI to remain stable until the major version is incremented again. There will be an appropriate deprecation process and changeover period. ### Memory Representation Please check out the source code, sorry if you needed that from the docs! ## Object, Operation, Setting, Value, Plugin, and Runtime ABIs The Giterated Runtime uses vtables to accomplish the goal of ensuring maximum compatibility. For every object that is shared between plugins, a vtable is used to allow each plugin to provide their own code for interacting with the object. When objects switch "runtime domains" (e.g. host -> plugin, plugin -> plugin, plugin -> host), their vtable is swapped out for the new runtime domain's own vtables. ### Untyped "Objects" (see above header for list) Untyped objects, in memory, are represented by a data pointer and a vtable pointer. Exactly like Rust traits. However, to prevent small compilation differences and other random garbage from making the interface not perfectly compatible we use the local plugin's idea of the vtable for the object at all times. An object that the plugin does not have a vtable for cannot be relevant to the plugin. It is important that the object's base representation in memory remain unchanged between major versions, but the vtables that provide methods for that object may be grown. The methods that operate on that object may be changed in an non-breaking fashion, and bugs can be fixed. ## Futures ABI The Giterated Runtime has an async runtime that allows for futures to be shared and awaited across FFI boundaries while only executing the future within the context of the Plugin who is running the underlying future. Futures are spawned onto the `RuntimeState` with the `RuntimeFuturesExt` trait. This takes a Rust future, boxes it, and provides a `RuntimeFuture` handle that can be used to drive the underlying Rust future locally. The `RuntimeFuture` handle is thread-safe and can be shared with the callee and `.await`'d directly like any other future. ### RuntimeFuture The `RuntimeFuture` mixes a vtable with data to allow for any caller to drive a spawned future. It contains: - A `poll_fn` which is used to poll the future for `Ready`-ness - A `wake_fn` which is used to wake the callee to poll for (expected) `Ready`-ness, it is populated when the `RuntimeFuture` is `await`'d. When the `RuntimeFuture` is polled, it causes the inner future to also be polled. We provide the inner future with a waker that triggers the `RuntimeFuture`'s waker so it is polled again. Breaking character to point out how freaking cool that is. `RuntimeFuture`s drop the associated inner future as they drop.