into/from_parts - #97
Baptistemontan wants to merge 4 commits into
Conversation
emilio
left a comment
There was a problem hiding this comment.
What's the use case for this?
| /// | ||
| /// [`from_parts`]: ThinVec::from_parts | ||
| #[must_use = "losing the pointer will leak memory"] | ||
| pub fn into_parts(self) -> (NonNull<T>, usize, usize) { |
There was a problem hiding this comment.
I don't get the point of returning pointer / len / capacity separately.
A from_raw / into_raw would be reasonable I guess, but that doesn't work for ZSTs.
There was a problem hiding this comment.
well capacity is indeed optionnal in theory and be retrieved in the allocation, but length is required for ZSTs, we could have a non-zst variant that just gives a pointer. But without the gecko-ffi feature, how do we properly check if it is a singleton or not ? we might get back a pointer that does'nt have a header, and without the capacity we can't know without doubts if there is one or not, heck even with the cap we can't, but since it has no capacity it did'nt allocate so we can just return a newly created one, and length does'nt helps as it could have allocated then cleared. So we do need the trio for reconstruction.
But at the end of the day, it's the same as Vec, from_parts do have stronger expectations than the Vec counterpart but the idea is the same: you get back a pointer, a length and a capacity, and you now own the underlying buffer and are responsible for it's memory management.
As for a use case, I guess the same ones as Vec::into_parts, you can create a ThinVec, operate on it, then need a way to own the allocation because there is an API that you use that needs it for XYZ reasons, might be for FFI where it expect the pointer of the buffer, but you can't keep the ThinVec alive as now it might alias, or keeping it alive for the whole usage might be difficult.
emilio
left a comment
There was a problem hiding this comment.
I think it'd be better to have a:
fn into_raw(self) -> NonNull<T> { .. }
fn from_raw(raw: NonNull<T>) -> Self { .. }Where NonNull<T> would be the fake len thingie, and for the others it'd be the offsetted pointer into the buffer.
That seems like it'd fulfill the same use cases in practice?
Seams awfully footgunny, pretty bad idea to return a seamingly ptr to T but with "unless it's a ZST, then it's the len, and you can't deref it unless align::<T> == 1", I guess we could have the fake pointer always aligned so it's always valid for deref, so |
Add
into_partsandfrom_partsforThinVec, mirroringVecAPI, but with different expectation forfrom_parts, which are closer to the ones ofRc::from_raw, since with the headerinto_partsis doing something akin toRc::into_rawwith the pointer offset.close #55