Skip to main content

reifydb_engine/arena/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::{
5	fmt::{self, Debug},
6	ops::Deref,
7};
8
9use bumpalo::Bump as BumpAlloc;
10use reifydb_type::storage::{DataBitVec, DataVec, Storage};
11
12type BumpaloVec<'bump, T> = bumpalo::collections::Vec<'bump, T>;
13
14pub mod convert;
15
16pub struct BumpVec<'bump, T: Clone + PartialEq> {
17	inner: BumpaloVec<'bump, T>,
18}
19
20impl<'bump, T: Clone + PartialEq + Debug> Debug for BumpVec<'bump, T> {
21	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22		f.debug_tuple("BumpVec").field(&self.inner.as_slice()).finish()
23	}
24}
25
26impl<'bump, T: Clone + PartialEq> BumpVec<'bump, T> {
27	pub fn with_capacity_in(capacity: usize, bump: &'bump BumpAlloc) -> Self {
28		Self {
29			inner: BumpaloVec::with_capacity_in(capacity, bump),
30		}
31	}
32
33	fn bump(&self) -> &'bump BumpAlloc {
34		self.inner.bump()
35	}
36}
37
38impl<'bump, T: Clone + PartialEq> Clone for BumpVec<'bump, T> {
39	fn clone(&self) -> Self {
40		let mut new = BumpaloVec::with_capacity_in(self.inner.len(), self.bump());
41		new.extend(self.inner.iter().cloned());
42		Self {
43			inner: new,
44		}
45	}
46}
47
48impl<'bump, T: Clone + PartialEq> PartialEq for BumpVec<'bump, T> {
49	fn eq(&self, other: &Self) -> bool {
50		self.inner.as_slice() == other.inner.as_slice()
51	}
52}
53
54impl<'bump, T: Clone + PartialEq> Deref for BumpVec<'bump, T> {
55	type Target = [T];
56
57	fn deref(&self) -> &Self::Target {
58		self.inner.as_slice()
59	}
60}
61
62impl<'bump, T: Clone + PartialEq> DataVec<T> for BumpVec<'bump, T> {
63	fn spawn(&self, capacity: usize) -> Self {
64		Self {
65			inner: BumpaloVec::with_capacity_in(capacity, self.bump()),
66		}
67	}
68
69	fn push(&mut self, value: T) {
70		self.inner.push(value);
71	}
72
73	fn clear(&mut self) {
74		self.inner.clear();
75	}
76
77	fn len(&self) -> usize {
78		self.inner.len()
79	}
80
81	fn as_slice(&self) -> &[T] {
82		self.inner.as_slice()
83	}
84
85	fn get(&self, idx: usize) -> Option<&T> {
86		self.inner.get(idx)
87	}
88
89	fn extend_from_slice(&mut self, other: &[T]) {
90		self.inner.extend(other.iter().cloned());
91	}
92
93	fn extend_iter(&mut self, iter: impl Iterator<Item = T>) {
94		self.inner.extend(iter);
95	}
96
97	fn capacity(&self) -> usize {
98		self.inner.capacity()
99	}
100}
101
102pub struct BumpBitVec<'bump> {
103	bits: BumpaloVec<'bump, u8>,
104	len: usize,
105}
106
107impl<'bump> Debug for BumpBitVec<'bump> {
108	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109		f.debug_struct("BumpBitVec").field("len", &self.len).finish()
110	}
111}
112
113impl<'bump> BumpBitVec<'bump> {
114	pub fn with_capacity_in(capacity: usize, bump: &'bump BumpAlloc) -> Self {
115		let byte_capacity = (capacity + 7) / 8;
116		Self {
117			bits: BumpaloVec::with_capacity_in(byte_capacity, bump),
118			len: 0,
119		}
120	}
121
122	fn bump(&self) -> &'bump BumpAlloc {
123		self.bits.bump()
124	}
125}
126
127impl<'bump> Clone for BumpBitVec<'bump> {
128	fn clone(&self) -> Self {
129		let mut new_bits = BumpaloVec::with_capacity_in(self.bits.len(), self.bump());
130		new_bits.extend(self.bits.iter().copied());
131		Self {
132			bits: new_bits,
133			len: self.len,
134		}
135	}
136}
137
138impl<'bump> PartialEq for BumpBitVec<'bump> {
139	fn eq(&self, other: &Self) -> bool {
140		if self.len != other.len {
141			return false;
142		}
143		// Compare full bytes
144		let full_bytes = self.len / 8;
145		if self.bits[..full_bytes] != other.bits[..full_bytes] {
146			return false;
147		}
148		// Compare remaining bits in last partial byte
149		let remainder = self.len % 8;
150		if remainder > 0 {
151			let mask = (1u8 << remainder) - 1;
152			let a = self.bits[full_bytes] & mask;
153			let b = other.bits[full_bytes] & mask;
154			if a != b {
155				return false;
156			}
157		}
158		true
159	}
160}
161
162impl<'bump> DataBitVec for BumpBitVec<'bump> {
163	fn spawn(&self, capacity: usize) -> Self {
164		BumpBitVec::with_capacity_in(capacity, self.bump())
165	}
166
167	fn push(&mut self, bit: bool) {
168		let byte_index = self.len / 8;
169		let bit_index = self.len % 8;
170
171		if byte_index >= self.bits.len() {
172			self.bits.push(0);
173		}
174
175		if bit {
176			self.bits[byte_index] |= 1 << bit_index;
177		}
178
179		self.len += 1;
180	}
181
182	fn get(&self, idx: usize) -> bool {
183		assert!(idx < self.len);
184		let byte = self.bits[idx / 8];
185		let bit = idx % 8;
186		(byte >> bit) & 1 != 0
187	}
188
189	fn set(&mut self, idx: usize, value: bool) {
190		assert!(idx < self.len);
191		let byte = &mut self.bits[idx / 8];
192		let bit = idx % 8;
193		if value {
194			*byte |= 1 << bit;
195		} else {
196			*byte &= !(1 << bit);
197		}
198	}
199
200	fn len(&self) -> usize {
201		self.len
202	}
203
204	fn clear(&mut self) {
205		self.bits.clear();
206		self.len = 0;
207	}
208
209	fn extend_from(&mut self, other: &Self) {
210		for i in 0..other.len {
211			self.push(DataBitVec::get(other, i));
212		}
213	}
214
215	fn count_ones(&self) -> usize {
216		let mut count: usize = self.bits.iter().map(|&byte: &u8| byte.count_ones() as usize).sum();
217
218		// Adjust for partial last byte
219		let full_bytes = self.len / 8;
220		let remainder_bits = self.len % 8;
221
222		if remainder_bits > 0 && full_bytes < self.bits.len() {
223			let last_byte = self.bits[full_bytes];
224			let mask = (1u8 << remainder_bits) - 1;
225			count -= (last_byte & !mask).count_ones() as usize;
226		}
227
228		count
229	}
230
231	fn iter(&self) -> impl Iterator<Item = bool> + '_ {
232		(0..self.len).map(|i| {
233			let byte = self.bits[i / 8];
234			let bit = i % 8;
235			(byte >> bit) & 1 != 0
236		})
237	}
238
239	fn capacity(&self) -> usize {
240		self.bits.capacity() * 8
241	}
242}
243
244#[derive(Clone)]
245pub struct Bump<'bump>(&'bump BumpAlloc);
246
247impl<'bump> Bump<'bump> {
248	pub fn new(bump: &'bump BumpAlloc) -> Self {
249		Self(bump)
250	}
251
252	pub fn inner(&self) -> &'bump BumpAlloc {
253		self.0
254	}
255}
256
257impl<'bump> Storage for Bump<'bump> {
258	type Vec<T: Clone + PartialEq + 'static> = BumpVec<'bump, T>;
259	type BitVec = BumpBitVec<'bump>;
260}
261
262pub struct QueryArena {
263	bump: BumpAlloc,
264}
265
266impl QueryArena {
267	pub fn new() -> Self {
268		Self {
269			bump: BumpAlloc::with_capacity(64 * 1024),
270		}
271	}
272
273	pub fn reset(&mut self) {
274		self.bump.reset();
275	}
276
277	pub fn bump(&self) -> &BumpAlloc {
278		&self.bump
279	}
280}
281
282impl Default for QueryArena {
283	fn default() -> Self {
284		Self::new()
285	}
286}
287
288#[cfg(test)]
289mod tests {
290	use reifydb_type::storage::{DataBitVec, DataVec};
291
292	use super::*;
293
294	mod bump_vec {
295		use super::*;
296
297		#[test]
298		fn test_push_and_get() {
299			let bump = BumpAlloc::new();
300			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
301			v.push(10);
302			v.push(20);
303			v.push(30);
304
305			assert_eq!(DataVec::len(&v), 3);
306			assert_eq!(DataVec::get(&v, 0), Some(&10));
307			assert_eq!(DataVec::get(&v, 1), Some(&20));
308			assert_eq!(DataVec::get(&v, 2), Some(&30));
309			assert_eq!(DataVec::get(&v, 3), None);
310		}
311
312		#[test]
313		fn test_extend_from_slice() {
314			let bump = BumpAlloc::new();
315			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(8, &bump);
316			v.push(1);
317			DataVec::extend_from_slice(&mut v, &[2, 3, 4]);
318			assert_eq!(v.as_slice(), &[1, 2, 3, 4]);
319		}
320
321		#[test]
322		fn test_spawn() {
323			let bump = BumpAlloc::new();
324			let v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
325			let v2 = DataVec::<i32>::spawn(&v, 8);
326			assert_eq!(DataVec::len(&v2), 0);
327			assert!(DataVec::capacity(&v2) >= 8);
328		}
329
330		#[test]
331		fn test_clone() {
332			let bump = BumpAlloc::new();
333			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
334			v.push(1);
335			v.push(2);
336
337			let v2 = v.clone();
338			assert_eq!(v.as_slice(), v2.as_slice());
339		}
340
341		#[test]
342		fn test_clear() {
343			let bump = BumpAlloc::new();
344			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
345			v.push(1);
346			v.push(2);
347			DataVec::clear(&mut v);
348			assert_eq!(DataVec::len(&v), 0);
349		}
350
351		#[test]
352		fn test_deref() {
353			let bump = BumpAlloc::new();
354			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
355			v.push(10);
356			v.push(20);
357			let slice: &[i32] = &*v;
358			assert_eq!(slice, &[10, 20]);
359		}
360
361		#[test]
362		fn test_eq() {
363			let bump = BumpAlloc::new();
364			let mut v1: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
365			v1.push(1);
366			v1.push(2);
367
368			let mut v2: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
369			v2.push(1);
370			v2.push(2);
371
372			assert_eq!(v1, v2);
373
374			v2.push(3);
375			assert_ne!(v1, v2);
376		}
377
378		#[test]
379		fn test_take() {
380			let bump = BumpAlloc::new();
381			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, &bump);
382			v.push(10);
383			v.push(20);
384			v.push(30);
385
386			let taken = DataVec::take(&v, 2);
387			assert_eq!(taken.as_slice(), &[10, 20]);
388
389			let taken_all = DataVec::take(&v, 5);
390			assert_eq!(taken_all.as_slice(), &[10, 20, 30]);
391		}
392	}
393
394	mod bump_bitvec {
395		use super::*;
396
397		#[test]
398		fn test_push_and_get() {
399			let bump = BumpAlloc::new();
400			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
401			bv.push(true);
402			bv.push(false);
403			bv.push(true);
404
405			assert_eq!(DataBitVec::len(&bv), 3);
406			assert!(DataBitVec::get(&bv, 0));
407			assert!(!DataBitVec::get(&bv, 1));
408			assert!(DataBitVec::get(&bv, 2));
409		}
410
411		#[test]
412		fn test_set() {
413			let bump = BumpAlloc::new();
414			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
415			bv.push(false);
416			bv.push(false);
417			bv.push(false);
418
419			DataBitVec::set(&mut bv, 1, true);
420			assert!(!DataBitVec::get(&bv, 0));
421			assert!(DataBitVec::get(&bv, 1));
422			assert!(!DataBitVec::get(&bv, 2));
423
424			DataBitVec::set(&mut bv, 1, false);
425			assert!(!DataBitVec::get(&bv, 1));
426		}
427
428		#[test]
429		fn test_cross_byte_boundary() {
430			let bump = BumpAlloc::new();
431			let mut bv = BumpBitVec::with_capacity_in(16, &bump);
432			for i in 0..17 {
433				bv.push(i % 3 == 0);
434			}
435
436			assert_eq!(DataBitVec::len(&bv), 17);
437			for i in 0..17 {
438				assert_eq!(DataBitVec::get(&bv, i), i % 3 == 0, "mismatch at bit {}", i);
439			}
440		}
441
442		#[test]
443		fn test_count_ones() {
444			let bump = BumpAlloc::new();
445			let mut bv = BumpBitVec::with_capacity_in(16, &bump);
446			bv.push(true);
447			bv.push(false);
448			bv.push(true);
449			bv.push(false);
450			bv.push(true);
451
452			assert_eq!(DataBitVec::count_ones(&bv), 3);
453			assert_eq!(DataBitVec::count_zeros(&bv), 2);
454		}
455
456		#[test]
457		fn test_count_ones_cross_byte() {
458			let bump = BumpAlloc::new();
459			let mut bv = BumpBitVec::with_capacity_in(16, &bump);
460			for i in 0..17 {
461				bv.push(i % 3 == 0);
462			}
463			let expected = (0..17).filter(|&i| i % 3 == 0).count();
464			assert_eq!(DataBitVec::count_ones(&bv), expected);
465		}
466
467		#[test]
468		fn test_extend_from() {
469			let bump = BumpAlloc::new();
470			let mut bv1 = BumpBitVec::with_capacity_in(8, &bump);
471			bv1.push(true);
472			bv1.push(false);
473
474			let mut bv2 = BumpBitVec::with_capacity_in(8, &bump);
475			bv2.push(false);
476			bv2.push(true);
477
478			DataBitVec::extend_from(&mut bv1, &bv2);
479			assert_eq!(DataBitVec::len(&bv1), 4);
480			assert!(DataBitVec::get(&bv1, 0));
481			assert!(!DataBitVec::get(&bv1, 1));
482			assert!(!DataBitVec::get(&bv1, 2));
483			assert!(DataBitVec::get(&bv1, 3));
484		}
485
486		#[test]
487		fn test_clone() {
488			let bump = BumpAlloc::new();
489			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
490			bv.push(true);
491			bv.push(false);
492			bv.push(true);
493
494			let bv2 = bv.clone();
495			assert_eq!(DataBitVec::len(&bv2), 3);
496			assert!(DataBitVec::get(&bv2, 0));
497			assert!(!DataBitVec::get(&bv2, 1));
498			assert!(DataBitVec::get(&bv2, 2));
499		}
500
501		#[test]
502		fn test_clear() {
503			let bump = BumpAlloc::new();
504			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
505			bv.push(true);
506			bv.push(false);
507			DataBitVec::clear(&mut bv);
508			assert_eq!(DataBitVec::len(&bv), 0);
509		}
510
511		#[test]
512		fn test_spawn() {
513			let bump = BumpAlloc::new();
514			let bv = BumpBitVec::with_capacity_in(8, &bump);
515			let bv2 = DataBitVec::spawn(&bv, 16);
516			assert_eq!(DataBitVec::len(&bv2), 0);
517			assert!(DataBitVec::capacity(&bv2) >= 16);
518		}
519
520		#[test]
521		fn test_iter() {
522			let bump = BumpAlloc::new();
523			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
524			bv.push(true);
525			bv.push(false);
526			bv.push(true);
527			bv.push(false);
528
529			let collected: Vec<bool> = DataBitVec::iter(&bv).collect();
530			assert_eq!(collected, vec![true, false, true, false]);
531		}
532
533		#[test]
534		fn test_eq() {
535			let bump = BumpAlloc::new();
536			let mut bv1 = BumpBitVec::with_capacity_in(8, &bump);
537			bv1.push(true);
538			bv1.push(false);
539
540			let mut bv2 = BumpBitVec::with_capacity_in(8, &bump);
541			bv2.push(true);
542			bv2.push(false);
543
544			assert_eq!(bv1, bv2);
545
546			bv2.push(true);
547			assert_ne!(bv1, bv2);
548		}
549
550		#[test]
551		fn test_take() {
552			let bump = BumpAlloc::new();
553			let mut bv = BumpBitVec::with_capacity_in(8, &bump);
554			bv.push(true);
555			bv.push(false);
556			bv.push(true);
557
558			let taken = DataBitVec::take(&bv, 2);
559			assert_eq!(DataBitVec::len(&taken), 2);
560			assert!(DataBitVec::get(&taken, 0));
561			assert!(!DataBitVec::get(&taken, 1));
562
563			let taken_all = DataBitVec::take(&bv, 5);
564			assert_eq!(DataBitVec::len(&taken_all), 3);
565		}
566	}
567
568	mod bump_storage {
569		use reifydb_type::value::container::{bool::BoolContainer, number::NumberContainer};
570
571		use super::*;
572
573		#[test]
574		fn test_number_container_with_bump() {
575			let bump_alloc = BumpAlloc::new();
576			let data = BumpVec::with_capacity_in(4, &bump_alloc);
577			let mut container: NumberContainer<i32, Bump<'_>> = NumberContainer::from_parts(data);
578
579			container.push(42);
580			container.push(99);
581
582			assert_eq!(container.len(), 2);
583			assert_eq!(container.get(0), Some(&42));
584			assert_eq!(container.get(1), Some(&99));
585		}
586
587		#[test]
588		fn test_bool_container_with_bump() {
589			let bump_alloc = BumpAlloc::new();
590			let data = BumpBitVec::with_capacity_in(4, &bump_alloc);
591			let mut container: BoolContainer<Bump<'_>> = BoolContainer::from_parts(data);
592
593			container.push(true);
594			container.push(false);
595			container.push_default();
596
597			assert_eq!(container.len(), 3);
598			assert_eq!(container.get(0), Some(true));
599			assert_eq!(container.get(1), Some(false));
600			// push_default on a bare container pushes false;
601			// nullability is tracked by the Option wrapper at the ColumnData level.
602			assert_eq!(container.get(2), Some(false));
603		}
604
605		#[test]
606		fn test_query_arena_reset() {
607			let mut arena = QueryArena::new();
608			let bump = arena.bump();
609			let mut v: BumpVec<i32> = BumpVec::with_capacity_in(4, bump);
610			v.push(1);
611			v.push(2);
612			assert_eq!(DataVec::len(&v), 2);
613
614			// After reset, the arena memory is reclaimed
615			drop(v);
616			arena.reset();
617
618			let bump = arena.bump();
619			let v2: BumpVec<i32> = BumpVec::with_capacity_in(4, bump);
620			assert_eq!(DataVec::len(&v2), 0);
621		}
622	}
623}