Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down