use std::ffi::c_char;
use std::ffi::c_void;
pub const FIDIUS_MAGIC: [u8; 8] = *b"FIDIUS\0\0";
pub const REGISTRY_VERSION: u32 = 1;
const fn parse_u32_const(s: &str) -> u32 {
let bytes = s.as_bytes();
let mut i = 0;
let mut n = 0u32;
while i < bytes.len() {
n = n * 10 + (bytes[i] - b'0') as u32;
i += 1;
}
n
}
const CRATE_MAJOR: u32 = parse_u32_const(env!("CARGO_PKG_VERSION_MAJOR"));
const CRATE_MINOR: u32 = parse_u32_const(env!("CARGO_PKG_VERSION_MINOR"));
pub const ABI_VERSION: u32 = if CRATE_MAJOR == 0 {
CRATE_MAJOR * 10000 + CRATE_MINOR * 100
} else {
CRATE_MAJOR * 10000
};
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BufferStrategyKind {
PluginAllocated = 1,
Arena = 2,
}
#[repr(C)]
pub struct MetaKv {
pub key: *const c_char,
pub value: *const c_char,
}
unsafe impl Send for MetaKv {}
unsafe impl Sync for MetaKv {}
#[repr(C)]
pub struct MethodMetaEntry {
pub kvs: *const MetaKv,
pub kv_count: u32,
}
unsafe impl Send for MethodMetaEntry {}
unsafe impl Sync for MethodMetaEntry {}
impl std::fmt::Display for BufferStrategyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BufferStrategyKind::PluginAllocated => write!(f, "PluginAllocated"),
BufferStrategyKind::Arena => write!(f, "Arena"),
}
}
}
#[repr(C)]
pub struct PluginRegistry {
pub magic: [u8; 8],
pub registry_version: u32,
pub plugin_count: u32,
pub descriptors: *const *const PluginDescriptor,
}
unsafe impl Send for PluginRegistry {}
unsafe impl Sync for PluginRegistry {}
#[repr(C)]
pub struct PluginDescriptor {
pub descriptor_size: u32,
pub abi_version: u32,
pub interface_name: *const c_char,
pub interface_hash: u64,
pub interface_version: u32,
pub capabilities: u64,
pub buffer_strategy: u8,
pub plugin_name: *const c_char,
pub vtable: *const c_void,
pub free_buffer: Option<unsafe extern "C" fn(*mut u8, usize)>,
pub method_count: u32,
pub method_metadata: *const MethodMetaEntry,
pub trait_metadata: *const MetaKv,
pub trait_metadata_count: u32,
pub construct: Option<unsafe extern "C" fn(*const u8, u32) -> *mut c_void>,
pub destroy: Option<unsafe extern "C" fn(*mut c_void)>,
}
unsafe impl Send for PluginDescriptor {}
unsafe impl Sync for PluginDescriptor {}
#[repr(transparent)]
pub struct DescriptorPtr(pub *const PluginDescriptor);
unsafe impl Send for DescriptorPtr {}
unsafe impl Sync for DescriptorPtr {}
impl PluginDescriptor {
pub unsafe fn interface_name_str(&self) -> &str {
let cstr = unsafe { std::ffi::CStr::from_ptr(self.interface_name) };
cstr.to_str().expect("interface_name is not valid UTF-8")
}
pub unsafe fn plugin_name_str(&self) -> &str {
let cstr = unsafe { std::ffi::CStr::from_ptr(self.plugin_name) };
cstr.to_str().expect("plugin_name is not valid UTF-8")
}
pub fn buffer_strategy_kind(&self) -> Result<BufferStrategyKind, u8> {
match self.buffer_strategy {
1 => Ok(BufferStrategyKind::PluginAllocated),
2 => Ok(BufferStrategyKind::Arena),
v => Err(v),
}
}
pub fn has_capability(&self, bit: u32) -> bool {
if bit >= 64 {
return false;
}
self.capabilities & (1u64 << bit) != 0
}
}