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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use core::marker::PhantomData;
use crate::allocator::{AllocatorProvider, Global};
use crate::vec::types::EcoVec;
impl<T> EcoVec<T, Global> {
/// Create a new, empty vector using the global allocator.
///
/// This is a `const fn` so it can be used in constant contexts.
///
/// # Example
/// ```
/// use turbocow::EcoVec;
/// const EMPTY: EcoVec<i32> = EcoVec::new();
/// assert!(EMPTY.is_empty());
/// ```
#[inline]
pub const fn new() -> EcoVec<T, Global> {
EcoVec::<T, Global>::new_in(Global)
}
/// Create a new, empty vector of at least the specified capacity using the default allocator.
///
/// Pinned to [`Global`] so that `EcoVec::with_capacity(..)` infers the
/// allocator without an explicit type annotation. Use
/// [`with_capacity_in`](EcoVec::with_capacity_in) for a custom allocator.
#[inline]
pub fn with_capacity(capacity: usize) -> EcoVec<T, Global> {
EcoVec::<T, Global>::with_capacity_in(capacity, Global)
}
}
impl<T, A> EcoVec<T, A>
where
A: AllocatorProvider,
{
/// Create a new, empty vector using the specified allocator.
#[inline(always)]
pub const fn new_in(alloc: A) -> Self {
Self {
ptr: Self::dangling(),
len: 0,
alloc,
phantom: PhantomData,
}
}
/// Create a new, empty vector of at least the specified capacity using the specified allocator.
#[inline(always)]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
let mut vec = Self::new_in(alloc);
if capacity > 0 {
unsafe {
// Safety:
// - The reference count starts at 1.
// - The capacity starts at 0 and the target capacity is checked
// to be `> 0`.
vec.grow(capacity);
}
}
vec
}
}
impl<T> EcoVec<T, Global>
where
T: Clone,
{
/// Create a new vector with `n` copies of `value` using the default allocator.
///
/// Pinned to [`Global`] so the allocator is inferred without an explicit
/// type annotation. Use [`from_elem_in`](EcoVec::from_elem_in) for a
/// custom allocator.
pub fn from_elem(value: T, n: usize) -> EcoVec<T, Global> {
EcoVec::<T, Global>::from_elem_in(value, n, Global)
}
/// Create a new vector from a slice using the default allocator.
///
/// Pinned to [`Global`] so the allocator is inferred without an explicit
/// type annotation. Use [`from_slice_in`](EcoVec::from_slice_in) for a
/// custom allocator.
pub fn from_slice(slice: &[T]) -> EcoVec<T, Global> {
EcoVec::<T, Global>::from_slice_in(slice, Global)
}
}
impl<T, A> EcoVec<T, A>
where
T: Clone,
A: AllocatorProvider + Clone,
{
/// Create a new vector with `n` copies of `value` using the specified allocator.
pub fn from_elem_in(value: T, n: usize, alloc: A) -> Self {
let mut vec = Self::with_capacity_in(n, alloc);
for _ in 0..n {
// Safety: we just called `with_capacity_in()`
unsafe { vec.push_unchecked(value.clone()) }
}
vec
}
/// Create a new vector from a slice using the specified allocator.
pub fn from_slice_in(slice: &[T], alloc: A) -> Self {
let mut vec = Self::with_capacity_in(slice.len(), alloc);
vec.extend_from_slice(slice);
vec
}
}
impl<T, A> EcoVec<T, A>
where
T: Copy + Clone,
A: AllocatorProvider + Clone,
{
/// Create a new vector with `n` copies of `value` using memcpy.
///
/// Faster than `from_elem_in` for `Copy` types: writes the first
/// element then bulk-copies the rest.
pub fn from_elem_copy_in(value: T, n: usize, alloc: A) -> Self {
if n == 0 {
return Self::new_in(alloc);
}
let mut vec = Self::with_capacity_in(n, alloc);
unsafe {
// Write the first element.
core::ptr::write(vec.data_mut(), value);
vec.len = 1;
// Copy it to fill the rest.
let mut filled = 1;
while filled < n {
let batch = (n - filled).min(filled);
core::ptr::copy_nonoverlapping(
vec.data(),
vec.data_mut().add(filled),
batch,
);
filled += batch;
}
vec.len = n;
}
vec
}
/// Create a new vector from a slice using memcpy.
///
/// Faster than `from_slice_in` for `Copy` types.
pub fn from_copy_slice_in(slice: &[T], alloc: A) -> Self {
let mut vec = Self::with_capacity_in(slice.len(), alloc);
vec.extend_from_copy_slice(slice);
vec
}
}