use alloc::borrow::{Borrow, Cow as StdCow};
use alloc::string::String;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr::NonNull;
#[cfg(target_pointer_width = "64")]
use crate::lean::internal::Lean;
use crate::traits::{Beef, Capacity};
use crate::wide::internal::Wide;
pub struct Cow<'a, T: Beef + ?Sized + 'a, U: Capacity> {
ptr: NonNull<T::PointerT>,
fat: usize,
cap: U::Field,
marker: PhantomData<&'a T>,
}
impl<T, U> Cow<'_, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
pub fn owned(val: T::Owned) -> Self {
let (ptr, fat, cap) = T::owned_into_parts::<U>(val);
Cow {
ptr,
fat,
cap,
marker: PhantomData,
}
}
}
impl<'a, T, U> Cow<'a, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
pub fn borrowed(val: &'a T) -> Self {
let (ptr, fat, cap) = T::ref_into_parts::<U>(val);
Cow {
ptr,
fat,
cap,
marker: PhantomData,
}
}
#[inline]
pub fn into_owned(self) -> T::Owned {
let cow = ManuallyDrop::new(self);
match cow.capacity() {
Some(capacity) => unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) },
None => unsafe { &*T::ref_from_parts::<U>(cow.ptr, cow.fat) }.to_owned(),
}
}
#[inline]
pub fn unwrap_borrowed(self) -> &'a T {
if self.capacity().is_some() {
panic!("Can not turn owned beef::Cow into a borrowed value")
}
unsafe { &*T::ref_from_parts::<U>(self.ptr, self.fat) }
}
#[inline]
pub fn is_borrowed(&self) -> bool {
self.capacity().is_none()
}
#[inline]
pub fn is_owned(&self) -> bool {
self.capacity().is_some()
}
#[inline]
fn borrow(&self) -> &T {
unsafe { &*T::ref_from_parts::<U>(self.ptr, self.fat) }
}
#[inline]
fn capacity(&self) -> Option<U::NonZero> {
U::maybe(self.fat, self.cap)
}
}
impl<'a> Cow<'a, str, Wide> {
pub const fn const_str(val: &'a str) -> Self {
Cow {
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) },
fat: val.len(),
cap: None,
marker: PhantomData,
}
}
}
#[cfg(target_pointer_width = "64")]
impl<'a> Cow<'a, str, Lean> {
pub const fn const_str(val: &'a str) -> Self {
Cow {
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) },
fat: Lean::mask_len(val.len()),
cap: Lean,
marker: PhantomData,
}
}
}
#[cfg(feature = "const_fn")]
impl<'a, T> Cow<'a, [T], Wide>
where
T: Clone,
{
pub const fn const_slice(val: &'a [T]) -> Self {
Cow {
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) },
fat: val.len(),
cap: None,
marker: PhantomData,
}
}
}
#[cfg(all(feature = "const_fn", target_pointer_width = "64"))]
impl<'a, T> Cow<'a, [T], Lean>
where
T: Clone,
{
pub const fn const_slice(val: &'a [T]) -> Self {
Cow {
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) },
fat: Lean::mask_len(val.len()),
cap: Lean,
marker: PhantomData,
}
}
}
impl<T, U> Hash for Cow<'_, T, U>
where
T: Hash + Beef + ?Sized,
U: Capacity,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.borrow().hash(state)
}
}
impl<'a, T, U> Default for Cow<'a, T, U>
where
T: Beef + ?Sized,
U: Capacity,
&'a T: Default,
{
#[inline]
fn default() -> Self {
Cow::borrowed(Default::default())
}
}
impl<T, U> Eq for Cow<'_, T, U>
where
T: Eq + Beef + ?Sized,
U: Capacity,
{
}
impl<A, B, U, V> PartialOrd<Cow<'_, B, V>> for Cow<'_, A, U>
where
A: Beef + ?Sized + PartialOrd<B>,
B: Beef + ?Sized,
U: Capacity,
V: Capacity,
{
#[inline]
fn partial_cmp(&self, other: &Cow<'_, B, V>) -> Option<Ordering> {
PartialOrd::partial_cmp(self.borrow(), other.borrow())
}
}
impl<T, U> Ord for Cow<'_, T, U>
where
T: Ord + Beef + ?Sized,
U: Capacity,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(self.borrow(), other.borrow())
}
}
impl<'a, T, U> From<&'a T> for Cow<'a, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn from(val: &'a T) -> Self {
Cow::borrowed(val)
}
}
impl<U> From<String> for Cow<'_, str, U>
where
U: Capacity,
{
#[inline]
fn from(s: String) -> Self {
Cow::owned(s)
}
}
impl<T, U> From<Vec<T>> for Cow<'_, [T], U>
where
T: Clone,
U: Capacity,
{
#[inline]
fn from(v: Vec<T>) -> Self {
Cow::owned(v)
}
}
impl<T, U> Drop for Cow<'_, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn drop(&mut self) {
if let Some(capacity) = self.capacity() {
unsafe { T::owned_from_parts::<U>(self.ptr, self.fat, capacity) };
}
}
}
impl<'a, T, U> Clone for Cow<'a, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn clone(&self) -> Self {
match self.capacity() {
Some(_) => Cow::owned(self.borrow().to_owned()),
None => Cow { ..*self },
}
}
}
impl<T, U> core::ops::Deref for Cow<'_, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.borrow()
}
}
impl<T, U> AsRef<T> for Cow<'_, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn as_ref(&self) -> &T {
self.borrow()
}
}
impl<T, U> Borrow<T> for Cow<'_, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn borrow(&self) -> &T {
self.borrow()
}
}
impl<'a, T, U> From<StdCow<'a, T>> for Cow<'a, T, U>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn from(stdcow: StdCow<'a, T>) -> Self {
match stdcow {
StdCow::Borrowed(v) => Self::borrowed(v),
StdCow::Owned(v) => Self::owned(v),
}
}
}
impl<'a, T, U> From<Cow<'a, T, U>> for StdCow<'a, T>
where
T: Beef + ?Sized,
U: Capacity,
{
#[inline]
fn from(cow: Cow<'a, T, U>) -> Self {
let cow = ManuallyDrop::new(cow);
match cow.capacity() {
Some(capacity) => {
StdCow::Owned(unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) })
}
None => StdCow::Borrowed(unsafe { &*T::ref_from_parts::<U>(cow.ptr, cow.fat) }),
}
}
}
impl<A, B, U, V> PartialEq<Cow<'_, B, V>> for Cow<'_, A, U>
where
A: Beef + ?Sized,
B: Beef + ?Sized,
U: Capacity,
V: Capacity,
A: PartialEq<B>,
{
fn eq(&self, other: &Cow<B, V>) -> bool {
self.borrow() == other.borrow()
}
}
macro_rules! impl_eq {
($($(@for< $bounds:tt >)? $ptr:ty => $([$($deref:tt)+])? <$with:ty>,)*) => {$(
impl<U $(, $bounds)*> PartialEq<$with> for Cow<'_, $ptr, U>
where
U: Capacity,
$( $bounds: Clone + PartialEq, )*
{
#[inline]
fn eq(&self, other: &$with) -> bool {
self.borrow() == $($($deref)*)* other
}
}
impl<U $(, $bounds)*> PartialEq<Cow<'_, $ptr, U>> for $with
where
U: Capacity,
$( $bounds: Clone + PartialEq, )*
{
#[inline]
fn eq(&self, other: &Cow<$ptr, U>) -> bool {
$($($deref)*)* self == other.borrow()
}
}
)*};
}
impl_eq! {
str => <str>,
str => [*]<&str>,
str => <String>,
@for<T> [T] => <[T]>,
@for<T> [T] => [*]<&[T]>,
@for<T> [T] => [&**]<Vec<T>>,
}
impl<T, U> fmt::Debug for Cow<'_, T, U>
where
T: Beef + fmt::Debug + ?Sized,
U: Capacity,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.borrow().fmt(f)
}
}
impl<T, U> fmt::Display for Cow<'_, T, U>
where
T: Beef + fmt::Display + ?Sized,
U: Capacity,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.borrow().fmt(f)
}
}
unsafe impl<T: Beef + Sync + ?Sized, U: Capacity> Sync for Cow<'_, T, U> {}
unsafe impl<T: Beef + Send + ?Sized, U: Capacity> Send for Cow<'_, T, U> {}