use {
::core::{
borrow::Borrow,
convert::AsRef,
ffi::CStr,
fmt::{self, Debug, Display},
hash::Hash,
ops::Deref,
},
::std::ffi::CString,
};
#[derive(Eq, Copy, Clone, PartialOrd, Ord)]
pub struct IStr(pub(super) &'static str);
macro_rules! intern_doc {() => {
r"Intern a new string, or return the extant [`IStr`] is one exists
This operation may be slow, depending on whether the string has been previously
interned."
};}
#[doc = intern_doc!()]
#[inline]
pub fn intern(s: &str) -> IStr {
crate::internal::THE_INTERNER.intern(s)
}
#[inline]
pub fn get_interned(s: &str) -> Option<IStr> {
crate::internal::THE_INTERNER.get_interned(s)
}
#[inline]
pub fn collect_interned_strings<B>() -> B
where
B: ::core::iter::FromIterator<IStr>,
{
crate::internal::THE_INTERNER.collect_interned_strings()
}
impl IStr {
#[doc = intern_doc!()]
#[inline]
pub fn new(s: &str) -> Self {
intern(s)
}
}
impl From<&'_ str> for IStr {
#[doc = intern_doc!()]
#[inline]
fn from(s: &str) -> Self {
intern(s)
}
}
impl From<String> for IStr {
#[doc = intern_doc!()]
#[inline]
fn from(s: String) -> Self {
intern(&s)
}
}
impl TryFrom<&'_ CStr> for IStr {
type Error = ::core::str::Utf8Error;
#[doc = intern_doc!()]
#[inline]
fn try_from(c: &'_ CStr) -> Result<Self, Self::Error> {
let s = c.to_str()?;
Ok(intern(s))
}
}
impl TryFrom<CString> for IStr {
type Error = ::core::str::Utf8Error;
#[doc = intern_doc!()]
#[inline]
fn try_from(c: CString) -> Result<Self, Self::Error> {
let s = c.to_str()?;
Ok(intern(s))
}
}
impl Deref for IStr {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.0
}
}
impl AsRef<str> for IStr {
#[inline]
fn as_ref(&self) -> &str {
self.0
}
}
impl AsRef<CStr> for IStr {
#[inline]
fn as_ref(&self) -> &CStr {
self.as_c_str()
}
}
impl Borrow<str> for IStr {
#[inline]
fn borrow(&self) -> &'static str {
self.0
}
}
impl IStr {
#[inline]
pub fn as_str(&self) -> &'static str {
self.0
}
#[inline]
pub fn as_c_str(&self) -> &'static CStr {
let ptr = self.0.as_ptr();
unsafe { CStr::from_ptr(ptr as _) }
}
}
impl From<IStr> for &'static str {
#[inline]
fn from(i: IStr) -> &'static str {
i.as_str()
}
}
impl From<IStr> for &'static CStr {
#[inline]
fn from(i: IStr) -> &'static CStr {
i.as_c_str()
}
}
impl From<IStr> for String {
#[inline]
fn from(s: IStr) -> String {
s.0.to_owned()
}
}
impl From<IStr> for CString {
#[inline]
fn from(s: IStr) -> CString {
s.as_c_str().to_owned()
}
}
impl IStr {
#[inline]
pub fn to_c_string(&self) -> CString {
self.as_c_str().to_owned()
}
}
impl Display for IStr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.0)
}
}
impl Debug for IStr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("IStr(\"{}\")", self.0))
}
}
impl PartialEq for IStr {
#[inline]
fn eq(&self, rhs: &IStr) -> bool {
::core::ptr::eq(self.0.as_ptr(), rhs.0.as_ptr())
}
}
impl PartialEq<&str> for IStr {
#[inline]
fn eq(&self, other: &&str) -> bool {
self.0 == *other
}
}
impl PartialEq<IStr> for &str {
#[inline]
fn eq(&self, other: &IStr) -> bool {
*self == other.0
}
}
impl PartialEq<&CStr> for IStr {
#[inline]
fn eq(&self, other: &&CStr) -> bool {
self.as_c_str() == *other
}
}
impl PartialEq<IStr> for &CStr {
#[inline]
fn eq(&self, other: &IStr) -> bool {
*self == other.as_c_str()
}
}
impl PartialEq<String> for IStr {
#[inline]
fn eq(&self, other: &String) -> bool {
self.0 == other
}
}
impl PartialEq<IStr> for String {
#[inline]
fn eq(&self, other: &IStr) -> bool {
self == other.0
}
}
impl PartialEq<&String> for IStr {
#[inline]
fn eq(&self, other: &&String) -> bool {
self.0 == *other
}
}
impl PartialEq<IStr> for &String {
#[inline]
fn eq(&self, other: &IStr) -> bool {
*self == other.0
}
}
impl PartialEq<CString> for IStr {
#[inline]
fn eq(&self, other: &CString) -> bool {
let o: &CStr = other;
self.as_c_str() == o
}
}
impl PartialEq<IStr> for CString {
#[inline]
fn eq(&self, other: &IStr) -> bool {
let s: &CStr = self;
s == other.as_c_str()
}
}
impl PartialEq<&CString> for IStr {
#[inline]
fn eq(&self, other: &&CString) -> bool {
let o: &CStr = other;
self.as_c_str() == o
}
}
impl PartialEq<IStr> for &CString {
#[inline]
fn eq(&self, other: &IStr) -> bool {
let s: &CStr = self;
s == other.as_c_str()
}
}
impl Hash for IStr {
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl IStr {
#[inline]
pub fn wyhash(&self) -> u64 {
use crate::internal::SIZE_OF_WYHASH;
let hash_array: &[u8; SIZE_OF_WYHASH] = unsafe {
let hash_ptr = self.0.as_ptr().sub(SIZE_OF_WYHASH);
&*(hash_ptr as *const [u8; SIZE_OF_WYHASH])
};
u64::from_ne_bytes(*hash_array)
}
}