//! This module contains the actual, albeit generic, implementaiton of the `Cow`, //! and the traits that are available to it. 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; /// A clone-on-write smart pointer, mostly compatible with [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html). /// /// This type is using a generic `U: Capacity`. Use either [`beef::Cow`](../type.Cow.html) or [`beef::lean::Cow`](../lean/type.Cow.html) in your code. pub struct Cow<'a, T: Beef + ?Sized + 'a, U: Capacity> { /// Pointer to data ptr: NonNull, /// This usize contains length, but it may contain other /// information pending on impl of `Capacity`, and must therefore /// always go through `U::len` or `U::unpack` fat: usize, /// Capacity field. For `beef::lean::Cow` this is 0-sized! cap: U::Field, /// Lifetime marker marker: PhantomData<&'a T>, } impl Cow<'_, T, U> where T: Beef + ?Sized, U: Capacity, { /// Owned data. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// let owned: Cow = Cow::owned("I own my content".to_string()); /// ``` #[inline] pub fn owned(val: T::Owned) -> Self { let (ptr, fat, cap) = T::owned_into_parts::(val); Cow { ptr, fat, cap, marker: PhantomData, } } } impl<'a, T, U> Cow<'a, T, U> where T: Beef + ?Sized, U: Capacity, { /// Borrowed data. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// let borrowed: Cow = Cow::borrowed("I'm just a borrow"); /// ``` #[inline] pub fn borrowed(val: &'a T) -> Self { let (ptr, fat, cap) = T::ref_into_parts::(val); Cow { ptr, fat, cap, marker: PhantomData, } } /// Extracts the owned data. /// /// Clones the data if it is not already owned. #[inline] pub fn into_owned(self) -> T::Owned { let cow = ManuallyDrop::new(self); match cow.capacity() { Some(capacity) => unsafe { T::owned_from_parts::(cow.ptr, cow.fat, capacity) }, None => unsafe { &*T::ref_from_parts::(cow.ptr, cow.fat) }.to_owned(), } } /// Extracts borrowed data. /// /// Panics: If the data is 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::(self.ptr, self.fat) } } /// Returns `true` if data is borrowed or had no capacity. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// let borrowed: Cow = Cow::borrowed("Borrowed"); /// let no_capacity: Cow = Cow::owned(String::new()); /// let owned: Cow = Cow::owned(String::from("Owned")); /// /// assert_eq!(borrowed.is_borrowed(), true); /// assert_eq!(no_capacity.is_borrowed(), true); /// assert_eq!(owned.is_borrowed(), false); /// ``` #[inline] pub fn is_borrowed(&self) -> bool { self.capacity().is_none() } /// Returns `true` if data is owned and has non-0 capacity. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// let borrowed: Cow = Cow::borrowed("Borrowed"); /// let no_capacity: Cow = Cow::owned(String::new()); /// let owned: Cow = Cow::owned(String::from("Owned")); /// /// assert_eq!(borrowed.is_owned(), false); /// assert_eq!(no_capacity.is_owned(), false); /// assert_eq!(owned.is_owned(), true); /// ``` #[inline] pub fn is_owned(&self) -> bool { self.capacity().is_some() } /// Internal convenience method for casting `ptr` into a `&T` #[inline] fn borrow(&self) -> &T { unsafe { &*T::ref_from_parts::(self.ptr, self.fat) } } #[inline] fn capacity(&self) -> Option { U::maybe(self.fat, self.cap) } } impl<'a> Cow<'a, str, Wide> { /// Borrowed data. /// /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow). /// We use impl specialization to allow this function to be `const`. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// const HELLO: Cow = Cow::const_str("Hello"); /// ``` pub const fn const_str(val: &'a str) -> Self { Cow { // We are casting *const T to *mut T, however for all borrowed values // this raw pointer is only ever dereferenced back to &T. 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> { /// Borrowed data. /// /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow). /// We use impl specialization to allow this function to be `const`. /// /// # Example /// /// ```rust /// use beef::lean::Cow; /// /// const HELLO: Cow = Cow::const_str("Hello"); /// ``` pub const fn const_str(val: &'a str) -> Self { Cow { // We are casting *const T to *mut T, however for all borrowed values // this raw pointer is only ever dereferenced back to &T. ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) }, fat: Lean::mask_len(val.len()), cap: Lean, marker: PhantomData, } } } // This requires nightly: // https://github.com/rust-lang/rust/issues/57563 #[cfg(feature = "const_fn")] impl<'a, T> Cow<'a, [T], Wide> where T: Clone, { /// Borrowed data. /// /// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow). /// We use impl specialization to allow this function to be `const`. /// /// # Example /// /// ```rust /// use beef::Cow; /// /// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]); /// ``` pub const fn const_slice(val: &'a [T]) -> Self { Cow { // We are casting *const T to *mut T, however for all borrowed values // this raw pointer is only ever dereferenced back to &T. ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) }, fat: val.len(), cap: None, marker: PhantomData, } } } // This requires nightly: // https://github.com/rust-lang/rust/issues/57563 #[cfg(all(feature = "const_fn", target_pointer_width = "64"))] impl<'a, T> Cow<'a, [T], Lean> where T: Clone, { /// Borrowed data. /// /// This i functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow). /// We use impl specialization to allow this function to be `const`. /// /// # Example /// /// ```rust /// use beef::lean::Cow; /// /// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]); /// ``` pub const fn const_slice(val: &'a [T]) -> Self { Cow { // We are casting *const T to *mut T, however for all borrowed values // this raw pointer is only ever dereferenced back to &T. ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) }, fat: Lean::mask_len(val.len()), cap: Lean, marker: PhantomData, } } } impl Hash for Cow<'_, T, U> where T: Hash + Beef + ?Sized, U: Capacity, { #[inline] fn hash(&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 Eq for Cow<'_, T, U> where T: Eq + Beef + ?Sized, U: Capacity, { } impl PartialOrd> for Cow<'_, A, U> where A: Beef + ?Sized + PartialOrd, B: Beef + ?Sized, U: Capacity, V: Capacity, { #[inline] fn partial_cmp(&self, other: &Cow<'_, B, V>) -> Option { PartialOrd::partial_cmp(self.borrow(), other.borrow()) } } impl 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 From for Cow<'_, str, U> where U: Capacity, { #[inline] fn from(s: String) -> Self { Cow::owned(s) } } impl From> for Cow<'_, [T], U> where T: Clone, U: Capacity, { #[inline] fn from(v: Vec) -> Self { Cow::owned(v) } } impl 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::(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 core::ops::Deref for Cow<'_, T, U> where T: Beef + ?Sized, U: Capacity, { type Target = T; #[inline] fn deref(&self) -> &T { self.borrow() } } impl AsRef for Cow<'_, T, U> where T: Beef + ?Sized, U: Capacity, { #[inline] fn as_ref(&self) -> &T { self.borrow() } } impl Borrow for Cow<'_, T, U> where T: Beef + ?Sized, U: Capacity, { #[inline] fn borrow(&self) -> &T { self.borrow() } } impl<'a, T, U> From> 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> 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::(cow.ptr, cow.fat, capacity) }) } None => StdCow::Borrowed(unsafe { &*T::ref_from_parts::(cow.ptr, cow.fat) }), } } } impl PartialEq> for Cow<'_, A, U> where A: Beef + ?Sized, B: Beef + ?Sized, U: Capacity, V: Capacity, A: PartialEq, { fn eq(&self, other: &Cow) -> bool { self.borrow() == other.borrow() } } macro_rules! impl_eq { ($($(@for< $bounds:tt >)? $ptr:ty => $([$($deref:tt)+])? <$with:ty>,)*) => {$( impl PartialEq<$with> for Cow<'_, $ptr, U> where U: Capacity, $( $bounds: Clone + PartialEq, )* { #[inline] fn eq(&self, other: &$with) -> bool { self.borrow() == $($($deref)*)* other } } impl PartialEq> 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 => , @for [T] => <[T]>, @for [T] => [*]<&[T]>, @for [T] => [&**]>, } impl 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 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) } } // Safety: Same bounds as `std::borrow::Cow`. unsafe impl Sync for Cow<'_, T, U> where U: Capacity, T: Beef + Sync + ?Sized, T::Owned: Sync, { } unsafe impl Send for Cow<'_, T, U> where U: Capacity, T: Beef + Sync + ?Sized, T::Owned: Send, { } impl Unpin for Cow<'_, T, U> where U: Capacity, T: Beef + ?Sized, T::Owned: Unpin, { }