//! # 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>>` /// /// 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, }