immut_string 0.1.0

immutable string
Documentation
use std::fmt;
use std::ops::{Add, Deref};
use std::sync::Arc;
use std::path::Path;
use std::str::FromStr;
use std::string::ParseError;

/// # Examples
/// ```
/// use immut_string::ImmutString;
///
/// let a: ImmutString = "Hello".into();
/// let b = ImmutString::from(", world!");
/// let c = a + b;
///
/// assert_eq!(c, "Hello, world!");
/// assert_eq!(c.len(), 13);
/// ```
#[derive(Clone, Eq, PartialOrd, Ord, Hash)]
pub struct ImmutString(Arc<String>);

impl ImmutString {
    #[inline]
    pub fn new(string: String) -> Self {
        ImmutString(Arc::new(string))
    }
    #[inline]
    pub fn new_empty() -> Self {
        Self::new(String::new())
    }

    #[inline]
    pub fn push(&self, ch: char) -> Self {
        let mut string = self.0.deref().clone();
        string.push(ch);
        string.into()
    }

    #[inline]
    pub fn push_str(&self, s: &str) -> Self {
        let mut string = self.0.deref().clone();
        string.push_str(s);
        string.into()
    }

    #[inline]
    pub fn append(&self, s: &ImmutString) -> Self {
        let mut string = self.0.deref().clone();
        unsafe {
            string.as_mut_vec().extend(s.as_bytes());
        }
        string.into()
    }

    #[inline]
    pub fn append_string(&self, s: String) -> Self {
        let mut string = self.0.deref().clone();
        unsafe {
            string.as_mut_vec().extend(s.into_bytes());
        }
        string.into()
    }

    #[inline]
    pub fn as_string(&self) -> &String {
        self.0.deref()
    }
    #[inline]
    pub fn into_string(&self) -> String {
        self.as_string().clone()
    }

    #[inline]
    pub fn into_bytes(&self) -> Vec<u8> {
        self.as_string().as_bytes().to_vec()
    }
}

impl fmt::Debug for ImmutString {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, f)
    }
}

impl fmt::Display for ImmutString {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl Add<ImmutString> for ImmutString {
    type Output = ImmutString;

    /// # Examples
    /// ```
    /// use immut_string::ImmutString;
    ///
    /// let a = ImmutString::from("a");
    /// let b = ImmutString::from("b");
    /// assert_eq!(&a + &b, "ab");
    /// assert_eq!(a + b, "ab");
    /// ```
    #[inline(always)]
    fn add(self, rhs: ImmutString) -> Self::Output {
        Add::add(&self, &rhs)
    }
}
impl<'a> Add<&'a ImmutString> for &'a ImmutString {
    type Output = ImmutString;

    #[inline]
    fn add(self, rhs: &'a ImmutString) -> Self::Output {
        self.push_str(rhs.deref())
    }
}

impl<'a> Add<ImmutString> for &'a ImmutString {
    type Output = ImmutString;

    #[inline]
    fn add(self, rhs: ImmutString) -> Self::Output {
        Add::add(self, &rhs)
    }
}

impl<'a> Add<&'a ImmutString> for ImmutString {
    type Output = ImmutString;

    #[inline]
    fn add(self, rhs: &'a ImmutString) -> Self::Output {
        Add::add(&self, rhs)
    }
}

impl Add<char> for ImmutString {
    type Output = ImmutString;

    /// # Examples
    /// ```
    /// use immut_string::ImmutString;
    ///
    /// let string = ImmutString::from("a");
    /// assert_eq!(&string + 'b', "ab");
    /// assert_eq!(string + 'b', "ab");
    /// ```
    #[inline(always)]
    fn add(self, rhs: char) -> Self::Output {
        Add::add(&self, rhs)
    }
}
impl<'a> Add<char> for &'a ImmutString {
    type Output = ImmutString;

    #[inline]
    fn add(self, rhs: char) -> Self::Output {
        self.push(rhs)
    }
}

impl<'a> Add<&'a str> for ImmutString {
    type Output = ImmutString;

    /// # Examples
    /// ```
    /// use immut_string::ImmutString;
    ///
    /// let string = ImmutString::from("abc");
    /// assert_eq!(&string + "def", "abcdef");
    /// assert_eq!(string + "def", "abcdef");
    /// ```
    #[inline(always)]
    fn add(self, rhs: &'a str) -> Self::Output {
        Add::add(&self, rhs)
    }
}
impl<'a> Add<&'a str> for &'a ImmutString {
    type Output = ImmutString;

    #[inline]
    fn add(self, rhs: &'a str) -> Self::Output {
        self.push_str(rhs)
    }
}

impl Add<String> for ImmutString {
    type Output = ImmutString;

    /// # Examples
    /// ```
    /// use immut_string::ImmutString;
    ///
    /// let string = ImmutString::from("abc");
    /// assert_eq!(&string + String::from("def"), "abcdef");
    /// assert_eq!(string + String::from("def"), "abcdef");
    /// ```
    #[inline(always)]
    fn add(self, rhs: String) -> Self::Output {
        Add::add(&self, rhs)
    }
}
impl<'a> Add<String> for &'a ImmutString {
    type Output = ImmutString;
    #[inline]
    fn add(self, rhs: String) -> Self::Output {
        self.append_string(rhs)
    }
}

impl AsRef<Path> for ImmutString {
    fn as_ref(&self) -> &Path {
        Path::new(self.deref())
    }
}

impl AsRef<str> for ImmutString {
    #[inline]
    fn as_ref(&self) -> &str {
        self.deref()
    }
}

impl AsRef<[u8]> for ImmutString {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        self.as_bytes()
    }
}

impl<'a> From<&'a str> for ImmutString {
    #[inline]
    fn from(value: &'a str) -> Self {
        ImmutString::new(value.into())
    }
}

impl From<String> for ImmutString {
    #[inline]
    fn from(value: String) -> Self {
        ImmutString::new(value)
    }
}

impl FromStr for ImmutString {
    type Err = ParseError;

    #[inline]
    fn from_str(s: &str) -> Result<ImmutString, ParseError> {
        Ok(ImmutString::from(s))
    }
}

impl PartialEq<str> for ImmutString {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.0.deref() == other
    }
}

impl<'a> PartialEq<&'a str> for ImmutString {
    #[inline]
    fn eq(&self, other: &&'a str) -> bool {
        self.0.deref() == other
    }
}

impl PartialEq<String> for ImmutString {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        self.0.deref() == other
    }
}

impl PartialEq<ImmutString> for ImmutString {
    #[inline]
    fn eq(&self, other: &ImmutString) -> bool {
        self.0.deref() == other.deref()
    }
}

impl Deref for ImmutString {
    type Target = String;

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}