mirror of
https://github.com/openharmony/third_party_rust_rust-smallvec.git
synced 2026-07-20 15:38:21 -04:00
Auto merge of #130 - heycam:from-raw-parts, r=mbrubeck
Add from_raw_parts. I have a need to create a `SmallVec` using a heap allocation that I control. Something that works just like `Vec::from_raw_parts` fits the bill. The PR here adds a similar method, with the important difference that it panics if asked to conjure up a `SmallVec` that would use its inline storage rather than spilled, heap storage. This is a dependency of my work in https://bugzilla.mozilla.org/show_bug.cgi?id=1474793. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/130) <!-- Reviewable:end -->
This commit is contained in:
@@ -940,6 +940,86 @@ impl<A: Array> SmallVec<A> {
|
||||
{
|
||||
self.dedup_by(|a, b| key(a) == key(b));
|
||||
}
|
||||
|
||||
/// Creates a `SmallVec` directly from the raw components of another
|
||||
/// `SmallVec`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is highly unsafe, due to the number of invariants that aren't
|
||||
/// checked:
|
||||
///
|
||||
/// * `ptr` needs to have been previously allocated via `SmallVec` for its
|
||||
/// spilled storage (at least, it's highly likely to be incorrect if it
|
||||
/// wasn't).
|
||||
/// * `ptr`'s `A::Item` type needs to be the same size and alignment that
|
||||
/// it was allocated with
|
||||
/// * `length` needs to be less than or equal to `capacity`.
|
||||
/// * `capacity` needs to be the capacity that the pointer was allocated
|
||||
/// with.
|
||||
///
|
||||
/// Violating these may cause problems like corrupting the allocator's
|
||||
/// internal data structures.
|
||||
///
|
||||
/// Additionally, `capacity` must be greater than the amount of inline
|
||||
/// storage `A` has; that is, the new `SmallVec` must need to spill over
|
||||
/// into heap allocated storage. This condition is asserted against.
|
||||
///
|
||||
/// The ownership of `ptr` is effectively transferred to the
|
||||
/// `SmallVec` which may then deallocate, reallocate or change the
|
||||
/// contents of memory pointed to by the pointer at will. Ensure
|
||||
/// that nothing else uses the pointer after calling this
|
||||
/// function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate smallvec;
|
||||
/// # use smallvec::SmallVec;
|
||||
/// use std::mem;
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut v: SmallVec<[_; 1]> = smallvec![1, 2, 3];
|
||||
///
|
||||
/// // Pull out the important parts of `v`.
|
||||
/// let p = v.as_mut_ptr();
|
||||
/// let len = v.len();
|
||||
/// let cap = v.capacity();
|
||||
/// let spilled = v.spilled();
|
||||
///
|
||||
/// unsafe {
|
||||
/// // Forget all about `v`. The heap allocation that stored the
|
||||
/// // three values won't be deallocated.
|
||||
/// mem::forget(v);
|
||||
///
|
||||
/// // Overwrite memory with [4, 5, 6].
|
||||
/// //
|
||||
/// // This is only safe if `spilled` is true! Otherwise, we are
|
||||
/// // writing into the old `SmallVec`'s inline storage on the
|
||||
/// // stack.
|
||||
/// assert!(spilled);
|
||||
/// for i in 0..len as isize {
|
||||
/// ptr::write(p.offset(i), 4 + i);
|
||||
/// }
|
||||
///
|
||||
/// // Put everything back together into a SmallVec with a different
|
||||
/// // amount of inline storage, but which is still less than `cap`.
|
||||
/// let rebuilt = SmallVec::<[_; 2]>::from_raw_parts(p, len, cap);
|
||||
/// assert_eq!(&*rebuilt, &[4, 5, 6]);
|
||||
/// }
|
||||
/// }
|
||||
pub unsafe fn from_raw_parts(
|
||||
ptr: *mut A::Item,
|
||||
length: usize,
|
||||
capacity: usize,
|
||||
) -> SmallVec<A> {
|
||||
assert!(capacity > A::size());
|
||||
SmallVec {
|
||||
capacity,
|
||||
data: SmallVecData::from_heap(ptr, length),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> SmallVec<A> where A::Item: Copy {
|
||||
|
||||
Reference in New Issue
Block a user