#![no_std]
#![deny(clippy::correctness)]
#![warn(
clippy::perf,
clippy::complexity,
clippy::style,
clippy::nursery,
clippy::pedantic,
clippy::clone_on_ref_ptr,
clippy::decimal_literal_representation,
clippy::float_cmp_const,
clippy::missing_docs_in_private_items,
clippy::multiple_inherent_impl,
clippy::unwrap_used,
clippy::cargo_common_metadata,
clippy::used_underscore_binding
)]
#![allow(clippy::inline_always)]
use core::fmt::{Formatter, Pointer};
use core::ops::Deref;
macro_rules! trait_impl {
($SelfType:ident) => {
impl<T> Clone for $SelfType<T> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for $SelfType<T> {}
impl<T> Pointer for $SelfType<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
core::fmt::Pointer::fmt(&self.0, f)
}
}
impl<T> Eq for $SelfType<T> {}
impl<T> PartialEq for $SelfType<T> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&self.0, &other.0)
}
}
impl<T> PartialOrd for $SelfType<T> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for $SelfType<T> {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
Ord::cmp(&self.0, &other.0)
}
}
impl<T> core::fmt::Debug for $SelfType<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_tuple(stringify!($SelfType)).field(&self.0).finish()
}
}
impl<T> core::hash::Hash for $SelfType<T> {
#[inline(always)]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
core::hash::Hash::hash(&self.0, state);
}
}
impl<T> From<$SelfType<T>> for usize {
#[inline(always)]
fn from(val: $SelfType<T>) -> Self {
val.as_address()
}
}
impl<T> From<usize> for $SelfType<T> {
#[inline(always)]
fn from(value: usize) -> Self {
Self::from_address(value)
}
}
};
}
#[repr(transparent)]
pub struct SyncMutPtr<T>(*mut T);
unsafe impl<T> Sync for SyncMutPtr<T> {}
unsafe impl<T> Send for SyncMutPtr<T> {}
trait_impl!(SyncMutPtr);
impl<T> Deref for SyncMutPtr<T> {
type Target = *mut T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<*mut T> for SyncMutPtr<T> {
#[inline(always)]
fn from(value: *mut T) -> Self {
Self(value)
}
}
impl<T> From<SyncMutPtr<T>> for *mut T {
#[inline(always)]
fn from(val: SyncMutPtr<T>) -> Self {
val.inner()
}
}
impl<T> From<SyncMutPtr<T>> for *const T {
#[inline(always)]
fn from(val: SyncMutPtr<T>) -> Self {
val.inner()
}
}
impl<T> SyncMutPtr<T> {
#[inline(always)]
#[must_use]
pub const fn new(ptr: *mut T) -> Self {
Self(ptr)
}
#[inline(always)]
#[must_use]
pub const fn from_address(addr: usize) -> Self {
Self(addr as *mut T)
}
#[inline(always)]
#[must_use]
pub fn as_address(&self) -> usize {
self.0 as usize
}
#[inline(always)]
#[must_use]
pub const fn null() -> Self {
Self(core::ptr::null_mut())
}
#[inline(always)]
#[must_use]
pub const fn cast<Y>(&self) -> SyncMutPtr<Y> {
SyncMutPtr(self.0.cast())
}
#[inline(always)]
#[must_use]
pub const fn inner(&self) -> *mut T {
self.0
}
#[inline(always)]
#[must_use]
pub const fn as_sync_const(&self) -> SyncConstPtr<T> {
SyncConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_const(&self) -> SendConstPtr<T> {
SendConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_sync_mut(&self) -> Self {
Self(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_mut(&self) -> SendMutPtr<T> {
SendMutPtr(self.0)
}
}
#[repr(transparent)]
pub struct SyncConstPtr<T>(*const T);
unsafe impl<T> Sync for SyncConstPtr<T> {}
unsafe impl<T> Send for SyncConstPtr<T> {}
trait_impl!(SyncConstPtr);
impl<T> Deref for SyncConstPtr<T> {
type Target = *const T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<*mut T> for SyncConstPtr<T> {
#[inline(always)]
fn from(value: *mut T) -> Self {
Self(value)
}
}
impl<T> From<*const T> for SyncConstPtr<T> {
#[inline(always)]
fn from(value: *const T) -> Self {
Self(value)
}
}
impl<T> From<SyncConstPtr<T>> for *const T {
#[inline(always)]
fn from(val: SyncConstPtr<T>) -> Self {
val.inner()
}
}
impl<T> SyncConstPtr<T> {
#[inline(always)]
#[must_use]
pub const fn new(ptr: *const T) -> Self {
Self(ptr)
}
#[inline(always)]
#[must_use]
pub const fn from_address(addr: usize) -> Self {
Self(addr as *mut T)
}
#[inline(always)]
#[must_use]
pub fn as_address(&self) -> usize {
self.0 as usize
}
#[inline(always)]
#[must_use]
pub const fn null() -> Self {
Self(core::ptr::null())
}
#[inline(always)]
#[must_use]
pub const fn cast<Y>(&self) -> SyncConstPtr<Y> {
SyncConstPtr(self.0.cast())
}
#[inline(always)]
#[must_use]
pub const fn inner(&self) -> *const T {
self.0
}
#[inline(always)]
#[must_use]
pub const fn as_sync_const(&self) -> Self {
Self(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_const(&self) -> SendConstPtr<T> {
SendConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_sync_mut(&self) -> SyncMutPtr<T> {
SyncMutPtr(self.0.cast_mut())
}
#[inline(always)]
#[must_use]
pub const fn as_send_mut(&self) -> SendMutPtr<T> {
SendMutPtr(self.0.cast_mut())
}
}
#[repr(transparent)]
pub struct SendMutPtr<T>(*mut T);
unsafe impl<T> Send for SendMutPtr<T> {}
trait_impl!(SendMutPtr);
impl<T> Deref for SendMutPtr<T> {
type Target = *mut T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<SendMutPtr<T>> for *mut T {
#[inline(always)]
fn from(val: SendMutPtr<T>) -> Self {
val.inner()
}
}
impl<T> From<SendMutPtr<T>> for *const T {
#[inline(always)]
fn from(val: SendMutPtr<T>) -> Self {
val.inner()
}
}
impl<T> SendMutPtr<T> {
#[inline(always)]
#[must_use]
pub const fn new(ptr: *mut T) -> Self {
Self(ptr)
}
#[inline(always)]
#[must_use]
pub const fn from_address(addr: usize) -> Self {
Self(addr as *mut T)
}
#[inline(always)]
#[must_use]
pub fn as_address(&self) -> usize {
self.0 as usize
}
#[inline(always)]
#[must_use]
pub const fn null() -> Self {
Self(core::ptr::null_mut())
}
#[inline(always)]
#[must_use]
pub const fn cast<Y>(&self) -> SendMutPtr<Y> {
SendMutPtr(self.0.cast())
}
#[inline(always)]
#[must_use]
pub const fn inner(&self) -> *mut T {
self.0
}
#[inline(always)]
#[must_use]
pub const fn as_sync_const(&self) -> SyncConstPtr<T> {
SyncConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_const(&self) -> SendConstPtr<T> {
SendConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_sync_mut(&self) -> SyncMutPtr<T> {
SyncMutPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_mut(&self) -> Self {
Self(self.0)
}
}
#[repr(transparent)]
pub struct SendConstPtr<T>(*const T);
unsafe impl<T> Send for SendConstPtr<T> {}
trait_impl!(SendConstPtr);
impl<T> Deref for SendConstPtr<T> {
type Target = *const T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<SendConstPtr<T>> for *const T {
#[inline(always)]
fn from(val: SendConstPtr<T>) -> *const T {
val.inner()
}
}
impl<T> SendConstPtr<T> {
#[inline(always)]
#[must_use]
pub const fn new(ptr: *const T) -> Self {
Self(ptr)
}
#[inline(always)]
#[must_use]
pub const fn from_address(addr: usize) -> Self {
Self(addr as *mut T)
}
#[inline(always)]
#[must_use]
pub fn as_address(&self) -> usize {
self.0 as usize
}
#[inline(always)]
#[must_use]
pub const fn null() -> Self {
Self(core::ptr::null())
}
#[inline(always)]
#[must_use]
pub const fn cast<Y>(&self) -> SendConstPtr<Y> {
SendConstPtr(self.0.cast())
}
#[inline(always)]
#[must_use]
pub const fn inner(&self) -> *const T {
self.0
}
#[inline(always)]
#[must_use]
pub const fn as_sync_const(&self) -> SyncConstPtr<T> {
SyncConstPtr(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_send_const(&self) -> Self {
Self(self.0)
}
#[inline(always)]
#[must_use]
pub const fn as_sync_mut(&self) -> SyncMutPtr<T> {
SyncMutPtr(self.0.cast_mut())
}
#[inline(always)]
#[must_use]
pub const fn as_send_mut(&self) -> SendMutPtr<T> {
SendMutPtr(self.0.cast_mut())
}
}
pub trait FromConstPtr<T>: Sized {
fn as_sync_const(&self) -> SyncConstPtr<T>;
fn as_send_const(&self) -> SendConstPtr<T>;
}
pub trait FromMutPtr<T>: FromConstPtr<T> {
fn as_sync_mut(&self) -> SyncMutPtr<T>;
fn as_send_mut(&self) -> SendMutPtr<T>;
}
impl<T> FromConstPtr<T> for *const T {
#[inline(always)]
fn as_sync_const(&self) -> SyncConstPtr<T> {
SyncConstPtr(self.cast())
}
#[inline(always)]
fn as_send_const(&self) -> SendConstPtr<T> {
SendConstPtr(self.cast())
}
}
impl<T> FromConstPtr<T> for *mut T {
#[inline(always)]
fn as_sync_const(&self) -> SyncConstPtr<T> {
SyncConstPtr(self.cast())
}
#[inline(always)]
fn as_send_const(&self) -> SendConstPtr<T> {
SendConstPtr(self.cast())
}
}
impl<T> FromMutPtr<T> for *mut T {
#[inline(always)]
fn as_sync_mut(&self) -> SyncMutPtr<T> {
SyncMutPtr(self.cast())
}
#[inline(always)]
fn as_send_mut(&self) -> SendMutPtr<T> {
SendMutPtr(self.cast())
}
}
#[cfg(feature = "fnptr")]
#[allow(clippy::incompatible_msrv)] mod fnptr {
use core::fmt::{Debug, Pointer};
use core::hash::Hash;
macro_rules! impl_pointer {
($SelfType:ident) => {
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> Default for $SelfType<T>
{
fn default() -> Self {
Self(None)
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> core::fmt::Pointer for $SelfType<T>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(r) = self.0.as_ref() {
Pointer::fmt(r, f)
} else {
Pointer::fmt(&core::ptr::null::<()>(), f)
}
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> core::ops::Deref for $SelfType<T>
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.0
.as_ref()
.expect("sync_ptr deref attempt to deref null function pointer")
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> core::ops::DerefMut for $SelfType<T>
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
.as_mut()
.expect("sync_ptr: deref_mut attempt to deref null function pointer")
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> From<$SelfType<T>> for usize
{
#[inline(always)]
fn from(value: $SelfType<T>) -> Self {
value.as_address()
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> From<$SelfType<T>> for *const core::ffi::c_void
{
#[inline(always)]
fn from(value: $SelfType<T>) -> Self {
value.as_raw_ptr()
}
}
impl<
T: Pointer
+ Copy
+ Clone
+ Sized
+ Eq
+ PartialEq
+ PartialOrd
+ Ord
+ Hash
+ Debug,
> $SelfType<T>
{
#[inline(always)]
pub const fn null() -> Self {
Self(None)
}
#[inline(always)]
pub const fn inner(&self) -> Option<T> {
self.0
}
#[inline(always)]
pub const fn unwrap(&self) -> T {
self.0.unwrap()
}
#[inline(always)]
pub const fn as_address(&self) -> usize {
if let Some(r) = self.0.as_ref() {
unsafe { core::mem::transmute_copy::<_, usize>(r) }
} else {
0
}
}
#[inline(always)]
pub const fn as_raw_ptr(&self) -> *const core::ffi::c_void {
if let Some(r) = self.0.as_ref() {
unsafe { core::mem::transmute_copy::<_, *const core::ffi::c_void>(r) }
} else {
core::ptr::null()
}
}
#[inline(always)]
pub const fn is_null(&self) -> bool {
self.0.is_none()
}
}
};
}
#[macro_export]
macro_rules! sync_fn_ptr {
($sig:ty, $var:expr) => {{
let x = $var as $sig;
_ = move || {
_ = core::ptr::fn_addr_eq(x, x);
};
assert!(core::mem::size_of::<SyncFnPtr::<$sig>>() == core::mem::size_of::<$sig>());
let n: SyncFnPtr<$sig> = unsafe { core::mem::transmute(Some(x)) };
n
}};
}
#[macro_export]
macro_rules! sync_fn_ptr_from_addr {
($sig:ty, $var:expr) => {
{
assert!(core::mem::size_of::<SyncFnPtr::<$sig>>() == core::mem::size_of::<$sig>());
let ptr = $var as *const core::ffi::c_void;
if ptr.is_null() {
SyncFnPtr::<$sig>::default()
} else {
let x : $sig = core::mem::transmute($var as *const core::ffi::c_void);
_ = move || {
_= core::ptr::fn_addr_eq(x, x);
};
core::mem::transmute(Some(x))
}
}
};
}
#[repr(transparent)]
#[derive(Copy, Clone, Ord, PartialOrd, Hash, Debug, Eq, PartialEq)]
pub struct SyncFnPtr<
T: Pointer + Copy + Clone + Sized + Eq + PartialEq + PartialOrd + Ord + Hash + Debug,
>(Option<T>);
unsafe impl<T: Pointer + Copy + Clone + Sized + Eq + PartialEq + PartialOrd + Ord + Hash + Debug>
Sync for SyncFnPtr<T>
{
}
unsafe impl<T: Pointer + Copy + Clone + Sized + Eq + PartialEq + PartialOrd + Ord + Hash + Debug>
Send for SyncFnPtr<T>
{
}
impl_pointer!(SyncFnPtr);
#[macro_export]
macro_rules! send_fn_ptr {
($sig:ty, $var:expr) => {{
let x = $var as $sig;
_ = move || {
_ = core::ptr::fn_addr_eq(x, x);
};
assert!(core::mem::size_of::<SendFnPtr::<$sig>>() == core::mem::size_of::<$sig>());
let n: SendFnPtr<$sig> = unsafe { core::mem::transmute(Some(x)) };
n
}};
}
#[macro_export]
macro_rules! send_fn_ptr_from_addr {
($sig:ty, $var:expr) => {
{
assert!(core::mem::size_of::<SendFnPtr::<$sig>>() == core::mem::size_of::<$sig>());
let ptr = $var as *const core::ffi::c_void;
if ptr.is_null() {
SendFnPtr::<$sig>::default()
} else {
let x : $sig = core::mem::transmute($var as *const core::ffi::c_void);
_ = move || {
_= core::ptr::fn_addr_eq(x, x);
};
core::mem::transmute(Some(x))
}
}
};
}
#[repr(transparent)]
#[derive(Copy, Clone, Ord, PartialOrd, Hash, Debug, Eq, PartialEq)]
pub struct SendFnPtr<
T: Pointer + Copy + Clone + Sized + Eq + PartialEq + PartialOrd + Ord + Hash + Debug,
>(Option<T>);
unsafe impl<T: Pointer + Copy + Clone + Sized + Eq + PartialEq + PartialOrd + Ord + Hash + Debug>
Send for SendFnPtr<T>
{
}
impl_pointer!(SendFnPtr);
}
#[cfg(feature = "fnptr")]
pub use fnptr::*;
#[cfg(doctest)]
#[cfg(feature = "fnptr")]
#[doc = include_str!("../README.md")]
struct ReadmeDocTests;