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