use crate::bindings::filesystem::types as async_filesystem;
use crate::bindings::sync::filesystem::types as sync_filesystem;
use crate::bindings::sync::io::streams;
use crate::runtime::in_tokio;
use crate::{FsError, FsResult, WasiImpl, WasiView};
use wasmtime::component::Resource;
impl<T> sync_filesystem::Host for WasiImpl<T>
where
T: WasiView,
{
fn convert_error_code(&mut self, err: FsError) -> anyhow::Result<sync_filesystem::ErrorCode> {
Ok(async_filesystem::Host::convert_error_code(self, err)?.into())
}
fn filesystem_error_code(
&mut self,
err: Resource<streams::Error>,
) -> anyhow::Result<Option<sync_filesystem::ErrorCode>> {
Ok(async_filesystem::Host::filesystem_error_code(self, err)?.map(|e| e.into()))
}
}
impl<T> sync_filesystem::HostDescriptor for WasiImpl<T>
where
T: WasiView,
{
fn advise(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
offset: sync_filesystem::Filesize,
len: sync_filesystem::Filesize,
advice: sync_filesystem::Advice,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::advise(self, fd, offset, len, advice.into()).await
})
}
fn sync_data(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> FsResult<()> {
in_tokio(async { async_filesystem::HostDescriptor::sync_data(self, fd).await })
}
fn get_flags(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<sync_filesystem::DescriptorFlags> {
Ok(in_tokio(async { async_filesystem::HostDescriptor::get_flags(self, fd).await })?.into())
}
fn get_type(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<sync_filesystem::DescriptorType> {
Ok(in_tokio(async { async_filesystem::HostDescriptor::get_type(self, fd).await })?.into())
}
fn set_size(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
size: sync_filesystem::Filesize,
) -> FsResult<()> {
in_tokio(async { async_filesystem::HostDescriptor::set_size(self, fd, size).await })
}
fn set_times(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
atim: sync_filesystem::NewTimestamp,
mtim: sync_filesystem::NewTimestamp,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::set_times(self, fd, atim.into(), mtim.into()).await
})
}
fn read(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
len: sync_filesystem::Filesize,
offset: sync_filesystem::Filesize,
) -> FsResult<(Vec<u8>, bool)> {
in_tokio(async { async_filesystem::HostDescriptor::read(self, fd, len, offset).await })
}
fn write(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
buf: Vec<u8>,
offset: sync_filesystem::Filesize,
) -> FsResult<sync_filesystem::Filesize> {
in_tokio(async { async_filesystem::HostDescriptor::write(self, fd, buf, offset).await })
}
fn read_directory(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<Resource<sync_filesystem::DirectoryEntryStream>> {
in_tokio(async { async_filesystem::HostDescriptor::read_directory(self, fd).await })
}
fn sync(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> FsResult<()> {
in_tokio(async { async_filesystem::HostDescriptor::sync(self, fd).await })
}
fn create_directory_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path: String,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::create_directory_at(self, fd, path).await
})
}
fn stat(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<sync_filesystem::DescriptorStat> {
Ok(in_tokio(async { async_filesystem::HostDescriptor::stat(self, fd).await })?.into())
}
fn stat_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path_flags: sync_filesystem::PathFlags,
path: String,
) -> FsResult<sync_filesystem::DescriptorStat> {
Ok(in_tokio(async {
async_filesystem::HostDescriptor::stat_at(self, fd, path_flags.into(), path).await
})?
.into())
}
fn set_times_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path_flags: sync_filesystem::PathFlags,
path: String,
atim: sync_filesystem::NewTimestamp,
mtim: sync_filesystem::NewTimestamp,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::set_times_at(
self,
fd,
path_flags.into(),
path,
atim.into(),
mtim.into(),
)
.await
})
}
fn link_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
old_path_flags: sync_filesystem::PathFlags,
old_path: String,
new_descriptor: Resource<sync_filesystem::Descriptor>,
new_path: String,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::link_at(
self,
fd,
old_path_flags.into(),
old_path,
new_descriptor,
new_path,
)
.await
})
}
fn open_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path_flags: sync_filesystem::PathFlags,
path: String,
oflags: sync_filesystem::OpenFlags,
flags: sync_filesystem::DescriptorFlags,
) -> FsResult<Resource<sync_filesystem::Descriptor>> {
in_tokio(async {
async_filesystem::HostDescriptor::open_at(
self,
fd,
path_flags.into(),
path,
oflags.into(),
flags.into(),
)
.await
})
}
fn drop(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> anyhow::Result<()> {
async_filesystem::HostDescriptor::drop(self, fd)
}
fn readlink_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path: String,
) -> FsResult<String> {
in_tokio(async { async_filesystem::HostDescriptor::readlink_at(self, fd, path).await })
}
fn remove_directory_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path: String,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::remove_directory_at(self, fd, path).await
})
}
fn rename_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
old_path: String,
new_fd: Resource<sync_filesystem::Descriptor>,
new_path: String,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::rename_at(self, fd, old_path, new_fd, new_path).await
})
}
fn symlink_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
src_path: String,
dest_path: String,
) -> FsResult<()> {
in_tokio(async {
async_filesystem::HostDescriptor::symlink_at(self, fd, src_path, dest_path).await
})
}
fn unlink_file_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path: String,
) -> FsResult<()> {
in_tokio(async { async_filesystem::HostDescriptor::unlink_file_at(self, fd, path).await })
}
fn read_via_stream(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
offset: sync_filesystem::Filesize,
) -> FsResult<Resource<streams::InputStream>> {
Ok(async_filesystem::HostDescriptor::read_via_stream(
self, fd, offset,
)?)
}
fn write_via_stream(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
offset: sync_filesystem::Filesize,
) -> FsResult<Resource<streams::OutputStream>> {
Ok(async_filesystem::HostDescriptor::write_via_stream(
self, fd, offset,
)?)
}
fn append_via_stream(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<Resource<streams::OutputStream>> {
Ok(async_filesystem::HostDescriptor::append_via_stream(
self, fd,
)?)
}
fn is_same_object(
&mut self,
a: Resource<sync_filesystem::Descriptor>,
b: Resource<sync_filesystem::Descriptor>,
) -> anyhow::Result<bool> {
in_tokio(async { async_filesystem::HostDescriptor::is_same_object(self, a, b).await })
}
fn metadata_hash(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
) -> FsResult<sync_filesystem::MetadataHashValue> {
Ok(
in_tokio(async { async_filesystem::HostDescriptor::metadata_hash(self, fd).await })?
.into(),
)
}
fn metadata_hash_at(
&mut self,
fd: Resource<sync_filesystem::Descriptor>,
path_flags: sync_filesystem::PathFlags,
path: String,
) -> FsResult<sync_filesystem::MetadataHashValue> {
Ok(in_tokio(async {
async_filesystem::HostDescriptor::metadata_hash_at(self, fd, path_flags.into(), path)
.await
})?
.into())
}
}
impl<T> sync_filesystem::HostDirectoryEntryStream for WasiImpl<T>
where
T: WasiView,
{
fn read_directory_entry(
&mut self,
stream: Resource<sync_filesystem::DirectoryEntryStream>,
) -> FsResult<Option<sync_filesystem::DirectoryEntry>> {
Ok(in_tokio(async {
async_filesystem::HostDirectoryEntryStream::read_directory_entry(self, stream).await
})?
.map(|e| e.into()))
}
fn drop(
&mut self,
stream: Resource<sync_filesystem::DirectoryEntryStream>,
) -> anyhow::Result<()> {
async_filesystem::HostDirectoryEntryStream::drop(self, stream)
}
}
impl From<async_filesystem::ErrorCode> for sync_filesystem::ErrorCode {
fn from(other: async_filesystem::ErrorCode) -> Self {
use async_filesystem::ErrorCode;
match other {
ErrorCode::Access => Self::Access,
ErrorCode::WouldBlock => Self::WouldBlock,
ErrorCode::Already => Self::Already,
ErrorCode::BadDescriptor => Self::BadDescriptor,
ErrorCode::Busy => Self::Busy,
ErrorCode::Deadlock => Self::Deadlock,
ErrorCode::Quota => Self::Quota,
ErrorCode::Exist => Self::Exist,
ErrorCode::FileTooLarge => Self::FileTooLarge,
ErrorCode::IllegalByteSequence => Self::IllegalByteSequence,
ErrorCode::InProgress => Self::InProgress,
ErrorCode::Interrupted => Self::Interrupted,
ErrorCode::Invalid => Self::Invalid,
ErrorCode::Io => Self::Io,
ErrorCode::IsDirectory => Self::IsDirectory,
ErrorCode::Loop => Self::Loop,
ErrorCode::TooManyLinks => Self::TooManyLinks,
ErrorCode::MessageSize => Self::MessageSize,
ErrorCode::NameTooLong => Self::NameTooLong,
ErrorCode::NoDevice => Self::NoDevice,
ErrorCode::NoEntry => Self::NoEntry,
ErrorCode::NoLock => Self::NoLock,
ErrorCode::InsufficientMemory => Self::InsufficientMemory,
ErrorCode::InsufficientSpace => Self::InsufficientSpace,
ErrorCode::NotDirectory => Self::NotDirectory,
ErrorCode::NotEmpty => Self::NotEmpty,
ErrorCode::NotRecoverable => Self::NotRecoverable,
ErrorCode::Unsupported => Self::Unsupported,
ErrorCode::NoTty => Self::NoTty,
ErrorCode::NoSuchDevice => Self::NoSuchDevice,
ErrorCode::Overflow => Self::Overflow,
ErrorCode::NotPermitted => Self::NotPermitted,
ErrorCode::Pipe => Self::Pipe,
ErrorCode::ReadOnly => Self::ReadOnly,
ErrorCode::InvalidSeek => Self::InvalidSeek,
ErrorCode::TextFileBusy => Self::TextFileBusy,
ErrorCode::CrossDevice => Self::CrossDevice,
}
}
}
impl From<sync_filesystem::Advice> for async_filesystem::Advice {
fn from(other: sync_filesystem::Advice) -> Self {
use sync_filesystem::Advice;
match other {
Advice::Normal => Self::Normal,
Advice::Sequential => Self::Sequential,
Advice::Random => Self::Random,
Advice::WillNeed => Self::WillNeed,
Advice::DontNeed => Self::DontNeed,
Advice::NoReuse => Self::NoReuse,
}
}
}
impl From<async_filesystem::DescriptorFlags> for sync_filesystem::DescriptorFlags {
fn from(other: async_filesystem::DescriptorFlags) -> Self {
let mut out = Self::empty();
if other.contains(async_filesystem::DescriptorFlags::READ) {
out |= Self::READ;
}
if other.contains(async_filesystem::DescriptorFlags::WRITE) {
out |= Self::WRITE;
}
if other.contains(async_filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {
out |= Self::FILE_INTEGRITY_SYNC;
}
if other.contains(async_filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {
out |= Self::DATA_INTEGRITY_SYNC;
}
if other.contains(async_filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {
out |= Self::REQUESTED_WRITE_SYNC;
}
if other.contains(async_filesystem::DescriptorFlags::MUTATE_DIRECTORY) {
out |= Self::MUTATE_DIRECTORY;
}
out
}
}
impl From<async_filesystem::DescriptorType> for sync_filesystem::DescriptorType {
fn from(other: async_filesystem::DescriptorType) -> Self {
use async_filesystem::DescriptorType;
match other {
DescriptorType::RegularFile => Self::RegularFile,
DescriptorType::Directory => Self::Directory,
DescriptorType::BlockDevice => Self::BlockDevice,
DescriptorType::CharacterDevice => Self::CharacterDevice,
DescriptorType::Fifo => Self::Fifo,
DescriptorType::Socket => Self::Socket,
DescriptorType::SymbolicLink => Self::SymbolicLink,
DescriptorType::Unknown => Self::Unknown,
}
}
}
impl From<async_filesystem::DirectoryEntry> for sync_filesystem::DirectoryEntry {
fn from(other: async_filesystem::DirectoryEntry) -> Self {
Self {
type_: other.type_.into(),
name: other.name,
}
}
}
impl From<async_filesystem::DescriptorStat> for sync_filesystem::DescriptorStat {
fn from(other: async_filesystem::DescriptorStat) -> Self {
Self {
type_: other.type_.into(),
link_count: other.link_count,
size: other.size,
data_access_timestamp: other.data_access_timestamp,
data_modification_timestamp: other.data_modification_timestamp,
status_change_timestamp: other.status_change_timestamp,
}
}
}
impl From<sync_filesystem::PathFlags> for async_filesystem::PathFlags {
fn from(other: sync_filesystem::PathFlags) -> Self {
let mut out = Self::empty();
if other.contains(sync_filesystem::PathFlags::SYMLINK_FOLLOW) {
out |= Self::SYMLINK_FOLLOW;
}
out
}
}
impl From<sync_filesystem::NewTimestamp> for async_filesystem::NewTimestamp {
fn from(other: sync_filesystem::NewTimestamp) -> Self {
use sync_filesystem::NewTimestamp;
match other {
NewTimestamp::NoChange => Self::NoChange,
NewTimestamp::Now => Self::Now,
NewTimestamp::Timestamp(datetime) => Self::Timestamp(datetime),
}
}
}
impl From<sync_filesystem::OpenFlags> for async_filesystem::OpenFlags {
fn from(other: sync_filesystem::OpenFlags) -> Self {
let mut out = Self::empty();
if other.contains(sync_filesystem::OpenFlags::CREATE) {
out |= Self::CREATE;
}
if other.contains(sync_filesystem::OpenFlags::DIRECTORY) {
out |= Self::DIRECTORY;
}
if other.contains(sync_filesystem::OpenFlags::EXCLUSIVE) {
out |= Self::EXCLUSIVE;
}
if other.contains(sync_filesystem::OpenFlags::TRUNCATE) {
out |= Self::TRUNCATE;
}
out
}
}
impl From<sync_filesystem::DescriptorFlags> for async_filesystem::DescriptorFlags {
fn from(other: sync_filesystem::DescriptorFlags) -> Self {
let mut out = Self::empty();
if other.contains(sync_filesystem::DescriptorFlags::READ) {
out |= Self::READ;
}
if other.contains(sync_filesystem::DescriptorFlags::WRITE) {
out |= Self::WRITE;
}
if other.contains(sync_filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {
out |= Self::FILE_INTEGRITY_SYNC;
}
if other.contains(sync_filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {
out |= Self::DATA_INTEGRITY_SYNC;
}
if other.contains(sync_filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {
out |= Self::REQUESTED_WRITE_SYNC;
}
if other.contains(sync_filesystem::DescriptorFlags::MUTATE_DIRECTORY) {
out |= Self::MUTATE_DIRECTORY;
}
out
}
}
impl From<async_filesystem::MetadataHashValue> for sync_filesystem::MetadataHashValue {
fn from(other: async_filesystem::MetadataHashValue) -> Self {
Self {
lower: other.lower,
upper: other.upper,
}
}
}