cheap_string 0.2.3

Non-mutable efficient string.
Documentation
use std::{fmt::{self, write}, ops::{Index, IndexMut}, rc::Rc, slice::SliceIndex, str::Chars};

/// Stores an Rc<str> which allows for the standard stack
/// strings to be stored on heap, it also allows shallow
/// cloning which just bumps the ref counter up, which is where
/// the name cheap string comes from.
/// # Example
/// ```
/// use cheap_string::CheapString;
/// 
/// let str = CheapString::from("Hello, world!");
/// println!("{}", str);
/// ```
#[derive(Debug, Eq, PartialOrd, Ord)]
pub struct CheapString {
    inner: Rc<str>,
}

impl CheapString {
    #[inline]
    pub fn from(str: &str) -> Self {
        Self { inner: Rc::from(str) }
    }
    
    #[inline]
    #[must_use]
    pub fn chars(&self) -> Chars { self.inner.chars() }
    
    #[inline]
    #[must_use]
    pub fn len(&self) -> usize { self.inner.len() }
    
    #[inline]
    #[must_use]
    pub fn as_str(&self) -> &str { &self.inner }
}

impl Clone for CheapString {
    #[inline]
    fn clone(&self) -> Self {
        Self { inner: self.inner.clone() }
    }
}

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

impl PartialEq<String> for CheapString {
    fn eq(&self, other: &String) -> bool {
        self.inner.as_ref() == other
    }
}

impl PartialEq<CheapString> for CheapString {
    fn eq(&self, other: &CheapString) -> bool {
        self == other
    }
}

impl<I> Index<I> for CheapString
where
    I: SliceIndex<str>,
{
    type Output = I::Output;

    #[inline]
    fn index(&self, index: I) -> &I::Output {
        self.as_str().get(index).unwrap()
    }
}

impl fmt::Display for CheapString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.inner.as_ref())
    }
}

pub trait AsCheapString {
    fn as_cheap_string(&self) -> CheapString;
}

impl AsCheapString for str {
    fn as_cheap_string(&self) -> CheapString { CheapString::from(self) }
}