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;
pub const ABI_VERSION: u32 = 2;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BufferStrategyKind {
CallerAllocated = 0,
PluginAllocated = 1,
Arena = 2,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WireFormat {
Json = 0,
Bincode = 1,
}
impl std::fmt::Display for BufferStrategyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BufferStrategyKind::CallerAllocated => write!(f, "CallerAllocated"),
BufferStrategyKind::PluginAllocated => write!(f, "PluginAllocated"),
BufferStrategyKind::Arena => write!(f, "Arena"),
}
}
}
impl std::fmt::Display for WireFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
WireFormat::Json => write!(f, "Json (debug build)"),
WireFormat::Bincode => write!(f, "Bincode (release build)"),
}
}
}
#[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 abi_version: u32,
pub interface_name: *const c_char,
pub interface_hash: u64,
pub interface_version: u32,
pub capabilities: u64,
pub wire_format: u8,
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,
}
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 {
0 => Ok(BufferStrategyKind::CallerAllocated),
1 => Ok(BufferStrategyKind::PluginAllocated),
2 => Ok(BufferStrategyKind::Arena),
v => Err(v),
}
}
pub fn wire_format_kind(&self) -> Result<WireFormat, u8> {
match self.wire_format {
0 => Ok(WireFormat::Json),
1 => Ok(WireFormat::Bincode),
v => Err(v),
}
}
pub fn has_capability(&self, bit: u32) -> bool {
if bit >= 64 {
return false;
}
self.capabilities & (1u64 << bit) != 0
}
}