Skip to content

Commit 03fa36f

Browse files
committed
cows and vecs
1 parent 609961e commit 03fa36f

File tree

2 files changed

+46
-50
lines changed

2 files changed

+46
-50
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "toolshed"
3-
version = "0.4.1"
3+
version = "0.5.0"
44
authors = ["maciejhirsz <[email protected]>"]
55
license = "MIT/Apache-2.0"
66
description = "Arena allocator and a handful of useful data structures"

src/arena.rs

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -82,50 +82,6 @@ impl Arena {
8282
}
8383
}
8484

85-
/// Allocate many items at once, without reallocating
86-
#[inline]
87-
pub fn alloc_many<'input, 'output, T: Sized + Copy + 'input, V: Into<Cow<'input, [T]>>>(
88-
&'output self,
89-
vals: V,
90-
) -> &'output [T] {
91-
use std::{mem, ptr, slice};
92-
93-
let vals = vals.into();
94-
95-
if vals.as_ref().is_empty() {
96-
return &[];
97-
}
98-
99-
let len = vals.as_ref().len();
100-
let bytes = len * mem::size_of::<T>();
101-
102-
match vals {
103-
Cow::Owned(mut vec) => {
104-
let p = vec.as_mut_ptr();
105-
let cap = vec.capacity();
106-
107-
mem::forget(vec);
108-
109-
let out = self.alloc_vec(unsafe {
110-
Vec::from_raw_parts(
111-
p as _,
112-
len * mem::size_of::<T>(),
113-
cap * mem::size_of::<T>(),
114-
)
115-
});
116-
117-
unsafe { slice::from_raw_parts(out as _, len) }
118-
}
119-
Cow::Borrowed(slice) => {
120-
let ptr = self.require(bytes);
121-
122-
unsafe { ptr::copy_nonoverlapping(slice.as_ptr() as _, ptr, bytes) };
123-
124-
unsafe { slice::from_raw_parts(ptr as _, len) }
125-
}
126-
}
127-
}
128-
12985
/// Put the value onto the page of the arena and return a reference to it.
13086
#[inline]
13187
pub fn alloc<'arena, T: Sized + Copy>(&'arena self, value: T) -> &'arena T {
@@ -157,6 +113,35 @@ impl Arena {
157113
}
158114
}
159115

116+
/// Put a `Vec<T>` on the arena without reallocating.
117+
pub fn alloc_vec<'arena, T: Copy>(&'arena self, mut val: Vec<T>) -> &'arena [T] {
118+
use std::{mem, slice};
119+
120+
let ptr = val.as_mut_ptr();
121+
let cap = val.capacity();
122+
let len = val.len();
123+
124+
mem::forget(val);
125+
126+
let out = self.alloc_byte_vec(unsafe {
127+
Vec::from_raw_parts(ptr as _, 0, cap * size_of::<T>())
128+
});
129+
130+
unsafe { slice::from_raw_parts(out as _, len) }
131+
}
132+
133+
/// Allocate many items at once, avoid allocation for owned values.
134+
#[inline]
135+
pub fn alloc_cow<'input, 'arena, T>(&'arena self, vals: Cow<'input, [T]>) -> &'arena [T]
136+
where
137+
T: Sized + Copy + 'input,
138+
{
139+
match vals {
140+
Cow::Owned(vec) => self.alloc_vec(vec),
141+
Cow::Borrowed(slice) => self.alloc_slice(slice),
142+
}
143+
}
144+
160145
/// Allocate an `&str` slice onto the arena and return a reference to it. This is
161146
/// useful when the original slice has an undefined lifetime.
162147
///
@@ -191,7 +176,7 @@ impl Arena {
191176
/// This does not copy or reallocate the original `String`.
192177
pub fn alloc_string<'arena>(&'arena self, val: String) -> &'arena str {
193178
let len = val.len();
194-
let ptr = self.alloc_vec(val.into_bytes());
179+
let ptr = self.alloc_byte_vec(val.into_bytes());
195180

196181
unsafe {
197182
use std::str::from_utf8_unchecked;
@@ -202,7 +187,7 @@ impl Arena {
202187
}
203188

204189
#[inline]
205-
fn alloc_vec(&self, mut val: Vec<u8>) -> *mut u8 {
190+
fn alloc_byte_vec(&self, mut val: Vec<u8>) -> *mut u8 {
206191
let ptr = val.as_mut_ptr();
207192

208193
let mut temp = self.store.replace(Vec::new());
@@ -213,7 +198,7 @@ impl Arena {
213198
}
214199

215200
fn alloc_bytes(&self, size: usize) -> *mut u8 {
216-
self.alloc_vec(Vec::with_capacity(size))
201+
self.alloc_byte_vec(Vec::with_capacity(size))
217202
}
218203

219204
#[inline]
@@ -243,7 +228,7 @@ impl Arena {
243228
}
244229

245230
fn grow(&self) {
246-
let ptr = self.alloc_vec(Vec::with_capacity(ARENA_BLOCK));
231+
let ptr = self.alloc_byte_vec(Vec::with_capacity(ARENA_BLOCK));
247232
self.ptr.set(ptr);
248233
}
249234

@@ -303,7 +288,18 @@ mod test {
303288
let vecs = vec![vec![1u64, 2, 3, 4], vec![7; ARENA_BLOCK * 2], vec![]];
304289

305290
for vec in vecs {
306-
assert_eq!(arena.alloc_many(vec.clone()), &vec[..]);
291+
assert_eq!(arena.alloc_vec(vec.clone()), &vec[..]);
292+
}
293+
}
294+
295+
#[test]
296+
fn allocate_some_cows() {
297+
let arena = Arena::new();
298+
299+
let vecs = vec![vec![1u64, 2, 3, 4], vec![7; ARENA_BLOCK * 2], vec![]];
300+
301+
for vec in vecs {
302+
assert_eq!(arena.alloc_cow(vec.clone().into()), &vec[..]);
307303
}
308304
}
309305

0 commit comments

Comments
 (0)