use std::ffi::c_void;
use std::fmt;
use std::marker::PhantomData;
use std::sync::Arc;
use crate::{FnPtr, Library, SymbolType};
pub struct Symbol<'lib, T> {
inner: T,
_lib: PhantomData<&'lib Library>,
}
impl<T: SymbolType> Symbol<'_, T> {
pub(crate) fn new(inner: T) -> Self {
Self {
inner,
_lib: PhantomData,
}
}
pub fn as_ptr(&self) -> *mut c_void {
self.inner.to_address()
}
pub unsafe fn into_inner(self) -> T {
self.inner
}
}
impl<T: FnPtr> Symbol<'_, T> {
pub unsafe fn call(&self, args: T::Args) -> T::Output {
unsafe { self.inner.call(args) }
}
}
impl<T: SymbolType> Clone for Symbol<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: SymbolType> Copy for Symbol<'_, T> {}
impl<T: SymbolType> fmt::Debug for Symbol<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Symbol").field(&self.as_ptr()).finish()
}
}
pub struct ArcSymbol<T> {
inner: T,
lib: Arc<Library>,
}
impl<T: SymbolType> ArcSymbol<T> {
pub(crate) fn new(inner: T, lib: Arc<Library>) -> Self {
Self { inner, lib }
}
pub fn library(&self) -> &Arc<Library> {
&self.lib
}
pub fn as_ptr(&self) -> *mut c_void {
self.inner.to_address()
}
pub unsafe fn into_inner(self) -> T {
self.inner
}
}
impl<T: FnPtr> ArcSymbol<T> {
pub unsafe fn call(&self, args: T::Args) -> T::Output {
unsafe { self.inner.call(args) }
}
}
impl<T: SymbolType> Clone for ArcSymbol<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner,
lib: Arc::clone(&self.lib),
}
}
}
impl<T: SymbolType> fmt::Debug for ArcSymbol<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ArcSymbol").field(&self.as_ptr()).finish()
}
}