haagenti_zstd/compress/
arena.rs1use core::cell::Cell;
26
27pub const DEFAULT_ARENA_SIZE: usize = 64 * 1024;
29
30#[derive(Debug)]
36pub struct Arena {
37 buffer: Vec<u8>,
39 pos: Cell<usize>,
42 peak_usage: Cell<usize>,
44}
45
46impl Arena {
47 pub fn new(capacity: usize) -> Self {
49 Self {
50 buffer: vec![0; capacity],
51 pos: Cell::new(0),
52 peak_usage: Cell::new(0),
53 }
54 }
55
56 pub fn with_default_size() -> Self {
58 Self::new(DEFAULT_ARENA_SIZE)
59 }
60
61 #[inline]
66 pub fn reset(&self) {
67 let current = self.pos.get();
69 if current > self.peak_usage.get() {
70 self.peak_usage.set(current);
71 }
72 self.pos.set(0);
73 }
74
75 #[inline]
82 #[allow(clippy::mut_from_ref)]
83 pub fn alloc_slice(&self, len: usize) -> Option<&mut [u8]> {
84 let pos = self.pos.get();
85 let new_pos = pos.checked_add(len)?;
86
87 if new_pos > self.buffer.len() {
88 return None;
89 }
90
91 self.pos.set(new_pos);
92
93 unsafe {
96 let ptr = self.buffer.as_ptr().add(pos) as *mut u8;
97 Some(core::slice::from_raw_parts_mut(ptr, len))
98 }
99 }
100
101 #[inline]
105 pub fn alloc_slice_zeroed(&self, len: usize) -> Option<&mut [u8]> {
106 let slice = self.alloc_slice(len)?;
107 slice.fill(0);
108 Some(slice)
109 }
110
111 pub fn alloc_vec(&self, initial_capacity: usize) -> Option<ArenaVec<'_>> {
115 let pos = self.pos.get();
116 let max_capacity = self.buffer.len().saturating_sub(pos);
117
118 if initial_capacity > max_capacity {
119 return None;
120 }
121
122 self.pos.set(pos + initial_capacity);
124
125 Some(ArenaVec {
126 arena: self,
127 start: pos,
128 len: 0,
129 capacity: initial_capacity,
130 })
131 }
132
133 #[inline]
135 pub fn usage(&self) -> usize {
136 self.pos.get()
137 }
138
139 #[inline]
141 pub fn capacity(&self) -> usize {
142 self.buffer.len()
143 }
144
145 #[inline]
147 pub fn remaining(&self) -> usize {
148 self.buffer.len().saturating_sub(self.pos.get())
149 }
150
151 #[inline]
153 pub fn peak_usage(&self) -> usize {
154 self.peak_usage.get().max(self.pos.get())
155 }
156}
157
158pub struct ArenaVec<'a> {
163 arena: &'a Arena,
164 start: usize,
165 len: usize,
166 capacity: usize,
167}
168
169impl<'a> ArenaVec<'a> {
170 #[inline]
174 pub fn push(&mut self, value: u8) -> bool {
175 if self.len >= self.capacity {
176 if !self.grow(1) {
178 return false;
179 }
180 }
181
182 unsafe {
184 let ptr = self.arena.buffer.as_ptr().add(self.start + self.len) as *mut u8;
185 *ptr = value;
186 }
187 self.len += 1;
188 true
189 }
190
191 pub fn extend_from_slice(&mut self, data: &[u8]) -> bool {
195 if self.len + data.len() > self.capacity {
196 if !self.grow(data.len()) {
198 return false;
199 }
200 }
201
202 unsafe {
204 let ptr = self.arena.buffer.as_ptr().add(self.start + self.len) as *mut u8;
205 core::ptr::copy_nonoverlapping(data.as_ptr(), ptr, data.len());
206 }
207 self.len += data.len();
208 true
209 }
210
211 fn grow(&mut self, additional: usize) -> bool {
213 let needed = self.len + additional;
214 if needed <= self.capacity {
215 return true;
216 }
217
218 let arena_pos = self.arena.pos.get();
220 let our_end = self.start + self.capacity;
221
222 if arena_pos == our_end {
223 let new_capacity = (needed * 2).min(self.arena.remaining() + self.capacity);
225 if new_capacity >= needed {
226 let growth = new_capacity - self.capacity;
227 self.arena.pos.set(arena_pos + growth);
228 self.capacity = new_capacity;
229 return true;
230 }
231 }
232
233 false
234 }
235
236 #[inline]
238 pub fn len(&self) -> usize {
239 self.len
240 }
241
242 #[inline]
244 pub fn is_empty(&self) -> bool {
245 self.len == 0
246 }
247
248 #[inline]
250 pub fn as_slice(&self) -> &[u8] {
251 unsafe {
253 let ptr = self.arena.buffer.as_ptr().add(self.start);
254 core::slice::from_raw_parts(ptr, self.len)
255 }
256 }
257
258 pub fn to_vec(&self) -> Vec<u8> {
260 self.as_slice().to_vec()
261 }
262}
263
264#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_arena_creation() {
274 let arena = Arena::new(1024);
275 assert_eq!(arena.capacity(), 1024);
276 assert_eq!(arena.usage(), 0);
277 assert_eq!(arena.remaining(), 1024);
278 }
279
280 #[test]
281 fn test_arena_alloc_slice() {
282 let arena = Arena::new(1024);
283
284 let slice1 = arena.alloc_slice(100).unwrap();
285 assert_eq!(slice1.len(), 100);
286 assert_eq!(arena.usage(), 100);
287
288 let slice2 = arena.alloc_slice(200).unwrap();
289 assert_eq!(slice2.len(), 200);
290 assert_eq!(arena.usage(), 300);
291 }
292
293 #[test]
294 fn test_arena_alloc_slice_zeroed() {
295 let arena = Arena::new(1024);
296
297 let slice = arena.alloc_slice(100).unwrap();
299 slice.fill(0xFF);
300
301 arena.reset();
302
303 let zeroed = arena.alloc_slice_zeroed(100).unwrap();
305 for &byte in zeroed.iter() {
306 assert_eq!(byte, 0);
307 }
308 }
309
310 #[test]
311 fn test_arena_reset() {
312 let arena = Arena::new(1024);
313
314 let _ = arena.alloc_slice(500).unwrap();
315 assert_eq!(arena.usage(), 500);
316
317 arena.reset();
318 assert_eq!(arena.usage(), 0);
319 assert_eq!(arena.peak_usage(), 500);
320 }
321
322 #[test]
323 fn test_arena_overflow() {
324 let arena = Arena::new(100);
325
326 assert!(arena.alloc_slice(50).is_some());
327 assert!(arena.alloc_slice(60).is_none()); assert_eq!(arena.usage(), 50); }
330
331 #[test]
332 fn test_arena_vec_basic() {
333 let arena = Arena::new(1024);
334
335 let mut vec = arena.alloc_vec(100).unwrap();
336 assert!(vec.is_empty());
337
338 vec.push(1);
339 vec.push(2);
340 vec.push(3);
341
342 assert_eq!(vec.len(), 3);
343 assert_eq!(vec.as_slice(), &[1, 2, 3]);
344 }
345
346 #[test]
347 fn test_arena_vec_extend() {
348 let arena = Arena::new(1024);
349
350 let mut vec = arena.alloc_vec(100).unwrap();
351 vec.extend_from_slice(b"Hello, ");
352 vec.extend_from_slice(b"World!");
353
354 assert_eq!(vec.as_slice(), b"Hello, World!");
355 }
356
357 #[test]
358 fn test_arena_vec_grow() {
359 let arena = Arena::new(1024);
360
361 let mut vec = arena.alloc_vec(10).unwrap();
362
363 for i in 0..50u8 {
365 assert!(vec.push(i));
366 }
367
368 assert_eq!(vec.len(), 50);
369
370 for (i, &b) in vec.as_slice().iter().enumerate() {
372 assert_eq!(b, i as u8);
373 }
374 }
375
376 #[test]
377 fn test_arena_vec_to_vec() {
378 let arena = Arena::new(1024);
379
380 let mut arena_vec = arena.alloc_vec(100).unwrap();
381 arena_vec.extend_from_slice(b"Test data");
382
383 let regular_vec = arena_vec.to_vec();
384 assert_eq!(regular_vec, b"Test data");
385 }
386
387 #[test]
388 fn test_arena_peak_usage() {
389 let arena = Arena::new(1024);
390
391 let _ = arena.alloc_slice(400);
393 arena.reset();
394
395 let _ = arena.alloc_slice(200);
397
398 assert_eq!(arena.peak_usage(), 400);
400 }
401
402 #[test]
403 fn test_default_arena_size() {
404 let arena = Arena::with_default_size();
405 assert_eq!(arena.capacity(), DEFAULT_ARENA_SIZE);
406 }
407}