Featherweight string-by-reference implementation.
You might want this crate if:
- you have a number of string values, the set of which is determined dynamically but does not grow (much) over time, such as from an initial configuration step, and
- you want to be able to compare these string values repeatedly at very low cost, and
- your usage pattern leans towards many comparisons but relatively few parses.
You probably don't want this crate if:
- the set of string values you care about changes significantly over time, or
- your usage pattern leans towards constructing strings and only rarely comparing them.
Conceptually, a StoredString is a lightweight reference to a string inside a
global string storage. The intended use is for rapid equality checks between strings drawn from
a small set, where the overhead of byte-by-byte string comparison is overkill.
More concretely, each StoredString contains a pointer to a string stored in
a global hash table. Since the hash table guarantees uniqueness, a string comparison can be
reduced to simply a pointer comparison. Constructing a StoredString involves a mutex lock and
hash table lookup, but copying one is nearly free as it is simply a pointer copy. No reference
tracking is performed, so any strings added to the global hash table will remain allocated
until program exit.
To avoid complications stemming from strings with different semantics sharing the same unique
pointer value, StoredString is abstracted across a NamespaceTag
implementation. This introduces no runtime overhead, but allows for catching many errors at
compile-time. As a concrete example; this is perfectly accepted:
# use ;
# ;
#
// we can compare StoredStrings directly
assert_eq!;
But this is not:
# use stringstore::StoredString;
let ss1 = StoredString::<Tag1>::new("string");
let ss2 = StoredString::<Tag2>::new("string");
assert_eq!(ss1.as_str().as_ptr(), ss2.as_str().as_ptr()); // this holds
assert_eq!(ss1, ss2); // this is a compilation error
The use of type aliases is highly encouraged.