stack-arena 0.12.0

A fast, stack-like arena allocator for efficient memory management, implemented in Rust.
Documentation
//! # stack-arena
//!
//! A fast, stack-like arena allocator for efficient memory management, implemented in Rust.
//!
//! ## Overview
//!
//! This library provides a set of memory allocation tools that follow a stack-like
//! (Last-In-First-Out) allocation pattern. It's designed for scenarios where performance
//! is critical and memory usage needs to be minimized with low per-allocation overhead.
//!
//! ## When to Use
//!
//! Stack-arena is ideal for scenarios where:
//!
//! - You need to allocate many small objects in sequence
//! - Objects follow a stack-like (LIFO) allocation/deallocation pattern
//! - Memory usage needs to be minimized with low per-allocation overhead
//! - Performance is critical, especially for parsers, interpreters, or compilers
//! - You want to avoid the overhead of the system allocator for short-lived objects
//!
//! ## Architecture
//!
//! The library is organized in layers:
//!
//! 1. [`Chunk`] - The lowest level, representing a contiguous region of memory
//! 2. [`BufferArena`] - Manages a single memory chunk with bump allocation
//! 3. [`StackArena`] - Manages multiple chunks with LIFO allocation/deallocation
//! 4. [`ObjectStack`] - High-level interface for building objects incrementally
//!
//! ## Features
//!
//! - Efficient allocation of variable-sized objects with minimal overhead
//! - Stack-like (LIFO) allocation and deallocation pattern
//! - Memory is managed in chunks, automatically growing when needed, with old chunks preserved to maintain pointer validity
//! - Objects can be built incrementally using `extend` and `finish` methods
//! - Implements `std::fmt::Write` for string formatting directly into objects
//! - Implements the [`Allocator`] trait for compatibility with allocation APIs
//! - Automatic chunk reuse for improved performance
//!
//! ## Usage Examples
//!
//! ### Using ObjectStack (high-level API)
//!
//! The [`ObjectStack`] provides a user-friendly interface for building and managing objects:
//!
//! ```rust
//! use stack_arena::ObjectStack;
//! use std::fmt::Write;
//!
//! let mut stack = ObjectStack::new();
//!
//! // Push a complete object
//! stack.push(b"greetings!");
//!
//! // Build an object incrementally
//! stack.extend("hello");
//! stack.extend(" ");
//! stack.extend("world");
//! write!(&mut stack, "!").unwrap();
//! let ptr = stack.finish();
//!
//! // Access the object
//! let hello_world = unsafe { std::str::from_utf8_unchecked(ptr.as_ref()) };
//! assert_eq!(hello_world, "hello world!");
//!
//! // Pop the object when done
//! stack.pop();
//! ```
//!
//! ### Using StackArena (low-level API)
//!
//! The [`StackArena`] provides more control over memory allocation:
//!
//! ```rust
//! use stack_arena::{StackArena, Allocator};
//! use std::alloc::Layout;
//!
//! // Create with default chunk size (4096 bytes)
//! let mut arena = StackArena::new();
//!
//! // Or create with a custom chunk size
//! let mut custom_arena = StackArena::with_chunk_size(8192);
//!
//! // Allocate memory
//! let layout = Layout::from_size_align(10, 1).unwrap();
//! let ptr = unsafe { arena.allocate(layout).unwrap() };
//!
//! // Use the memory...
//! unsafe { std::ptr::write_bytes(ptr.as_ptr() as *mut u8, 0xAA, 10) };
//!
//! // Deallocate when done
//! unsafe { arena.deallocate(ptr.cast(), layout) };
//! ```
//!
//! ## Performance
//!
//! The library is optimized for scenarios with many small allocations that follow
//! a stack-like pattern. Benchmarks show it significantly outperforms the system
//! allocator in these cases:
//!
//! - Up to 10x faster for consecutive small allocations
//! - Minimal overhead for allocation and deallocation
//! - Efficient memory reuse with the LIFO pattern
//! - Reduced memory fragmentation
//!
//! ## Safety
//!
//! - All returned pointers are valid until the corresponding object is deallocated
//! - Objects are stored in contiguous memory chunks
//! - Unsafe operations are used internally for performance
//! - The library follows LIFO (Last-In-First-Out) allocation pattern for efficiency
//! - Users must ensure proper memory safety when working with raw pointers

mod buffer_arena;
mod chunk;
mod error;
mod object_stack;
mod stack_arena;
mod traits;

pub use buffer_arena::BufferArena;
pub use error::AllocError;
pub use object_stack::ObjectStack;
pub use stack_arena::StackArena;
pub use traits::Allocator;

#[cfg(test)]
mod tests {
    use crate::ObjectStack;
    use std::fmt::Write;

    #[test]
    fn test_object_stack() {
        let mut stack = ObjectStack::new();

        // Test extending with string slices
        stack.extend("hello");
        stack.extend(" ");
        stack.extend("world");

        // Test Write trait implementation
        write!(&mut stack, "!").unwrap();

        // Finish and verify
        let result = unsafe { stack.finish().as_ref() };
        let expected = b"hello world!";
        assert_eq!(result, expected);
    }

    #[test]
    fn test_push_and_pop() {
        let mut stack = ObjectStack::new();

        // Push some objects
        stack.push(b"first");
        stack.push(b"second");

        // Verify length
        assert_eq!(stack.len(), 2);

        // Pop and verify
        stack.pop();
        assert_eq!(stack.len(), 1);
    }
}