fyrox-core 0.23.0

Shared core for the Fyrox engine and its external crates.
Documentation
use std::{
    fmt::{Debug, Formatter},
    marker::PhantomData,
    sync::atomic::{AtomicUsize, Ordering},
};

pub struct AtomicIndex<T> {
    index: AtomicUsize,
    phantom: PhantomData<T>,
}

impl<T> Debug for AtomicIndex<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "AtomicIndex: {}", self.get())
    }
}

unsafe impl<T> Send for AtomicIndex<T> {}
unsafe impl<T> Sync for AtomicIndex<T> {}

impl<T> Clone for AtomicIndex<T> {
    fn clone(&self) -> Self {
        Self {
            index: AtomicUsize::new(self.index.load(Ordering::SeqCst)),
            phantom: PhantomData,
        }
    }
}

impl<T> Default for AtomicIndex<T> {
    fn default() -> Self {
        Self::unassigned()
    }
}

impl<T> AtomicIndex<T> {
    pub fn unassigned() -> Self {
        Self {
            index: AtomicUsize::new(usize::MAX),
            phantom: PhantomData,
        }
    }

    fn new(index: usize) -> Self {
        Self {
            index: AtomicUsize::new(index),
            phantom: PhantomData,
        }
    }

    pub fn set(&self, index: usize) {
        self.index.store(index, Ordering::SeqCst)
    }

    pub fn get(&self) -> usize {
        self.index.load(Ordering::SeqCst)
    }
}

pub struct SparseBuffer<T> {
    vec: Vec<Option<T>>,
    free: Vec<usize>,
}

impl<T> Default for SparseBuffer<T> {
    fn default() -> Self {
        Self {
            vec: Default::default(),
            free: Default::default(),
        }
    }
}

impl<T: Clone> Clone for SparseBuffer<T> {
    fn clone(&self) -> Self {
        Self {
            vec: self.vec.clone(),
            free: self.free.clone(),
        }
    }
}

impl<T> SparseBuffer<T> {
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            vec: Vec::with_capacity(capacity),
            free: vec![],
        }
    }

    pub fn spawn(&mut self, payload: T) -> AtomicIndex<T> {
        match self.free.pop() {
            Some(free) => {
                let old = self.vec[free].replace(payload);
                debug_assert!(old.is_none());
                AtomicIndex::new(free)
            }
            None => {
                let index = AtomicIndex::new(self.vec.len());
                self.vec.push(Some(payload));
                index
            }
        }
    }

    pub fn free(&mut self, index: &AtomicIndex<T>) -> Option<T> {
        self.free_raw(index.get())
    }

    pub fn free_raw(&mut self, index: usize) -> Option<T> {
        match self.vec.get_mut(index) {
            Some(entry) => match entry.take() {
                Some(payload) => {
                    self.free.push(index);
                    Some(payload)
                }
                None => None,
            },
            None => None,
        }
    }

    pub fn len(&self) -> usize {
        self.vec.len()
    }

    pub fn is_empty(&self) -> bool {
        self.filled() == 0
    }

    pub fn filled(&self) -> usize {
        self.vec.len() - self.free.len()
    }

    pub fn is_index_valid(&self, index: &AtomicIndex<T>) -> bool {
        self.get(index).is_some()
    }

    pub fn get(&self, index: &AtomicIndex<T>) -> Option<&T> {
        self.get_raw(index.get())
    }

    pub fn get_mut(&mut self, index: &AtomicIndex<T>) -> Option<&mut T> {
        self.get_mut_raw(index.get())
    }

    pub fn get_raw(&self, index: usize) -> Option<&T> {
        self.vec.get(index).and_then(|entry| entry.as_ref())
    }

    pub fn get_mut_raw(&mut self, index: usize) -> Option<&mut T> {
        self.vec.get_mut(index).and_then(|entry| entry.as_mut())
    }

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.vec.iter().filter_map(|entry| entry.as_ref())
    }

    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.vec.iter_mut().filter_map(|entry| entry.as_mut())
    }

    pub fn clear(&mut self) {
        self.vec.clear();
        self.free.clear();
    }
}