poolshark 0.2.8

Thread safe object pool
Documentation
//! Built-in [`Poolable`] and [`IsoPoolable`] implementations.
//!
//! This module provides pooling support for standard library types:
//!
//! - **Containers**: `Vec<T>`, `VecDeque<T>`, `HashMap<K, V>`, `HashSet<K>`
//! - **Strings**: `String`
//! - **Optional containers**: `Option<T>` where `T: Poolable`
//! - **IndexMap types** (with `indexmap` feature): `IndexMap<K, V>`, `IndexSet<K>`
//!
//! You don't need to import anything from this module - the implementations are
//! automatically available when you use the pooled types.
use super::{location_id, Discriminant, IsoPoolable, Poolable};
use ahash::{AHashMap, AHashSet};
#[cfg(feature = "indexmap")]
use indexmap::{IndexMap, IndexSet};
use std::{
    cmp::Eq,
    collections::{HashMap, HashSet, VecDeque},
    default::Default,
    hash::{BuildHasher, Hash},
};

impl<K, V, R> Poolable for HashMap<K, V, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    fn empty() -> Self {
        HashMap::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        HashMap::capacity(self)
    }
}

unsafe impl<K, V, R> IsoPoolable for HashMap<K, V, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    const DISCRIMINANT: Option<Discriminant> =
        { Discriminant::new_p3::<K, V, R>(location_id!()) };
}

impl<K, V> Poolable for AHashMap<K, V>
where
    K: Hash + Eq,
{
    fn empty() -> Self {
        AHashMap::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        HashMap::capacity(self)
    }
}

unsafe impl<K, V> IsoPoolable for AHashMap<K, V>
where
    K: Hash + Eq,
{
    const DISCRIMINANT: Option<Discriminant> =
        { Discriminant::new_p2::<K, V>(location_id!()) };
}

#[cfg(feature = "indexmap")]
impl<K, V, R> Poolable for IndexMap<K, V, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    fn empty() -> Self {
        IndexMap::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        IndexMap::capacity(self)
    }
}

#[cfg(feature = "indexmap")]
unsafe impl<K, V, R> IsoPoolable for IndexMap<K, V, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    const DISCRIMINANT: Option<Discriminant> =
        { Discriminant::new_p3::<K, V, R>(location_id!()) };
}

impl<K, R> Poolable for HashSet<K, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    fn empty() -> Self {
        HashSet::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        HashSet::capacity(self)
    }
}

unsafe impl<K, R> IsoPoolable for HashSet<K, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    const DISCRIMINANT: Option<Discriminant> =
        Discriminant::new_p2::<K, R>(location_id!());
}

impl<K> Poolable for AHashSet<K>
where
    K: Hash + Eq,
{
    fn empty() -> Self {
        AHashSet::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        HashSet::capacity(self)
    }
}

unsafe impl<K> IsoPoolable for AHashSet<K>
where
    K: Hash + Eq,
{
    const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p1::<K>(location_id!());
}

#[cfg(feature = "indexmap")]
impl<K, R> Poolable for IndexSet<K, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    fn empty() -> Self {
        IndexSet::default()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        IndexSet::capacity(self)
    }
}

#[cfg(feature = "indexmap")]
unsafe impl<K, R> IsoPoolable for IndexSet<K, R>
where
    K: Hash + Eq,
    R: Default + BuildHasher,
{
    const DISCRIMINANT: Option<Discriminant> =
        Discriminant::new_p2::<K, R>(location_id!());
}

impl<T> Poolable for Vec<T> {
    fn empty() -> Self {
        Vec::new()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        Vec::capacity(self)
    }
}

unsafe impl<T> IsoPoolable for Vec<T> {
    const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p1::<T>(location_id!());
}

impl<T> Poolable for VecDeque<T> {
    fn empty() -> Self {
        VecDeque::new()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        VecDeque::capacity(self)
    }
}

unsafe impl<T> IsoPoolable for VecDeque<T> {
    const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p1::<T>(location_id!());
}

impl Poolable for String {
    fn empty() -> Self {
        String::new()
    }

    fn reset(&mut self) {
        self.clear()
    }

    fn capacity(&self) -> usize {
        self.capacity()
    }
}

unsafe impl IsoPoolable for String {
    const DISCRIMINANT: Option<Discriminant> = Discriminant::new(location_id!());
}

impl<T: Poolable> Poolable for Option<T> {
    fn empty() -> Self {
        None
    }

    fn reset(&mut self) {
        if let Some(inner) = self {
            inner.reset()
        }
    }

    fn capacity(&self) -> usize {
        self.as_ref().map(|i| i.capacity()).unwrap_or(0)
    }

    fn really_dropped(&mut self) -> bool {
        self.as_mut().map(|i| i.really_dropped()).unwrap_or(true)
    }
}