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)
}
}