[−][src]Struct arcstr::ArcStr
A better atomically-reference counted string type.
Benefits of ArcStr
over Arc<str>
-
It's possible to create a const
ArcStr
from a literal via thearcstr::literal!
macro. This is probably the killer feature, to be honest.These "static"
ArcStr
s are zero cost, take no heap allocation, and don't even need to perform atomic reads/writes when being cloned or dropped (nor at any other time).They even get stored in the read-only memory of your executable, which can be beneficial for performance and memory usage. (In theory your linker may even dedupe these for you, but usually not)
-
ArcStr
s fromarcstr::literal!
can be turned into&'static str
safely at any time usingArcStr::as_static
. (This returns an Option, which isNone
if theArcStr
was not static) -
This should be unsurprising given the literal functionality, but
ArcStr::new
is able to be aconst
function. -
ArcStr
is thin, e.g. only a single pointer. Great for cases where you want to keep the data structure lightweight or need to do some FFI stuff with it. -
ArcStr
is totally immutable. No need to lose sleep because you're afraid of code which thinks it has a right to mutate yourArc
s just because it holds the only reference... -
Lower reference counting operations are lower overhead because we don't support
Weak
references. This can be a drawback for some use cases, but improves performance for the common case of no-weak-refs.
What does "zero-cost literals" mean?
In a few places I call the literal arcstrs "zero-cost". No overhead most
accesses accesses (aside from stuff like as_static
which obviously
requires it). and it imposes a extra branch in both clone
and drop
.
This branch in clone
/drop
is not on the result of an atomic load, and is
just a normal memory read. This is actually what allows literal/static
ArcStr
s to avoid needing to perform any atomic operations in those
functions, which seems likely more than cover the cost.
(Additionally, it's almost certain that in the future we'll be able to
reduce the synchronization required for atomic instructions. This is due to
our guarantee of immutability and lack of support for Weak
.)
Usage
As a const
The big unique feature of ArcStr
is the ability to create static/const
ArcStr
s. (See the macro docs or the feature
overview
const WOW: ArcStr = arcstr::literal!("cool robot!"); assert_eq!(WOW, "cool robot!");
As a str
(This is not unique to ArcStr
, but is a frequent source of confusion I've
seen): ArcStr
implements Deref<Target = str>
, and so all functions and
methods from str
work on it, even though we don't expose them on ArcStr
directly.
let s = ArcStr::from("something"); // These go through `Deref`, so they work even though // there is no `ArcStr::eq_ignore_ascii_case` function assert!(s.eq_ignore_ascii_case("SOMETHING"));
Additionally, &ArcStr
can be passed to any function which accepts &str
.
For example:
fn accepts_str(s: &str) { // s... } let test_str: ArcStr = "test".into(); // This works even though `&test_str` is normally an `&ArcStr` accepts_str(&test_str); // Of course, this works for functionality from the standard library as well. let test_but_loud = ArcStr::from("TEST"); assert!(test_str.eq_ignore_ascii_case(&test_but_loud));
Implementations
impl ArcStr
[src]
pub const fn new() -> Self
[src]
pub fn as_str(&self) -> &str
[src]
Extract a string slice containing our data.
Note: This is an equivalent to our Deref
implementation, but can be
more readable than &*s
in the cases where a manual invocation of
Deref
would be required.
Examples
let s = ArcStr::from("abc"); assert_eq!(s.as_str(), "abc");
pub fn len(&self) -> usize
[src]
Returns the length of this ArcStr
in bytes.
Examples
let a = ArcStr::from("foo"); assert_eq!(a.len(), 3);
pub fn is_empty(&self) -> bool
[src]
Returns true if this ArcStr
is empty.
Examples
assert!(!ArcStr::from("foo").is_empty()); assert!(ArcStr::new().is_empty());
pub fn to_string(&self) -> String
[src]
Convert us to a std::string::String
.
This is provided as an inherent method to avoid needing to route through
the Display
machinery, but is equivalent to ToString::to_string
.
Examples
let s = ArcStr::from("abc"); assert_eq!(s.to_string(), "abc");
pub fn as_bytes(&self) -> &[u8]
[src]
Extract a byte slice containing the string's data.
Examples
let foobar = ArcStr::from("foobar"); assert_eq!(foobar.as_bytes(), b"foobar");
pub fn into_raw(this: Self) -> NonNull<()>
[src]
Return the raw pointer this ArcStr
wraps, for advanced use cases.
Note that in addition to the NonNull
constraint expressed in the type
signature, we also guarantee the pointer has an alignment of at least 8
bytes, even on platforms where a lower alignment would be acceptable.
Examples
let s = ArcStr::from("abcd"); let p = ArcStr::into_raw(s); // Some time later... let s = unsafe { ArcStr::from_raw(p) }; assert_eq!(s, "abcd");
pub unsafe fn from_raw(ptr: NonNull<()>) -> Self
[src]
The opposite version of Self::into_raw
. Still intended only for
advanced use cases.
Safety
This function must be used on a valid pointer returned from
ArcStr::into_raw
. Additionally, you must ensure that a given ArcStr
instance is only dropped once.
Examples
let s = ArcStr::from("abcd"); let p = ArcStr::into_raw(s); // Some time later... let s = unsafe { ArcStr::from_raw(p) }; assert_eq!(s, "abcd");
pub fn ptr_eq(lhs: &Self, rhs: &Self) -> bool
[src]
Returns true if the two ArcStr
s point to the same allocation.
Note that functions like PartialEq
check this already, so there's
no performance benefit to doing something like ArcStr::ptr_eq(&a1, &a2) || (a1 == a2)
.
Caveat: const
s aren't guaranteed to only occur in an executable a
single time, and so this may be non-deterministic for ArcStr
defined
in a const
with arcstr::literal!
, unless one
was created by a clone()
on the other.
Examples
use arcstr::ArcStr; let foobar = ArcStr::from("foobar"); let same_foobar = foobar.clone(); let other_foobar = ArcStr::from("foobar"); assert!(ArcStr::ptr_eq(&foobar, &same_foobar)); assert!(!ArcStr::ptr_eq(&foobar, &other_foobar)); const YET_AGAIN_A_DIFFERENT_FOOBAR: ArcStr = arcstr::literal!("foobar"); let strange_new_foobar = YET_AGAIN_A_DIFFERENT_FOOBAR.clone(); let wild_blue_foobar = strange_new_foobar.clone(); assert!(ArcStr::ptr_eq(&strange_new_foobar, &wild_blue_foobar));
pub fn strong_count(this: &Self) -> Option<usize>
[src]
Returns the number of references that exist to this ArcStr
. If this is
a static ArcStr
(For example, one from
arcstr::literal!
), returns None
.
Despite the difference in return type, this is named to match the method
from the stdlib's Arc:
Arc::strong_count
.
If you aren't sure how to handle static ArcStr
in the context of this
return value, ArcStr::strong_count(&s).unwrap_or(usize::MAX)
is
frequently reasonable.
Safety
This method by itself is safe, but using it correctly requires extra care. Another thread can change the strong count at any time, including potentially between calling this method and acting on the result.
However, it may never change from None
to Some
or from Some
to
None
for a given ArcStr
— whether or not it is static is determined
at construction, and never changes.
Examples
Dynamic ArcStr
let foobar = ArcStr::from("foobar"); assert_eq!(Some(1), ArcStr::strong_count(&foobar)); let also_foobar = ArcStr::clone(&foobar); assert_eq!(Some(2), ArcStr::strong_count(&foobar)); assert_eq!(Some(2), ArcStr::strong_count(&also_foobar));
Static ArcStr
let baz = arcstr::literal!("baz"); assert_eq!(None, ArcStr::strong_count(&baz)); // Similarly: assert_eq!(None, ArcStr::strong_count(&ArcStr::default()));
pub fn is_static(this: &Self) -> bool
[src]
Returns true if this
is a "static" ArcStr. For example, if it was
created from a call to arcstr::literal!
),
returned by ArcStr::new
, etc.
Static ArcStr
s can be converted to &'static str
for free using
ArcStr::as_static
, without leaking memory — they're static constants
in the program (somewhere).
Examples
const STATIC: ArcStr = arcstr::literal!("Electricity!"); assert!(ArcStr::is_static(&STATIC)); let still_static = arcstr::literal!("Shocking!"); assert!(ArcStr::is_static(&still_static)); assert!( ArcStr::is_static(&still_static.clone()), "Cloned statics are still static" ); let nonstatic = ArcStr::from("Grounded..."); assert!(!ArcStr::is_static(&nonstatic));
pub fn as_static(this: &Self) -> Option<&'static str>
[src]
Returns true if this
is a "static"/"literal"
ArcStr. For example, if
it was created from a call to literal!
), returned by
ArcStr::new
, etc.
Static ArcStr
s can be converted to &'static str
for free using
ArcStr::as_static
, without leaking memory — they're static constants
in the program (somewhere).
Examples
const STATIC: ArcStr = arcstr::literal!("Electricity!"); assert_eq!(ArcStr::as_static(&STATIC), Some("Electricity!")); // Note that they don't have to be consts, just made using `literal!`: let still_static = arcstr::literal!("Shocking!"); assert_eq!(ArcStr::as_static(&still_static), Some("Shocking!")); // Cloning a static still produces a static. assert_eq!(ArcStr::as_static(&still_static.clone()), Some("Shocking!")); // But it won't work for strings from other sources. let nonstatic = ArcStr::from("Grounded..."); assert_eq!(ArcStr::as_static(&nonstatic), None);
pub fn substr(&self, range: impl RangeBounds<usize>) -> Substr
[src]
feature = "substr"
Returns a substr of self
over the given range.
Examples
use arcstr::{ArcStr, Substr}; let a = ArcStr::from("abcde"); let b: Substr = a.substr(2..); assert_eq!(b, "cde");
Panics
If any of the following are untrue, we panic
range.start() <= range.end()
range.end() <= self.len()
self.is_char_boundary(start) && self.is_char_boundary(end)
- These can be conveniently verified in advance using
self.get(start..end).is_some()
if needed.
pub fn substr_from(&self, substr: &str) -> Substr
[src]
feature = "substr"
Returns a Substr
of self over the given &str
.
It is not rare to end up with a &str
which holds a view into a
ArcStr
's backing data. A common case is when using functionality that
takes and returns &str
and are entirely unaware of arcstr
, for
example: str::trim()
.
This function allows you to reconstruct a Substr
from a &str
which
is a view into this ArcStr
's backing string.
Examples
use arcstr::{ArcStr, Substr}; let text = ArcStr::from(" abc"); let trimmed = text.trim(); let substr: Substr = text.substr_from(trimmed); assert_eq!(substr, "abc"); // for illustration assert!(ArcStr::ptr_eq(substr.parent(), &text)); assert_eq!(substr.range(), 3..6);
Panics
Panics if substr
isn't a view into our memory.
Also panics if substr
is a view into our memory but is >= u32::MAX
bytes away from our start, if we're a 64-bit machine and
substr-usize-indices
is not enabled.
pub fn try_substr_from(&self, substr: &str) -> Option<Substr>
[src]
feature = "substr"
If possible, returns a Substr
of self over the
given &str
.
This is a fallible version of ArcStr::substr_from
.
It is not rare to end up with a &str
which holds a view into a
ArcStr
's backing data. A common case is when using functionality that
takes and returns &str
and are entirely unaware of arcstr
, for
example: str::trim()
.
This function allows you to reconstruct a Substr
from a &str
which
is a view into this ArcStr
's backing string.
Examples
use arcstr::{ArcStr, Substr}; let text = ArcStr::from(" abc"); let trimmed = text.trim(); let substr: Option<Substr> = text.try_substr_from(trimmed); assert_eq!(substr.unwrap(), "abc"); // `&str`s not derived from `self` will return None. let not_substr = text.try_substr_from("abc"); assert!(not_substr.is_none());
Panics
Panics if substr
is a view into our memory but is >= u32::MAX
bytes
away from our start, if we're a 64-bit machine and
substr-usize-indices
is not enabled.
pub fn try_substr_using(&self, f: impl FnOnce(&str) -> &str) -> Option<Substr>
[src]
feature = "substr"
Compute a derived &str
a function of &str
=>
&str
, and produce a Substr of the result if possible.
The function may return either a derived string, or any empty string.
This function is mainly a wrapper around ArcStr::try_substr_from
. If
you're coming to arcstr
from the shared_string
crate, this is the
moral equivalent of the slice_with
function.
Examples
use arcstr::{ArcStr, Substr}; let text = ArcStr::from(" abc"); let trimmed: Option<Substr> = text.try_substr_using(str::trim); assert_eq!(trimmed.unwrap(), "abc"); let other = text.try_substr_using(|_s| "different string!"); assert_eq!(other, None); // As a special case, this is allowed. let empty = text.try_substr_using(|_s| ""); assert_eq!(empty.unwrap(), "");
pub fn substr_using(&self, f: impl FnOnce(&str) -> &str) -> Substr
[src]
feature = "substr"
Compute a derived &str
a function of &str
=>
&str
, and produce a Substr of the result.
The function may return either a derived string, or any empty string. Returning anything else will result in a panic.
This function is mainly a wrapper around ArcStr::try_substr_from
. If
you're coming to arcstr
from the shared_string
crate, this is the
likely closest to the slice_with_unchecked
function, but this panics
instead of UB on dodginess.
Examples
use arcstr::{ArcStr, Substr}; let text = ArcStr::from(" abc"); let trimmed: Substr = text.substr_using(str::trim); assert_eq!(trimmed, "abc"); // As a special case, this is allowed. let empty = text.substr_using(|_s| ""); assert_eq!(empty, "");
Trait Implementations
impl AsRef<[u8]> for ArcStr
[src]
impl AsRef<str> for ArcStr
[src]
impl Borrow<str> for ArcStr
[src]
impl Clone for ArcStr
[src]
fn clone(&self) -> Self
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl Debug for ArcStr
[src]
impl Default for ArcStr
[src]
impl Deref for ArcStr
[src]
impl Display for ArcStr
[src]
impl Drop for ArcStr
[src]
impl Eq for ArcStr
[src]
impl<'_> From<&'_ ArcStr> for ArcStr
[src]
impl<'_> From<&'_ ArcStr> for Substr
[src]
impl<'_> From<&'_ String> for ArcStr
[src]
impl<'_> From<&'_ mut str> for ArcStr
[src]
impl<'_> From<&'_ str> for ArcStr
[src]
impl<'a> From<&'a ArcStr> for Cow<'a, str>
[src]
impl From<Arc<str>> for ArcStr
[src]
impl From<ArcStr> for Box<str>
[src]
impl From<ArcStr> for Rc<str>
[src]
impl From<ArcStr> for Arc<str>
[src]
impl<'a> From<ArcStr> for Cow<'a, str>
[src]
impl From<ArcStr> for Substr
[src]
impl From<Box<str>> for ArcStr
[src]
impl<'a> From<Cow<'a, str>> for ArcStr
[src]
impl From<Rc<str>> for ArcStr
[src]
impl From<String> for ArcStr
[src]
impl FromStr for ArcStr
[src]
type Err = Infallible
The associated error which can be returned from parsing.
fn from_str(s: &str) -> Result<Self, Self::Err>
[src]
impl Hash for ArcStr
[src]
fn hash<H: Hasher>(&self, h: &mut H)
[src]
fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
impl Index<Range<usize>> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: Range<usize>) -> &Self::Output
[src]
impl Index<RangeFrom<usize>> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: RangeFrom<usize>) -> &Self::Output
[src]
impl Index<RangeFull> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: RangeFull) -> &Self::Output
[src]
impl Index<RangeInclusive<usize>> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: RangeInclusive<usize>) -> &Self::Output
[src]
impl Index<RangeTo<usize>> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: RangeTo<usize>) -> &Self::Output
[src]
impl Index<RangeToInclusive<usize>> for ArcStr
[src]
type Output = str
The returned type after indexing.
fn index(&self, i: RangeToInclusive<usize>) -> &Self::Output
[src]
impl Ord for ArcStr
[src]
fn cmp(&self, s: &Self) -> Ordering
[src]
#[must_use]fn max(self, other: Self) -> Self
1.21.0[src]
#[must_use]fn min(self, other: Self) -> Self
1.21.0[src]
#[must_use]fn clamp(self, min: Self, max: Self) -> Self
[src]
impl<'a> PartialEq<&'a str> for ArcStr
[src]
impl<'a> PartialEq<Arc<str>> for ArcStr
[src]
impl PartialEq<ArcStr> for ArcStr
[src]
impl<'a> PartialEq<ArcStr> for str
[src]
impl<'a> PartialEq<ArcStr> for &'a str
[src]
impl<'a> PartialEq<ArcStr> for String
[src]
impl<'a> PartialEq<ArcStr> for Cow<'a, str>
[src]
impl<'a> PartialEq<ArcStr> for Box<str>
[src]
impl<'a> PartialEq<ArcStr> for Arc<str>
[src]
impl<'a> PartialEq<ArcStr> for Rc<str>
[src]
impl PartialEq<ArcStr> for Substr
[src]
impl<'a> PartialEq<Box<str>> for ArcStr
[src]
impl<'a> PartialEq<Cow<'a, str>> for ArcStr
[src]
impl<'a> PartialEq<Rc<str>> for ArcStr
[src]
impl<'a> PartialEq<String> for ArcStr
[src]
impl PartialEq<Substr> for ArcStr
[src]
impl<'a> PartialEq<str> for ArcStr
[src]
impl PartialOrd<ArcStr> for ArcStr
[src]
fn partial_cmp(&self, s: &Self) -> Option<Ordering>
[src]
#[must_use]fn lt(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]fn le(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]fn gt(&self, other: &Rhs) -> bool
1.0.0[src]
#[must_use]fn ge(&self, other: &Rhs) -> bool
1.0.0[src]
impl Send for ArcStr
[src]
impl Sync for ArcStr
[src]
Auto Trait Implementations
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
[src]
fn clone_into(&self, target: &mut T)
[src]
impl<T> ToString for T where
T: Display + ?Sized,
[src]
T: Display + ?Sized,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,