use alloc::boxed::Box;
use alloc::string::String;
#[cfg(all(feature = "no_std_error", not(feature = "std")))]
use core::error;
#[cfg(feature = "std")]
use std::error;
#[cfg(windows)]
pub const LIBRARY: &str = "vulkan-1.dll";
#[cfg(target_os = "android")]
pub const LIBRARY: &str = "libvulkan.so";
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub const LIBRARY: &str = "libvulkan.dylib";
#[cfg(all(
unix,
not(target_os = "android"),
not(target_os = "ios"),
not(target_os = "macos")
))]
pub const LIBRARY: &str = "libvulkan.so.1";
#[cfg(any(feature = "std", feature = "no_std_error"))]
pub trait LoaderError: error::Error + Send + Sync + 'static {}
#[cfg(not(any(feature = "std", feature = "no_std_error")))]
pub trait LoaderError: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static {}
#[derive(Clone, Debug)]
pub struct StringLoaderError(String);
impl core::fmt::Display for StringLoaderError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str(&self.0)
}
}
#[cfg(any(feature = "std", feature = "no_std_error"))]
impl error::Error for StringLoaderError {}
impl LoaderError for StringLoaderError {}
impl<'a> From<&'a str> for Box<dyn LoaderError> {
fn from(value: &'a str) -> Self {
Box::new(StringLoaderError(value.into())) as Box<dyn LoaderError>
}
}
impl From<String> for Box<dyn LoaderError> {
fn from(value: String) -> Self {
Box::new(StringLoaderError(value)) as Box<dyn LoaderError>
}
}
pub trait Loader {
unsafe fn load(&self, name: &[u8]) -> Result<extern "system" fn(), Box<dyn LoaderError>>;
}
#[cfg(feature = "libloading")]
mod libloading_loader {
use std::boxed::Box;
use std::ffi::OsStr;
use std::mem;
use libloading::{Error, Library, Symbol};
use super::*;
impl LoaderError for Error {}
impl From<Error> for Box<dyn LoaderError> {
fn from(value: Error) -> Self {
Box::new(value) as Box<dyn LoaderError>
}
}
#[derive(Debug)]
pub struct LibloadingLoader(Library);
impl LibloadingLoader {
#[inline]
pub unsafe fn new(filename: impl AsRef<OsStr>) -> Result<Self, Error> {
Library::new(filename).map(Self)
}
#[inline]
pub fn library(&self) -> &Library {
&self.0
}
}
impl Loader for LibloadingLoader {
#[inline]
unsafe fn load(&self, name: &[u8]) -> Result<extern "system" fn(), Box<dyn LoaderError>> {
let symbol: Symbol<Option<extern "C" fn()>> = self.0.get(name)?;
let pointer = symbol.try_as_raw_ptr().ok_or("missing function pointer")?;
Ok(mem::transmute::<*mut core::ffi::c_void, extern "system" fn()>(pointer))
}
}
}
#[cfg(feature = "libloading")]
pub use self::libloading_loader::*;