use std::{
borrow::Borrow, convert::identity, convert::Infallible, ffi::OsStr, ffi::OsString, hash,
hash::Hash, ops::Deref, path::Path, path::PathBuf, rc::Rc, str::FromStr, sync::Arc,
};
use crate::{
intern::Interned,
mow_os_str::MowOsStr,
pool::{Intern, OS_STR_POOL},
};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct IOsStr(Intern<OsStr>);
impl IOsStr {
#[inline]
pub fn new(s: impl AsRef<OsStr>) -> Self {
Self(OS_STR_POOL.intern(s.as_ref(), Arc::from))
}
#[inline]
pub fn from_os_string(s: OsString) -> Self {
Self(OS_STR_POOL.intern(s, Arc::from))
}
#[inline]
pub fn from_boxed(s: Box<OsStr>) -> Self {
Self(OS_STR_POOL.intern(s, Arc::from))
}
#[inline]
pub fn from_arc(s: Arc<OsStr>) -> Self {
Self(OS_STR_POOL.intern(s, identity))
}
#[inline]
pub fn from_rc(s: Rc<OsStr>) -> Self {
Self(OS_STR_POOL.intern(s, |s| Arc::from(s.to_os_string())))
}
#[inline]
pub fn from_mow(s: MowOsStr) -> Self {
s.into()
}
#[inline]
pub fn from_to_arc<S: AsRef<OsStr>>(s: S, to_arc: impl FnOnce(S) -> Arc<OsStr>) -> Self {
Self(OS_STR_POOL.intern(s, to_arc))
}
}
impl IOsStr {
#[inline]
pub fn as_os_str(&self) -> &OsStr {
self.deref()
}
#[inline]
pub fn into_boxed_os_str(&self) -> Box<OsStr> {
self.deref().into()
}
#[inline]
pub fn into_mut(&self) -> MowOsStr {
MowOsStr::from(self.clone())
}
}
unsafe impl Interned for IOsStr {}
impl Deref for IOsStr {
type Target = OsStr;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<OsStr> for IOsStr {
#[inline]
fn as_ref(&self) -> &OsStr {
self.0.get()
}
}
impl AsRef<Path> for IOsStr {
#[inline]
fn as_ref(&self) -> &Path {
self.deref().as_ref()
}
}
impl Hash for IOsStr {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl Borrow<OsStr> for IOsStr {
#[inline]
fn borrow(&self) -> &OsStr {
self.deref()
}
}
impl From<&'_ String> for IOsStr {
#[inline]
fn from(s: &'_ String) -> Self {
Self::new(s)
}
}
impl From<&'_ str> for IOsStr {
#[inline]
fn from(s: &'_ str) -> Self {
Self::new(s)
}
}
impl From<&'_ mut str> for IOsStr {
#[inline]
fn from(s: &'_ mut str) -> Self {
Self::new(s)
}
}
impl From<char> for IOsStr {
#[inline]
fn from(c: char) -> Self {
let mut tmp = [0; 4];
Self::new(c.encode_utf8(&mut tmp))
}
}
impl From<Box<OsStr>> for IOsStr {
#[inline]
fn from(s: Box<OsStr>) -> Self {
Self::from_boxed(s)
}
}
impl From<Arc<OsStr>> for IOsStr {
#[inline]
fn from(s: Arc<OsStr>) -> Self {
Self::from_arc(s)
}
}
impl From<Rc<OsStr>> for IOsStr {
#[inline]
fn from(s: Rc<OsStr>) -> Self {
Self::from_rc(s)
}
}
impl From<PathBuf> for IOsStr {
#[inline]
fn from(s: PathBuf) -> Self {
Self::from_os_string(s.into())
}
}
impl From<OsString> for IOsStr {
#[inline]
fn from(s: OsString) -> Self {
Self::from_os_string(s)
}
}
impl From<&'_ OsStr> for IOsStr {
#[inline]
fn from(s: &OsStr) -> Self {
Self::new(s)
}
}
impl From<&'_ OsString> for IOsStr {
#[inline]
fn from(s: &OsString) -> Self {
Self::new(s)
}
}
impl From<String> for IOsStr {
#[inline]
fn from(s: String) -> Self {
Self::from_os_string(s.into())
}
}
impl FromStr for IOsStr {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
OsString::from_str(s).map(Self::from_os_string)
}
}
impl From<IOsStr> for Box<OsStr> {
#[inline]
fn from(v: IOsStr) -> Self {
Self::from(v.deref())
}
}
impl From<IOsStr> for Arc<OsStr> {
#[inline]
fn from(v: IOsStr) -> Self {
v.0.into()
}
}
impl From<IOsStr> for Rc<OsStr> {
#[inline]
fn from(v: IOsStr) -> Self {
Self::from(v.deref())
}
}
impl From<IOsStr> for OsString {
#[inline]
fn from(v: IOsStr) -> Self {
Self::from(v.deref())
}
}
impl From<IOsStr> for PathBuf {
#[inline]
fn from(v: IOsStr) -> Self {
Self::from(v.deref())
}
}
impl PartialEq<OsStr> for IOsStr {
fn eq(&self, other: &OsStr) -> bool {
self.deref() == other
}
}
impl PartialEq<&OsStr> for IOsStr {
fn eq(&self, other: &&OsStr) -> bool {
self.deref() == *other
}
}
impl PartialEq<OsString> for IOsStr {
fn eq(&self, other: &OsString) -> bool {
self.deref() == *other
}
}
impl PartialEq<str> for IOsStr {
fn eq(&self, other: &str) -> bool {
self.deref() == other
}
}
impl PartialEq<&str> for IOsStr {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
impl PartialEq<String> for IOsStr {
fn eq(&self, other: &String) -> bool {
self.deref() == other.as_str()
}
}