use crate::{api::API, plugin::Plugin};
use bitflags::bitflags;
use core::fmt;
use rustsynth_sys as ffi;
use std::{ffi::CStr, marker::PhantomData, ptr::NonNull};
bitflags! {
pub struct CoreCreationFlags: u32 {
const NONE = 0b00000000;
const ENABLE_GRAPH_INSPECTION = 0b00000001;
const DISABLE_AUTO_LOADING = 0b00000010;
const DISABLE_LIBRARY_UNLOADING = 0b00000100;
}
}
#[derive(Debug, Clone, Copy)]
pub struct CoreRef<'core> {
handle: NonNull<ffi::VSCore>,
_owner: PhantomData<&'core ()>,
}
unsafe impl<'core> Send for CoreRef<'core> {}
unsafe impl<'core> Sync for CoreRef<'core> {}
impl<'core> CoreRef<'core> {
#[inline]
pub fn new(flags: CoreCreationFlags) -> Self {
let api = API::get().unwrap();
unsafe {
let handle = api.create_core(flags.bits() as i32);
Self::from_ptr(handle)
}
}
#[inline]
pub(crate) unsafe fn from_ptr(handle: *mut ffi::VSCore) -> Self {
Self {
handle: NonNull::new_unchecked(handle),
_owner: PhantomData,
}
}
#[inline]
pub(crate) fn ptr(&self) -> *mut ffi::VSCore {
self.handle.as_ptr()
}
pub fn info(&self) -> CoreInfo {
let core_info = unsafe { API::get_cached().get_core_info(self.ptr()) };
let version_string = unsafe { CStr::from_ptr(core_info.versionString).to_str().unwrap() };
debug_assert!(core_info.numThreads >= 0);
debug_assert!(core_info.maxFramebufferSize >= 0);
debug_assert!(core_info.usedFramebufferSize >= 0);
CoreInfo {
version_string,
core_version: core_info.core,
api_version: core_info.api,
num_threads: core_info.numThreads as usize,
max_framebuffer_size: core_info.maxFramebufferSize as u64,
used_framebuffer_size: core_info.usedFramebufferSize as u64,
}
}
pub fn plugin_by_namespace(&self, namespace: &str) -> Option<Plugin<'core>> {
unsafe { API::get_cached() }.plugin_by_namespace(namespace, self)
}
pub fn plugin_by_id(&self, id: &str) -> Option<Plugin<'_>> {
unsafe { API::get_cached() }.plugin_by_id(id, self)
}
pub fn plugins(&self) -> Plugins<'_> {
unsafe { API::get_cached() }.plugins(self)
}
pub fn set_thread_count(&self, count: usize) -> i32 {
unsafe { API::get_cached().set_thread_count(self.ptr(), count as i32) }
}
pub unsafe fn free_core(self) {
API::get_cached().free_core(self.handle.as_ptr());
}
}
#[derive(Debug, Clone, Copy, Hash)]
pub struct CoreInfo {
pub version_string: &'static str,
pub core_version: i32,
pub api_version: i32,
pub num_threads: usize,
pub max_framebuffer_size: u64,
pub used_framebuffer_size: u64,
}
#[derive(Debug, Clone, Copy)]
pub struct Plugins<'core> {
plugin: Option<Plugin<'core>>,
core: &'core CoreRef<'core>,
}
impl<'core> Plugins<'core> {
pub(crate) fn new(core: &'core CoreRef<'core>) -> Self {
Plugins { plugin: None, core }
}
}
impl<'core> Iterator for Plugins<'core> {
type Item = Plugin<'core>;
fn next(&mut self) -> Option<Self::Item> {
self.plugin = unsafe { API::get_cached().next_plugin(self.plugin, self.core) };
self.plugin
}
}
impl fmt::Display for CoreInfo {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.version_string)?;
writeln!(f, "Worker threads: {}", self.num_threads)?;
writeln!(
f,
"Max framebuffer cache size: {}",
self.max_framebuffer_size
)?;
writeln!(
f,
"Current framebuffer cache size: {}",
self.used_framebuffer_size
)
}
}