#![allow(clippy::from_over_into)]
use std::{
fmt::Debug,
ops::{Deref, DerefMut},
sync::atomic::{AtomicUsize, Ordering},
};
#[cfg(not(feature = "atomic"))]
pub type Index = std::rc::Rc<AtomicUsize>;
#[cfg(feature = "atomic")]
pub type Index = std::sync::Arc<AtomicUsize>;
#[derive(Debug)]
pub struct ValueIndex(pub(crate) Index);
#[cfg(feature = "clone")]
impl Clone for ValueIndex {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl Into<Index> for ValueIndex {
fn into(self) -> Index {
self.0
}
}
pub struct Value<T> {
data: T,
index: Index,
}
impl<'a, T> Into<ValueRef<'a, T>> for &'a Value<T> {
fn into(self) -> ValueRef<'a, T> {
ValueRef {
data: &self.data,
index: &self.index,
}
}
}
#[cfg(feature = "clone")]
impl<T> Into<Index> for Value<T> {
fn into(self) -> Index {
self.index
}
}
impl<T> Deref for Value<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> DerefMut for Value<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<T: Debug> Debug for Value<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", self.data))
}
}
pub struct ValueRef<'a, T> {
data: &'a T,
#[allow(dead_code)]
index: &'a Index,
}
#[cfg(feature = "clone")]
impl<'a, T> Into<ValueIndex> for ValueRef<'a, T> {
fn into(self) -> ValueIndex {
ValueIndex(self.index.clone())
}
}
impl<'a, T> Deref for ValueRef<'a, T> {
type Target = &'a T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<'a, T> DerefMut for ValueRef<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<'a, T: Debug> Debug for ValueRef<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", self.data))
}
}
#[derive(Clone, Debug)]
struct Capacity {
original: usize,
current: usize,
}
impl Capacity {
const fn new(original: usize) -> Self {
Self {
original,
current: original,
}
}
pub fn shrink(&mut self) {
self.current -= self.original;
}
pub fn grow(&mut self) {
self.current += self.original;
}
}
#[derive(Debug)]
pub struct Bucket<T> {
data: Vec<Value<T>>,
capacity: Capacity,
}
impl<T> Bucket<T> {
pub fn new(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity),
capacity: Capacity::new(capacity),
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub const fn capacity(&self) -> usize {
self.capacity.current
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[cfg(feature = "clone")]
pub fn iter(&self) -> impl Iterator<Item = ValueRef<'_, T>> {
self.data.iter().map(Into::into)
}
#[cfg(not(feature = "clone"))]
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.data.iter().map(|v| &v.data)
}
#[cfg(feature = "get")]
pub fn get(&self, index: &ValueIndex) -> &T {
&self.data[index.0.load(Ordering::Relaxed)].data
}
pub fn insert(&mut self, data: T) -> ValueIndex {
let n = self.len();
if n == self.capacity() {
self.grow();
}
let index_shared = Index::new(AtomicUsize::new(n));
self.data.push(Value {
data,
index: index_shared.clone(),
});
ValueIndex(index_shared)
}
#[cfg(not(feature = "clone"))]
pub fn remove(&mut self, index: impl Into<Index>) -> T {
let index = index.into().load(Ordering::Relaxed);
self._remove(index)
}
#[cfg(feature = "clone")]
pub fn remove(&mut self, index: impl Into<Index>) -> Option<T> {
let index = index.into().load(Ordering::Relaxed);
self.data.get(index).is_some().then(|| self._remove(index))
}
fn _remove(&mut self, i: usize) -> T {
let j = self.len() - 1;
if self.len() > 1 && i < j {
self.data.swap(i, j);
self.data[i].index.store(i, Ordering::Relaxed)
}
let value = {
#[cfg(test)]
{
self.data.pop().unwrap()
}
#[cfg(not(test))]
unsafe {
self.data.pop().unwrap_unchecked()
}
};
if j > 0 && j == self.capacity.current - self.capacity.original {
self.shrink()
}
value.data
}
fn grow(&mut self) {
self.capacity.grow();
self.data.reserve(self.capacity.original);
}
fn shrink(&mut self) {
self.capacity.shrink();
self.data.shrink_to(self.capacity.current);
}
}
impl<T> Default for Bucket<T> {
fn default() -> Self {
Self::new(32)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_initialization() {
let bucket = Bucket::<u8>::new(10);
assert_eq!(bucket.len(), 0);
assert!(bucket.is_empty());
}
#[test]
#[cfg(feature = "get")]
fn test_insert() {
let mut bucket = Bucket::new(2);
let idx1 = bucket.insert(42);
let idx2 = bucket.insert(43);
assert_eq!(*bucket.get(&idx1), 42);
assert_eq!(*bucket.get(&idx2), 43);
}
#[test]
fn test_remove() {
let mut bucket = Bucket::new(2);
let idx = bucket.insert(42);
let value = bucket.remove(idx);
#[cfg(not(feature = "clone"))]
assert_eq!(value, 42);
#[cfg(feature = "clone")]
assert_eq!(value, Some(42));
assert!(bucket.is_empty());
}
#[test]
fn test_capacity_growth() {
let mut bucket = Bucket::new(2);
bucket.insert(1);
bucket.insert(2);
bucket.insert(3); assert_eq!(bucket.len(), 3);
}
#[test]
fn test_capacity_shrink() {
let mut bucket = Bucket::new(10);
for i in 0..10 {
bucket.insert(i);
}
bucket.capacity.shrink();
assert_eq!(bucket.capacity(), 0);
}
#[test]
#[cfg(feature = "get")]
fn test_edge_cases() {
let mut bucket = Bucket::new(1);
let idx = bucket.insert(10);
assert_eq!(*bucket.get(&idx), 10);
bucket.remove(idx);
assert!(bucket.is_empty());
}
#[cfg(not(feature = "clone"))]
#[test]
#[should_panic]
fn test_remove_empty() {
let mut bucket = Bucket::new(1);
let idx = bucket.insert(1);
let idx_clone = ValueIndex(idx.0.clone());
bucket.remove(idx);
bucket.remove(idx_clone); }
#[cfg(feature = "clone")]
#[test]
fn test_remove_empty() {
let mut bucket = Bucket::new(1);
let idx = bucket.insert(1);
let idx_clone = ValueIndex(idx.0.clone());
bucket.remove(idx);
assert_eq!(bucket.remove(idx_clone), None)
}
#[test]
fn test_capacity_management() {
let mut bucket = Bucket::new(2);
let a = bucket.insert(1);
let b = bucket.insert(2);
let c = bucket.insert(3);
assert_eq!(bucket.capacity(), 4);
assert_eq!(bucket.len(), 3);
bucket.remove(a);
bucket.remove(b);
bucket.remove(c);
assert_eq!(bucket.capacity(), 2);
}
#[test]
fn test_iter_after_removal() {
let mut bucket = Bucket::new(5);
let idx1 = bucket.insert(1);
_ = bucket.insert(2);
bucket.remove(idx1);
#[cfg(not(feature = "clone"))]
let values: Vec<_> = bucket.iter().collect();
#[cfg(feature = "clone")]
let values: Vec<_> = bucket.iter().map(|v| v.data).collect();
assert_eq!(values, vec![&2]);
}
#[test]
#[cfg(feature = "get")]
fn test_repeated_inserts_removals() {
let mut bucket = Bucket::new(3);
for i in 0..5 {
let idx = bucket.insert(i);
assert_eq!(*bucket.get(&idx), i);
bucket.remove(idx);
}
assert!(bucket.is_empty());
}
}