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 fn info(&self) -> Option<crate::AddressInfo> {
crate::AddressInfo::of(self.as_ptr())
}
pub unsafe fn with<R>(&self, f: impl FnOnce(T) -> R) -> R {
f(self.inner)
}
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<'lib, T> Symbol<'lib, *const T> {
pub unsafe fn as_ref(&self) -> &'lib T {
unsafe { &*self.inner }
}
}
impl<'lib, T> Symbol<'lib, *mut T> {
pub unsafe fn as_ref(&self) -> &'lib T {
unsafe { &*self.inner }
}
#[allow(clippy::mut_from_ref)]
pub unsafe fn as_mut(&self) -> &'lib mut T {
unsafe { &mut *self.inner }
}
}
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 with<R>(&self, f: impl FnOnce(T) -> R) -> R {
f(self.inner)
}
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> ArcSymbol<*const T> {
pub unsafe fn as_ref(&self) -> &T {
unsafe { &*self.inner }
}
}
impl<T> ArcSymbol<*mut T> {
pub unsafe fn as_ref(&self) -> &T {
unsafe { &*self.inner }
}
}
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()
}
}