#![forbid(unsafe_code)]
use prost::alloc::{borrow::ToOwned, collections::BTreeMap, string::String, vec::Vec};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ArenaVec<T> {
inner: Vec<T>,
slab_size: usize,
}
impl<T> ArenaVec<T> {
pub fn new() -> Self {
Self::with_slab(64)
}
pub fn with_slab(slab_size: usize) -> Self {
let slab = slab_size.max(1);
Self {
inner: Vec::with_capacity(slab),
slab_size: slab,
}
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
pub fn slab_size(&self) -> usize {
self.slab_size
}
pub fn push(&mut self, value: T) {
if self.inner.len() == self.inner.capacity() {
self.inner.reserve_exact(self.slab_size);
}
self.inner.push(value);
}
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.inner.iter()
}
pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
self.inner.iter_mut()
}
pub fn as_slice(&self) -> &[T] {
self.inner.as_slice()
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.inner.as_mut_slice()
}
pub fn clear(&mut self) {
self.inner.clear();
}
pub fn into_vec(self) -> Vec<T> {
self.inner
}
pub fn from_vec(v: Vec<T>, slab_size: usize) -> Self {
Self {
inner: v,
slab_size: slab_size.max(1),
}
}
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.push(item);
}
}
pub fn reserve(&mut self, additional: usize) {
let slabs_needed = additional.div_ceil(self.slab_size);
self.inner.reserve_exact(slabs_needed * self.slab_size);
}
pub fn estimated_resizes(&self) -> usize {
if self.inner.is_empty() || self.slab_size == 0 {
return 0;
}
self.inner.len().saturating_sub(1) / self.slab_size
}
}
impl<T> core::ops::Index<usize> for ArenaVec<T> {
type Output = T;
fn index(&self, idx: usize) -> &T {
&self.inner[idx]
}
}
impl<T> core::ops::IndexMut<usize> for ArenaVec<T> {
fn index_mut(&mut self, idx: usize) -> &mut T {
&mut self.inner[idx]
}
}
impl<T> IntoIterator for ArenaVec<T> {
type Item = T;
type IntoIter = prost::alloc::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a, T> IntoIterator for &'a ArenaVec<T> {
type Item = &'a T;
type IntoIter = core::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.iter()
}
}
impl<T> From<ArenaVec<T>> for Vec<T> {
fn from(av: ArenaVec<T>) -> Vec<T> {
av.inner
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StringIndex(pub u32);
impl StringIndex {
pub fn as_usize(self) -> usize {
self.0 as usize
}
}
impl core::fmt::Display for StringIndex {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "StringIndex({})", self.0)
}
}
#[derive(Debug, Default, Clone)]
pub struct StringPool {
strings: Vec<String>,
index: BTreeMap<String, u32>,
}
impl StringPool {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
strings: Vec::with_capacity(capacity),
index: BTreeMap::new(),
}
}
pub fn intern(&mut self, s: &str) -> StringIndex {
if let Some(&idx) = self.index.get(s) {
return StringIndex(idx);
}
let idx = self.strings.len() as u32;
let owned = s.to_owned();
self.index.insert(owned.clone(), idx);
self.strings.push(owned);
StringIndex(idx)
}
pub fn get(&self, idx: StringIndex) -> &str {
&self.strings[idx.as_usize()]
}
pub fn get_checked(&self, idx: StringIndex) -> Option<&str> {
self.strings.get(idx.as_usize()).map(|s| s.as_str())
}
pub fn unique_count(&self) -> usize {
self.strings.len()
}
pub fn is_empty(&self) -> bool {
self.strings.is_empty()
}
pub fn iter(&self) -> core::slice::Iter<'_, String> {
self.strings.iter()
}
pub fn total_bytes(&self) -> usize {
self.strings.iter().map(|s| s.len()).sum()
}
pub fn clear(&mut self) {
self.strings.clear();
self.index.clear();
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BytesHandle {
pub start: usize,
pub len: usize,
}
impl BytesHandle {
pub fn is_empty(self) -> bool {
self.len == 0
}
}
#[derive(Debug, Default, Clone)]
pub struct BytesArena {
buf: Vec<u8>,
handles: Vec<BytesHandle>,
}
impl BytesArena {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity_bytes: usize, capacity_entries: usize) -> Self {
Self {
buf: Vec::with_capacity(capacity_bytes),
handles: Vec::with_capacity(capacity_entries),
}
}
pub fn append(&mut self, data: &[u8]) -> BytesHandle {
let start = self.buf.len();
self.buf.extend_from_slice(data);
let handle = BytesHandle {
start,
len: data.len(),
};
self.handles.push(handle);
handle
}
pub fn get(&self, handle: BytesHandle) -> Option<&[u8]> {
let end = handle.start.checked_add(handle.len)?;
self.buf.get(handle.start..end)
}
pub fn get_unchecked(&self, handle: BytesHandle) -> &[u8] {
&self.buf[handle.start..handle.start + handle.len]
}
pub fn entry_count(&self) -> usize {
self.handles.len()
}
pub fn total_bytes(&self) -> usize {
self.buf.len()
}
pub fn is_empty(&self) -> bool {
self.handles.is_empty()
}
pub fn handles(&self) -> core::slice::Iter<'_, BytesHandle> {
self.handles.iter()
}
pub fn iter(&self) -> BytesArenaIter<'_> {
BytesArenaIter {
arena: self,
pos: 0,
}
}
pub fn into_parts(self) -> (Vec<u8>, Vec<BytesHandle>) {
(self.buf, self.handles)
}
pub fn clear(&mut self) {
self.buf.clear();
self.handles.clear();
}
pub fn reserve(&mut self, additional_bytes: usize, additional_entries: usize) {
self.buf.reserve(additional_bytes);
self.handles.reserve(additional_entries);
}
}
pub struct BytesArenaIter<'a> {
arena: &'a BytesArena,
pos: usize,
}
impl<'a> Iterator for BytesArenaIter<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<&'a [u8]> {
if self.pos >= self.arena.handles.len() {
return None;
}
let handle = self.arena.handles[self.pos];
self.pos += 1;
self.arena.get(handle)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.arena.handles.len() - self.pos;
(remaining, Some(remaining))
}
}
impl<'a> ExactSizeIterator for BytesArenaIter<'a> {}
#[derive(Debug, Default)]
pub struct ArenaDecoder<T> {
pub elements: ArenaVec<T>,
pub bytes_store: BytesArena,
}
impl<T> ArenaDecoder<T> {
pub fn new(slab_size: usize, bytes_capacity: usize) -> Self {
Self {
elements: ArenaVec::with_slab(slab_size),
bytes_store: BytesArena::with_capacity(bytes_capacity, slab_size),
}
}
pub fn push_element(&mut self, elem: T) {
self.elements.push(elem);
}
pub fn append_bytes(&mut self, data: &[u8]) -> BytesHandle {
self.bytes_store.append(data)
}
pub fn element_count(&self) -> usize {
self.elements.len()
}
pub fn clear(&mut self) {
self.elements.clear();
self.bytes_store.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arena_vec_new_starts_empty() {
let v: ArenaVec<i32> = ArenaVec::new();
assert!(v.is_empty());
assert_eq!(v.len(), 0);
}
#[test]
fn arena_vec_push_and_index() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
for i in 0..10i32 {
v.push(i);
}
assert_eq!(v.len(), 10);
assert_eq!(v[0], 0);
assert_eq!(v[9], 9);
}
#[test]
fn arena_vec_slab_growth() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
assert_eq!(v.capacity(), 4);
for i in 0..4 {
v.push(i);
}
assert_eq!(v.capacity(), 4); v.push(4);
assert_eq!(v.capacity(), 8); }
#[test]
fn arena_vec_clear_retains_capacity() {
let mut v: ArenaVec<String> = ArenaVec::with_slab(8);
for _ in 0..8 {
v.push("hello".to_owned());
}
let cap = v.capacity();
v.clear();
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), cap);
}
#[test]
fn arena_vec_extend() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(2);
v.extend([1, 2, 3, 4, 5]);
assert_eq!(v.len(), 5);
assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5]);
}
#[test]
fn arena_vec_into_vec() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
v.push(1);
v.push(2);
let plain: Vec<i32> = v.into_vec();
assert_eq!(plain, vec![1, 2]);
}
#[test]
fn arena_vec_from_vec() {
let plain = vec![10, 20, 30];
let av = ArenaVec::from_vec(plain.clone(), 8);
assert_eq!(av.len(), plain.len());
assert_eq!(av.as_slice(), plain.as_slice());
}
#[test]
fn arena_vec_iter() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
v.push(7);
v.push(8);
let collected: Vec<i32> = v.iter().copied().collect();
assert_eq!(collected, vec![7, 8]);
}
#[test]
fn arena_vec_reserve() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
v.reserve(12);
assert!(v.capacity() >= 12);
}
#[test]
fn arena_vec_estimated_resizes_zero_when_empty() {
let v: ArenaVec<i32> = ArenaVec::with_slab(4);
assert_eq!(v.estimated_resizes(), 0);
}
#[test]
fn arena_vec_into_iter() {
let mut v: ArenaVec<i32> = ArenaVec::with_slab(4);
v.push(1);
v.push(2);
v.push(3);
let sum: i32 = v.into_iter().sum();
assert_eq!(sum, 6);
}
#[test]
fn string_pool_intern_unique() {
let mut pool = StringPool::new();
let a = pool.intern("hello");
let b = pool.intern("world");
assert_ne!(a, b);
assert_eq!(pool.unique_count(), 2);
}
#[test]
fn string_pool_intern_dedup() {
let mut pool = StringPool::new();
let a = pool.intern("admin");
let b = pool.intern("admin");
assert_eq!(a, b);
assert_eq!(pool.unique_count(), 1);
}
#[test]
fn string_pool_get_correct_value() {
let mut pool = StringPool::new();
let idx = pool.intern("oxiproto");
assert_eq!(pool.get(idx), "oxiproto");
}
#[test]
fn string_pool_get_checked_none_for_oob() {
let pool = StringPool::new();
assert!(pool.get_checked(StringIndex(99)).is_none());
}
#[test]
fn string_pool_total_bytes() {
let mut pool = StringPool::new();
pool.intern("abc");
pool.intern("de");
assert_eq!(pool.total_bytes(), 5);
}
#[test]
fn string_pool_clear() {
let mut pool = StringPool::new();
pool.intern("foo");
pool.intern("bar");
pool.clear();
assert!(pool.is_empty());
assert_eq!(pool.unique_count(), 0);
}
#[test]
fn string_pool_iter_order() {
let mut pool = StringPool::new();
pool.intern("c");
pool.intern("a");
pool.intern("b");
let words: Vec<&str> = pool.iter().map(|s| s.as_str()).collect();
assert_eq!(words, vec!["c", "a", "b"]);
}
#[test]
fn string_pool_with_capacity_no_panic() {
let mut pool = StringPool::with_capacity(16);
for i in 0..20u32 {
pool.intern(&prost::alloc::format!("str_{i}"));
}
assert_eq!(pool.unique_count(), 20);
}
#[test]
fn bytes_arena_append_and_get() {
let mut arena = BytesArena::new();
let h1 = arena.append(b"hello");
let h2 = arena.append(b"world");
assert_eq!(arena.get(h1), Some(b"hello".as_ref()));
assert_eq!(arena.get(h2), Some(b"world".as_ref()));
}
#[test]
fn bytes_arena_entry_count_and_total() {
let mut arena = BytesArena::new();
arena.append(b"abc");
arena.append(b"de");
assert_eq!(arena.entry_count(), 2);
assert_eq!(arena.total_bytes(), 5);
}
#[test]
fn bytes_arena_iter() {
let mut arena = BytesArena::new();
arena.append(b"x");
arena.append(b"yy");
arena.append(b"zzz");
let slices: Vec<&[u8]> = arena.iter().collect();
assert_eq!(slices, vec![b"x".as_ref(), b"yy".as_ref(), b"zzz".as_ref()]);
}
#[test]
fn bytes_arena_iter_exact_size() {
let mut arena = BytesArena::new();
arena.append(b"a");
arena.append(b"b");
let it = arena.iter();
assert_eq!(it.len(), 2);
}
#[test]
fn bytes_arena_get_stale_handle_returns_none() {
let mut arena = BytesArena::new();
let h = arena.append(b"abc");
arena.clear();
assert!(arena.get(h).is_none());
}
#[test]
fn bytes_arena_clear_resets() {
let mut arena = BytesArena::new();
arena.append(b"data");
arena.clear();
assert!(arena.is_empty());
assert_eq!(arena.total_bytes(), 0);
assert_eq!(arena.entry_count(), 0);
}
#[test]
fn bytes_arena_handle_is_empty() {
let mut arena = BytesArena::new();
let h_empty = arena.append(&[]);
let h_nonempty = arena.append(b"a");
assert!(h_empty.is_empty());
assert!(!h_nonempty.is_empty());
}
#[test]
fn bytes_arena_get_unchecked() {
let mut arena = BytesArena::new();
let h = arena.append(b"test");
assert_eq!(arena.get_unchecked(h), b"test");
}
#[test]
fn bytes_arena_reserve() {
let mut arena = BytesArena::new();
arena.reserve(1024, 32);
assert!(arena.is_empty());
}
#[test]
fn bytes_arena_into_parts() {
let mut arena = BytesArena::new();
arena.append(b"abc");
let (buf, handles) = arena.into_parts();
assert_eq!(&buf[..3], b"abc");
assert_eq!(handles.len(), 1);
assert_eq!(handles[0].start, 0);
assert_eq!(handles[0].len, 3);
}
#[test]
fn bytes_arena_handles_iter() {
let mut arena = BytesArena::new();
arena.append(b"a");
arena.append(b"bb");
let hs: Vec<BytesHandle> = arena.handles().copied().collect();
assert_eq!(hs.len(), 2);
assert_eq!(hs[0].len, 1);
assert_eq!(hs[1].len, 2);
}
#[test]
fn arena_decoder_push_and_count() {
let mut dec: ArenaDecoder<i32> = ArenaDecoder::new(8, 64);
dec.push_element(1);
dec.push_element(2);
dec.push_element(3);
assert_eq!(dec.element_count(), 3);
}
#[test]
fn arena_decoder_append_bytes() {
let mut dec: ArenaDecoder<BytesHandle> = ArenaDecoder::new(8, 64);
let h = dec.append_bytes(b"payload");
dec.push_element(h);
assert_eq!(dec.element_count(), 1);
let stored = dec.bytes_store.get(h).expect("handle valid");
assert_eq!(stored, b"payload");
}
#[test]
fn arena_decoder_clear() {
let mut dec: ArenaDecoder<i32> = ArenaDecoder::new(4, 32);
dec.push_element(99);
dec.clear();
assert_eq!(dec.element_count(), 0);
}
#[test]
fn arena_vec_of_string_indices() {
let mut pool = StringPool::new();
let mut indices: ArenaVec<StringIndex> = ArenaVec::with_slab(4);
let data = ["alpha", "beta", "alpha", "gamma", "beta", "alpha"];
for s in &data {
let idx = pool.intern(s);
indices.push(idx);
}
assert_eq!(indices.len(), data.len());
assert_eq!(pool.unique_count(), 3);
let alpha_idx = pool.intern("alpha");
for (i, &idx) in indices.iter().enumerate() {
if data[i] == "alpha" {
assert_eq!(idx, alpha_idx);
}
}
}
#[test]
fn bytes_arena_large_payload() {
let mut arena = BytesArena::with_capacity(8192, 16);
let payload: Vec<u8> = (0u8..=255).cycle().take(1000).collect();
let h = arena.append(&payload);
assert_eq!(arena.get(h), Some(payload.as_slice()));
}
#[test]
fn arena_vec_min_slab_one() {
let mut v: ArenaVec<u8> = ArenaVec::with_slab(0);
assert_eq!(v.slab_size(), 1);
v.push(42);
assert_eq!(v[0], 42);
}
}