1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Freeze a transient builder into arena-owned `Arc` or `Box` slices.
use core::mem::ManuallyDrop;
use allocator_api2::alloc::{AllocError, Allocator};
use super::Vec;
use crate::arc::Arc;
use crate::r#box::Box;
impl<T, A: Allocator + Clone> Vec<'_, T, A> {
/// Freeze into an [`Arc<[T], A>`](crate::Arc).
///
/// The contents are moved into a fresh shared-flavor arena
/// allocation.
///
/// # Panics
///
/// Panics if the underlying allocator fails.
#[must_use]
pub fn into_arena_arc(self) -> Arc<[T], A>
where
T: Send + Sync,
A: Send + Sync,
{
let arena = self.arena;
let mut me = ManuallyDrop::new(self);
let iter = me.buf.drain_all();
let arc = arena.alloc_slice_fill_iter_arc::<T, _>(iter);
// `drain_all` set `buf.len = 0`, so `into_inner`'s normal `Drop`
// only releases the (unused) backing buffer.
drop(ManuallyDrop::into_inner(me));
arc
}
/// Fallible variant of [`Self::into_arena_arc`].
///
/// # Errors
///
/// Returns [`AllocError`] if the backing shared-flavor allocation
/// fails. On error, `self` is consumed and any elements remaining
/// after a partial move are dropped before this function returns.
pub fn try_into_arena_arc(self) -> Result<Arc<[T], A>, AllocError>
where
T: Send + Sync,
A: Send + Sync,
{
let arena = self.arena;
let mut me = ManuallyDrop::new(self);
let iter = me.buf.drain_all();
let result = arena.try_alloc_slice_fill_iter_arc::<T, _>(iter);
// See `into_arena_arc`.
drop(ManuallyDrop::into_inner(me));
result
}
/// Freeze into a [`Box<[T], A>`](crate::Box).
///
/// **O(1)**: the existing buffer is handed to the `Box` directly.
/// `Box<[T]>`'s `Drop` runs `drop_in_place::<[T]>` over the slice
/// (using its fat-pointer length) when the box is dropped, so no
/// trailing chunk drop entry is needed regardless of `T: Drop`.
///
/// If the buffer's tail still sits at the chunk's bump cursor, the
/// unused tail (`cap - len`) is returned to the cursor.
///
/// # Panics
///
/// Panics if the underlying allocator fails on the copy fallback
/// for the ZST / empty-builder cases.
#[must_use]
pub fn into_arena_box(self) -> Box<[T], A> {
let arena = self.arena;
let mut me = ManuallyDrop::new(self);
let iter = me.buf.drain_all();
let bx = arena.alloc_slice_fill_iter_box::<T, _>(iter);
// See `into_arena_arc`.
drop(ManuallyDrop::into_inner(me));
bx
}
}