irid-std 0.3.1

A replacement for std when running without a filesystem on the irid kernel
Documentation
use core::{borrow::Borrow, fmt::{self, Debug, Display, Formatter}, ops::Deref, str::{MatchIndices, RMatchIndices}};

use alloc::{borrow::{Cow, ToOwned}, str::{self, pattern::{Pattern, ReverseSearcher}}, string::String};

#[derive(Clone, Default)]
pub struct OsString {
    data: String
}

impl OsString {
    pub const fn new() -> Self {
        Self {
            data: String::new()
        }
    }
    
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            data: String::with_capacity(capacity)
        }
    }
    
    pub fn as_os_string(&self) -> &OsStr {
        self.as_ref()    
    }

    pub fn capacity(&self) -> usize {
        self.data.capacity()
    }

    pub fn clear(&mut self) {
        self.data.clear();
    }

    pub fn into_string(self) -> Result<String, Self> {
        Ok(self.data)
    }

    pub fn push(&mut self, value: impl AsRef<OsStr>) {
        self.data.push_str(value.as_ref().as_str());
    }
}

impl From<String> for OsString {
    fn from(value: String) -> Self {
        Self {
            data: value
        }
    }
}

impl Deref for OsString {
    type Target = OsStr;

    fn deref(&self) -> &Self::Target {
        OsStr::new(&self.data)
    }
}

impl Borrow<OsStr> for OsString {
    fn borrow(&self) -> &OsStr {
        OsStr::new(&self.data)
    }
}

impl AsRef<OsStr> for OsString {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(&self.data)
    }
}

impl AsRef<OsStr> for str {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self)
    }
}

impl AsRef<OsStr> for String {
    fn as_ref(&self) -> &OsStr {
        OsStr::new(self.as_str())
    }
}

#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OsStr {
    data: str
}

impl PartialEq<str> for OsStr {
    fn eq(&self, other: &str) -> bool {
        &self.data == other
    }
}

impl Default for &OsStr {
    fn default() -> Self {
        "".as_ref()
    }
}

impl ToOwned for OsStr {
    type Owned = OsString;

    fn to_owned(&self) -> Self::Owned {
        OsString {
            data: self.data.to_owned()
        }
    }
}

impl AsRef<OsStr> for OsStr {
    fn as_ref(&self) -> &OsStr {
        self 
    }
}

impl Debug for OsStr {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        Debug::fmt(&self.data, f)
    }
}

impl OsStr {
    pub fn new<S: AsRef<str> + ?Sized>(path: &S) -> &Self {
        unsafe {&*(path.as_ref() as *const str as *const OsStr)}
    }

    pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self {
        unsafe {&*(str::from_utf8_unchecked(bytes) as *const str as *const OsStr)}
    }

    pub(crate) fn as_str(&self) -> &str {
        &self.data
    }

    pub fn to_str(&self) -> Option<&str> {
        Some(&self.data)
    }

    pub fn to_string_lossy(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.data)
    }

    pub fn to_os_string(&self) -> OsString {
        self.to_owned()
    }

    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }

    pub fn as_encoded_bytes(&self) -> &[u8] {
        self.data.as_bytes()
    }

    pub fn make_ascii_lowercase(&mut self) {
        self.data.make_ascii_lowercase();
    }
    
    pub fn make_ascii_uppercase(&mut self) {
        self.data.make_ascii_uppercase();
    }

    pub fn to_ascii_lowercase(&self) -> OsString {
        OsString { 
            data: self.data.to_ascii_lowercase() 
        }
    }
    
    pub fn to_ascii_uppercase(&self) -> OsString {
        OsString { 
            data: self.data.to_ascii_uppercase() 
        }
    }

    pub fn is_ascii(&self) -> bool {
        self.data.is_ascii()
    }

    pub fn eq_ignore_ascii_case(&self, other: impl AsRef<OsStr>) -> bool {
        self.data.eq_ignore_ascii_case(&other.as_ref().data)
    }

    pub(crate) fn starts_with(&self, arg: impl Pattern) -> bool {
        self.data.starts_with(arg)
    }

    pub(crate) fn rmatch_indices<P: Pattern>(&self, arg: P) -> RMatchIndices<'_, P> where for <'a> <P as Pattern>::Searcher<'a> : ReverseSearcher<'a> {
        self.data.rmatch_indices(arg)
    }

    pub(crate) fn ends_with<P: Pattern>(&self, arg: P) -> bool where for <'a> <P as Pattern>::Searcher<'a> : ReverseSearcher<'a> {
        self.data.ends_with(arg)
    }

    pub(crate) fn match_indices<P: Pattern>(&self, arg: P) -> MatchIndices<'_, P> {
        self.data.match_indices(arg)
    }

    pub fn display(&self) -> StrDisplay<'_> {
        StrDisplay { data: &self.data }
    }
}

pub struct StrDisplay<'a> {
    pub(crate) data: &'a str
}

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