diff --git a/src/backend.rs b/src/backend.rs index 3827082..474dd93 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,3 +1,8 @@ +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::string::String; + #[cfg(feature = "arc")] pub(crate) type DefaultStr = crate::backend::ArcStr; #[cfg(not(feature = "arc"))] @@ -8,15 +13,15 @@ pub type BoxedStr = Box; static_assertions::assert_eq_size!(DefaultStr, BoxedStr); /// Cross-thread, O(1) clones -pub type ArcStr = std::sync::Arc; +pub type ArcStr = alloc::sync::Arc; static_assertions::assert_eq_size!(DefaultStr, ArcStr); /// O(1) clones -pub type RcStr = std::rc::Rc; +pub type RcStr = alloc::rc::Rc; static_assertions::assert_eq_size!(DefaultStr, RcStr); /// Abstract over different type of heap-allocated strings -pub trait HeapStr: std::fmt::Debug + Clone + private::Sealed { +pub trait HeapStr: core::fmt::Debug + Clone + private::Sealed { fn from_str(other: &str) -> Self; fn from_string(other: String) -> Self; fn from_boxed_str(other: BoxedStr) -> Self; diff --git a/src/lib.rs b/src/lib.rs index 94fdc23..bffbefc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,10 +37,13 @@ //! #![cfg_attr(feature = "document-features", doc = document_features::document_features!())] #![cfg_attr(not(feature = "unsafe"), forbid(unsafe_code))] +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(clippy::std_instead_of_core)] +#![warn(clippy::std_instead_of_alloc)] -#[cfg(not(feature = "std"))] -compile_error!("`std` feature is required; reserved for future `no_std` support"); +#[allow(unused_extern_crates)] +extern crate alloc; mod stack; mod string; @@ -60,20 +63,20 @@ mod test { fn test_size() { println!( "String: {}", - std::mem::size_of::() + core::mem::size_of::() ); println!( "Box: {}", - std::mem::size_of::() + core::mem::size_of::() ); println!( "Box>: {}", - std::mem::size_of::>() + core::mem::size_of::>() ); - println!("str: {}", std::mem::size_of::<&'static str>()); + println!("str: {}", core::mem::size_of::<&'static str>()); println!( "Cow: {}", - std::mem::size_of::>() + core::mem::size_of::>() ); } } diff --git a/src/stack.rs b/src/stack.rs index faad13e..76318f7 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,4 +1,6 @@ -use std::fmt; +#[cfg(not(feature = "std"))] +use alloc::string::String; +use core::fmt; pub(crate) type Len = u8; @@ -257,7 +259,7 @@ impl Default for StackString { } } -impl std::ops::Deref for StackString { +impl core::ops::Deref for StackString { type Target = str; #[inline] @@ -298,42 +300,42 @@ impl PartialEq for StackString { impl Ord for StackString { #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_str().cmp(other.as_str()) } } impl PartialOrd> for StackString { #[inline] - fn partial_cmp(&self, other: &StackString) -> Option { + fn partial_cmp(&self, other: &StackString) -> Option { self.as_str().partial_cmp(other.as_str()) } } impl PartialOrd for StackString { #[inline] - fn partial_cmp(&self, other: &str) -> Option { + fn partial_cmp(&self, other: &str) -> Option { self.as_str().partial_cmp(other) } } impl PartialOrd<&str> for StackString { #[inline] - fn partial_cmp(&self, other: &&str) -> Option { + fn partial_cmp(&self, other: &&str) -> Option { self.as_str().partial_cmp(other) } } impl PartialOrd for StackString { #[inline] - fn partial_cmp(&self, other: &String) -> Option { + fn partial_cmp(&self, other: &String) -> Option { self.as_str().partial_cmp(other.as_str()) } } -impl std::hash::Hash for StackString { +impl core::hash::Hash for StackString { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.as_str().hash(state); } } @@ -366,6 +368,7 @@ impl AsRef<[u8]> for StackString { } } +#[cfg(feature = "std")] impl AsRef for StackString { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { @@ -373,6 +376,7 @@ impl AsRef for StackString { } } +#[cfg(feature = "std")] impl AsRef for StackString { #[inline] fn as_ref(&self) -> &std::path::Path { @@ -380,7 +384,7 @@ impl AsRef for StackString { } } -impl std::borrow::Borrow for StackString { +impl alloc::borrow::Borrow for StackString { #[inline] fn borrow(&self) -> &str { self.as_str() @@ -414,14 +418,14 @@ impl StrBuffer { #[cfg(not(feature = "unsafe"))] pub(crate) fn as_str(&self, len: usize) -> &str { let slice = self.0.get(..len).unwrap(); - std::str::from_utf8(slice).unwrap() + core::str::from_utf8(slice).unwrap() } #[inline] #[cfg(not(feature = "unsafe"))] pub(crate) fn as_mut_str(&mut self, len: usize) -> &mut str { let slice = self.0.get_mut(..len).unwrap(); - std::str::from_utf8_mut(slice).unwrap() + core::str::from_utf8_mut(slice).unwrap() } } @@ -443,14 +447,14 @@ impl StrBuffer { #[cfg(feature = "unsafe")] pub(crate) unsafe fn as_str_unchecked(&self, len: usize) -> &str { let slice = self.0.get_unchecked(..len); - std::str::from_utf8_unchecked(slice) + core::str::from_utf8_unchecked(slice) } #[inline] #[cfg(feature = "unsafe")] pub(crate) unsafe fn as_mut_str_unchecked(&mut self, len: usize) -> &mut str { let slice = self.0.get_unchecked_mut(..len); - std::str::from_utf8_unchecked_mut(slice) + core::str::from_utf8_unchecked_mut(slice) } } diff --git a/src/string.rs b/src/string.rs index b33ecc2..cf10541 100644 --- a/src/string.rs +++ b/src/string.rs @@ -1,10 +1,12 @@ -use std::{borrow::Cow, fmt}; +#[cfg(not(feature = "std"))] +use alloc::string::String; +use alloc::{borrow::Cow, fmt}; use crate::stack::StackString; use crate::KStringCowBase; use crate::KStringRef; -pub(crate) type StdString = std::string::String; +pub(crate) type StdString = alloc::string::String; /// A UTF-8 encoded, immutable string. pub type KString = KStringBase; @@ -107,7 +109,7 @@ impl KStringBase { } } -impl std::ops::Deref for KStringBase { +impl core::ops::Deref for KStringBase { type Target = str; #[inline] @@ -148,21 +150,21 @@ impl PartialEq for KStringBase { impl Ord for KStringBase { #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_str().cmp(other.as_str()) } } impl PartialOrd for KStringBase { #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl std::hash::Hash for KStringBase { +impl core::hash::Hash for KStringBase { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.as_str().hash(state); } } @@ -195,6 +197,7 @@ impl AsRef<[u8]> for KStringBase { } } +#[cfg(feature = "std")] impl AsRef for KStringBase { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { @@ -202,6 +205,7 @@ impl AsRef for KStringBase { } } +#[cfg(feature = "std")] impl AsRef for KStringBase { #[inline] fn as_ref(&self) -> &std::path::Path { @@ -209,7 +213,7 @@ impl AsRef for KStringBase { } } -impl std::borrow::Borrow for KStringBase { +impl alloc::borrow::Borrow for KStringBase { #[inline] fn borrow(&self) -> &str { self.as_str() @@ -286,8 +290,8 @@ impl From<&'static str> for KStringBase { } } -impl std::str::FromStr for KStringBase { - type Err = std::convert::Infallible; +impl core::str::FromStr for KStringBase { + type Err = core::convert::Infallible; #[inline] fn from_str(s: &str) -> Result { Ok(Self::from_ref(s)) @@ -311,12 +315,12 @@ impl<'de, B: crate::backend::HeapStr> serde::Deserialize<'de> for KStringBase where D: serde::Deserializer<'de>, { - deserializer.deserialize_string(StringVisitor(std::marker::PhantomData)) + deserializer.deserialize_string(StringVisitor(core::marker::PhantomData)) } } #[cfg(feature = "serde")] -struct StringVisitor(std::marker::PhantomData); +struct StringVisitor(core::marker::PhantomData); #[cfg(feature = "serde")] impl serde::de::Visitor<'_> for StringVisitor { @@ -344,7 +348,7 @@ impl serde::de::Visitor<'_> for StringVisitor { where E: serde::de::Error, { - match std::str::from_utf8(v) { + match core::str::from_utf8(v) { Ok(s) => Ok(Self::Value::from_ref(s)), Err(_) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(v), @@ -476,20 +480,20 @@ mod inner { } #[allow(unused)] - const LEN_SIZE: usize = std::mem::size_of::(); + const LEN_SIZE: usize = core::mem::size_of::(); #[allow(unused)] - const TAG_SIZE: usize = std::mem::size_of::(); + const TAG_SIZE: usize = core::mem::size_of::(); #[allow(unused)] const MAX_CAPACITY: usize = - std::mem::size_of::() - TAG_SIZE - LEN_SIZE; + core::mem::size_of::() - TAG_SIZE - LEN_SIZE; // Performance seems to slow down when trying to occupy all of the padding left by `String`'s // discriminant. The question is whether faster len=1-16 "allocations" outweighs going to the heap // for len=17-22. #[allow(unused)] - const ALIGNED_CAPACITY: usize = std::mem::size_of::() - LEN_SIZE; + const ALIGNED_CAPACITY: usize = core::mem::size_of::() - LEN_SIZE; #[cfg(feature = "max_inline")] const CAPACITY: usize = MAX_CAPACITY; @@ -505,7 +509,7 @@ mod inner { pub(super) union KStringInner { tag: TagVariant, singleton: SingletonVariant, - owned: std::mem::ManuallyDrop>, + owned: core::mem::ManuallyDrop>, inline: InlineVariant, } @@ -540,7 +544,7 @@ mod inner { #[allow(clippy::useless_conversion)] let payload = B::from_boxed_str(other); Self { - owned: std::mem::ManuallyDrop::new(OwnedVariant::new(payload)), + owned: core::mem::ManuallyDrop::new(OwnedVariant::new(payload)), } } @@ -573,7 +577,7 @@ mod inner { #[allow(clippy::useless_conversion)] let payload = B::from_str(other); Self { - owned: std::mem::ManuallyDrop::new(OwnedVariant::new(payload)), + owned: core::mem::ManuallyDrop::new(OwnedVariant::new(payload)), } } } @@ -659,7 +663,7 @@ mod inner { unsafe { // SAFETY: `tag` ensures access to correct variant Self { - owned: std::mem::ManuallyDrop::new(OwnedVariant::new( + owned: core::mem::ManuallyDrop::new(OwnedVariant::new( self.owned.payload.clone(), )), } @@ -668,7 +672,7 @@ mod inner { unsafe { // SAFETY: `tag` ensures access to correct variant // SAFETY: non-owned types are copyable - std::mem::transmute_copy(self) + core::mem::transmute_copy(self) } } } @@ -680,24 +684,24 @@ mod inner { if tag.is_owned() { unsafe { // SAFETY: `tag` ensures we are using the right variant - std::mem::ManuallyDrop::drop(&mut self.owned) + core::mem::ManuallyDrop::drop(&mut self.owned) } } } } #[allow(unused)] - const LEN_SIZE: usize = std::mem::size_of::(); + const LEN_SIZE: usize = core::mem::size_of::(); #[allow(unused)] - const TAG_SIZE: usize = std::mem::size_of::(); + const TAG_SIZE: usize = core::mem::size_of::(); #[allow(unused)] - const PAYLOAD_SIZE: usize = std::mem::size_of::(); + const PAYLOAD_SIZE: usize = core::mem::size_of::(); type Payload = Padding; #[allow(unused)] - const TARGET_SIZE: usize = std::mem::size_of::(); + const TARGET_SIZE: usize = core::mem::size_of::(); type Target = crate::string::StdString; #[allow(unused)] @@ -747,9 +751,9 @@ mod inner { } } - impl std::fmt::Debug for SingletonVariant { + impl core::fmt::Debug for SingletonVariant { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.payload.fmt(f) } } @@ -775,9 +779,9 @@ mod inner { } } - impl std::fmt::Debug for OwnedVariant { + impl core::fmt::Debug for OwnedVariant { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.payload.fmt(f) } } @@ -802,9 +806,9 @@ mod inner { } } - impl std::fmt::Debug for InlineVariant { + impl core::fmt::Debug for InlineVariant { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.payload.fmt(f) } } @@ -836,13 +840,13 @@ mod inner { #[derive(Copy, Clone)] #[repr(transparent)] - struct Padding([std::mem::MaybeUninit; L]); + struct Padding([core::mem::MaybeUninit; L]); impl Padding { const fn new() -> Self { let padding = unsafe { // SAFETY: Padding, never actually used - std::mem::MaybeUninit::uninit().assume_init() + core::mem::MaybeUninit::uninit().assume_init() }; Self(padding) } @@ -861,6 +865,6 @@ mod test { #[test] fn test_size() { - println!("KString: {}", std::mem::size_of::()); + println!("KString: {}", core::mem::size_of::()); } } diff --git a/src/string_cow.rs b/src/string_cow.rs index 93962c5..ee5c108 100644 --- a/src/string_cow.rs +++ b/src/string_cow.rs @@ -1,10 +1,14 @@ -use std::{borrow::Cow, fmt}; +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::string::String; +use alloc::{borrow::Cow, fmt}; use crate::KStringBase; use crate::KStringRef; use crate::KStringRefInner; -type StdString = std::string::String; +type StdString = alloc::string::String; type BoxedStr = Box; /// A reference to a UTF-8 encoded, immutable string. @@ -155,7 +159,7 @@ impl<'s, B: crate::backend::HeapStr> KStringCowInner<'s, B> { } } -impl std::ops::Deref for KStringCowBase<'_, B> { +impl core::ops::Deref for KStringCowBase<'_, B> { type Target = str; #[inline] @@ -196,21 +200,21 @@ impl PartialEq for KStringCowBase<'_, B> { impl Ord for KStringCowBase<'_, B> { #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_str().cmp(other.as_str()) } } impl PartialOrd for KStringCowBase<'_, B> { #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl std::hash::Hash for KStringCowBase<'_, B> { +impl core::hash::Hash for KStringCowBase<'_, B> { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.as_str().hash(state); } } @@ -243,6 +247,7 @@ impl AsRef<[u8]> for KStringCowBase<'_, B> { } } +#[cfg(feature = "std")] impl AsRef for KStringCowBase<'_, B> { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { @@ -250,6 +255,7 @@ impl AsRef for KStringCowBase<'_, B } } +#[cfg(feature = "std")] impl AsRef for KStringCowBase<'_, B> { #[inline] fn as_ref(&self) -> &std::path::Path { @@ -257,7 +263,7 @@ impl AsRef for KStringCowBase<'_, B } } -impl std::borrow::Borrow for KStringCowBase<'_, B> { +impl core::borrow::Borrow for KStringCowBase<'_, B> { #[inline] fn borrow(&self) -> &str { self.as_str() @@ -343,8 +349,8 @@ impl<'s, B: crate::backend::HeapStr> From<&'s str> for KStringCowBase<'s, B> { } } -impl std::str::FromStr for KStringCowBase<'_, B> { - type Err = std::convert::Infallible; +impl core::str::FromStr for KStringCowBase<'_, B> { + type Err = core::convert::Infallible; #[inline] fn from_str(s: &str) -> Result { Ok(Self::from_string(s.into())) @@ -378,6 +384,9 @@ mod test { #[test] fn test_size() { - println!("KStringCow: {}", std::mem::size_of::>()); + println!( + "KStringCow: {}", + core::mem::size_of::>() + ); } } diff --git a/src/string_ref.rs b/src/string_ref.rs index 31ff1d5..2c69583 100644 --- a/src/string_ref.rs +++ b/src/string_ref.rs @@ -1,9 +1,15 @@ -use std::fmt; +#[cfg(not(feature = "std"))] +use crate::alloc::borrow::ToOwned; +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::string::String; +use core::fmt; use crate::KStringBase; use crate::KStringCowBase; -type StdString = std::string::String; +type StdString = alloc::string::String; type BoxedStr = Box; /// A reference to a UTF-8 encoded, immutable string. @@ -92,7 +98,7 @@ impl KStringRefInner<'_> { } } -impl std::ops::Deref for KStringRef<'_> { +impl core::ops::Deref for KStringRef<'_> { type Target = str; #[inline] @@ -133,21 +139,21 @@ impl PartialEq for KStringRef<'_> { impl Ord for KStringRef<'_> { #[inline] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_str().cmp(other.as_str()) } } impl PartialOrd for KStringRef<'_> { #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl std::hash::Hash for KStringRef<'_> { +impl core::hash::Hash for KStringRef<'_> { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.as_str().hash(state); } } @@ -180,6 +186,7 @@ impl AsRef<[u8]> for KStringRef<'_> { } } +#[cfg(feature = "std")] impl AsRef for KStringRef<'_> { #[inline] fn as_ref(&self) -> &std::ffi::OsStr { @@ -187,6 +194,7 @@ impl AsRef for KStringRef<'_> { } } +#[cfg(feature = "std")] impl AsRef for KStringRef<'_> { #[inline] fn as_ref(&self) -> &std::path::Path { @@ -194,7 +202,7 @@ impl AsRef for KStringRef<'_> { } } -impl std::borrow::Borrow for KStringRef<'_> { +impl alloc::borrow::Borrow for KStringRef<'_> { #[inline] fn borrow(&self) -> &str { self.as_str() @@ -272,6 +280,9 @@ mod test { #[test] fn test_size() { - println!("KStringRef: {}", std::mem::size_of::>()); + println!( + "KStringRef: {}", + core::mem::size_of::>() + ); } }