assets 0.3.0

asynchronous asset management
Documentation
use std::ptr;
use std::sync::{Arc, Mutex};

use hibitset::BitSetLike;

pub struct Storage<T> {
    vec: Vec<Arc<T>>,
    len: Mutex<usize>,
}

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

impl<T> Default for Storage<T> {
    #[inline]
    fn default() -> Self {
        Storage {
            vec: Vec::default(),
            len: Mutex::new(0),
        }
    }
}

impl<T> Storage<T> {
    #[inline]
    unsafe fn vec_as_mut(&self) -> &mut Vec<Arc<T>> {
        &mut *(&self.vec as *const Vec<Arc<T>> as *mut Vec<Arc<T>>)
    }

    pub unsafe fn clean<B>(&self, has: B)
    where
        B: BitSetLike,
    {
        match self.len.lock() {
            Ok(mut len) => {
                let mut vec = self.vec_as_mut();

                for (i, v) in vec.iter_mut().enumerate() {
                    if has.contains(i as u32) {
                        ptr::drop_in_place(v);
                    }
                }
                vec.set_len(0);
                *len = 0;
            }
            Err(_) => (),
        }
    }

    #[inline]
    pub unsafe fn reserve(&self, index: usize) {
        match self.len.lock() {
            Ok(mut len) => {
                if *len <= index {
                    let vec = self.vec_as_mut();
                    let new_len = index + 1;
                    let delta = new_len - vec.len();

                    vec.reserve(delta);
                    vec.set_len(new_len);
                    *len = new_len;
                }
            }
            Err(_) => (),
        }
    }

    #[inline]
    pub unsafe fn insert(&self, id: u32, value: T) {
        let index = id as usize;

        match self.len.lock() {
            Ok(_) => {
                ptr::write(self.get_unchecked_mut(index), Arc::new(value));
            }
            Err(_) => (),
        }
    }

    #[inline]
    pub unsafe fn remove(&self, id: u32) -> Arc<T> {
        ptr::read(self.get_unchecked(id as usize))
    }

    #[inline]
    pub unsafe fn get_unchecked(&self, index: usize) -> &Arc<T> {
        self.vec.get_unchecked(index)
    }

    #[inline]
    pub unsafe fn get_unchecked_mut(&self, index: usize) -> &mut Arc<T> {
        self.vec_as_mut().get_unchecked_mut(index)
    }

    #[inline]
    pub fn get(&self, id: u32) -> Option<Arc<T>> {
        let index = id as usize;

        if index < self.vec.len() {
            Some(unsafe { self.get_unchecked(index).clone() })
        } else {
            None
        }
    }
}