diff --git a/src/backend.rs b/src/backend.rs index a4669ec..3827082 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -3,23 +3,27 @@ pub(crate) type DefaultStr = crate::backend::ArcStr; #[cfg(not(feature = "arc"))] pub(crate) type DefaultStr = crate::backend::BoxedStr; +/// Fast allocations, O(n) clones pub type BoxedStr = Box; static_assertions::assert_eq_size!(DefaultStr, BoxedStr); +/// Cross-thread, O(1) clones pub type ArcStr = std::sync::Arc; static_assertions::assert_eq_size!(DefaultStr, ArcStr); +/// O(1) clones pub type RcStr = std::rc::Rc; static_assertions::assert_eq_size!(DefaultStr, RcStr); -pub trait StorageBackend: std::fmt::Debug + Clone + private::Sealed { +/// Abstract over different type of heap-allocated strings +pub trait HeapStr: std::fmt::Debug + Clone + private::Sealed { fn from_str(other: &str) -> Self; fn from_string(other: String) -> Self; fn from_boxed_str(other: BoxedStr) -> Self; fn as_str(&self) -> &str; } -impl StorageBackend for BoxedStr { +impl HeapStr for BoxedStr { #[inline] fn from_str(other: &str) -> Self { other.into() @@ -41,7 +45,7 @@ impl StorageBackend for BoxedStr { } } -impl StorageBackend for ArcStr { +impl HeapStr for ArcStr { #[inline] fn from_str(other: &str) -> Self { other.into() @@ -63,7 +67,7 @@ impl StorageBackend for ArcStr { } } -impl StorageBackend for RcStr { +impl HeapStr for RcStr { #[inline] fn from_str(other: &str) -> Self { other.into() diff --git a/src/string.rs b/src/string.rs index f2411db..f662304 100644 --- a/src/string.rs +++ b/src/string.rs @@ -43,7 +43,7 @@ impl KStringBase { } } -impl KStringBase { +impl KStringBase { /// Create an owned `KStringBase`. #[inline] #[must_use] @@ -107,7 +107,7 @@ impl KStringBase { } } -impl std::ops::Deref for KStringBase { +impl std::ops::Deref for KStringBase { type Target = str; #[inline] @@ -116,177 +116,177 @@ impl std::ops::Deref for KStringBase { } } -impl Eq for KStringBase {} +impl Eq for KStringBase {} -impl<'s, B: crate::backend::StorageBackend> PartialEq> for KStringBase { +impl<'s, B: crate::backend::HeapStr> PartialEq> for KStringBase { #[inline] fn eq(&self, other: &Self) -> bool { PartialEq::eq(self.as_str(), other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq for KStringBase { +impl<'s, B: crate::backend::HeapStr> PartialEq for KStringBase { #[inline] fn eq(&self, other: &str) -> bool { PartialEq::eq(self.as_str(), other) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq<&'s str> for KStringBase { +impl<'s, B: crate::backend::HeapStr> PartialEq<&'s str> for KStringBase { #[inline] fn eq(&self, other: &&str) -> bool { PartialEq::eq(self.as_str(), *other) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq for KStringBase { +impl<'s, B: crate::backend::HeapStr> PartialEq for KStringBase { #[inline] fn eq(&self, other: &StdString) -> bool { PartialEq::eq(self.as_str(), other.as_str()) } } -impl Ord for KStringBase { +impl Ord for KStringBase { #[inline] fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_str().cmp(other.as_str()) } } -impl PartialOrd for KStringBase { +impl PartialOrd for KStringBase { #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.as_str().partial_cmp(other.as_str()) } } -impl std::hash::Hash for KStringBase { +impl std::hash::Hash for KStringBase { #[inline] fn hash(&self, state: &mut H) { self.as_str().hash(state); } } -impl fmt::Debug for KStringBase { +impl fmt::Debug for KStringBase { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_str().fmt(f) } } -impl fmt::Display for KStringBase { +impl fmt::Display for KStringBase { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self.as_str(), f) } } -impl AsRef for KStringBase { +impl AsRef for KStringBase { #[inline] fn as_ref(&self) -> &str { self.as_str() } } -impl AsRef<[u8]> for KStringBase { +impl AsRef<[u8]> for KStringBase { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } -impl AsRef for KStringBase { +impl AsRef for KStringBase { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { (&**self).as_ref() } } -impl AsRef for KStringBase { +impl AsRef for KStringBase { #[inline] fn as_ref(&self) -> &std::path::Path { std::path::Path::new(self) } } -impl std::borrow::Borrow for KStringBase { +impl std::borrow::Borrow for KStringBase { #[inline] fn borrow(&self) -> &str { self.as_str() } } -impl Default for KStringBase { +impl Default for KStringBase { #[inline] fn default() -> Self { Self::new() } } -impl<'s, B: crate::backend::StorageBackend> From> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From> for KStringBase { #[inline] fn from(other: KStringRef<'s>) -> Self { other.to_owned() } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringRef<'s>> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringRef<'s>> for KStringBase { #[inline] fn from(other: &'s KStringRef<'s>) -> Self { other.to_owned() } } -impl<'s, B: crate::backend::StorageBackend> From> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From> for KStringBase { #[inline] fn from(other: KStringCowBase<'s, B>) -> Self { other.into_owned() } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringCowBase<'s, B>> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringCowBase<'s, B>> for KStringBase { #[inline] fn from(other: &'s KStringCowBase<'s, B>) -> Self { other.clone().into_owned() } } -impl From for KStringBase { +impl From for KStringBase { #[inline] fn from(other: StdString) -> Self { Self::from_string(other) } } -impl<'s, B: crate::backend::StorageBackend> From<&'s StdString> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From<&'s StdString> for KStringBase { #[inline] fn from(other: &'s StdString) -> Self { Self::from_ref(other) } } -impl From for KStringBase { +impl From for KStringBase { #[inline] fn from(other: crate::backend::BoxedStr) -> Self { Self::from_boxed(other) } } -impl<'s, B: crate::backend::StorageBackend> From<&'s crate::backend::BoxedStr> for KStringBase { +impl<'s, B: crate::backend::HeapStr> From<&'s crate::backend::BoxedStr> for KStringBase { #[inline] fn from(other: &'s crate::backend::BoxedStr) -> Self { Self::from_ref(other) } } -impl From<&'static str> for KStringBase { +impl From<&'static str> for KStringBase { #[inline] fn from(other: &'static str) -> Self { Self::from_static(other) } } -impl std::str::FromStr for KStringBase { +impl std::str::FromStr for KStringBase { type Err = std::convert::Infallible; #[inline] fn from_str(s: &str) -> Result { @@ -295,7 +295,7 @@ impl std::str::FromStr for KStringBase { } #[cfg(feature = "serde")] -impl serde::Serialize for KStringBase { +impl serde::Serialize for KStringBase { #[inline] fn serialize(&self, serializer: S) -> Result where @@ -306,7 +306,7 @@ impl serde::Serialize for KStringBase { } #[cfg(feature = "serde")] -impl<'de, B: crate::backend::StorageBackend> serde::Deserialize<'de> for KStringBase { +impl<'de, B: crate::backend::HeapStr> serde::Deserialize<'de> for KStringBase { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -319,7 +319,7 @@ impl<'de, B: crate::backend::StorageBackend> serde::Deserialize<'de> for KString struct StringVisitor(std::marker::PhantomData); #[cfg(feature = "serde")] -impl<'de, B: crate::backend::StorageBackend> serde::de::Visitor<'de> for StringVisitor { +impl<'de, B: crate::backend::HeapStr> serde::de::Visitor<'de> for StringVisitor { type Value = KStringBase; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -392,7 +392,7 @@ mod inner { } } - impl KStringInner { + impl KStringInner { #[inline] pub(super) fn from_boxed(other: BoxedStr) -> Self { #[allow(clippy::useless_conversion)] @@ -465,7 +465,7 @@ mod inner { // // My only guess is that the `clone()` calls we delegate to are just that much bigger than // `as_str()` that, when combined with a jump table, is blowing the icache, slowing things down. - impl Clone for KStringInner { + impl Clone for KStringInner { fn clone(&self) -> Self { match self { Self::Singleton(s) => Self::Singleton(s), @@ -533,7 +533,7 @@ mod inner { } } - impl KStringInner { + impl KStringInner { #[inline] pub(super) fn from_boxed(other: crate::backend::BoxedStr) -> Self { #[allow(clippy::useless_conversion)] @@ -774,7 +774,7 @@ mod inner { } } - impl std::fmt::Debug for OwnedVariant { + impl std::fmt::Debug for OwnedVariant { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.payload.fmt(f) diff --git a/src/string_cow.rs b/src/string_cow.rs index b0fe338..6a1b4b8 100644 --- a/src/string_cow.rs +++ b/src/string_cow.rs @@ -41,7 +41,7 @@ impl<'s, B> KStringCowBase<'s, B> { } } -impl<'s, B: crate::backend::StorageBackend> KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> KStringCowBase<'s, B> { /// Create an owned `KStringCowBase`. #[inline] #[must_use] @@ -112,7 +112,7 @@ impl<'s, B: crate::backend::StorageBackend> KStringCowBase<'s, B> { } } -impl<'s, B: crate::backend::StorageBackend> KStringCowInner<'s, B> { +impl<'s, B: crate::backend::HeapStr> KStringCowInner<'s, B> { #[inline] fn as_ref(&self) -> KStringRef<'_> { match self { @@ -155,7 +155,7 @@ impl<'s, B: crate::backend::StorageBackend> KStringCowInner<'s, B> { } } -impl<'s, B: crate::backend::StorageBackend> std::ops::Deref for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> std::ops::Deref for KStringCowBase<'s, B> { type Target = str; #[inline] @@ -164,102 +164,100 @@ impl<'s, B: crate::backend::StorageBackend> std::ops::Deref for KStringCowBase<' } } -impl<'s, B: crate::backend::StorageBackend> Eq for KStringCowBase<'s, B> {} +impl<'s, B: crate::backend::HeapStr> Eq for KStringCowBase<'s, B> {} -impl<'s, B: crate::backend::StorageBackend> PartialEq> - for KStringCowBase<'s, B> -{ +impl<'s, B: crate::backend::HeapStr> PartialEq> for KStringCowBase<'s, B> { #[inline] fn eq(&self, other: &KStringCowBase<'s, B>) -> bool { PartialEq::eq(self.as_str(), other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> PartialEq for KStringCowBase<'s, B> { #[inline] fn eq(&self, other: &str) -> bool { PartialEq::eq(self.as_str(), other) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq<&'s str> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> PartialEq<&'s str> for KStringCowBase<'s, B> { #[inline] fn eq(&self, other: &&str) -> bool { PartialEq::eq(self.as_str(), *other) } } -impl<'s, B: crate::backend::StorageBackend> PartialEq for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> PartialEq for KStringCowBase<'s, B> { #[inline] fn eq(&self, other: &StdString) -> bool { PartialEq::eq(self.as_str(), other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> Ord for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> Ord for KStringCowBase<'s, B> { #[inline] fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_str().cmp(other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> PartialOrd for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> PartialOrd for KStringCowBase<'s, B> { #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.as_str().partial_cmp(other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> std::hash::Hash for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> std::hash::Hash for KStringCowBase<'s, B> { #[inline] fn hash(&self, state: &mut H) { self.as_str().hash(state); } } -impl<'s, B: crate::backend::StorageBackend> fmt::Debug for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> fmt::Debug for KStringCowBase<'s, B> { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_str().fmt(f) } } -impl<'s, B: crate::backend::StorageBackend> fmt::Display for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> fmt::Display for KStringCowBase<'s, B> { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self.as_str(), f) } } -impl<'s, B: crate::backend::StorageBackend> AsRef for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> AsRef for KStringCowBase<'s, B> { #[inline] fn as_ref(&self) -> &str { self.as_str() } } -impl<'s, B: crate::backend::StorageBackend> AsRef<[u8]> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> AsRef<[u8]> for KStringCowBase<'s, B> { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } -impl<'s, B: crate::backend::StorageBackend> AsRef for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> AsRef for KStringCowBase<'s, B> { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { (&**self).as_ref() } } -impl<'s, B: crate::backend::StorageBackend> AsRef for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> AsRef for KStringCowBase<'s, B> { #[inline] fn as_ref(&self) -> &std::path::Path { std::path::Path::new(self) } } -impl<'s, B: crate::backend::StorageBackend> std::borrow::Borrow for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> std::borrow::Borrow for KStringCowBase<'s, B> { #[inline] fn borrow(&self) -> &str { self.as_str() @@ -273,7 +271,7 @@ impl<'s, B> Default for KStringCowBase<'s, B> { } } -impl<'s, B: crate::backend::StorageBackend> From> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From> for KStringCowBase<'s, B> { #[inline] fn from(other: KStringBase) -> Self { let inner = KStringCowInner::Owned(other); @@ -281,7 +279,7 @@ impl<'s, B: crate::backend::StorageBackend> From> for KStringCowB } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringBase> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringBase> for KStringCowBase<'s, B> { #[inline] fn from(other: &'s KStringBase) -> Self { let other = other.as_ref(); @@ -289,7 +287,7 @@ impl<'s, B: crate::backend::StorageBackend> From<&'s KStringBase> for KString } } -impl<'s, B: crate::backend::StorageBackend> From> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From> for KStringCowBase<'s, B> { #[inline] fn from(other: KStringRef<'s>) -> Self { match other.inner { @@ -299,7 +297,7 @@ impl<'s, B: crate::backend::StorageBackend> From> for KStringCowB } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringRef<'s>> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringRef<'s>> for KStringCowBase<'s, B> { #[inline] fn from(other: &'s KStringRef<'s>) -> Self { match other.inner { @@ -309,21 +307,21 @@ impl<'s, B: crate::backend::StorageBackend> From<&'s KStringRef<'s>> for KString } } -impl<'s, B: crate::backend::StorageBackend> From for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From for KStringCowBase<'s, B> { #[inline] fn from(other: StdString) -> Self { Self::from_string(other) } } -impl<'s, B: crate::backend::StorageBackend> From<&'s StdString> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From<&'s StdString> for KStringCowBase<'s, B> { #[inline] fn from(other: &'s StdString) -> Self { Self::from_ref(other.as_str()) } } -impl<'s, B: crate::backend::StorageBackend> From for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From for KStringCowBase<'s, B> { #[inline] fn from(other: BoxedStr) -> Self { // Since the memory is already allocated, don't bother moving it into a FixedString @@ -331,21 +329,21 @@ impl<'s, B: crate::backend::StorageBackend> From for KStringCowBase<'s } } -impl<'s, B: crate::backend::StorageBackend> From<&'s BoxedStr> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From<&'s BoxedStr> for KStringCowBase<'s, B> { #[inline] fn from(other: &'s BoxedStr) -> Self { Self::from_ref(other) } } -impl<'s, B: crate::backend::StorageBackend> From<&'s str> for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> From<&'s str> for KStringCowBase<'s, B> { #[inline] fn from(other: &'s str) -> Self { Self::from_ref(other) } } -impl std::str::FromStr for KStringCowBase<'_, B> { +impl std::str::FromStr for KStringCowBase<'_, B> { type Err = std::convert::Infallible; #[inline] fn from_str(s: &str) -> Result { @@ -354,7 +352,7 @@ impl std::str::FromStr for KStringCowBase<'_, } #[cfg(feature = "serde")] -impl<'s, B: crate::backend::StorageBackend> serde::Serialize for KStringCowBase<'s, B> { +impl<'s, B: crate::backend::HeapStr> serde::Serialize for KStringCowBase<'s, B> { #[inline] fn serialize(&self, serializer: S) -> Result where @@ -365,7 +363,7 @@ impl<'s, B: crate::backend::StorageBackend> serde::Serialize for KStringCowBase< } #[cfg(feature = "serde")] -impl<'de, 's, B: crate::backend::StorageBackend> serde::Deserialize<'de> for KStringCowBase<'s, B> { +impl<'de, 's, B: crate::backend::HeapStr> serde::Deserialize<'de> for KStringCowBase<'s, B> { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, diff --git a/src/string_ref.rs b/src/string_ref.rs index 97b206a..a79b9d4 100644 --- a/src/string_ref.rs +++ b/src/string_ref.rs @@ -49,7 +49,7 @@ impl<'s> KStringRef<'s> { #[inline] #[must_use] #[allow(clippy::wrong_self_convention)] - pub fn to_owned(&self) -> KStringBase { + pub fn to_owned(&self) -> KStringBase { self.inner.to_owned() } @@ -71,7 +71,7 @@ impl<'s> KStringRef<'s> { impl<'s> KStringRefInner<'s> { #[inline] #[allow(clippy::wrong_self_convention)] - fn to_owned(&self) -> KStringBase { + fn to_owned(&self) -> KStringBase { match self { Self::Borrowed(s) => KStringBase::from_ref(s), Self::Singleton(s) => KStringBase::from_static(s), @@ -208,14 +208,14 @@ impl<'s> Default for KStringRef<'s> { } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringBase> for KStringRef<'s> { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringBase> for KStringRef<'s> { #[inline] fn from(other: &'s KStringBase) -> Self { other.as_ref() } } -impl<'s, B: crate::backend::StorageBackend> From<&'s KStringCowBase<'s, B>> for KStringRef<'s> { +impl<'s, B: crate::backend::HeapStr> From<&'s KStringCowBase<'s, B>> for KStringRef<'s> { #[inline] fn from(other: &'s KStringCowBase<'s, B>) -> Self { other.as_ref()