use alloc::vec::Vec;
#[derive(Clone, Copy)]
struct Slot {
next: u32,
prev: u32,
}
pub struct Allocator {
slots: Vec<Slot>,
head: Option<u32>,
}
impl Allocator {
pub fn new(initial_size: usize) -> Self {
let mut allocator = Allocator {
slots: Vec::new(),
head: None,
};
if initial_size > 2 {
allocator.extend(2, initial_size as u32);
} else {
allocator.slots.resize(initial_size, Slot { next: 0, prev: 0 });
}
allocator
}
pub fn extend(&mut self, old_size: u32, new_size: u32) {
if new_size <= old_size {
return;
}
self.slots.resize(new_size as usize, Slot { next: 0, prev: 0 });
let start = old_size.max(2); if start >= new_size {
return;
}
for idx in start..new_size {
self.slots[idx as usize].next = if idx + 1 < new_size { idx + 1 } else { start };
self.slots[idx as usize].prev = if idx > start { idx - 1 } else { new_size - 1 };
}
match self.head {
None => {
self.head = Some(start);
}
Some(h) => {
let old_tail = self.slots[h as usize].prev;
let new_tail = new_size - 1;
self.slots[old_tail as usize].next = start;
self.slots[start as usize].prev = old_tail;
self.slots[new_tail as usize].next = h;
self.slots[h as usize].prev = new_tail;
}
}
}
pub fn delete(&mut self, idx: u32) {
let prev = self.slots[idx as usize].prev;
let next = self.slots[idx as usize].next;
if prev == idx {
self.head = None;
} else {
self.slots[prev as usize].next = next;
self.slots[next as usize].prev = prev;
if self.head == Some(idx) {
self.head = Some(next);
}
}
}
pub fn iter(&self) -> AllocatorIter<'_> {
AllocatorIter {
slots: &self.slots,
head: self.head,
current: self.head,
}
}
}
pub struct AllocatorIter<'a> {
slots: &'a [Slot],
head: Option<u32>,
current: Option<u32>,
}
impl<'a> Iterator for AllocatorIter<'a> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
let idx = self.current?;
let next = self.slots[idx as usize].next;
self.current = if Some(next) == self.head {
None
} else {
Some(next)
};
Some(idx)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_with_initial_size() {
let alloc = Allocator::new(10);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
fn test_new_small_size() {
let alloc = Allocator::new(2);
assert_eq!(alloc.iter().count(), 0);
}
#[test]
fn test_extend() {
let mut alloc = Allocator::new(4); alloc.extend(4, 7);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![2, 3, 4, 5, 6]);
}
#[test]
fn test_extend_from_empty() {
let mut alloc = Allocator::new(2); alloc.extend(2, 5);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![2, 3, 4]);
}
#[test]
fn test_delete_middle() {
let mut alloc = Allocator::new(6);
alloc.delete(3);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![2, 4, 5]);
}
#[test]
fn test_delete_head() {
let mut alloc = Allocator::new(6);
alloc.delete(2);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![3, 4, 5]);
}
#[test]
fn test_delete_tail() {
let mut alloc = Allocator::new(6);
alloc.delete(5);
let indices: Vec<u32> = alloc.iter().collect();
assert_eq!(indices, vec![2, 3, 4]);
}
#[test]
fn test_delete_all() {
let mut alloc = Allocator::new(4);
alloc.delete(2);
alloc.delete(3);
assert_eq!(alloc.iter().count(), 0);
}
#[test]
fn test_circular_structure() {
let alloc = Allocator::new(5);
assert_eq!(alloc.slots[2].next, 3);
assert_eq!(alloc.slots[2].prev, 4);
assert_eq!(alloc.slots[4].next, 2);
assert_eq!(alloc.slots[4].prev, 3);
}
}