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
use crate::{base::Base, internal, RawMem};
use std::alloc::LayoutError;
use std::cmp::Ordering;
use std::{
alloc::{Allocator, Layout},
error::Error,
io, ptr,
ptr::NonNull,
};
pub struct AllocMem<T, A: Allocator> {
base: Base<T>,
alloc: A,
}
impl<T: Default, A: Allocator> AllocMem<T, A> {
pub fn new(alloc: A) -> Self {
Self {
base: Base::new(NonNull::slice_from_raw_parts(NonNull::dangling(), 0)),
alloc,
}
}
unsafe fn alloc_impl(&mut self, capacity: usize) -> io::Result<&mut [T]> {
let old_capacity = self.base.ptr.len();
let new_capacity = capacity;
let result: Result<_, Box<dyn Error + Sync + Send>> = try {
if self.base.ptr.as_non_null_ptr() == NonNull::dangling() {
let layout = Layout::array::<T>(capacity)?;
self.alloc.allocate_zeroed(layout)?
} else {
let old_layout = Layout::array::<T>(old_capacity)?;
let new_layout = Layout::array::<T>(new_capacity)?;
let ptr = internal::align_from(self.base.ptr);
match old_capacity.cmp(&new_capacity) {
Ordering::Less => {
self.alloc
.grow_zeroed(ptr.as_non_null_ptr(), old_layout, new_layout)?
}
Ordering::Greater => {
self.alloc
.shrink(ptr.as_non_null_ptr(), old_layout, new_layout)?
}
Ordering::Equal => ptr,
}
}
};
result
.map(|ptr| {
self.base.ptr = internal::guaranteed_align_to(ptr);
for i in old_capacity..new_capacity {
self.base.ptr.as_mut_ptr().add(i).write(T::default());
}
self.base.ptr.as_mut()
})
.map_err(io::Error::other)
}
}
impl<T: Default, A: Allocator> RawMem<T> for AllocMem<T, A> {
fn alloc(&mut self, capacity: usize) -> io::Result<&mut [T]> {
unsafe { self.alloc_impl(capacity) }
}
fn allocated(&self) -> usize {
self.base.ptr.len()
}
fn occupy(&mut self, capacity: usize) -> io::Result<()> {
self.base.occupy(capacity)
}
fn occupied(&self) -> usize {
self.base.occupied
}
}
impl<T, A: Allocator> Drop for AllocMem<T, A> {
fn drop(&mut self) {
unsafe {
let slice = self.base.ptr.as_mut();
for item in slice {
ptr::drop_in_place(item);
}
}
let _: Result<_, LayoutError> = try {
let ptr = self.base.ptr;
let layout = Layout::array::<T>(ptr.len())?;
unsafe {
let ptr = ptr.as_non_null_ptr().cast();
self.alloc.deallocate(ptr, layout);
}
};
}
}