The question is that the String object will be only allocated on heap and never be created on stack, so I tend to declare the second field as a type of str instead of String to avoid a second heap allocation. This struct then be unsized, trapped me when I implement the following functions.
impl String {
fn new(s: &str) -> Box<Self> {
// how to allocate memory and copy from the input string?
}
fn drop(self) {
// how to free resource?
}
}
So what is the correct way? The size of the struct need to be
sizeof(String) =
sizeof(GCHeader)
+ sizeof(usize) // length of string
+ sizeof(string_buffer) // the actual buffer for string
Thanks for your nice advice. But I am curious why length in StrWithHeader is duplicatedly stored with the method len() in str. In addition, I need a struct of #[repr(packed)] insread of `#[repr(C)]' for the reason of memory usage. Anyway, it is a good reference for me.
I wouldn't use repr(packed) for this, since it disallowed getting references to any fields of your type (unless they have an alignment of 1).
The length method on the string reads from pointer. But if you se erasable, then the pointer won't store the length, so it must read from the data next to the string.
Default representation of &str
[Address, length]
|
\/
[Str data]
Representation of erasable::Thin<slice_dst::StrWithHeader<Header>>
[Address]
|
\/
[Len, header, str data]
As you can see, these crates just move where the length is stored.