solar_data_structures/
bump_ext.rs1use bumpalo::Bump;
2use smallvec::SmallVec;
3
4#[allow(clippy::mut_from_ref)] pub trait BumpExt {
7 fn used_bytes(&self) -> usize;
9
10 fn alloc_as_slice<T>(&self, value: T) -> &mut [T];
12
13 fn alloc_from_iter<T>(&self, iter: impl Iterator<Item = T>) -> &mut [T];
17
18 fn alloc_vec<T>(&self, values: Vec<T>) -> &mut [T];
23
24 fn alloc_smallvec<A: smallvec::Array>(&self, values: SmallVec<A>) -> &mut [A::Item];
29
30 fn alloc_array<T, const N: usize>(&self, values: [T; N]) -> &mut [T];
35
36 unsafe fn alloc_slice_unchecked<'a, T>(&'a self, slice: &[T]) -> &'a mut [T];
44}
45
46impl BumpExt for Bump {
47 fn used_bytes(&self) -> usize {
48 unsafe { self.iter_allocated_chunks_raw().map(|(_ptr, len)| len).sum::<usize>() }
50 }
51
52 #[inline]
53 fn alloc_as_slice<T>(&self, value: T) -> &mut [T] {
54 std::slice::from_mut(self.alloc(value))
55 }
56
57 #[inline]
58 fn alloc_from_iter<T>(&self, mut iter: impl Iterator<Item = T>) -> &mut [T] {
59 match iter.size_hint() {
60 (min, Some(max)) if min == max => self.alloc_slice_fill_with(min, |_| {
61 iter.next().expect("Iterator supplied too few elements")
62 }),
63 _ => self.alloc_smallvec(SmallVec::<[T; 8]>::from_iter(iter)),
64 }
65 }
66
67 #[inline]
68 fn alloc_vec<T>(&self, mut values: Vec<T>) -> &mut [T] {
69 if values.is_empty() {
70 return &mut [];
71 }
72
73 unsafe {
75 let r = self.alloc_slice_unchecked(values.as_slice());
76 values.set_len(0);
77 r
78 }
79 }
80
81 #[inline]
82 fn alloc_smallvec<A: smallvec::Array>(&self, mut values: SmallVec<A>) -> &mut [A::Item] {
83 if values.is_empty() {
84 return &mut [];
85 }
86
87 unsafe {
89 let r = self.alloc_slice_unchecked(values.as_slice());
90 values.set_len(0);
91 r
92 }
93 }
94
95 #[inline]
96 fn alloc_array<T, const N: usize>(&self, values: [T; N]) -> &mut [T] {
97 if values.is_empty() {
98 return &mut [];
99 }
100
101 let values = std::mem::ManuallyDrop::new(values);
102 unsafe { self.alloc_slice_unchecked(values.as_slice()) }
104 }
105
106 #[inline]
107 unsafe fn alloc_slice_unchecked<'a, T>(&'a self, src: &[T]) -> &'a mut [T] {
108 let layout = std::alloc::Layout::for_value(src);
110 let dst = self.alloc_layout(layout).cast::<T>();
111 unsafe {
112 std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), src.len());
113 std::slice::from_raw_parts_mut(dst.as_ptr(), src.len())
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[derive(Debug, PartialEq, Eq)]
123 struct DropBomb(i32, bool);
124 impl DropBomb {
125 fn new(i: i32) -> Self {
126 Self(i, true)
127 }
128 fn defuse(&mut self) {
129 self.1 = false;
130 }
131 }
132 impl Drop for DropBomb {
133 fn drop(&mut self) {
134 if self.1 && !std::thread::panicking() {
135 panic!("boom");
136 }
137 }
138 }
139
140 #[test]
141 fn test_alloc_vec() {
142 let bump = Bump::new();
143 let vec = vec![DropBomb::new(1), DropBomb::new(2), DropBomb::new(3)];
144 let other_vec = vec![DropBomb::new(1), DropBomb::new(2), DropBomb::new(3)];
145 let slice = bump.alloc_vec(vec);
146 assert_eq!(slice, &other_vec[..]);
147 for item in slice {
148 item.defuse();
149 }
150 for mut item in other_vec {
151 item.defuse();
152 }
153 }
154}