use core::{
any,
borrow,
cmp,
convert,
fmt,
future,
hash,
iter,
marker::{self, PhantomData},
mem::{self, MaybeUninit},
ops,
pin,
ptr::{self, NonNull},
task,
};
#[cfg(feature = "nightly-async-stream")]
use core::stream;
#[cfg(feature = "nightly-coerce-unsized")]
use core::ops::CoerceUnsized;
#[cfg(feature = "nightly-dispatch-from-dyn")]
use core::ops::DispatchFromDyn;
pub struct StaticRcRef<'a, T: ?Sized, const NUM: usize, const DEN: usize> {
pointer: NonNull<T>,
_marker: PhantomData<&'a mut T>,
}
impl<'a, T, const N: usize> StaticRcRef<'a, T, N, N> {
#[inline(always)]
pub fn new(value: &'a mut T) -> Self {
let pointer = NonNull::from(value);
Self { pointer, _marker: PhantomData }
}
#[inline(always)]
pub fn pin(value: &'a mut T) -> pin::Pin<Self> {
unsafe { pin::Pin::new_unchecked(Self::new(value)) }
}
#[inline(always)]
pub fn into_inner(this: Self) -> &'a mut T {
unsafe { &mut *this.pointer.as_ptr() }
}
}
impl<'a, T: ?Sized, const N: usize> StaticRcRef<'a, T, N, N> {
#[inline(always)]
pub fn get_mut(this: &mut Self) -> &mut T {
unsafe { this.pointer.as_mut() }
}
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
pub fn into_raw(this: Self) -> NonNull<T> { this.pointer }
#[inline(always)]
pub fn as_ptr(this: &Self) -> NonNull<T> { this.pointer }
#[inline(always)]
pub fn get_ref(this: &Self) -> &T {
unsafe { this.pointer.as_ref() }
}
#[inline(always)]
pub unsafe fn from_raw(pointer: NonNull<T>) -> Self { Self { pointer, _marker: PhantomData, } }
#[inline(always)]
pub fn ptr_eq<const N: usize, const D: usize>(this: &Self, other: &StaticRcRef<'a, T, N, D>) -> bool {
StaticRcRef::as_ptr(this) == StaticRcRef::as_ptr(other)
}
#[inline(always)]
pub fn adjust<const N: usize, const D: usize>(this: Self) -> StaticRcRef<'a, T, N, D>
where
AssertEqType!(N * DEN, NUM * D): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert_eq!(NUM * D, N * DEN, "{} / {} != {} / {}", NUM, DEN, N, D);
StaticRcRef { pointer: this.pointer, _marker: PhantomData }
}
#[inline(always)]
pub fn split<const A: usize, const B: usize>(this: Self) -> (StaticRcRef<'a, T, A, DEN>, StaticRcRef<'a, T, B, DEN>)
where
AssertEqType!(A + B, NUM): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert_eq!(NUM, A + B, "{} != {} + {}", NUM, A, B);
let pointer = this.pointer;
let _marker = PhantomData;
(StaticRcRef { pointer, _marker, }, StaticRcRef { pointer, _marker, })
}
#[inline(always)]
pub fn split_array<const N: usize, const D: usize, const DIM: usize>(this: Self) -> [StaticRcRef<'a, T, N, D>; DIM]
where
T: 'a,
AssertEqType!(N * DIM * DEN, NUM * D): Sized,
AssertLeType!(mem::size_of::<[StaticRcRef<'a, T, N, D>; DIM]>(), usize::MAX / 2 + 1): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert_eq!(NUM * D, N * DIM * DEN, "{} * {} != {} * {} * {}", NUM, D, N, DIM, DEN);
#[cfg(not(feature = "compile-time-ratio"))]
assert!(mem::size_of::<[StaticRcRef<T, N, D>; DIM]>() <= (isize::MAX as usize),
"Size of result ({}) exceeeds isize::MAX", mem::size_of::<[StaticRcRef<T, N, D>; DIM]>());
let pointer = this.pointer;
let _marker = PhantomData;
let mut array = MaybeUninit::uninit();
for i in 0..DIM {
let destination = unsafe { (array.as_mut_ptr() as *mut StaticRcRef<T, N, D>).add(i) };
unsafe { ptr::write(destination, StaticRcRef { pointer, _marker, }); }
}
unsafe { array.assume_init() }
}
#[inline(always)]
pub fn join<const A: usize, const B: usize>(left: StaticRcRef<'a, T, A, DEN>, right: StaticRcRef<'a, T, B, DEN>) -> Self
where
AssertEqType!(NUM, A + B): Sized,
{
assert!(StaticRcRef::ptr_eq(&left, &right), "{:?} != {:?}", left.pointer.as_ptr(), right.pointer.as_ptr());
unsafe { Self::join_unchecked(left, right) }
}
#[inline(always)]
pub unsafe fn join_unchecked<const A: usize, const B: usize>(
left: StaticRcRef<'a, T, A, DEN>,
_right: StaticRcRef<'a, T, B, DEN>,
) -> Self
where
AssertEqType!(NUM, A + B): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert_eq!(NUM, A + B, "{} != {} + {}", NUM, A, B);
Self { pointer: left.pointer, _marker: PhantomData, }
}
pub fn lift<'b, F>(this: Self, fun: F) -> Option<Self>
where
'a: 'b,
T: 'b,
F: FnOnce(&'b Self) -> &'b mut Option<Self>,
{
let slot = {
let this_ref = unsafe { &*(&this as *const _) };
fun(this_ref) as *mut Option<Self>
};
let slot = unsafe { &mut *slot };
slot.replace(this)
}
}
impl<'a, const NUM: usize, const DEN: usize> StaticRcRef<'a, dyn any::Any, NUM, DEN> {
pub fn downcast<T: any::Any>(self) -> Result<StaticRcRef<'a, T, NUM, DEN>, Self> {
if Self::get_ref(&self).is::<T>() {
let pointer = Self::into_raw(self).cast::<T>();
Ok(StaticRcRef { pointer, _marker: PhantomData, })
} else {
Err(self)
}
}
}
impl<'a, T: ?Sized, const N: usize> convert::AsMut<T> for StaticRcRef<'a, T, N, N> {
#[inline(always)]
fn as_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> convert::AsRef<T> for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn as_ref(&self) -> &T { Self::get_ref(self) }
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> borrow::Borrow<T> for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn borrow(&self) -> &T { Self::get_ref(self) }
}
impl<'a, T: ?Sized, const N: usize> borrow::BorrowMut<T> for StaticRcRef<'a, T, N, N> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
#[cfg(feature = "nightly-coerce-unsized")]
impl<'a, T, U, const NUM: usize, const DEN: usize> CoerceUnsized<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
where
T: ?Sized + marker::Unsize<U>,
U: ?Sized,
{}
impl<'a, T: ?Sized + fmt::Debug, const NUM: usize, const DEN: usize> fmt::Debug for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt::Debug::fmt(Self::get_ref(self), f)
}
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> ops::Deref for StaticRcRef<'a, T, NUM, DEN> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T { Self::get_ref(self) }
}
impl<'a, T: ?Sized, const N: usize> ops::DerefMut for StaticRcRef<'a, T, N, N> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
impl<'a, T: ?Sized + fmt::Display, const NUM: usize, const DEN: usize> fmt::Display for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt::Display::fmt(Self::get_ref(self), f)
}
}
#[cfg(feature = "nightly-dispatch-from-dyn")]
impl<'a, T, U, const NUM: usize, const DEN: usize> DispatchFromDyn<StaticRcRef<'a, U, NUM, DEN>> for StaticRcRef<'a, T, NUM, DEN>
where
T: ?Sized + marker::Unsize<U>,
U: ?Sized,
{}
impl<'a, I: iter::DoubleEndedIterator + ?Sized, const N: usize> iter::DoubleEndedIterator for StaticRcRef<'a, I, N, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<I::Item> { Self::get_mut(self).next_back() }
#[inline(always)]
fn nth_back(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth_back(n) }
}
impl<'a, T: ?Sized + cmp::Eq, const NUM: usize, const DEN: usize> cmp::Eq for StaticRcRef<'a, T, NUM, DEN> {}
impl<'a, I: iter::ExactSizeIterator + ?Sized, const N: usize> iter::ExactSizeIterator for StaticRcRef<'a, I, N, N> {
#[inline(always)]
fn len(&self) -> usize { Self::get_ref(self).len() }
}
impl<'a, const NUM: usize, const DEN: usize> From<StaticRcRef<'a, str, NUM, DEN>> for StaticRcRef<'a, [u8], NUM, DEN> {
#[inline(always)]
fn from(value: StaticRcRef<'a, str, NUM, DEN>) -> Self {
let pointer = value.pointer.as_ptr() as *mut [u8];
debug_assert!(!pointer.is_null());
let pointer = unsafe { NonNull::new_unchecked(pointer) };
Self { pointer, _marker: PhantomData, }
}
}
impl<'a, I: iter::FusedIterator + ?Sized, const N: usize> iter::FusedIterator for StaticRcRef<'a, I, N, N> {}
impl<'a, F: ?Sized + future::Future + marker::Unpin, const N: usize> future::Future for StaticRcRef<'a, F, N, N> {
type Output = F::Output;
fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
F::poll(pin::Pin::new(&mut *self), cx)
}
}
#[cfg(feature = "nightly-generator-trait")]
impl<'a, G: ?Sized + ops::Generator<R> + marker::Unpin, R, const N: usize> ops::Generator<R> for StaticRcRef<'a, G, N, N> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
G::resume(pin::Pin::new(&mut *self), arg)
}
}
#[cfg(feature = "nightly-generator-trait")]
impl<'a, G: ?Sized + ops::Generator<R>, R, const N: usize> ops::Generator<R> for pin::Pin<StaticRcRef<'a, G, N, N>> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
G::resume((*self).as_mut(), arg)
}
}
impl<'a, T: ?Sized + hash::Hash, const NUM: usize, const DEN: usize> hash::Hash for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Self::get_ref(self).hash(state);
}
}
impl<'a, I: iter::Iterator + ?Sized, const N: usize> iter::Iterator for StaticRcRef<'a, I, N, N> {
type Item = I::Item;
#[inline(always)]
fn next(&mut self) -> Option<I::Item> { Self::get_mut(self).next() }
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) { Self::get_ref(self).size_hint() }
#[inline(always)]
fn nth(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth(n) }
#[inline(always)]
fn last(mut self) -> Option<I::Item> { Self::get_mut(&mut self).last() }
}
impl<'a, T: ?Sized + cmp::Ord, const NUM: usize, const DEN: usize> cmp::Ord for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn cmp(&self, other: &Self) -> cmp::Ordering {
if Self::ptr_eq(self, other) {
cmp::Ordering::Equal
} else {
Self::get_ref(self).cmp(Self::get_ref(other))
}
}
}
impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialEq<StaticRcRef<'a, T, N, D>>
for StaticRcRef<'a, T, NUM, DEN>
where
T: ?Sized + PartialEq<T>
{
#[inline(always)]
fn eq(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).eq(StaticRcRef::get_ref(other)) }
#[inline(always)]
fn ne(&self, other: &StaticRcRef<'a, T, N, D>) -> bool { Self::get_ref(self).ne(StaticRcRef::get_ref(other)) }
}
impl<'a, T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialOrd<StaticRcRef<'a, T, N, D>>
for StaticRcRef<'a, T, NUM, DEN>
where
T: ?Sized + PartialOrd<T>
{
#[inline(always)]
fn partial_cmp(&self, other: &StaticRcRef<'a, T, N, D>) -> Option<cmp::Ordering> {
Self::get_ref(self).partial_cmp(StaticRcRef::get_ref(other))
}
#[inline(always)]
fn lt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
Self::get_ref(self).lt(StaticRcRef::get_ref(other))
}
#[inline(always)]
fn le(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
Self::get_ref(self).le(StaticRcRef::get_ref(other))
}
#[inline(always)]
fn gt(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
Self::get_ref(self).gt(StaticRcRef::get_ref(other))
}
#[inline(always)]
fn ge(&self, other: &StaticRcRef<'a, T, N, D>) -> bool {
Self::get_ref(self).ge(StaticRcRef::get_ref(other))
}
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> fmt::Pointer for StaticRcRef<'a, T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&Self::as_ptr(self).as_ptr(), f)
}
}
#[cfg(feature = "nightly-async-stream")]
impl<'a, S: ?Sized + stream::Stream + marker::Unpin, const N: usize> stream::Stream for StaticRcRef<'a, S, N, N> {
type Item = S::Item;
fn poll_next(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Option<Self::Item>> {
pin::Pin::new(&mut **self).poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
impl<'a, T: ?Sized, const NUM: usize, const DEN: usize> marker::Unpin for StaticRcRef<'a, T, NUM, DEN> {}
unsafe impl<'a, T: ?Sized + marker::Send, const NUM: usize, const DEN: usize> marker::Send for StaticRcRef<'a, T, NUM, DEN> {}
unsafe impl<'a, T: ?Sized + marker::Sync, const NUM: usize, const DEN: usize> marker::Sync for StaticRcRef<'a, T, NUM, DEN> {}
#[cfg(test)]
mod tests {
fn test_use_after_free() {
#![allow(dead_code)]
}
}