1use std::mem;
2use std::ptr;
3use std::slice;
4
5pub struct PrefixedArray<I: PrefixedArrayInfo, T> {
7 inner: *mut Inner<I, T>,
8}
9
10pub trait PrefixedArrayInfo {
11 fn len(&self) -> usize;
12
13 fn capacity(&self) -> usize;
14}
15
16#[repr(C)]
17struct Inner<I, T> {
18 info: I,
19 data: [T; 0],
20}
21
22impl<I: PrefixedArrayInfo, T> PrefixedArray<I, T> {
23 pub fn allocate(info: I) -> Self {
24 assert_ne!(0, ::std::mem::size_of::<T>(), "ZST not supported");
25 let mut data = Vec::<I>::with_capacity(Self::vec_cap(info.capacity()));
26 let inner = data.as_mut_ptr();
27 unsafe {
28 ptr::write(&mut *inner, info);
29 }
30 mem::forget(data);
31 PrefixedArray { inner: inner as _ }
32 }
33
34 fn vec_cap(len: usize) -> usize {
35 let bytes = mem::size_of::<I>() + mem::size_of::<T>() * len;
38 div_round_up(bytes, mem::size_of::<I>())
39 }
40
41 #[inline]
43 pub unsafe fn write(&mut self, offset: usize, value: T) {
44 ptr::write(self.data_mut().offset(offset as isize), value);
45 }
46
47 #[inline]
49 pub fn as_slice(&self) -> &[T] {
50 unsafe { slice::from_raw_parts(self.data(), self.len()) }
51 }
52
53 #[inline]
55 pub fn as_mut_slice(&mut self) -> &mut [T] {
56 unsafe { slice::from_raw_parts_mut(self.data_mut(), self.len()) }
57 }
58
59 #[inline]
61 pub unsafe fn clone_shallow(&self) -> Self {
62 PrefixedArray { inner: self.inner }
63 }
64
65 #[inline]
67 pub unsafe fn drop_and_deallocate(&mut self) {
68 let cap = self.info().capacity();
69 ptr::drop_in_place(self.as_mut_slice());
70 ptr::drop_in_place(&mut *self);
71 Vec::from_raw_parts(self.inner, 0, Self::vec_cap(cap));
72 }
73
74 pub fn info(&self) -> &I {
75 &self.inner().info
76 }
77
78 pub fn info_mut(&mut self) -> &mut I {
79 &mut self.inner_mut().info
80 }
81
82 fn data(&self) -> *const T {
83 self.inner().data.as_ptr()
84 }
85
86 fn data_mut(&mut self) -> *mut T {
87 self.inner_mut().data.as_mut_ptr()
88 }
89
90 fn len(&self) -> usize {
91 self.info().len()
92 }
93
94 fn inner(&self) -> &Inner<I, T> {
95 unsafe { &*self.inner }
96 }
97
98 fn inner_mut(&mut self) -> &mut Inner<I, T> {
99 unsafe { &mut *self.inner }
100 }
101}
102
103#[inline]
104fn div_round_up(divident: usize, divisor: usize) -> usize {
105 1 + ((divident - 1) / divisor)
106}
107
108#[cfg(test)]
109mod tests {
110 use super::{PrefixedArray, PrefixedArrayInfo, div_round_up};
111 use testdrop::{self, TestDrop};
112
113 #[test]
114 fn test_div_round_up() {
115 assert_eq!(6, div_round_up(6, 1));
116 assert_eq!(7, div_round_up(7, 1));
117 assert_eq!(8, div_round_up(8, 1));
118
119 assert_eq!(3, div_round_up(6, 2));
120 assert_eq!(4, div_round_up(7, 2));
121 assert_eq!(4, div_round_up(8, 2));
122
123 assert_eq!(2, div_round_up(6, 3));
124 assert_eq!(3, div_round_up(7, 3));
125 assert_eq!(3, div_round_up(8, 3));
126 assert_eq!(3, div_round_up(9, 3));
127 assert_eq!(4, div_round_up(10, 3));
128 }
129
130 struct Info {
131 len: usize,
132 cap: usize,
133 }
134
135 impl PrefixedArrayInfo for Info {
136 fn len(&self) -> usize {
137 self.len
138 }
139
140 fn capacity(&self) -> usize {
141 self.cap
142 }
143 }
144
145 #[test]
146 fn drop_and_deallocate() {
147 let test = TestDrop::new();
148 let v = &mut PrefixedArray::allocate(Info { len: 0, cap: 5 });
149
150 let (a, item_a) = test.new_item();
151 let (b, item_b) = test.new_item();
152 let (c, item_c) = test.new_item();
153 let (d, item_d) = test.new_item();
154 let (e, item_e) = test.new_item();
155
156 fn test_write<'a>(
157 v: &mut PrefixedArray<Info, testdrop::Item<'a>>,
158 id: usize,
159 item: testdrop::Item<'a>,
160 index: usize,
161 ) {
162 unsafe {
163 let len = v.inner().info.len;
164 v.write(len, item);
165 v.inner_mut().info.len = len + 1;
166 }
167 assert_eq!(index + 1, v.len());
168 assert_eq!(index + 1, v.as_slice().len());
169 assert_eq!(index + 1, v.as_mut_slice().len());
170 assert_eq!(id, v.as_slice()[index].id());
171 assert_eq!(id, v.as_mut_slice()[index].id());
172 }
173
174 test_write(v, a, item_a, 0);
175 test_write(v, b, item_b, 1);
176 test_write(v, c, item_c, 2);
177 test_write(v, d, item_d, 3);
178 test_write(v, e, item_e, 4);
179
180 v.inner_mut().info.len = 3;
182
183 unsafe {
184 v.drop_and_deallocate();
185 }
186
187 test.assert_drop(a);
188 test.assert_drop(b);
189 test.assert_drop(c);
190 test.assert_no_drop(d);
191 test.assert_no_drop(e);
192 }
193}