use crate::fs::{error::wasi_errno_to_io_error, File, OpenOptions, ReadDir};
use crate::{host, hostcalls, wasi, WasiCtx};
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
use std::{io, path::Path};
pub struct Dir<'ctx> {
ctx: &'ctx mut WasiCtx,
fd: wasi::__wasi_fd_t,
}
impl<'ctx> Dir<'ctx> {
pub unsafe fn from_raw_wasi_fd(ctx: &'ctx mut WasiCtx, fd: wasi::__wasi_fd_t) -> Self {
Self { ctx, fd }
}
pub fn open_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<File> {
let path = path.as_ref();
let mut fd = 0;
unimplemented!("Dir::open_file");
let ctx = self.ctx;
Ok(unsafe { File::from_raw_wasi_fd(ctx, fd) })
}
pub fn open_file_with<P: AsRef<Path>>(
&mut self,
path: P,
options: &OpenOptions,
) -> io::Result<File> {
unimplemented!("Dir::open_file_with");
}
pub fn open_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<Self> {
let path = path.as_ref();
let mut fd = 0;
unimplemented!("Dir::open_dir");
let ctx = self.ctx;
Ok(unsafe { Dir::from_raw_wasi_fd(ctx, fd) })
}
pub fn create_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<File> {
let path = path.as_ref();
let mut fd = 0;
unimplemented!("Dir::create_file");
let ctx = self.ctx;
Ok(unsafe { File::from_raw_wasi_fd(ctx, fd) })
}
pub fn read(&mut self) -> io::Result<ReadDir> {
unimplemented!("Dir::read")
}
pub fn into_read(self) -> ReadDir {
unsafe { ReadDir::from_raw_wasi_fd(self.fd) }
}
pub fn read_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<Vec<u8>> {
use io::Read;
let mut file = self.open_file(path)?;
let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
file.read_to_end(&mut bytes)?;
Ok(bytes)
}
pub fn read_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<ReadDir> {
self.open_dir(path)?.read()
}
}
impl<'ctx> Drop for Dir<'ctx> {
fn drop(&mut self) {
let _ = unsafe { hostcalls::fd_close(self.ctx, &mut [], self.fd) };
}
}
fn initial_buffer_size(file: &File) -> usize {
file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0)
}