use std::{
borrow::Borrow,
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
mem::ManuallyDrop,
ops::Deref,
ptr::{slice_from_raw_parts, NonNull},
sync::Arc,
};
#[derive(Clone, Copy)]
enum Kind {
Owned,
Borrowed,
Shared,
}
pub struct Cow<'a, T: Cowable + ?Sized + 'a> {
ptr: NonNull<T::Pointer>,
metadata: Metadata,
_lifetime: PhantomData<&'a T>,
}
impl<T> Cow<'_, T>
where
T: Cowable + ?Sized,
{
fn from_parts(ptr: NonNull<T::Pointer>, metadata: Metadata) -> Self {
Self { ptr, metadata, _lifetime: PhantomData }
}
pub fn from_owned(owned: T::Owned) -> Self {
let (ptr, metadata) = T::owned_into_parts(owned);
if metadata.capacity() == usize::MAX {
panic!("Invalid capacity of `usize::MAX` for owned value.");
}
Self::from_parts(ptr, metadata)
}
pub fn from_shared(arc: Arc<T>) -> Self {
let (ptr, metadata) = T::shared_into_parts(arc);
Self::from_parts(ptr, metadata)
}
pub fn into_owned(self) -> <T as ToOwned>::Owned {
let cow = ManuallyDrop::new(self);
T::owned_from_parts(cow.ptr, &cow.metadata)
}
}
impl<'a, T> Cow<'a, T>
where
T: Cowable + ?Sized,
{
pub fn from_borrowed(borrowed: &'a T) -> Self {
let (ptr, metadata) = T::borrowed_into_parts(borrowed);
Self::from_parts(ptr, metadata)
}
}
impl<'a, T> Cow<'a, [T]>
where
T: Clone,
{
pub const fn const_slice(val: &'a [T]) -> Cow<'a, [T]> {
let ptr = unsafe { NonNull::new_unchecked(val.as_ptr() as *mut _) };
let metadata = Metadata::borrowed(val.len());
Self { ptr, metadata, _lifetime: PhantomData }
}
}
impl<T> Cow<'static, [T]>
where
T: Clone,
{
pub(crate) fn to_retained(&self) -> Self {
match self.metadata.kind() {
Kind::Borrowed | Kind::Shared => self.clone(),
Kind::Owned => Cow::from_shared(Arc::<[T]>::from(self.deref())),
}
}
}
impl<'a> Cow<'a, str> {
pub const fn const_str(val: &'a str) -> Self {
let ptr = unsafe { NonNull::new_unchecked(val.as_ptr() as *mut _) };
let metadata = Metadata::borrowed(val.len());
Self { ptr, metadata, _lifetime: PhantomData }
}
}
impl Cow<'static, str> {
pub(crate) fn to_retained(&self) -> Self {
match self.metadata.kind() {
Kind::Borrowed | Kind::Shared => self.clone(),
Kind::Owned => Cow::from_shared(Arc::<str>::from(self.deref())),
}
}
}
impl<T> Deref for Cow<'_, T>
where
T: Cowable + ?Sized,
{
type Target = T;
fn deref(&self) -> &Self::Target {
let borrowed_ptr = T::borrowed_from_parts(self.ptr, &self.metadata);
unsafe { borrowed_ptr.as_ref().unwrap() }
}
}
impl<T> Clone for Cow<'_, T>
where
T: Cowable + ?Sized,
{
fn clone(&self) -> Self {
let (ptr, metadata) = T::clone_from_parts(self.ptr, &self.metadata);
Self { ptr, metadata, _lifetime: PhantomData }
}
}
impl<T> Drop for Cow<'_, T>
where
T: Cowable + ?Sized,
{
fn drop(&mut self) {
T::drop_from_parts(self.ptr, &self.metadata);
}
}
impl<T> Hash for Cow<'_, T>
where
T: Hash + Cowable + ?Sized,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl<'a, T> Default for Cow<'a, T>
where
T: Cowable + ?Sized,
&'a T: Default,
{
#[inline]
fn default() -> Self {
Cow::from_borrowed(Default::default())
}
}
impl<T> Eq for Cow<'_, T> where T: Eq + Cowable + ?Sized {}
impl<A, B> PartialOrd<Cow<'_, B>> for Cow<'_, A>
where
A: Cowable + ?Sized + PartialOrd<B>,
B: Cowable + ?Sized,
{
#[inline]
fn partial_cmp(&self, other: &Cow<'_, B>) -> Option<Ordering> {
PartialOrd::partial_cmp(self.deref(), other.deref())
}
}
impl<T> Ord for Cow<'_, T>
where
T: Ord + Cowable + ?Sized,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(self.deref(), other.deref())
}
}
impl<'a, T> From<&'a T> for Cow<'a, T>
where
T: Cowable + ?Sized,
{
#[inline]
fn from(val: &'a T) -> Self {
Cow::from_borrowed(val)
}
}
impl<'a, T> From<Arc<T>> for Cow<'a, T>
where
T: Cowable + ?Sized,
{
#[inline]
fn from(val: Arc<T>) -> Self {
Cow::from_shared(val)
}
}
impl<'a> From<std::borrow::Cow<'a, str>> for Cow<'a, str> {
#[inline]
fn from(s: std::borrow::Cow<'a, str>) -> Self {
match s {
std::borrow::Cow::Borrowed(bs) => Cow::from_borrowed(bs),
std::borrow::Cow::Owned(os) => Cow::from_owned(os),
}
}
}
impl<'a, T: Cowable + ?Sized> From<Cow<'a, T>> for std::borrow::Cow<'a, T> {
#[inline]
fn from(value: Cow<'a, T>) -> Self {
match value.metadata.kind() {
Kind::Owned | Kind::Shared => Self::Owned(value.into_owned()),
Kind::Borrowed => {
Self::Borrowed(unsafe { &*T::borrowed_from_parts(value.ptr, &value.metadata) })
}
}
}
}
impl From<String> for Cow<'_, str> {
#[inline]
fn from(s: String) -> Self {
Cow::from_owned(s)
}
}
impl<T> From<Vec<T>> for Cow<'_, [T]>
where
T: Clone,
{
#[inline]
fn from(v: Vec<T>) -> Self {
Cow::from_owned(v)
}
}
impl<T> AsRef<T> for Cow<'_, T>
where
T: Cowable + ?Sized,
{
#[inline]
fn as_ref(&self) -> &T {
self.borrow()
}
}
impl<T> Borrow<T> for Cow<'_, T>
where
T: Cowable + ?Sized,
{
#[inline]
fn borrow(&self) -> &T {
self.deref()
}
}
impl<A, B> PartialEq<Cow<'_, B>> for Cow<'_, A>
where
A: Cowable + ?Sized,
B: Cowable + ?Sized,
A: PartialEq<B>,
{
fn eq(&self, other: &Cow<B>) -> bool {
self.deref() == other.deref()
}
}
impl<T> fmt::Debug for Cow<'_, T>
where
T: Cowable + fmt::Debug + ?Sized,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(f)
}
}
impl<T> fmt::Display for Cow<'_, T>
where
T: Cowable + fmt::Display + ?Sized,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(f)
}
}
unsafe impl<T: Cowable + Sync + ?Sized> Sync for Cow<'_, T> {}
unsafe impl<T: Cowable + Send + ?Sized> Send for Cow<'_, T> {}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Metadata(usize, usize);
impl Metadata {
#[inline]
const fn len(&self) -> usize {
self.0
}
#[inline]
const fn capacity(&self) -> usize {
self.1
}
#[inline]
const fn kind(&self) -> Kind {
match (self.0, self.1) {
(_, usize::MAX) => Kind::Shared,
(_, 0) => Kind::Borrowed,
_ => Kind::Owned,
}
}
#[inline]
const fn shared(len: usize) -> Metadata {
Metadata(len, usize::MAX)
}
#[inline]
const fn borrowed(len: usize) -> Metadata {
Metadata(len, 0)
}
#[inline]
const fn owned(len: usize, capacity: usize) -> Metadata {
Metadata(len, capacity)
}
}
pub trait Cowable: ToOwned {
type Pointer;
fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata);
fn owned_into_parts(owned: <Self as ToOwned>::Owned) -> (NonNull<Self::Pointer>, Metadata);
fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata);
fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self;
fn owned_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> <Self as ToOwned>::Owned;
fn clone_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> (NonNull<Self::Pointer>, Metadata);
fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata);
}
impl Cowable for str {
type Pointer = u8;
#[inline]
fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata) {
let ptr = unsafe { NonNull::new_unchecked(self.as_ptr() as *mut _) };
let metadata = Metadata::borrowed(self.len());
(ptr, metadata)
}
#[inline]
fn owned_into_parts(owned: Self::Owned) -> (NonNull<Self::Pointer>, Metadata) {
let mut owned = ManuallyDrop::new(owned.into_bytes());
let ptr = unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) };
let metadata = Metadata::owned(owned.len(), owned.capacity());
(ptr, metadata)
}
#[inline]
fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata) {
let metadata = Metadata::shared(arc.len());
let ptr = unsafe { NonNull::new_unchecked(Arc::into_raw(arc) as *mut _) };
(ptr, metadata)
}
#[inline]
fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self {
slice_from_raw_parts(ptr.as_ptr(), metadata.len()) as *const _
}
#[inline]
fn owned_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> <Self as ToOwned>::Owned {
match metadata.kind() {
Kind::Borrowed => {
let s = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
s.to_owned()
}
Kind::Owned => unsafe {
String::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity())
},
Kind::Shared => {
let s = unsafe { Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)) };
s.to_string()
}
}
}
#[inline]
fn clone_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> (NonNull<Self::Pointer>, Metadata) {
match metadata.kind() {
Kind::Borrowed => (ptr, *metadata),
Kind::Owned => {
let s = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
Self::owned_into_parts(s.to_string())
}
Kind::Shared => clone_shared::<Self>(ptr, metadata),
}
}
#[inline]
fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) {
match metadata.kind() {
Kind::Borrowed => {}
Kind::Owned => unsafe {
drop(Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity()));
},
Kind::Shared => unsafe {
drop(Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)));
},
}
}
}
impl<T> Cowable for [T]
where
T: Clone,
{
type Pointer = T;
#[inline]
fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata) {
let ptr = unsafe { NonNull::new_unchecked(self.as_ptr() as *mut _) };
let metadata = Metadata::borrowed(self.len());
(ptr, metadata)
}
#[inline]
fn owned_into_parts(owned: <Self as ToOwned>::Owned) -> (NonNull<Self::Pointer>, Metadata) {
let mut owned = ManuallyDrop::new(owned);
let ptr = unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) };
let metadata = Metadata::owned(owned.len(), owned.capacity());
(ptr, metadata)
}
#[inline]
fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata) {
let metadata = Metadata::shared(arc.len());
let ptr = unsafe { NonNull::new_unchecked(Arc::into_raw(arc) as *mut _) };
(ptr, metadata)
}
#[inline]
fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self {
slice_from_raw_parts(ptr.as_ptr(), metadata.len()) as *const _
}
#[inline]
fn owned_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> <Self as ToOwned>::Owned {
match metadata.kind() {
Kind::Borrowed => {
let data = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
data.to_vec()
}
Kind::Owned => unsafe {
Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity())
},
Kind::Shared => {
let arc = unsafe { Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)) };
arc.to_vec()
}
}
}
#[inline]
fn clone_from_parts(
ptr: NonNull<Self::Pointer>,
metadata: &Metadata,
) -> (NonNull<Self::Pointer>, Metadata) {
match metadata.kind() {
Kind::Borrowed => (ptr, *metadata),
Kind::Owned => {
let vec_ptr = Self::borrowed_from_parts(ptr, metadata);
let new_vec = unsafe { vec_ptr.as_ref().unwrap().to_vec() };
Self::owned_into_parts(new_vec)
}
Kind::Shared => clone_shared::<Self>(ptr, metadata),
}
}
#[inline]
fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) {
match metadata.kind() {
Kind::Borrowed => {}
Kind::Owned => unsafe {
drop(Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity()));
},
Kind::Shared => unsafe {
drop(Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)));
},
}
}
}
fn clone_shared<T: Cowable + ?Sized>(
ptr: NonNull<T::Pointer>,
metadata: &Metadata,
) -> (NonNull<T::Pointer>, Metadata) {
let arc_ptr = T::borrowed_from_parts(ptr, metadata);
unsafe {
Arc::increment_strong_count(arc_ptr);
}
(ptr, *metadata)
}
pub(crate) mod const_cow {
use super::*;
use crate::Label;
use std::ptr::slice_from_raw_parts;
impl Cow<'static, str> {
pub(crate) const fn as_const_str(&self) -> &str {
let borrowed_ptr =
slice_from_raw_parts(self.ptr.as_ptr(), self.metadata.len()) as *const str;
unsafe { &*borrowed_ptr }
}
}
impl Cow<'static, [Label]> {
pub(crate) const fn as_const_slice(&self) -> &[Label] {
let borrowed_ptr =
slice_from_raw_parts(self.ptr.as_ptr(), self.metadata.len()) as *const [Label];
unsafe { &*borrowed_ptr }
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn test_as_const_str() {
let cow = Cow::const_str("hello");
assert_eq!(cow.as_const_str(), "hello");
let cow: Cow<'static, str> = Cow::from_owned(String::from("hello"));
assert_eq!(cow.as_const_str(), "hello");
let arc: Arc<str> = Arc::from("hello");
let cow: Cow<'static, str> = Cow::from_shared(arc);
assert_eq!(cow.as_const_str(), "hello");
}
#[test]
fn test_as_const_slice() {
{
static LABELS: [Label; 2] = [
Label::from_static_parts("key1", "value1"),
Label::from_static_parts("key2", "value2"),
];
let cow = Cow::const_slice(&LABELS);
let slice = cow.as_const_slice();
assert_eq!(slice.len(), 2);
assert_eq!(slice[0].key(), "key1");
assert_eq!(slice[0].value(), "value1");
assert_eq!(slice[1].key(), "key2");
assert_eq!(slice[1].value(), "value2");
}
{
let labels = vec![
Label::from_static_parts("key1", "value1"),
Label::from_static_parts("key2", "value2"),
];
let cow: Cow<'static, [Label]> = Cow::from_owned(labels);
let slice = cow.as_const_slice();
assert_eq!(slice.len(), 2);
assert_eq!(slice[0].key(), "key1");
assert_eq!(slice[0].value(), "value1");
assert_eq!(slice[1].key(), "key2");
assert_eq!(slice[1].value(), "value2");
}
{
let labels: Arc<[Label]> = Arc::from([
Label::from_static_parts("key1", "value1"),
Label::from_static_parts("key2", "value2"),
]);
let cow: Cow<'static, [Label]> = Cow::from_shared(labels);
let slice = cow.as_const_slice();
assert_eq!(slice.len(), 2);
assert_eq!(slice[0].key(), "key1");
assert_eq!(slice[0].value(), "value1");
assert_eq!(slice[1].key(), "key2");
assert_eq!(slice[1].value(), "value2");
}
}
#[test]
fn test_to_retained_str() {
let borrowed = Cow::const_str("hello").to_retained();
assert!(matches!(borrowed.metadata.kind(), Kind::Borrowed));
let owned: Cow<'static, str> = Cow::from_owned(String::from("hello"));
let retained = owned.to_retained();
assert!(matches!(retained.metadata.kind(), Kind::Shared));
let shared = Cow::from_shared(Arc::<str>::from("hello")).to_retained();
assert!(matches!(shared.metadata.kind(), Kind::Shared));
}
#[test]
fn test_to_retained_slice() {
static LABELS: [Label; 2] = [
Label::from_static_parts("key1", "value1"),
Label::from_static_parts("key2", "value2"),
];
let borrowed = Cow::const_slice(&LABELS).to_retained();
assert!(matches!(borrowed.metadata.kind(), Kind::Borrowed));
let owned: Cow<'static, [Label]> = Cow::from_owned(LABELS.to_vec());
let retained = owned.to_retained();
assert!(matches!(retained.metadata.kind(), Kind::Shared));
let shared = Cow::from_shared(Arc::<[Label]>::from(&LABELS[..])).to_retained();
assert!(matches!(shared.metadata.kind(), Kind::Shared));
}
}
}