cowvec 0.1.2

Faster version of `Cow<[T]>` and `Cow<str>`
Documentation
use std::ops::Deref;
use std::{fmt, mem, ptr, slice, str};

#[derive(Clone)]
pub struct CowStr<'a>(CowVec<'a, u8>);

impl<'a> CowStr<'a> {
    #[inline]
    pub fn borrowed(b: &'a str) -> Self {
        CowStr(CowVec::borrowed(b.as_bytes()))
    }

    #[inline]
    pub fn owned(v: String) -> Self {
        CowStr(CowVec::owned(v.into_bytes()))
    }

    #[inline]
    pub fn into_owned(self) -> String {
        unsafe { String::from_utf8_unchecked(self.0.into_owned()) }
    }

    #[inline]
    pub fn try_owned(self) -> Option<String> {
        self.0
            .try_owned()
            .map(|v| unsafe { String::from_utf8_unchecked(v) })
    }
}

impl<'a> PartialEq<&'a str> for CowStr<'a> {
    fn eq(&self, other: &&str) -> bool {
        self.as_ref() == *other
    }
}

impl<'a> PartialEq<String> for CowStr<'a> {
    fn eq(&self, other: &String) -> bool {
        *self == &**other
    }
}

impl<'a> PartialEq for CowStr<'a> {
    fn eq(&self, other: &Self) -> bool {
        *self == other.as_ref()
    }
}

impl<'a> fmt::Debug for CowStr<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

impl<'a> fmt::Display for CowStr<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

impl<'a> From<&'a str> for CowStr<'a> {
    fn from(other: &'a str) -> Self {
        CowStr::borrowed(other)
    }
}

impl From<String> for CowStr<'static> {
    fn from(other: String) -> Self {
        CowStr::owned(other)
    }
}

impl<'a> AsRef<str> for CowStr<'a> {
    #[inline]
    fn as_ref(&self) -> &str {
        unsafe { str::from_utf8_unchecked(self.0.as_ref()) }
    }
}

impl<'a> Deref for CowStr<'a> {
    type Target = str;

    #[inline]
    fn deref(&self) -> &str {
        unsafe { str::from_utf8_unchecked(self.0.deref()) }
    }
}

pub struct CowVec<'a, T: 'a> {
    ptr: *const T,
    len: usize,
    cap: usize,
    _marker: ::std::marker::PhantomData<&'a [T]>,
}

impl<'a, T> CowVec<'a, T> {
    #[inline]
    pub fn borrowed(b: &'a [T]) -> Self {
        CowVec {
            ptr: b.as_ptr(),
            len: b.len(),
            cap: 0,
            _marker: Default::default(),
        }
    }

    #[inline]
    pub fn owned(v: Vec<T>) -> Self {
        let out = CowVec {
            ptr: v.as_ptr(),
            len: v.len(),
            cap: v.capacity(),
            _marker: Default::default(),
        };

        mem::forget(v);

        out
    }

    #[inline]
    pub fn into_owned(self) -> Vec<T>
    where
        T: Clone,
    {
        self.owned_or(|x| x, |a: &_| Vec::from(a))
    }

    #[inline]
    pub fn try_owned(self) -> Option<Vec<T>> {
        self.owned_or(Some, |_: &_| None)
    }

    fn owned_or<Out, MF, OF>(self, map: MF, or: OF) -> Out
    where
        MF: FnOnce(Vec<T>) -> Out,
        OF: FnOnce(&[T]) -> Out,
    {
        let out = if self.cap == 0 {
            or(self.as_ref())
        } else {
            map(unsafe { Vec::from_raw_parts(self.ptr as *mut T, self.len, self.cap) })
        };

        mem::forget(self);

        out
    }
}

impl<'a, T> Clone for CowVec<'a, T>
where
    T: Clone,
{
    fn clone(&self) -> Self {
        if self.cap == 0 {
            CowVec { ..*self }
        } else {
            Vec::from(self.as_ref()).into()
        }
    }
}

impl<'a, T> PartialEq<&'a [T]> for CowVec<'a, T>
where
    for<'any> &'any [T]: PartialEq,
{
    fn eq(&self, other: &&[T]) -> bool {
        self.as_ref() == *other
    }
}

impl<'a, T> PartialEq<Vec<T>> for CowVec<'a, T>
where
    for<'any> &'any [T]: PartialEq,
{
    fn eq(&self, other: &Vec<T>) -> bool {
        *self == &**other
    }
}

impl<'a, T> PartialEq for CowVec<'a, T>
where
    for<'any> &'any [T]: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        *self == other.as_ref()
    }
}

impl<'a, T> fmt::Debug for CowVec<'a, T>
where
    for<'any> &'any [T]: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

impl<'a, T> From<&'a [T]> for CowVec<'a, T> {
    fn from(other: &'a [T]) -> Self {
        CowVec::borrowed(other)
    }
}

impl<'a, T> From<Vec<T>> for CowVec<'a, T> {
    fn from(other: Vec<T>) -> Self {
        CowVec::owned(other)
    }
}

impl<'a, T> AsRef<[T]> for CowVec<'a, T> {
    #[inline]
    fn as_ref(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.len) }
    }
}

impl<'a, T> Drop for CowVec<'a, T> {
    #[inline]
    fn drop(&mut self) {
        let _ = unsafe { ptr::read(self) }.try_owned();
    }
}

impl<'a, T> Deref for CowVec<'a, T> {
    type Target = [T];

    #[inline]
    fn deref(&self) -> &[T] {
        self.as_ref()
    }
}

#[cfg(test)]
mod tests {
    use super::{CowStr, CowVec};

    #[test]
    fn borrowed() {
        let arr = &[1, 2, 3, 4, 5];
        let v = CowVec::borrowed(arr);

        assert_eq!(arr, &*v);
    }

    #[test]
    fn owned() {
        let arr = vec![1, 2, 3, 4, 5];
        let v = CowVec::owned(arr.clone());

        assert_eq!(arr, &*v);
    }

    #[test]
    fn borrowed_str() {
        let msg = "Hello, world!";
        let v = CowStr::borrowed(msg);

        assert_eq!(msg, &*v);
    }

    #[test]
    fn owned_str() {
        let msg = "Hello, world!".to_owned();
        let v = CowStr::owned(msg.clone());

        assert_eq!(msg, &*v);
    }
}