use core::ffi::{c_char, c_void};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SokrVersion {
pub major: u32,
pub minor: u32,
pub patch: u32,
}
impl SokrVersion {
pub const CURRENT: Self = Self {
major: 0,
minor: 1,
patch: 1,
};
#[must_use]
pub const fn check_compatible(self, core: Self) -> SokrResult {
if self.major != core.major {
return SokrResult::VersionMismatch;
}
if self.minor > core.minor {
return SokrResult::VersionMismatch;
}
SokrResult::Ok
}
}
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SokrResult {
Ok = 0,
CapabilityDenied = 1,
DispatchFailed = 2,
Timeout = 3,
VersionMismatch = 4,
NoCapableSubstrate = 5,
InvalidInput = 6,
InvalidIR = 7,
NotFound = 8,
RegistryFull = 9,
}
impl SokrResult {
#[must_use]
pub const fn is_ok(self) -> bool {
matches!(self, Self::Ok)
}
#[must_use]
pub const fn is_err(self) -> bool {
!self.is_ok()
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SokrComputationId {
pub high: u64,
pub low: u64,
}
#[repr(C)]
pub struct SokrCapabilityQuery {
pub computation_id: SokrComputationId,
pub ir_format: *const c_char,
pub ir_data_ptr: *const c_void,
pub ir_data_len: usize,
pub padding: [u8; 8],
}
#[repr(C)]
pub struct SokrCapabilityResponse {
pub result: SokrResult,
pub padding: u32,
pub substrate_id: u64,
pub estimated_latency_ns: u64,
}
#[repr(C)]
pub struct SokrDispatchRequest {
pub computation_id: SokrComputationId,
pub substrate_id: u64,
pub ir_data_ptr: *const c_void,
pub ir_data_len: usize,
pub params_ptr: *const c_void,
pub params_len: usize,
pub padding: [u8; 16],
}
#[repr(C)]
pub struct SokrDispatchResponse {
pub result: SokrResult,
pub padding: u32,
pub completion_token: SokrCompletionToken,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SokrCompletionToken {
pub handle: u64,
}
#[repr(C)]
pub struct SokrCompletionQuery {
pub completion_token: SokrCompletionToken,
pub timeout_ns: u64,
pub padding: [u8; 8],
}
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SokrCompletionSignal {
Pending = 0,
Complete = 1,
Failed = 2,
TimedOut = 3,
}
pub type SokrCapabilityFn = extern "C" fn(
version: *const SokrVersion,
query: *const SokrCapabilityQuery,
response: *mut SokrCapabilityResponse,
) -> SokrResult;
pub type SokrDispatchFn = extern "C" fn(
request: *const SokrDispatchRequest,
response: *mut SokrDispatchResponse,
) -> SokrResult;
pub type SokrCompletionFn = extern "C" fn(
query: *const SokrCompletionQuery,
signal: *mut SokrCompletionSignal,
) -> SokrResult;
pub type SokrDestroyFn = extern "C" fn();
#[repr(C)]
pub struct SokrSubstratePlugin {
pub version: SokrVersion,
pub capability_fn: SokrCapabilityFn,
pub dispatch_fn: SokrDispatchFn,
pub completion_fn: SokrCompletionFn,
pub destroy_fn: SokrDestroyFn,
pub padding: [u8; 16],
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn version_compatible_same() {
let v = SokrVersion::CURRENT;
assert!(v.check_compatible(v).is_ok());
}
#[test]
fn version_incompatible_major_mismatch() {
let plugin = SokrVersion {
major: 1,
minor: 0,
patch: 0,
};
let core = SokrVersion {
major: 0,
minor: 1,
patch: 0,
};
assert!(plugin.check_compatible(core).is_err());
}
#[test]
fn version_incompatible_plugin_too_new() {
let plugin = SokrVersion {
major: 0,
minor: 5,
patch: 0,
};
let core = SokrVersion {
major: 0,
minor: 1,
patch: 0,
};
assert!(plugin.check_compatible(core).is_err());
}
#[test]
fn version_compatible_older_plugin() {
let plugin = SokrVersion {
major: 0,
minor: 0,
patch: 5,
};
let core = SokrVersion {
major: 0,
minor: 1,
patch: 0,
};
assert!(plugin.check_compatible(core).is_ok());
}
#[test]
fn version_compatible_patch_ignored() {
let plugin = SokrVersion {
major: 0,
minor: 1,
patch: 99,
};
let core = SokrVersion {
major: 0,
minor: 1,
patch: 0,
};
assert!(plugin.check_compatible(core).is_ok());
}
#[test]
fn result_is_ok() {
assert!(SokrResult::Ok.is_ok());
assert!(!SokrResult::Ok.is_err());
}
#[test]
fn result_is_err() {
assert!(SokrResult::VersionMismatch.is_err());
assert!(!SokrResult::VersionMismatch.is_ok());
}
#[test]
fn computation_id_equality() {
let id1 = SokrComputationId { high: 1, low: 2 };
let id2 = SokrComputationId { high: 1, low: 2 };
let id3 = SokrComputationId { high: 2, low: 1 };
assert_eq!(id1, id2);
assert_ne!(id1, id3);
}
}