use core::ffi::c_void;
use polyplug_utils::BundleId;
use crate::{
guest::{GuestContractInstance, GuestContractInterface},
plugin::{GuestContractHandle, PluginDescriptor},
types::{AbiError, Array, DependencyInfo, StringView},
};
#[repr(C)]
pub struct HostApi {
pub runtime: *mut c_void,
pub register_guest_contract: unsafe extern "C" fn(
this: *const HostApi,
descriptor: *const PluginDescriptor,
interface: *const GuestContractInterface,
out_err: *mut AbiError,
),
pub alloc: unsafe extern "C" fn(this: *const HostApi, size: usize, align: usize) -> *mut u8,
pub free: unsafe extern "C" fn(this: *const HostApi, ptr: *mut u8, size: usize, align: usize),
pub find_guest_contract: unsafe extern "C" fn(
this: *const HostApi,
contract_id: u64,
min_version: u32,
) -> GuestContractHandle,
pub find_all_guest_contracts: unsafe extern "C" fn(
this: *const HostApi,
contract_id: u64,
min_version: u32,
) -> Array<GuestContractHandle>,
pub resolve_guest_contract: unsafe extern "C" fn(
this: *const HostApi,
handle: GuestContractHandle,
) -> *const GuestContractInterface,
pub get_host_contract: unsafe extern "C" fn(
this: *const HostApi,
contract_id: u64,
min_version: u32,
) -> crate::host::HostContractInstance,
pub resolve_host_contract_interface:
unsafe extern "C" fn(
this: *const HostApi,
contract_id: u64,
min_version: u32,
) -> *const crate::host::HostContractInterface,
pub list_bundles: unsafe extern "C" fn(this: *const HostApi) -> Array<BundleId>,
pub get_dependencies: unsafe extern "C" fn(this: *const HostApi) -> Array<DependencyInfo>,
pub load_bundle: unsafe extern "C" fn(
this: *const HostApi,
path: *const u8,
path_len: usize,
out_err: *mut AbiError,
),
pub reload_bundle: unsafe extern "C" fn(
this: *const HostApi,
path: *const u8,
path_len: usize,
out_err: *mut AbiError,
),
pub register_host_contract: unsafe extern "C" fn(
this: *const HostApi,
interface: *const crate::host::HostContractInterface,
out_err: *mut AbiError,
),
pub register_loader:
unsafe extern "C" fn(this: *const HostApi, loader_ptr: *mut c_void, out_err: *mut AbiError),
pub get_last_error:
unsafe extern "C" fn(this: *const HostApi, buf: *mut u8, buf_len: usize) -> usize,
pub get_error_len: unsafe extern "C" fn(this: *const HostApi) -> usize,
pub unload_bundle:
unsafe extern "C" fn(this: *const HostApi, bundle_id: BundleId, out_err: *mut AbiError),
pub log: unsafe extern "C" fn(
this: *const HostApi,
level: u32,
scope: StringView,
message: StringView,
),
pub create_guest_instance: unsafe extern "C" fn(
this: *const HostApi,
interface: *const GuestContractInterface,
args: *const c_void,
out_instance: *mut GuestContractInstance,
),
pub destroy_guest_instance: unsafe extern "C" fn(
this: *const HostApi,
interface: *const GuestContractInterface,
instance: GuestContractInstance,
),
pub revision_counter: unsafe extern "C" fn(this: *const HostApi) -> *const u64,
pub reserved: *const core::ffi::c_void,
}
unsafe impl Send for HostApi {}
unsafe impl Sync for HostApi {}
#[cfg(test)]
mod tests {
use core::mem::{align_of, offset_of, size_of};
use crate::host::host_api::HostApi;
#[test]
fn layout_host_api() {
assert_eq!(size_of::<HostApi>(), 184);
assert_eq!(align_of::<HostApi>(), 8);
assert_eq!(offset_of!(HostApi, runtime), 0);
assert_eq!(offset_of!(HostApi, register_guest_contract), 8);
assert_eq!(offset_of!(HostApi, alloc), 16);
assert_eq!(offset_of!(HostApi, free), 24);
assert_eq!(offset_of!(HostApi, find_guest_contract), 32);
assert_eq!(offset_of!(HostApi, find_all_guest_contracts), 40);
assert_eq!(offset_of!(HostApi, resolve_guest_contract), 48);
assert_eq!(offset_of!(HostApi, get_host_contract), 56);
assert_eq!(offset_of!(HostApi, resolve_host_contract_interface), 64);
assert_eq!(offset_of!(HostApi, list_bundles), 72);
assert_eq!(offset_of!(HostApi, get_dependencies), 80);
assert_eq!(offset_of!(HostApi, load_bundle), 88);
assert_eq!(offset_of!(HostApi, reload_bundle), 96);
assert_eq!(offset_of!(HostApi, register_host_contract), 104);
assert_eq!(offset_of!(HostApi, register_loader), 112);
assert_eq!(offset_of!(HostApi, get_last_error), 120);
assert_eq!(offset_of!(HostApi, get_error_len), 128);
assert_eq!(offset_of!(HostApi, unload_bundle), 136);
assert_eq!(offset_of!(HostApi, log), 144);
assert_eq!(offset_of!(HostApi, create_guest_instance), 152);
assert_eq!(offset_of!(HostApi, destroy_guest_instance), 160);
assert_eq!(offset_of!(HostApi, revision_counter), 168);
assert_eq!(offset_of!(HostApi, reserved), 176);
}
#[test]
fn host_api_has_runtime_field() {
assert_eq!(offset_of!(HostApi, runtime), 0);
assert_eq!(size_of::<*mut core::ffi::c_void>(), 8);
}
#[test]
fn list_bundles_field_exists() {
assert_eq!(offset_of!(HostApi, list_bundles), 72);
}
#[test]
fn get_dependencies_field_exists() {
assert_eq!(offset_of!(HostApi, get_dependencies), 80);
}
}