Files
orchid/orchid-api/src/binary.rs

91 lines
2.6 KiB
Rust

//! # Binary extension definition
//!
//! A binary extension is a DLL / shared object / dylib with a symbol called
//! `orchid_extension_main` which accepts a single argument of type
//! [ExtensionContext]. Once that is received, communication continuees through
//! the channel with the same protocol outlined in [crate::proto]
use unsync_pipe::{Reader, Writer};
/// !Send !Sync owned waker
///
/// This object is [Clone] for convenience but it has `drop` and no `clone` so
/// interactions must reflect a single logical owner
#[derive(Clone, Copy)]
#[repr(C)]
pub struct OwnedWakerBin {
pub data: *const (),
/// `self`
pub drop: extern "C" fn(*const ()),
/// `self`
pub wake: extern "C" fn(*const ()),
/// `&self`
pub wake_ref: extern "C" fn(*const ()),
}
/// !Send !Sync, equivalent to `&mut Context<'a>`, hence no `drop`.
/// When received in [FutureBin::poll], it must not outlive the call.
///
/// You cannot directly wake using this waker, because such a trampoline would
/// pass through the binary interface twice for no reason. An efficient
/// implementation should implement that trampoline action internally, whereas
/// an inefficient but compliant implementation can clone a fresh waker and use
/// it up.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct FutureContextBin {
pub data: *const (),
/// `&self`
pub waker: extern "C" fn(*const ()) -> OwnedWakerBin,
}
/// ABI-stable `Poll<()>`
#[derive(Clone, Copy)]
#[repr(C)]
pub enum UnitPoll {
Pending,
Ready,
}
/// ABI-stable `Pin<Box<dyn Future<Output = ()>>>`
///
/// This object is [Clone] for convenience, but it has `drop` and no `clone` so
/// interactions must reflect a single logical owner
#[derive(Clone, Copy)]
#[repr(C)]
pub struct FutureBin {
pub data: *const (),
/// `self`
pub drop: extern "C" fn(*const ()),
/// `&mut self` Equivalent to [Future::poll]
pub poll: extern "C" fn(*const (), FutureContextBin) -> UnitPoll,
}
/// Handle for a runtime that allows its holder to spawn futures across dynamic
/// library boundaries
#[derive(Clone, Copy)]
#[repr(C)]
pub struct SpawnerBin {
pub data: *const (),
/// `self`
pub drop: extern "C" fn(*const ()),
/// `&self` Add a future to this extension's task
pub spawn: extern "C" fn(*const (), FutureBin),
}
/// Extension context.
///
/// This struct is a plain old value, all of the contained values have a
/// distinct `drop` member
#[repr(C)]
pub struct ExtensionContext {
/// Spawns tasks associated with this extension
pub spawner: SpawnerBin,
/// serialized [crate::HostExtChannel]
pub input: Reader,
/// serialized [crate::ExtHostChannel]
pub output: Writer,
/// UTF-8 log stream directly to log service.
pub log: Writer,
}