ayaka-bindings 0.3.0

WASM bindings of plugins written for Ayaka.
Documentation
use crate::import;
use ayaka_bindings_types::{FileMetadata, FileSeekFrom};
use std::io::{Read, Result, Seek, SeekFrom, Write};
use vfs::{error::VfsErrorKind, *};

#[import("fs")]
extern "C" {
    fn __read_dir(path: &str) -> Option<Vec<String>>;
    fn __metadata(path: &str) -> Option<FileMetadata>;
    fn __exists(path: &str) -> bool;

    fn __open_file(path: &str) -> Option<u64>;
    fn __close_file(fd: u64);

    fn __file_read(fd: u64, ptr: i32, len: i32) -> Option<usize>;
    fn __file_seek(fd: u64, pos: FileSeekFrom) -> Option<u64>;
}

#[derive(Debug, Default)]
pub struct HostFS;

impl FileSystem for HostFS {
    fn read_dir(&self, path: &str) -> VfsResult<Box<dyn Iterator<Item = String> + Send>> {
        match __read_dir(path) {
            Some(paths) => Ok(Box::new(paths.into_iter())),
            None => Err(VfsErrorKind::FileNotFound.into()),
        }
    }

    fn create_dir(&self, _path: &str) -> VfsResult<()> {
        Err(VfsErrorKind::NotSupported.into())
    }

    fn open_file(&self, path: &str) -> VfsResult<Box<dyn SeekAndRead + Send>> {
        match __open_file(path) {
            Some(fd) => Ok(Box::new(HostFile { fd })),
            None => Err(VfsErrorKind::FileNotFound.into()),
        }
    }

    fn create_file(&self, _path: &str) -> VfsResult<Box<dyn Write + Send>> {
        Err(VfsErrorKind::NotSupported.into())
    }

    fn append_file(&self, _path: &str) -> VfsResult<Box<dyn Write + Send>> {
        Err(VfsErrorKind::NotSupported.into())
    }

    fn metadata(&self, path: &str) -> VfsResult<VfsMetadata> {
        match __metadata(path) {
            Some(meta) => Ok(meta.into()),
            None => Err(VfsErrorKind::FileNotFound.into()),
        }
    }

    fn exists(&self, path: &str) -> VfsResult<bool> {
        Ok(__exists(path))
    }

    fn remove_file(&self, _path: &str) -> VfsResult<()> {
        Err(VfsErrorKind::NotSupported.into())
    }

    fn remove_dir(&self, _path: &str) -> VfsResult<()> {
        Err(VfsErrorKind::NotSupported.into())
    }
}

#[derive(Debug)]
struct HostFile {
    fd: u64,
}

impl Read for HostFile {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        __file_read(self.fd, buf.as_mut_ptr() as _, buf.len() as _)
            .ok_or_else(|| std::io::ErrorKind::NotFound.into())
    }
}

impl Seek for HostFile {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        __file_seek(self.fd, pos.into()).ok_or_else(|| std::io::ErrorKind::NotFound.into())
    }
}

impl Drop for HostFile {
    fn drop(&mut self) {
        __close_file(self.fd)
    }
}