I would note that prior experience with std::string
(C++) is not all rosy. There are performance issues with the optimizers having trouble optimizing out the branches for reads/writes due to the indirection, issues that do not occur for more straightforward types.
This is sufficient, as far as I am concerned, to avoid using such a "clever" trick as the default representation, and instead aim at offering a parameterizable implementation of String
which can be declined in multiple formats:
InlineString<N>
:len
in0..=N
,cap
=N
.SmallString<N>
: originally inline iflen <= N
, then heap-allocated.String
: regular, default, heap-allocated.
Then people can choose what makes sense for their own usecase, and do not need to pay for fancy features they do not use.
Disclaimer: I am biased.
The idea of declining collections in such a way is what has motivated me to work on the Store API RFC.
The obvious follow-ups of the RFC would be the "Store-ification" of the standard library collection types: Box
, Vec
, String
, etc... and putting them in core
.
This, in itself, is not enough to have a truly compact small string. Just swapping out the pointer + allocator of Vec
for a handle + store allow defining an InlineVec<N>
or SmallVec<N>
, but those still retain the two usize
fields for len
and cap
. However, since nobody depends on core::Vec
and core::String
today since they do not exist, merely defining them -- unstably, at first -- would open the possibility of adding more parameterization to the types, such as defining Length and Capacity traits, or any other combination.
The re-exports made by the alloc
or collection
crates can then take care of exposing an API matching the current one, for example: pub type String = core::String<usize, usize, Global>;
.