Skip to main content

ox_content_allocator/
lib.rs

1//! Arena allocator for Ox Content.
2//!
3//! This crate provides a high-performance arena allocator based on bumpalo,
4//! designed for efficient memory management during parsing operations.
5
6use std::ops::Deref;
7
8pub use bumpalo::Bump;
9
10/// Arena allocator wrapper for Ox Content.
11///
12/// This type wraps bumpalo's `Bump` allocator to provide fast, arena-based
13/// allocation for AST nodes and other parsing-related data structures.
14#[derive(Default)]
15pub struct Allocator {
16    bump: Bump,
17}
18
19impl Allocator {
20    /// Creates a new allocator with default capacity.
21    #[must_use]
22    pub fn new() -> Self {
23        Self { bump: Bump::new() }
24    }
25
26    /// Creates a new allocator with the specified capacity in bytes.
27    #[must_use]
28    pub fn with_capacity(capacity: usize) -> Self {
29        Self { bump: Bump::with_capacity(capacity) }
30    }
31
32    /// Returns the underlying bump allocator.
33    #[must_use]
34    pub fn bump(&self) -> &Bump {
35        &self.bump
36    }
37
38    /// Allocates a value in the arena and returns a reference to it.
39    pub fn alloc<T>(&self, val: T) -> &mut T {
40        self.bump.alloc(val)
41    }
42
43    /// Allocates a string in the arena.
44    pub fn alloc_str(&self, s: &str) -> &str {
45        self.bump.alloc_str(s)
46    }
47
48    /// Creates a new `Vec` in the arena.
49    pub fn new_vec<T>(&self) -> Vec<'_, T> {
50        Vec::new_in(&self.bump)
51    }
52
53    /// Creates a new `Vec` in the arena with the given capacity.
54    pub fn new_vec_with_capacity<T>(&self, capacity: usize) -> Vec<'_, T> {
55        Vec::with_capacity_in(capacity, &self.bump)
56    }
57
58    /// Creates a new `String` in the arena.
59    pub fn new_string(&self) -> String<'_> {
60        String::new_in(&self.bump)
61    }
62
63    /// Creates a new `String` in the arena from a `&str`.
64    pub fn new_string_from(&self, s: &str) -> String<'_> {
65        String::from_str_in(s, &self.bump)
66    }
67
68    /// Resets the allocator, freeing all allocated memory.
69    pub fn reset(&mut self) {
70        self.bump.reset();
71    }
72
73    /// Returns the total bytes allocated in this arena.
74    #[must_use]
75    pub fn allocated_bytes(&self) -> usize {
76        self.bump.allocated_bytes()
77    }
78}
79
80impl Deref for Allocator {
81    type Target = Bump;
82
83    fn deref(&self) -> &Self::Target {
84        &self.bump
85    }
86}
87
88/// A boxed value allocated in an arena.
89pub type Box<'a, T> = bumpalo::boxed::Box<'a, T>;
90
91/// A vector allocated in an arena.
92pub type Vec<'a, T> = bumpalo::collections::Vec<'a, T>;
93
94/// A string allocated in an arena.
95pub type String<'a> = bumpalo::collections::String<'a>;
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_allocator_creation() {
103        let allocator = Allocator::new();
104        assert_eq!(allocator.allocated_bytes(), 0);
105    }
106
107    #[test]
108    fn test_alloc_value() {
109        let allocator = Allocator::new();
110        let value = allocator.alloc(42);
111        assert_eq!(*value, 42);
112    }
113
114    #[test]
115    fn test_alloc_str() {
116        let allocator = Allocator::new();
117        let s = allocator.alloc_str("hello");
118        assert_eq!(s, "hello");
119    }
120
121    #[test]
122    fn test_arena_vec() {
123        let allocator = Allocator::new();
124        let mut vec = allocator.new_vec();
125        vec.push(1);
126        vec.push(2);
127        vec.push(3);
128        assert_eq!(vec.as_slice(), &[1, 2, 3]);
129    }
130
131    #[test]
132    fn test_arena_string() {
133        let allocator = Allocator::new();
134        let mut s = allocator.new_string();
135        s.push_str("hello");
136        s.push_str(" world");
137        assert_eq!(s.as_str(), "hello world");
138    }
139}