Struct arcstr::ArcStr[][src]

#[repr(transparent)]
pub struct ArcStr(_);
Expand description

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 the arcstr::literal! macro. This is probably the killer feature, to be honest.

    These “static” ArcStrs 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)

  • ArcStrs from arcstr::literal! can be turned into &'static str safely at any time using ArcStr::as_static. (This returns an Option, which is None if the ArcStr was not static)

  • This should be unsurprising given the literal functionality, but ArcStr::new is able to be a const 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 your Arcs 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 ArcStrs 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 ArcStrs. (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

Construct a new empty string.

Examples

let s = ArcStr::new();
assert_eq!(s, "");

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");

Returns the length of this ArcStr in bytes.

Examples

let a = ArcStr::from("foo");
assert_eq!(a.len(), 3);

Returns true if this ArcStr is empty.

Examples

assert!(!ArcStr::from("foo").is_empty());
assert!(ArcStr::new().is_empty());

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");

Extract a byte slice containing the string’s data.

Examples

let foobar = ArcStr::from("foobar");
assert_eq!(foobar.as_bytes(), b"foobar");

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");

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");

Returns true if the two ArcStrs 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: consts 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));

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()));

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 ArcStrs 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));

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 ArcStrs 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);

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.

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.

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.

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(), "");

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

Performs the conversion.

Performs the conversion.

Immutably borrows from an owned value. Read more

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

The resulting type after dereferencing.

Dereferences the value.

Formats the value using the given formatter. Read more

Executes the destructor for this type. Read more

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

Performs the conversion.

The associated error which can be returned from parsing.

Parses a string s to return a value of this type. Read more

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method returns an ordering between self and other values if one exists. Read more

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

Uses borrowed data to replace owned data, usually by cloning. Read more

Converts the given value to a String. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.