#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
use core::{
borrow::{Borrow, BorrowMut},
cmp,
error::Error,
fmt,
future::Future,
hash::{Hash, Hasher},
iter::FusedIterator,
marker::PhantomData,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
task::{Context, Poll},
};
macro_rules! cfg_select {
(@apply [$cond:meta] { $($body:item)* }) => {
$( #[cfg($cond)] $body )*
};
(@munch [$($prev:meta),*] _ => { $($body:item)* }) => {
$crate::cfg_select!(@apply [not(any($($prev),*))] { $($body)* });
};
(@munch [$($prev:meta),*] $cond:meta => { $($body:item)* } $($rest:tt)*) => {
$crate::cfg_select!(@apply [all($cond $(, not($prev))*)] { $($body)* });
$crate::cfg_select!(@munch [$cond $(, $prev)*] $($rest)*);
};
(@munch [$($prev:meta),*]) => {};
($($tokens:tt)*) => { $crate::cfg_select!(@munch [] $($tokens)*); };
}
pub(crate) use cfg_select;
mod refcount;
pub use refcount::__Rc;
#[must_use]
pub struct Lien {
rc: NonNull<__Rc>,
}
impl Lien {
#[inline]
fn new(rc: &__Rc) -> Self {
rc.inc();
Self {
rc: NonNull::from(rc),
}
}
}
unsafe impl Send for Lien {}
unsafe impl Sync for Lien {}
impl fmt::Debug for Lien {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lien").finish_non_exhaustive()
}
}
impl Clone for Lien {
#[inline]
fn clone(&self) -> Self {
Self::new(unsafe { self.rc.as_ref() })
}
}
impl Drop for Lien {
#[inline]
fn drop(&mut self) {
unsafe { __Rc::dec(self.rc.as_ptr()) }
}
}
#[must_use]
pub struct Scope<'a> {
#[doc(hidden)]
pub __rc: &'a __Rc,
#[doc(hidden)]
pub __phantom: PhantomData<fn(&'a ()) -> &'a ()>,
}
impl<'a> Scope<'a> {
#[inline]
pub fn lien(&self) -> Lien {
Lien::new(self.__rc)
}
#[inline]
pub fn lend<T: ?Sized>(&self, value: &'a T) -> Ref<T> {
Ref {
ptr: NonNull::from(value),
_lien: self.lien(),
}
}
#[inline]
pub fn lend_mut<T: ?Sized>(&self, value: &'a mut T) -> RefMut<T> {
RefMut {
ptr: NonNull::from(value),
_lien: self.lien(),
_phantom: PhantomData,
}
}
#[inline(always)]
extern "C" fn wait(&self) {
self.__rc.wait()
}
}
impl Drop for Scope<'_> {
#[inline]
fn drop(&mut self) {
self.wait();
}
}
pub struct Rehypothecator<'a> {
lien: &'a Lien,
_phantom: PhantomData<fn(&'a ()) -> &'a ()>,
}
impl<'a> Rehypothecator<'a> {
#[inline]
pub fn lien(&self) -> Lien {
self.lien.clone()
}
#[inline]
pub fn lend<T: ?Sized>(&self, value: &'a T) -> Ref<T> {
Ref {
ptr: NonNull::from(value),
_lien: self.lien(),
}
}
#[inline]
pub fn lend_mut<T: ?Sized>(&self, value: &'a mut T) -> RefMut<T> {
RefMut {
ptr: NonNull::from(value),
_lien: self.lien(),
_phantom: PhantomData,
}
}
}
macro_rules! impl_deref_traits {
($ty:ident) => {
impl<T: ?Sized> Deref for $ty<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<T: ?Sized> AsRef<T> for $ty<T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized> Borrow<T> for $ty<T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<T: fmt::Debug + ?Sized> fmt::Debug for $ty<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: fmt::Display + ?Sized> fmt::Display for $ty<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> fmt::Pointer for $ty<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
}
}
impl<T: Hash + ?Sized> Hash for $ty<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: PartialEq + ?Sized> PartialEq for $ty<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<T: Eq + ?Sized> Eq for $ty<T> {}
impl<T: PartialOrd + ?Sized> PartialOrd for $ty<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<T: Ord + ?Sized> Ord for $ty<T> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
(**self).cmp(&**other)
}
}
impl<T: Error + ?Sized> Error for $ty<T> {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
(**self).source()
}
}
};
}
#[must_use]
pub struct Ref<T: ?Sized> {
ptr: NonNull<T>,
_lien: Lien,
}
unsafe impl<T: Sync + ?Sized> Send for Ref<T> {}
unsafe impl<T: Sync + ?Sized> Sync for Ref<T> {}
impl<T: ?Sized> Clone for Ref<T> {
#[inline]
fn clone(&self) -> Self {
Self {
ptr: self.ptr,
_lien: self._lien.clone(),
}
}
}
impl<T: ?Sized> Ref<T> {
#[inline]
pub fn map<R>(&self, f: impl for<'a> FnOnce(&'a T, Rehypothecator<'a>) -> R) -> R {
f(
unsafe { self.ptr.as_ref() },
Rehypothecator {
lien: &self._lien,
_phantom: PhantomData,
},
)
}
#[inline]
#[must_use]
pub fn as_ptr(this: &Self) -> *const T {
this.ptr.as_ptr()
}
}
impl_deref_traits!(Ref);
impl<T: ?Sized> From<RefMut<T>> for Ref<T> {
#[inline]
fn from(r: RefMut<T>) -> Self {
Self {
ptr: r.ptr,
_lien: r._lien,
}
}
}
#[must_use]
pub struct RefMut<T: ?Sized> {
ptr: NonNull<T>,
_lien: Lien,
_phantom: PhantomData<(*mut T, &'static mut ())>,
}
unsafe impl<T: Send + ?Sized> Send for RefMut<T> {}
unsafe impl<T: Sync + ?Sized> Sync for RefMut<T> {}
impl<T: ?Sized> RefMut<T> {
#[inline]
pub fn map<R>(self, f: impl for<'a> FnOnce(&'a mut T, Rehypothecator<'a>) -> R) -> R {
let lien = self._lien;
f(
unsafe { &mut *self.ptr.as_ptr() },
Rehypothecator {
lien: &lien,
_phantom: PhantomData,
},
)
}
#[inline]
#[must_use]
pub fn as_ptr(this: &Self) -> *const T {
this.ptr.as_ptr()
}
#[inline]
#[must_use]
pub fn as_mut_ptr(this: &mut Self) -> *mut T {
this.ptr.as_ptr()
}
}
impl_deref_traits!(RefMut);
impl<T: ?Sized> DerefMut for RefMut<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.ptr.as_mut() }
}
}
impl<T: ?Sized> AsMut<T> for RefMut<T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T: ?Sized> BorrowMut<T> for RefMut<T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<T: Hasher + ?Sized> Hasher for RefMut<T> {
#[inline]
fn finish(&self) -> u64 {
(**self).finish()
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
(**self).write(bytes)
}
#[inline]
fn write_u8(&mut self, i: u8) {
(**self).write_u8(i)
}
#[inline]
fn write_u16(&mut self, i: u16) {
(**self).write_u16(i)
}
#[inline]
fn write_u32(&mut self, i: u32) {
(**self).write_u32(i)
}
#[inline]
fn write_u64(&mut self, i: u64) {
(**self).write_u64(i)
}
#[inline]
fn write_u128(&mut self, i: u128) {
(**self).write_u128(i)
}
#[inline]
fn write_usize(&mut self, i: usize) {
(**self).write_usize(i)
}
#[inline]
fn write_i8(&mut self, i: i8) {
(**self).write_i8(i)
}
#[inline]
fn write_i16(&mut self, i: i16) {
(**self).write_i16(i)
}
#[inline]
fn write_i32(&mut self, i: i32) {
(**self).write_i32(i)
}
#[inline]
fn write_i64(&mut self, i: i64) {
(**self).write_i64(i)
}
#[inline]
fn write_i128(&mut self, i: i128) {
(**self).write_i128(i)
}
#[inline]
fn write_isize(&mut self, i: isize) {
(**self).write_isize(i)
}
}
impl<I: Iterator + ?Sized> Iterator for RefMut<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I::Item> {
(**self).nth(n)
}
}
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for RefMut<I> {
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
(**self).next_back()
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
(**self).nth_back(n)
}
}
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for RefMut<I> {
#[inline]
fn len(&self) -> usize {
(**self).len()
}
}
impl<I: FusedIterator + ?Sized> FusedIterator for RefMut<I> {}
impl<F: Future + Unpin + ?Sized> Future for RefMut<F> {
type Output = F::Output;
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
F::poll(Pin::new(&mut **self), cx)
}
}
#[cfg(feature = "std")]
impl<T: std::io::Read + ?Sized> std::io::Read for RefMut<T> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
(**self).read(buf)
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
(**self).read_vectored(bufs)
}
#[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
(**self).read_to_end(buf)
}
#[inline]
fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
(**self).read_to_string(buf)
}
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
(**self).read_exact(buf)
}
}
#[cfg(feature = "std")]
impl<T: std::io::Write + ?Sized> std::io::Write for RefMut<T> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
(**self).write(buf)
}
#[inline]
fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
(**self).write_vectored(bufs)
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
(**self).flush()
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
(**self).write_all(buf)
}
#[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> std::io::Result<()> {
(**self).write_fmt(fmt)
}
}
#[cfg(feature = "std")]
impl<T: std::io::Seek + ?Sized> std::io::Seek for RefMut<T> {
#[inline]
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
(**self).seek(pos)
}
#[inline]
fn rewind(&mut self) -> std::io::Result<()> {
(**self).rewind()
}
#[inline]
fn stream_position(&mut self) -> std::io::Result<u64> {
(**self).stream_position()
}
#[inline]
fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> {
(**self).seek_relative(offset)
}
}
#[cfg(feature = "std")]
impl<T: std::io::BufRead + ?Sized> std::io::BufRead for RefMut<T> {
#[inline]
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
(**self).fill_buf()
}
#[inline]
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
#[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> std::io::Result<usize> {
(**self).read_until(byte, buf)
}
#[inline]
fn skip_until(&mut self, byte: u8) -> std::io::Result<usize> {
(**self).skip_until(byte)
}
#[inline]
fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
(**self).read_line(buf)
}
}
#[doc(hidden)]
pub use core::marker::PhantomData as __PhantomData;
#[macro_export]
macro_rules! scope {
() => {
&$crate::Scope {
__rc: &$crate::__Rc::new(),
__phantom: $crate::__PhantomData,
}
};
}