assets 0.3.0

asynchronous asset management
Documentation
use std::io;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};

use futures::{Async, Future, Poll};

use super::Importer;

pub struct FileImporter<P>(PhantomData<P>);

unsafe impl<P> Send for FileImporter<P> {}
unsafe impl<P> Sync for FileImporter<P> {}

impl<P> Default for FileImporter<P> {
    #[inline(always)]
    fn default() -> Self {
        FileImporter(PhantomData)
    }
}

impl<P> FileImporter<P> {
    #[inline(always)]
    pub fn new() -> Self {
        Self::default()
    }
}

impl<P> Importer for FileImporter<P>
where
    P: Clone + AsRef<Path>,
{
    type Path = P;
    type Options = ();
    type Output = Vec<u8>;
    type Error = io::Error;
    type Future = FileLoadFuture;

    #[inline(always)]
    fn import(&self, path: Self::Path, _: Self::Options) -> Self::Future {
        FileLoadFuture {
            path: path.as_ref().to_path_buf(),
        }
    }
}

pub struct FileLoadFuture {
    path: PathBuf,
}

impl Future for FileLoadFuture {
    type Item = Vec<u8>;
    type Error = io::Error;

    #[cfg(not(target_os = "android"))]
    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        use std::fs;
        use std::io::Read;

        let mut file = fs::File::open(&self.path)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        Ok(Async::Ready(buf))
    }

    #[cfg(target_os = "android")]
    #[inline]
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        use android_glue::{self, AssetError};
        use std::io::{Error, ErrorKind};

        match android_glue::import_asset(&*(self.path.as_ref().to_string_lossy())) {
            Ok(buf) => Ok(Async::Ready(buf)),
            Err(asset_error) => match asset_error {
                AssetError::AssetMissing => Err(Error::new(ErrorKind::NotFound, "asset missing")),
                AssetError::EmptyBuffer => Err(Error::new(ErrorKind::InvalidData, "empty buffer")),
            },
        }
    }
}

#[test]
fn test_import() {
    use futures::Future;

    let file_importer = FileImporter::new();

    match file_importer.import("assets/crate.jpg", ()).wait() {
        Ok(_) => (),
        Err(e) => panic!("{:?}", e),
    }
}