#[cfg(feature = "alloc")]
use alloc::{boxed::Box, rc::Rc, sync::Arc};
#[cfg(feature = "alloc")]
use core::{alloc::Allocator, mem::MaybeUninit};
use core::{
any::Any,
borrow::{Borrow, BorrowMut},
error::Error,
fmt,
hash::{Hash, Hasher},
mem,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
task::{Context, Poll},
};
use crate::{
pin::{DropSlot, POwn},
place::{Owned, Place, PlaceRef},
uninit::Uninit,
};
pub type Own<'a, T> = PlaceRef<'a, T, Owned>;
#[macro_export]
#[allow_internal_unstable(super_let)]
macro_rules! own {
($e:expr) => {{
super let mut place = ::core::mem::MaybeUninit::uninit();
$crate::place::Place::write(&mut place, $e)
}};
}
impl<'a, T: ?Sized> Deref for Own<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.inner.as_ref() }
}
}
impl<'a, T: ?Sized> DerefMut for Own<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.inner.as_mut() }
}
}
impl<'a, T: ?Sized> AsRef<T> for Own<'a, T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<'a, T: ?Sized> AsMut<T> for Own<'a, T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<'a, T: ?Sized> Borrow<T> for Own<'a, T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<'a, T: ?Sized> BorrowMut<T> for Own<'a, T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<'a, T: ?Sized> Own<'a, T> {
#[inline]
pub fn into_pin<'b>(this: Self, slot: DropSlot<'a, 'b, T>) -> POwn<'b, T> {
POwn::new(this, slot)
}
#[inline]
pub const fn as_ptr(this: &Self) -> *const T {
this.inner.as_ptr()
}
#[inline]
pub const fn as_mut_ptr(this: &mut Self) -> *mut T {
this.inner.as_ptr()
}
#[inline]
pub const fn leak(this: Self) -> &'a mut T {
let mut inner = this.inner;
mem::forget(this);
unsafe { inner.as_mut() }
}
#[inline]
pub const fn into_raw(this: Self) -> *mut T {
let inner = this.inner;
mem::forget(this);
inner.as_ptr()
}
#[inline]
pub const unsafe fn from_raw(ptr: *mut T) -> Self {
let inner = unsafe { NonNull::new_unchecked(ptr) };
unsafe { Own::from_inner(inner) }
}
#[inline]
pub unsafe fn from_mut(place: &'a mut impl Place<T>) -> Self {
unsafe { Own::from_raw(place.as_mut_ptr()) }
}
#[inline]
pub fn drop(this: Self) -> Uninit<'a, T> {
let inner = this.inner;
mem::forget(this);
unsafe { inner.drop_in_place() };
unsafe { Uninit::from_inner(inner) }
}
}
impl<'a, T> Own<'a, T> {
#[inline]
pub const fn take(this: Self) -> (T, Uninit<'a, T>) {
let inner = this.inner;
mem::forget(this);
let value = unsafe { inner.read() };
let place = unsafe { Uninit::from_inner(inner) };
(value, place)
}
}
macro_rules! impl_downcast {
($([$($t:tt)*])*) => {$(
impl<'a> Own<'a, dyn $($t)*> {
/// Attempts to downcast the owned reference to a concrete type.
///
/// # Errors
///
/// Returns the original owned reference if the downcast fails.
///
/// # Examples
///
/// ```rust,ignore
/// use placid::prelude::*;
/// use std::any::Any;
///
#[doc = concat!("let value: Own<dyn ", stringify!($($t)*), "> = own!(42i32);")]
#[inline]
pub fn downcast<U: $($t)*>(self) -> Result<Own<'a, U>, Self> {
if (*self).is::<U>() {
Ok(unsafe { self.downcast_unchecked() })
} else {
Err(self)
}
}
#[doc = concat!("let value: Own<dyn ", stringify!($($t)*), "> = own!(\"hello\");")]
#[inline]
pub unsafe fn downcast_unchecked<U: $($t)*>(self) -> Own<'a, U> {
let raw = Own::into_raw(self).cast::<U>();
unsafe { Own::from_raw(raw) }
}
}
)*};
}
impl_downcast!([Any][Any + Send][Any + Send + Sync]);
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for Own<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'a, T: ?Sized + fmt::Display> fmt::Display for Own<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<'a, T: ?Sized> fmt::Pointer for Own<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.inner, f)
}
}
impl<'a, T: Clone> Own<'a, T> {
#[inline]
pub fn clone<'b>(&self, to: &'b mut impl Place<T>) -> Own<'b, T> {
to.write(|| (**self).clone())
}
}
impl<'a, T: Default> Own<'a, T> {
#[inline]
pub fn default(place: &'a mut impl Place<T>) -> Self {
place.write(T::default)
}
}
impl<'a, T> Default for Own<'a, [T]> {
#[inline]
fn default() -> Self {
unsafe { Own::from_inner(NonNull::from_mut(&mut [])) }
}
}
impl<'a> Default for Own<'a, str> {
#[inline]
fn default() -> Self {
unsafe { Own::from_inner(NonNull::from_ref("")) }
}
}
impl<'a> Default for Own<'a, core::ffi::CStr> {
#[inline]
fn default() -> Self {
unsafe { Own::from_inner(NonNull::from_ref(c"")) }
}
}
impl<'a, 'b, T: ?Sized + PartialEq<U>, U: ?Sized> PartialEq<Own<'b, U>> for Own<'a, T> {
#[inline]
fn eq(&self, other: &Own<'b, U>) -> bool {
**self == **other
}
}
impl<'a, T: ?Sized + Eq> Eq for Own<'a, T> {}
impl<'a, 'b, T: ?Sized + PartialOrd<U>, U: ?Sized> PartialOrd<Own<'b, U>> for Own<'a, T> {
#[inline]
fn partial_cmp(&self, other: &Own<'b, U>) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<'a, T: ?Sized + Ord> Ord for Own<'a, T> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(**self).cmp(&**other)
}
}
impl<'a, T: ?Sized + Hash> Hash for Own<'a, T> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<'a, T: ?Sized + Hasher> Hasher for Own<'a, T> {
#[inline]
fn finish(&self) -> u64 {
(**self).finish()
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
(**self).write(bytes);
}
}
impl<'a, T: ?Sized + Error> Error for Own<'a, T> {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
(**self).source()
}
}
impl<'a, F: ?Sized + Future + Unpin> Future for Own<'a, F> {
type Output = F::Output;
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut **self).poll(cx)
}
}
#[cfg(feature = "alloc")]
#[allow(dead_code)]
#[inline]
fn into_undrop_box<T: ?Sized>(own: Own<'_, T>) -> Box<T, impl Allocator> {
use core::alloc::{AllocError, Allocator, Layout};
let inner = own.inner;
mem::forget(own);
unsafe {
struct NullAlloc;
unsafe impl Allocator for NullAlloc {
fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Err(AllocError)
}
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
}
}
Box::from_raw_in(inner.as_ptr(), NullAlloc)
}
}
impl<'a, I: ?Sized + Iterator> Iterator for Own<'a, I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
(**self).next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
(**self).nth(n)
}
}
#[cfg(feature = "fn-impl")]
mod fn_impl;
pub unsafe trait IntoOwn: Deref + Sized {
type Place: Place<Self::Target, Init = Self>;
#[inline]
fn into_own_place(self) -> Self::Place {
Place::from_init(self)
}
}
#[cfg(feature = "alloc")]
macro_rules! impl_std_alloc {
(@IMP $ty:ident) => {
unsafe impl<T, A: Allocator> IntoOwn for $ty<T, A> {
type Place = $ty<MaybeUninit<T>, A>;
}
unsafe impl<T, A: Allocator> IntoOwn for $ty<[T], A> {
type Place = $ty<[MaybeUninit<T>], A>;
}
unsafe impl<A: Allocator> IntoOwn for $ty<str, A> {
type Place = $ty<[MaybeUninit<u8>], A>;
}
};
($($ty:ident),*) => {
$(impl_std_alloc!(@IMP $ty);)*
};
}
#[cfg(feature = "alloc")]
impl_std_alloc!(Box, Arc, Rc);
#[macro_export]
#[allow_internal_unstable(super_let)]
macro_rules! into_own {
($p:ident <- $e:expr) => {{
$p = $crate::owned::IntoOwn::into_own_place($e);
unsafe { $crate::owned::Own::from_mut(&mut $p) }
}};
($e:expr) => {{
super let mut p;
$crate::into_own!(p <- $e)
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_place_macro() {
let my_place = own!(10);
assert_eq!(*my_place, 10);
}
#[test]
fn test_own_take() {
let my_place = own!(100);
let (value, uninit_place) = Own::take(my_place);
assert_eq!(value, 100);
let my_place_again = uninit_place.write(200);
assert_eq!(*my_place_again, 200);
}
#[cfg(feature = "alloc")]
#[test]
fn test_into_own() {
let mut my_place;
let owned = into_own!(my_place <- Box::new(55));
assert_eq!(*owned, 55);
drop(owned);
my_place.write(123);
let owned2 = into_own!(Box::new(77));
assert_eq!(*owned2, 77);
}
}