assets_manager 0.1.3

Conveniently load, store and cache external resources
Documentation
mod loaders {
    use crate::loader::*;

    fn raw(s: &str) -> Vec<u8> {
        s.to_string().into_bytes()
    }

    #[test]
    #[allow(deprecated)]
    fn string_loader() {
        let raw = raw("Hello World!");
        let loaded = StringLoader::load(raw).unwrap();

        assert_eq!(loaded, "Hello World!");
    }

    #[test]
    fn parse_loader() {
        let n = rand::random::<i32>();
        let raw = raw(&format!("{}", n));

        let loaded: i32 = ParseLoader::load(raw).unwrap();

        assert_eq!(loaded, n);
    }

    cfg_if::cfg_if! { if #[cfg(feature = "serde")] {
        use serde::{Serialize, Deserialize};
        use rand::{
            Rng,
            distributions::{Distribution, Standard},
        };

        #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
        struct Point {
            x: i32,
            y: i32,
        }

        impl Distribution<Point> for Standard {
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
                Point {
                    x: rng.gen(),
                    y: rng.gen(),
                }
            }
        }

        macro_rules! test_loader {
            ($name:ident, $loader:ty, $ser:expr) => {
                #[test]
                fn $name() {
                    let point = rand::random::<Point>();
                    let raw = ($ser)(&point).unwrap();

                    let loaded: Point = <$loader>::load(raw).unwrap();

                    assert_eq!(loaded, point);
                }
            }
        }
    }}

    #[cfg(feature = "bincode")]
    test_loader!(bincode_loader, BincodeLoader, serde_bincode::serialize);

    #[cfg(feature = "cbor")]
    test_loader!(cbor_loader, CborLoader, serde_cbor::to_vec);

    #[cfg(feature = "json")]
    test_loader!(json_loader, JsonLoader, serde_json::to_vec);

    #[cfg(feature = "msgpack")]
    test_loader!(msgpack_loader, MessagePackLoader, serde_msgpack::encode::to_vec);

    #[cfg(feature = "ron")]
    test_loader!(ron_loader, RonLoader, |p| serde_ron::ser::to_string(p).map(String::into_bytes));

    #[cfg(feature = "toml")]
    test_loader!(toml_loader, TomlLoader, serde_toml::ser::to_vec);

    #[cfg(feature = "yaml")]
    test_loader!(yaml_loader, YamlLoader, serde_yaml::to_vec);
}

mod asset_cache {
    use crate::{Asset, AssetCache, loader};

    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    struct X(i32);

    impl Asset for X {
        type Loader = loader::CustomLoader;
        const EXT: &'static str = "";
    }

    #[test]
    fn load_cached() {
        let x = X(rand::random());

        let cache = AssetCache::new("");

        assert!(cache.load_cached::<X>("").is_none());
        cache.add_asset(String::new(), x);
        assert_eq!(*cache.load_cached::<X>("").unwrap().read(), x);
    }

    #[test]
    fn take() {
        let x = X(rand::random());

        let mut cache = AssetCache::new("");

        cache.add_asset(String::new(), x);
        assert!(cache.load_cached::<X>("").is_some());
        assert_eq!(cache.take(""), Some(x));
        assert!(cache.load_cached::<X>("").is_none());
    }

    #[test]
    fn remove() {
        let x = X(rand::random());

        let mut cache = AssetCache::new("");

        cache.add_asset(String::new(), x);
        assert!(cache.load_cached::<X>("").is_some());
        cache.remove::<X>("");
        assert!(cache.load_cached::<X>("").is_none());
    }
}

mod cache_entry {
    use std::sync::Mutex;
    use crate::lock::CacheEntry;

    struct DropCounter<'a> {
        count: &'a Mutex<usize>,
    }

    impl Drop for DropCounter<'_> {
        fn drop(&mut self) {
            let mut count = self.count.lock().unwrap();
            *count += 1;
        }
    }

    #[test]
    fn drop_inner() {
        let count = &Mutex::new(0);

        let entry_1 = CacheEntry::new(DropCounter { count });
        let entry_2 = CacheEntry::new(DropCounter { count });
        assert_eq!(*count.lock().unwrap(), 0);
        drop(entry_1);
        assert_eq!(*count.lock().unwrap(), 1);
        drop(entry_2);
        assert_eq!(*count.lock().unwrap(), 2);
    }

    #[test]
    fn read() {
        let val = rand::random::<i32>();

        let entry = CacheEntry::new(val);
        let guard = unsafe { entry.get_ref::<i32>() };

        assert_eq!(*guard.read(), val);
    }

    #[test]
    fn write() {
        let x = rand::random::<i32>();
        let y = rand::random::<i32>();

        let entry = CacheEntry::new(x);
        unsafe {
            let guard = entry.write(y);
            assert_eq!(*guard.read(), y);
            let guard = entry.get_ref::<i32>();
            assert_eq!(*guard.read(), y);
        }
    }

    #[test]
    fn ptr_eq() {
        let x = rand::random::<i32>();

        let entry = CacheEntry::new(x);
        unsafe {
            let ref_1 = entry.get_ref::<i32>();
            let ref_2 = entry.get_ref::<i32>();
            assert!(ref_1.ptr_eq(&ref_2));
        }
    }
}