Skip to main content

proxima_core/
arena.rs

1//! Reused byte arena — append bytes, reference them by `(offset, len)`,
2//! read them back without copying. One backing allocation grown
3//! power-of-two; the store-once / reference-many shape (mirrors
4//! a consumer crate's `ByteBuffer`/`HeapBuffer`, but single-writer so no
5//! atomics). The consumer owns the reclamation policy: [`reset`] drops
6//! everything at once, which is the right primitive for a bounded
7//! in-flight window that fully drains (e.g. a per-connection retransmit
8//! buffer between quiescent points). A ring / free-list layer can sit on
9//! top when out-of-order partial reclaim is needed.
10//!
11//! [`reset`]: ByteArena::reset
12
13use alloc::vec::Vec;
14
15/// Append-only byte store addressed by `u32` offset. `data.len()` is the
16/// (zero-filled) capacity; `cursor` is the live high-water mark — bytes
17/// `[0, cursor)` are the appended payloads.
18#[derive(Debug, Default, Clone)]
19pub struct ByteArena {
20    data: Vec<u8>,
21    cursor: usize,
22}
23
24impl ByteArena {
25    /// Empty arena, no allocation until the first append.
26    #[must_use]
27    pub const fn new() -> Self {
28        Self {
29            data: Vec::new(),
30            cursor: 0,
31        }
32    }
33
34    /// Empty arena pre-grown to `capacity` so the first appends don't
35    /// re-grow.
36    #[must_use]
37    pub fn with_capacity(capacity: usize) -> Self {
38        Self {
39            data: alloc::vec![0; capacity],
40            cursor: 0,
41        }
42    }
43
44    /// Append `bytes`, returning the offset they were written at. Grows
45    /// the backing power-of-two when the bump would overflow capacity.
46    ///
47    /// # Panics
48    ///
49    /// Panics if the resulting high-water mark exceeds `u32::MAX` — the
50    /// address width of the returned offset. Callers with a bounded
51    /// window (in-flight bytes ≤ congestion window) never reach this.
52    pub fn append(&mut self, bytes: &[u8]) -> u32 {
53        let offset = self.cursor;
54        let end = offset + bytes.len();
55        assert!(
56            end <= u32::MAX as usize,
57            "byte arena exceeded u32 offset space"
58        );
59        if end > self.data.len() {
60            self.data.resize(end.next_power_of_two(), 0);
61        }
62        self.data[offset..end].copy_from_slice(bytes);
63        self.cursor = end;
64        offset as u32
65    }
66
67    /// Borrow the `len` bytes written at `offset`.
68    #[must_use]
69    pub fn read(&self, offset: u32, len: u32) -> &[u8] {
70        let start = offset as usize;
71        &self.data[start..start + len as usize]
72    }
73
74    /// Reclaim everything: the next append starts at offset 0 again. The
75    /// backing allocation is retained for reuse. Sound only when no live
76    /// `(offset, len)` reference into the arena outlives the reset.
77    pub fn reset(&mut self) {
78        self.cursor = 0;
79    }
80
81    /// Live bytes appended since the last [`reset`](Self::reset).
82    #[must_use]
83    pub fn bytes_used(&self) -> usize {
84        self.cursor
85    }
86
87    /// Retained backing capacity in bytes.
88    #[must_use]
89    pub fn capacity(&self) -> usize {
90        self.data.len()
91    }
92
93    /// True when nothing has been appended since the last reset.
94    #[must_use]
95    pub fn is_empty(&self) -> bool {
96        self.cursor == 0
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::ByteArena;
103
104    #[test]
105    fn append_returns_offsets_and_reads_back_each_payload() {
106        let mut arena = ByteArena::new();
107        let first = arena.append(b"hello");
108        let second = arena.append(b"world!");
109        assert_eq!(first, 0);
110        assert_eq!(second, 5);
111        assert_eq!(arena.read(first, 5), b"hello");
112        assert_eq!(arena.read(second, 6), b"world!");
113        assert_eq!(arena.bytes_used(), 11);
114    }
115
116    #[test]
117    fn grows_power_of_two_and_preserves_prior_payloads() {
118        let mut arena = ByteArena::with_capacity(4);
119        let a = arena.append(b"ab");
120        let b = arena.append(b"cdef"); // overflows the initial 4, forces grow
121        assert_eq!(arena.read(a, 2), b"ab");
122        assert_eq!(arena.read(b, 4), b"cdef");
123        assert!(arena.capacity().is_power_of_two());
124        assert!(arena.capacity() >= 6);
125    }
126
127    #[test]
128    fn reset_rewinds_cursor_and_keeps_capacity() {
129        let mut arena = ByteArena::new();
130        arena.append(b"some bytes");
131        let cap = arena.capacity();
132        arena.reset();
133        assert!(arena.is_empty());
134        assert_eq!(arena.bytes_used(), 0);
135        assert_eq!(arena.capacity(), cap, "reset retains the allocation");
136        // a fresh append reuses offset 0
137        assert_eq!(arena.append(b"x"), 0);
138    }
139}