Saving space on owned heap-allocated slices and strings.
If we have a
hello, it takes
5 bytes on the heap and whole 24 bytes
on the stack (on 64bit platform). That's a lot of overhead. One can use
that uses only 16 bytes on the stack. With this library,
6 bytes are on the heap and 8 on the
stack (no, this is not the short string optimization ‒ that one stops being useful at very
Also, this library works for other arrays/slices not just strings.
The types work with null pointer optimisation (
Option<OwnedSlice<T>> has the same size as
OwnedSlice<T>) and empty slice/string doesn't allocate.
The downside is, they can't change their length like
Vec. Therefore, this is
suited for storing large amounts of smallish strings.
How does it work
The length is stored as a header on the heap, followed by the actual data. The length is variable length encoded ‒ short strings take only 1 byte header, longer ones take 2 bytes... There's a limit at how large the string can be (current limit is 2^38 characters).
The datastructures are parametrized by a
Header. The future versions will have a limited
Rc builtin functionality ‒ it'll be possible to
share single string/slice between multiple owners. They'll still be sized one word on the
Also, there's a plan to be able to put multiple these variable length slices/strings inside a single allocationd behind a single pointer. Then it'll be possible to save even more on structures holding multiple shortish strings. But how the API will look like is still unknown.
Support for integrating with other libraries (
heapsize) will be added behind feature
Support for allocating from an arena (eg.
bumpalo to cut
down on the allocator overhead might also come.
stdfeature (on by default) adds some little convenience details (eg. the
std::error::Error). By opting out of this feature, the library needs only
(Some of it may be lifted in future versions)
The structures dereference to slice/
str, but explicit dereferencing may be necessary at
Sometimes it is needed to hint the type resolution with the right type (as in the example below).
use squash::Str; // Takes 24 + 5 + allocator overhead let string = String::from("Hello"); // Takes 8 + 6 + allocator overhead let squashed_string: Str = Str::new(&string).unwrap(); assert_eq!(&string as &str, &squashed_string as &str);
If you are trying to save some memory, you might also have a look at these:
A header without sharing support.
An owned slice.
An owned string slice.
An error returned when the slice or string is longer than the header is able to encode.
Description of the header encoding a length.