mod convert;
mod extent;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr::NonNull;
use crate::imp;
use crate::imp::Cow as _;
use self::convert::{Convert, IsOwned};
pub struct Cow<'a, T>
where
T: ?Sized + Convert,
{
ptr: NonNull<T::Ptr>,
extent: T::Extent,
marker: PhantomData<&'a T>,
}
impl<'a, T> imp::Cow<'a, T> for Cow<'a, T>
where
T: ?Sized + Convert,
{
#[inline]
fn borrowed(b: &'a T) -> Self {
let (ptr, extent) = T::unmake_borrowed(b);
Self {
ptr,
extent,
marker: PhantomData,
}
}
#[inline]
fn owned(o: T::Owned) -> Self {
let (ptr, extent) = T::unmake_owned(o);
Self {
ptr,
extent,
marker: PhantomData,
}
}
#[inline]
fn is_borrowed(&self) -> bool {
!self.extent.is_owned()
}
#[inline]
fn is_owned(&self) -> bool {
self.extent.is_owned()
}
#[inline]
fn make_ref(&self) -> &T {
unsafe { &*T::make_ptr(self.ptr, self.extent) }
}
#[inline]
fn into_owned(self) -> T::Owned {
if self.is_owned() {
let cow = ManuallyDrop::new(self);
unsafe { T::make_owned(cow.ptr, cow.extent) }
} else {
self.make_ref().to_owned()
}
}
#[inline]
fn apply<F>(&mut self, f: F)
where
F: FnOnce(&mut T::Owned),
{
let mut o = if self.is_owned() {
let o = unsafe { T::make_owned(self.ptr, self.extent) };
self.extent = T::Extent::default();
o
} else {
self.make_ref().to_owned()
};
f(&mut o);
let (ptr, extent) = T::unmake_owned(o);
self.ptr = ptr;
self.extent = extent;
}
}
impl<T> Clone for Cow<'_, T>
where
T: ?Sized + Convert,
{
#[inline]
fn clone(&self) -> Self {
if self.is_owned() {
Self::owned(self.make_ref().to_owned())
} else {
Self { ..*self }
}
}
}
impl<T> Drop for Cow<'_, T>
where
T: ?Sized + Convert,
{
#[inline]
fn drop(&mut self) {
if self.is_owned() {
unsafe { T::make_owned(self.ptr, self.extent) };
}
}
}