Merge pull request #2570 from bytecodealliance/pch/wiggle_flags_bitflags
wiggle: generate flags using `bitflags`
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2815,6 +2815,7 @@ dependencies = [
|
|||||||
name = "wiggle"
|
name = "wiggle"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
"proptest",
|
"proptest",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl Entry {
|
|||||||
/// `HandleRights` structure is a subset of rights attached to this `Entry`. The check is
|
/// `HandleRights` structure is a subset of rights attached to this `Entry`. The check is
|
||||||
/// performed using `Entry::validate_rights` method. If the check fails, `Error::Notcapable`
|
/// performed using `Entry::validate_rights` method. If the check fails, `Error::Notcapable`
|
||||||
/// is returned.
|
/// is returned.
|
||||||
pub(crate) fn as_handle(&self, rights: &HandleRights) -> Result<EntryHandle> {
|
pub(crate) fn as_handle(&self, rights: HandleRights) -> Result<EntryHandle> {
|
||||||
self.validate_rights(rights)?;
|
self.validate_rights(rights)?;
|
||||||
Ok(self.handle.get())
|
Ok(self.handle.get())
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ impl Entry {
|
|||||||
/// rights attached to this `Entry` object are a superset.
|
/// rights attached to this `Entry` object are a superset.
|
||||||
///
|
///
|
||||||
/// Upon unsuccessful check, `Error::Notcapable` is returned.
|
/// Upon unsuccessful check, `Error::Notcapable` is returned.
|
||||||
pub(crate) fn validate_rights(&self, rights: &HandleRights) -> Result<()> {
|
pub(crate) fn validate_rights(&self, rights: HandleRights) -> Result<()> {
|
||||||
let this_rights = self.handle.get_rights();
|
let this_rights = self.handle.get_rights();
|
||||||
if this_rights.contains(rights) {
|
if this_rights.contains(rights) {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ impl HandleRights {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if `other` is a subset of those rights.
|
/// Checks if `other` is a subset of those rights.
|
||||||
pub fn contains(&self, other: &Self) -> bool {
|
pub fn contains(&self, other: Self) -> bool {
|
||||||
self.base.contains(&other.base) && self.inheriting.contains(&other.inheriting)
|
self.base.contains(other.base) && self.inheriting.contains(other.inheriting)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns base rights.
|
/// Returns base rights.
|
||||||
@@ -100,7 +100,7 @@ pub trait Handle {
|
|||||||
let file_type = self.get_file_type();
|
let file_type = self.get_file_type();
|
||||||
let rights = self.get_rights();
|
let rights = self.get_rights();
|
||||||
let required_rights = HandleRights::from_base(Rights::FD_SEEK | Rights::FD_TELL);
|
let required_rights = HandleRights::from_base(Rights::FD_SEEK | Rights::FD_TELL);
|
||||||
file_type == Filetype::CharacterDevice && rights.contains(&required_rights)
|
file_type == Filetype::CharacterDevice && rights.contains(required_rights)
|
||||||
}
|
}
|
||||||
// TODO perhaps should be a separate trait?
|
// TODO perhaps should be a separate trait?
|
||||||
// FdOps
|
// FdOps
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub(crate) use crate::sys::path::{from_host, open_rights};
|
|||||||
/// This is a workaround for not having Capsicum support in the OS.
|
/// This is a workaround for not having Capsicum support in the OS.
|
||||||
pub(crate) fn get(
|
pub(crate) fn get(
|
||||||
entry: &Entry,
|
entry: &Entry,
|
||||||
required_rights: &HandleRights,
|
required_rights: HandleRights,
|
||||||
dirflags: Lookupflags,
|
dirflags: Lookupflags,
|
||||||
path: &str,
|
path: &str,
|
||||||
needs_final_component: bool,
|
needs_final_component: bool,
|
||||||
@@ -140,7 +140,7 @@ pub(crate) fn get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else if ends_with_slash || dirflags.contains(&Lookupflags::SYMLINK_FOLLOW)
|
} else if ends_with_slash || dirflags.contains(Lookupflags::SYMLINK_FOLLOW)
|
||||||
{
|
{
|
||||||
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
||||||
// symlink expansion
|
// symlink expansion
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let required_rights = HandleRights::from_base(types::Rights::FD_ADVISE);
|
let required_rights = HandleRights::from_base(types::Rights::FD_ADVISE);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.advise(advice, offset, len)
|
.advise(advice, offset, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_ALLOCATE);
|
let required_rights = HandleRights::from_base(types::Rights::FD_ALLOCATE);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry.as_handle(&required_rights)?.allocate(offset, len)
|
entry.as_handle(required_rights)?.allocate(offset, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_close(&self, fd: types::Fd) -> Result<()> {
|
fn fd_close(&self, fd: types::Fd) -> Result<()> {
|
||||||
@@ -89,12 +89,12 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
fn fd_datasync(&self, fd: types::Fd) -> Result<()> {
|
fn fd_datasync(&self, fd: types::Fd) -> Result<()> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_DATASYNC);
|
let required_rights = HandleRights::from_base(types::Rights::FD_DATASYNC);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry.as_handle(&required_rights)?.datasync()
|
entry.as_handle(required_rights)?.datasync()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_fdstat_get(&self, fd: types::Fd) -> Result<types::Fdstat> {
|
fn fd_fdstat_get(&self, fd: types::Fd) -> Result<types::Fdstat> {
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
let file = entry.as_handle(&HandleRights::empty())?;
|
let file = entry.as_handle(HandleRights::empty())?;
|
||||||
let fs_flags = file.fdstat_get()?;
|
let fs_flags = file.fdstat_get()?;
|
||||||
let rights = entry.get_rights();
|
let rights = entry.get_rights();
|
||||||
let fdstat = types::Fdstat {
|
let fdstat = types::Fdstat {
|
||||||
@@ -109,7 +109,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<()> {
|
fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<()> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_FDSTAT_SET_FLAGS);
|
let required_rights = HandleRights::from_base(types::Rights::FD_FDSTAT_SET_FLAGS);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry.as_handle(&required_rights)?.fdstat_set_flags(flags)
|
entry.as_handle(required_rights)?.fdstat_set_flags(flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_fdstat_set_rights(
|
fn fd_fdstat_set_rights(
|
||||||
@@ -120,7 +120,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let rights = HandleRights::new(fs_rights_base, fs_rights_inheriting);
|
let rights = HandleRights::new(fs_rights_base, fs_rights_inheriting);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
if !entry.get_rights().contains(&rights) {
|
if !entry.get_rights().contains(rights) {
|
||||||
return Err(Error::Notcapable);
|
return Err(Error::Notcapable);
|
||||||
}
|
}
|
||||||
entry.set_rights(rights);
|
entry.set_rights(rights);
|
||||||
@@ -130,14 +130,14 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat> {
|
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_GET);
|
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_GET);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
let host_filestat = entry.as_handle(&required_rights)?.filestat_get()?;
|
let host_filestat = entry.as_handle(required_rights)?.filestat_get()?;
|
||||||
Ok(host_filestat)
|
Ok(host_filestat)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<()> {
|
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<()> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_SET_SIZE);
|
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_SET_SIZE);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry.as_handle(&required_rights)?.filestat_set_size(size)
|
entry.as_handle(required_rights)?.filestat_set_size(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_filestat_set_times(
|
fn fd_filestat_set_times(
|
||||||
@@ -150,7 +150,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_SET_TIMES);
|
let required_rights = HandleRights::from_base(types::Rights::FD_FILESTAT_SET_TIMES);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.filestat_set_times(atim, mtim, fst_flags)
|
.filestat_set_times(atim, mtim, fst_flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
.map(|s| io::IoSliceMut::new(&mut *s))
|
.map(|s| io::IoSliceMut::new(&mut *s))
|
||||||
.collect::<Vec<io::IoSliceMut<'_>>>();
|
.collect::<Vec<io::IoSliceMut<'_>>>();
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.preadv(&mut buf, offset)?
|
.preadv(&mut buf, offset)?
|
||||||
.try_into()?
|
.try_into()?
|
||||||
};
|
};
|
||||||
@@ -255,7 +255,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let buf: Vec<io::IoSlice> =
|
let buf: Vec<io::IoSlice> =
|
||||||
guest_slices.iter().map(|s| io::IoSlice::new(&*s)).collect();
|
guest_slices.iter().map(|s| io::IoSlice::new(&*s)).collect();
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.pwritev(&buf, offset)?
|
.pwritev(&buf, offset)?
|
||||||
.try_into()?
|
.try_into()?
|
||||||
};
|
};
|
||||||
@@ -278,7 +278,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
.map(|s| io::IoSliceMut::new(&mut *s))
|
.map(|s| io::IoSliceMut::new(&mut *s))
|
||||||
.collect();
|
.collect();
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.read_vectored(&mut slices)?
|
.read_vectored(&mut slices)?
|
||||||
.try_into()?
|
.try_into()?
|
||||||
};
|
};
|
||||||
@@ -298,7 +298,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
|
|
||||||
let mut bufused = 0;
|
let mut bufused = 0;
|
||||||
let mut buf = buf.clone();
|
let mut buf = buf.clone();
|
||||||
for pair in entry.as_handle(&required_rights)?.readdir(cookie)? {
|
for pair in entry.as_handle(required_rights)?.readdir(cookie)? {
|
||||||
let (dirent, name) = pair?;
|
let (dirent, name) = pair?;
|
||||||
let dirent_raw = dirent.as_bytes()?;
|
let dirent_raw = dirent.as_bytes()?;
|
||||||
let dirent_len: types::Size = dirent_raw.len().try_into()?;
|
let dirent_len: types::Size = dirent_raw.len().try_into()?;
|
||||||
@@ -379,21 +379,21 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
types::Whence::End => SeekFrom::End(offset),
|
types::Whence::End => SeekFrom::End(offset),
|
||||||
types::Whence::Set => SeekFrom::Start(offset as u64),
|
types::Whence::Set => SeekFrom::Start(offset as u64),
|
||||||
};
|
};
|
||||||
let host_newoffset = entry.as_handle(&required_rights)?.seek(pos)?;
|
let host_newoffset = entry.as_handle(required_rights)?.seek(pos)?;
|
||||||
Ok(host_newoffset)
|
Ok(host_newoffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_sync(&self, fd: types::Fd) -> Result<()> {
|
fn fd_sync(&self, fd: types::Fd) -> Result<()> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_SYNC);
|
let required_rights = HandleRights::from_base(types::Rights::FD_SYNC);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
entry.as_handle(&required_rights)?.sync()
|
entry.as_handle(required_rights)?.sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize> {
|
fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize> {
|
||||||
let required_rights = HandleRights::from_base(types::Rights::FD_TELL);
|
let required_rights = HandleRights::from_base(types::Rights::FD_TELL);
|
||||||
let entry = self.get_entry(fd)?;
|
let entry = self.get_entry(fd)?;
|
||||||
let host_offset = entry
|
let host_offset = entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.seek(SeekFrom::Current(0))?;
|
.seek(SeekFrom::Current(0))?;
|
||||||
Ok(host_offset)
|
Ok(host_offset)
|
||||||
}
|
}
|
||||||
@@ -411,7 +411,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let slices: Vec<io::IoSlice> =
|
let slices: Vec<io::IoSlice> =
|
||||||
guest_slices.iter().map(|s| io::IoSlice::new(&*s)).collect();
|
guest_slices.iter().map(|s| io::IoSlice::new(&*s)).collect();
|
||||||
entry
|
entry
|
||||||
.as_handle(&required_rights)?
|
.as_handle(required_rights)?
|
||||||
.write_vectored(&slices)?
|
.write_vectored(&slices)?
|
||||||
.try_into()?
|
.try_into()?
|
||||||
};
|
};
|
||||||
@@ -426,7 +426,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
let (dirfd, path) = path::get(
|
let (dirfd, path) = path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
path.deref(),
|
path.deref(),
|
||||||
false,
|
false,
|
||||||
@@ -443,9 +443,9 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_GET);
|
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_GET);
|
||||||
let entry = self.get_entry(dirfd)?;
|
let entry = self.get_entry(dirfd)?;
|
||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
let (dirfd, path) = path::get(&entry, &required_rights, flags, path.deref(), false)?;
|
let (dirfd, path) = path::get(&entry, required_rights, flags, path.deref(), false)?;
|
||||||
let host_filestat =
|
let host_filestat =
|
||||||
dirfd.filestat_get_at(&path, flags.contains(&types::Lookupflags::SYMLINK_FOLLOW))?;
|
dirfd.filestat_get_at(&path, flags.contains(types::Lookupflags::SYMLINK_FOLLOW))?;
|
||||||
Ok(host_filestat)
|
Ok(host_filestat)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,13 +461,13 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_SET_TIMES);
|
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_SET_TIMES);
|
||||||
let entry = self.get_entry(dirfd)?;
|
let entry = self.get_entry(dirfd)?;
|
||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
let (dirfd, path) = path::get(&entry, &required_rights, flags, path.deref(), false)?;
|
let (dirfd, path) = path::get(&entry, required_rights, flags, path.deref(), false)?;
|
||||||
dirfd.filestat_set_times_at(
|
dirfd.filestat_set_times_at(
|
||||||
&path,
|
&path,
|
||||||
atim,
|
atim,
|
||||||
mtim,
|
mtim,
|
||||||
fst_flags,
|
fst_flags,
|
||||||
flags.contains(&types::Lookupflags::SYMLINK_FOLLOW),
|
flags.contains(types::Lookupflags::SYMLINK_FOLLOW),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let old_path = old_path.as_str()?;
|
let old_path = old_path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&old_entry,
|
&old_entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
old_path.deref(),
|
old_path.deref(),
|
||||||
false,
|
false,
|
||||||
@@ -500,7 +500,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let new_path = new_path.as_str()?;
|
let new_path = new_path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&new_entry,
|
&new_entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
new_path.deref(),
|
new_path.deref(),
|
||||||
false,
|
false,
|
||||||
@@ -510,7 +510,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
&old_path,
|
&old_path,
|
||||||
new_dirfd,
|
new_dirfd,
|
||||||
&new_path,
|
&new_path,
|
||||||
old_flags.contains(&types::Lookupflags::SYMLINK_FOLLOW),
|
old_flags.contains(types::Lookupflags::SYMLINK_FOLLOW),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +535,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&needed_rights,
|
needed_rights,
|
||||||
dirflags,
|
dirflags,
|
||||||
path.deref(),
|
path.deref(),
|
||||||
oflags & types::Oflags::CREAT != types::Oflags::empty(),
|
oflags & types::Oflags::CREAT != types::Oflags::empty(),
|
||||||
@@ -581,7 +581,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
path.deref(),
|
path.deref(),
|
||||||
false,
|
false,
|
||||||
@@ -599,7 +599,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
path.deref(),
|
path.deref(),
|
||||||
true,
|
true,
|
||||||
@@ -621,7 +621,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let old_path = old_path.as_str()?;
|
let old_path = old_path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
old_path.deref(),
|
old_path.deref(),
|
||||||
true,
|
true,
|
||||||
@@ -633,7 +633,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let new_path = new_path.as_str()?;
|
let new_path = new_path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
new_path.deref(),
|
new_path.deref(),
|
||||||
true,
|
true,
|
||||||
@@ -654,7 +654,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let new_path = new_path.as_str()?;
|
let new_path = new_path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
new_path.deref(),
|
new_path.deref(),
|
||||||
true,
|
true,
|
||||||
@@ -672,7 +672,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
|||||||
let path = path.as_str()?;
|
let path = path.as_str()?;
|
||||||
path::get(
|
path::get(
|
||||||
&entry,
|
&entry,
|
||||||
&required_rights,
|
required_rights,
|
||||||
types::Lookupflags::empty(),
|
types::Lookupflags::empty(),
|
||||||
path.deref(),
|
path.deref(),
|
||||||
false,
|
false,
|
||||||
@@ -815,7 +815,7 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fd_events.push(sched::FdEventData {
|
fd_events.push(sched::FdEventData {
|
||||||
handle: entry.as_handle(&required_rights)?,
|
handle: entry.as_handle(required_rights)?,
|
||||||
r#type: types::Eventtype::FdRead,
|
r#type: types::Eventtype::FdRead,
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
});
|
});
|
||||||
@@ -841,7 +841,7 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fd_events.push(sched::FdEventData {
|
fd_events.push(sched::FdEventData {
|
||||||
handle: entry.as_handle(&required_rights)?,
|
handle: entry.as_handle(required_rights)?,
|
||||||
r#type: types::Eventtype::FdWrite,
|
r#type: types::Eventtype::FdWrite,
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ pub(crate) fn filestat_set_times(
|
|||||||
st_mtim: Timestamp,
|
st_mtim: Timestamp,
|
||||||
fst_flags: Fstflags,
|
fst_flags: Fstflags,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let set_atim = fst_flags.contains(&Fstflags::ATIM);
|
let set_atim = fst_flags.contains(Fstflags::ATIM);
|
||||||
let set_atim_now = fst_flags.contains(&Fstflags::ATIM_NOW);
|
let set_atim_now = fst_flags.contains(Fstflags::ATIM_NOW);
|
||||||
let set_mtim = fst_flags.contains(&Fstflags::MTIM);
|
let set_mtim = fst_flags.contains(Fstflags::MTIM);
|
||||||
let set_mtim_now = fst_flags.contains(&Fstflags::MTIM_NOW);
|
let set_mtim_now = fst_flags.contains(Fstflags::MTIM_NOW);
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
||||||
return Err(Error::Inval);
|
return Err(Error::Inval);
|
||||||
|
|||||||
@@ -147,19 +147,19 @@ impl From<Clockid> for ClockId {
|
|||||||
impl From<Fdflags> for OFlags {
|
impl From<Fdflags> for OFlags {
|
||||||
fn from(fdflags: Fdflags) -> Self {
|
fn from(fdflags: Fdflags) -> Self {
|
||||||
let mut nix_flags = Self::empty();
|
let mut nix_flags = Self::empty();
|
||||||
if fdflags.contains(&Fdflags::APPEND) {
|
if fdflags.contains(Fdflags::APPEND) {
|
||||||
nix_flags.insert(Self::APPEND);
|
nix_flags.insert(Self::APPEND);
|
||||||
}
|
}
|
||||||
if fdflags.contains(&Fdflags::DSYNC) {
|
if fdflags.contains(Fdflags::DSYNC) {
|
||||||
nix_flags.insert(Self::DSYNC);
|
nix_flags.insert(Self::DSYNC);
|
||||||
}
|
}
|
||||||
if fdflags.contains(&Fdflags::NONBLOCK) {
|
if fdflags.contains(Fdflags::NONBLOCK) {
|
||||||
nix_flags.insert(Self::NONBLOCK);
|
nix_flags.insert(Self::NONBLOCK);
|
||||||
}
|
}
|
||||||
if fdflags.contains(&Fdflags::RSYNC) {
|
if fdflags.contains(Fdflags::RSYNC) {
|
||||||
nix_flags.insert(O_RSYNC);
|
nix_flags.insert(O_RSYNC);
|
||||||
}
|
}
|
||||||
if fdflags.contains(&Fdflags::SYNC) {
|
if fdflags.contains(Fdflags::SYNC) {
|
||||||
nix_flags.insert(Self::SYNC);
|
nix_flags.insert(Self::SYNC);
|
||||||
}
|
}
|
||||||
nix_flags
|
nix_flags
|
||||||
@@ -191,16 +191,16 @@ impl From<OFlags> for Fdflags {
|
|||||||
impl From<Oflags> for OFlags {
|
impl From<Oflags> for OFlags {
|
||||||
fn from(oflags: Oflags) -> Self {
|
fn from(oflags: Oflags) -> Self {
|
||||||
let mut nix_flags = Self::empty();
|
let mut nix_flags = Self::empty();
|
||||||
if oflags.contains(&Oflags::CREAT) {
|
if oflags.contains(Oflags::CREAT) {
|
||||||
nix_flags.insert(Self::CREAT);
|
nix_flags.insert(Self::CREAT);
|
||||||
}
|
}
|
||||||
if oflags.contains(&Oflags::DIRECTORY) {
|
if oflags.contains(Oflags::DIRECTORY) {
|
||||||
nix_flags.insert(Self::DIRECTORY);
|
nix_flags.insert(Self::DIRECTORY);
|
||||||
}
|
}
|
||||||
if oflags.contains(&Oflags::EXCL) {
|
if oflags.contains(Oflags::EXCL) {
|
||||||
nix_flags.insert(Self::EXCL);
|
nix_flags.insert(Self::EXCL);
|
||||||
}
|
}
|
||||||
if oflags.contains(&Oflags::TRUNC) {
|
if oflags.contains(Oflags::TRUNC) {
|
||||||
nix_flags.insert(Self::TRUNC);
|
nix_flags.insert(Self::TRUNC);
|
||||||
}
|
}
|
||||||
nix_flags
|
nix_flags
|
||||||
|
|||||||
@@ -239,10 +239,10 @@ pub(crate) fn filestat_set_times_at(
|
|||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
use yanix::filetime::*;
|
use yanix::filetime::*;
|
||||||
|
|
||||||
let set_atim = fst_flags.contains(&Fstflags::ATIM);
|
let set_atim = fst_flags.contains(Fstflags::ATIM);
|
||||||
let set_atim_now = fst_flags.contains(&Fstflags::ATIM_NOW);
|
let set_atim_now = fst_flags.contains(Fstflags::ATIM_NOW);
|
||||||
let set_mtim = fst_flags.contains(&Fstflags::MTIM);
|
let set_mtim = fst_flags.contains(Fstflags::MTIM);
|
||||||
let set_mtim_now = fst_flags.contains(&Fstflags::MTIM_NOW);
|
let set_mtim_now = fst_flags.contains(Fstflags::MTIM_NOW);
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
||||||
return Err(Error::Inval);
|
return Err(Error::Inval);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ fn file_access_mode_from_fdflags(fdflags: Fdflags, read: bool, write: bool) -> A
|
|||||||
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
||||||
// This makes the handle "append only".
|
// This makes the handle "append only".
|
||||||
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
|
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
|
||||||
if fdflags.contains(&Fdflags::APPEND) {
|
if fdflags.contains(Fdflags::APPEND) {
|
||||||
access_mode.insert(AccessMode::FILE_APPEND_DATA);
|
access_mode.insert(AccessMode::FILE_APPEND_DATA);
|
||||||
access_mode.remove(AccessMode::FILE_WRITE_DATA);
|
access_mode.remove(AccessMode::FILE_WRITE_DATA);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,13 +147,13 @@ impl TryFrom<&File> for Filestat {
|
|||||||
|
|
||||||
impl From<Oflags> for CreationDisposition {
|
impl From<Oflags> for CreationDisposition {
|
||||||
fn from(oflags: Oflags) -> Self {
|
fn from(oflags: Oflags) -> Self {
|
||||||
if oflags.contains(&Oflags::CREAT) {
|
if oflags.contains(Oflags::CREAT) {
|
||||||
if oflags.contains(&Oflags::EXCL) {
|
if oflags.contains(Oflags::EXCL) {
|
||||||
CreationDisposition::CREATE_NEW
|
CreationDisposition::CREATE_NEW
|
||||||
} else {
|
} else {
|
||||||
CreationDisposition::CREATE_ALWAYS
|
CreationDisposition::CREATE_ALWAYS
|
||||||
}
|
}
|
||||||
} else if oflags.contains(&Oflags::TRUNC) {
|
} else if oflags.contains(Oflags::TRUNC) {
|
||||||
CreationDisposition::TRUNCATE_EXISTING
|
CreationDisposition::TRUNCATE_EXISTING
|
||||||
} else {
|
} else {
|
||||||
CreationDisposition::OPEN_EXISTING
|
CreationDisposition::OPEN_EXISTING
|
||||||
@@ -171,9 +171,9 @@ impl From<Fdflags> for Flags {
|
|||||||
// treat I/O operations on files as synchronous. WASI might have an async-io API in the future.
|
// treat I/O operations on files as synchronous. WASI might have an async-io API in the future.
|
||||||
|
|
||||||
// Technically, Windows only supports __WASI_FDFLAGS_SYNC, but treat all the flags as the same.
|
// Technically, Windows only supports __WASI_FDFLAGS_SYNC, but treat all the flags as the same.
|
||||||
if fdflags.contains(&Fdflags::DSYNC)
|
if fdflags.contains(Fdflags::DSYNC)
|
||||||
|| fdflags.contains(&Fdflags::RSYNC)
|
|| fdflags.contains(Fdflags::RSYNC)
|
||||||
|| fdflags.contains(&Fdflags::SYNC)
|
|| fdflags.contains(Fdflags::SYNC)
|
||||||
{
|
{
|
||||||
flags.insert(Flags::FILE_FLAG_WRITE_THROUGH);
|
flags.insert(Flags::FILE_FLAG_WRITE_THROUGH);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ fn file_access_mode_from_fdflags(fdflags: Fdflags, read: bool, write: bool) -> A
|
|||||||
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
|
||||||
// This makes the handle "append only".
|
// This makes the handle "append only".
|
||||||
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
|
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
|
||||||
if fdflags.contains(&Fdflags::APPEND) {
|
if fdflags.contains(Fdflags::APPEND) {
|
||||||
access_mode.insert(AccessMode::FILE_APPEND_DATA);
|
access_mode.insert(AccessMode::FILE_APPEND_DATA);
|
||||||
access_mode.remove(AccessMode::FILE_WRITE_DATA);
|
access_mode.remove(AccessMode::FILE_WRITE_DATA);
|
||||||
}
|
}
|
||||||
@@ -100,16 +100,16 @@ pub(crate) fn open_rights(
|
|||||||
let mut needed_inheriting = input_rights.base | input_rights.inheriting;
|
let mut needed_inheriting = input_rights.base | input_rights.inheriting;
|
||||||
|
|
||||||
// convert open flags
|
// convert open flags
|
||||||
if oflags.contains(&Oflags::CREAT) {
|
if oflags.contains(Oflags::CREAT) {
|
||||||
needed_base |= Rights::PATH_CREATE_FILE;
|
needed_base |= Rights::PATH_CREATE_FILE;
|
||||||
} else if oflags.contains(&Oflags::TRUNC) {
|
} else if oflags.contains(Oflags::TRUNC) {
|
||||||
needed_base |= Rights::PATH_FILESTAT_SET_SIZE;
|
needed_base |= Rights::PATH_FILESTAT_SET_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert file descriptor flags
|
// convert file descriptor flags
|
||||||
if fdflags.contains(&Fdflags::DSYNC)
|
if fdflags.contains(Fdflags::DSYNC)
|
||||||
|| fdflags.contains(&Fdflags::RSYNC)
|
|| fdflags.contains(Fdflags::RSYNC)
|
||||||
|| fdflags.contains(&Fdflags::SYNC)
|
|| fdflags.contains(Fdflags::SYNC)
|
||||||
{
|
{
|
||||||
needed_inheriting |= Rights::FD_DATASYNC;
|
needed_inheriting |= Rights::FD_DATASYNC;
|
||||||
needed_inheriting |= Rights::FD_SYNC;
|
needed_inheriting |= Rights::FD_SYNC;
|
||||||
@@ -211,13 +211,13 @@ pub(crate) fn open(
|
|||||||
) -> Result<Box<dyn Handle>> {
|
) -> Result<Box<dyn Handle>> {
|
||||||
use winx::file::{AccessMode, CreationDisposition, Flags};
|
use winx::file::{AccessMode, CreationDisposition, Flags};
|
||||||
|
|
||||||
let is_trunc = oflags.contains(&Oflags::TRUNC);
|
let is_trunc = oflags.contains(Oflags::TRUNC);
|
||||||
|
|
||||||
if is_trunc {
|
if is_trunc {
|
||||||
// Windows does not support append mode when opening for truncation
|
// Windows does not support append mode when opening for truncation
|
||||||
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
|
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
|
||||||
// of the `FILE_WRITE_DATA` permission.
|
// of the `FILE_WRITE_DATA` permission.
|
||||||
if fdflags.contains(&Fdflags::APPEND) {
|
if fdflags.contains(Fdflags::APPEND) {
|
||||||
return Err(Error::Notsup);
|
return Err(Error::Notsup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ pub(crate) fn open(
|
|||||||
return Err(Error::Loop);
|
return Err(Error::Loop);
|
||||||
}
|
}
|
||||||
// check if we are trying to open a file as a dir
|
// check if we are trying to open a file as a dir
|
||||||
if file_type.is_file() && oflags.contains(&Oflags::DIRECTORY) {
|
if file_type.is_file() && oflags.contains(Oflags::DIRECTORY) {
|
||||||
return Err(Error::Notdir);
|
return Err(Error::Notdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ impl Handle for InMemoryFile {
|
|||||||
trace!("write_vectored(iovs={:?})", iovs);
|
trace!("write_vectored(iovs={:?})", iovs);
|
||||||
let mut data = self.data.borrow_mut();
|
let mut data = self.data.borrow_mut();
|
||||||
|
|
||||||
let append_mode = self.fd_flags.get().contains(&Fdflags::APPEND);
|
let append_mode = self.fd_flags.get().contains(Fdflags::APPEND);
|
||||||
trace!(" | fd_flags={}", self.fd_flags.get());
|
trace!(" | fd_flags={}", self.fd_flags.get());
|
||||||
|
|
||||||
// If this file is in append mode, we write to the end.
|
// If this file is in append mode, we write to the end.
|
||||||
@@ -353,7 +353,7 @@ impl Handle for InMemoryFile {
|
|||||||
oflags: Oflags,
|
oflags: Oflags,
|
||||||
_fd_flags: Fdflags,
|
_fd_flags: Fdflags,
|
||||||
) -> Result<Box<dyn Handle>> {
|
) -> Result<Box<dyn Handle>> {
|
||||||
if oflags.contains(&Oflags::DIRECTORY) {
|
if oflags.contains(Oflags::DIRECTORY) {
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
"InMemoryFile::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
"InMemoryFile::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
||||||
path
|
path
|
||||||
@@ -652,7 +652,7 @@ impl Handle for VirtualDir {
|
|||||||
return Err(Error::Exist);
|
return Err(Error::Exist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if oflags.contains(&Oflags::DIRECTORY)
|
if oflags.contains(Oflags::DIRECTORY)
|
||||||
&& e.get().get_file_type() != Filetype::Directory
|
&& e.get().get_file_type() != Filetype::Directory
|
||||||
{
|
{
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
@@ -665,7 +665,7 @@ impl Handle for VirtualDir {
|
|||||||
e.get().try_clone().map_err(Into::into)
|
e.get().try_clone().map_err(Into::into)
|
||||||
}
|
}
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
if oflags.contains(&Oflags::CREAT) {
|
if oflags.contains(Oflags::CREAT) {
|
||||||
if self.writable {
|
if self.writable {
|
||||||
// Enforce a hard limit at `u32::MAX - 2` files.
|
// Enforce a hard limit at `u32::MAX - 2` files.
|
||||||
// This is to have a constant limit (rather than target-dependent limit we
|
// This is to have a constant limit (rather than target-dependent limit we
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ thiserror = "1"
|
|||||||
witx = { path = "../wasi-common/WASI/tools/witx", version = "0.8.7", optional = true }
|
witx = { path = "../wasi-common/WASI/tools/witx", version = "0.8.7", optional = true }
|
||||||
wiggle-macro = { path = "macro", version = "0.22.0" }
|
wiggle-macro = { path = "macro", version = "0.22.0" }
|
||||||
tracing = "0.1.15"
|
tracing = "0.1.15"
|
||||||
|
bitflags = "1.2"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ pub fn define_func(
|
|||||||
let func_name = &func.name.as_str();
|
let func_name = &func.name.as_str();
|
||||||
|
|
||||||
if func.noreturn {
|
if func.noreturn {
|
||||||
quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> {
|
quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, #rt::Trap> {
|
||||||
let _span = #rt::tracing::span!(
|
let _span = #rt::tracing::span!(
|
||||||
#rt::tracing::Level::TRACE,
|
#rt::tracing::Level::TRACE,
|
||||||
"wiggle abi",
|
"wiggle abi",
|
||||||
@@ -184,7 +184,7 @@ pub fn define_func(
|
|||||||
Err(trap)
|
Err(trap)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, wiggle::Trap> {
|
quote!(pub fn #ident(#abi_args) -> Result<#abi_ret, #rt::Trap> {
|
||||||
let _span = #rt::tracing::span!(
|
let _span = #rt::tracing::span!(
|
||||||
#rt::tracing::Level::TRACE,
|
#rt::tracing::Level::TRACE,
|
||||||
"wiggle abi",
|
"wiggle abi",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ pub fn generate(doc: &witx::Document, names: &Names, errs: &ErrorTransform) -> T
|
|||||||
let abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime());
|
let abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime());
|
||||||
let user_typename = errtype.typename();
|
let user_typename = errtype.typename();
|
||||||
let methodname = names.user_error_conversion_method(&errtype);
|
let methodname = names.user_error_conversion_method(&errtype);
|
||||||
quote!(fn #methodname(&self, e: super::#user_typename) -> Result<#abi_typename, wiggle::Trap>;)
|
quote!(fn #methodname(&self, e: super::#user_typename) -> Result<#abi_typename, #rt::Trap>;)
|
||||||
});
|
});
|
||||||
let user_error_conversion = quote! {
|
let user_error_conversion = quote! {
|
||||||
pub trait UserErrorConversion {
|
pub trait UserErrorConversion {
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ pub fn define_module_trait(names: &Names, m: &Module, errxform: &ErrorTransform)
|
|||||||
.unwrap_or(quote!(()));
|
.unwrap_or(quote!(()));
|
||||||
quote!( Result<(#(#rets),*), #err> )
|
quote!( Result<(#(#rets),*), #err> )
|
||||||
} else {
|
} else {
|
||||||
quote!(wiggle::Trap)
|
let rt = names.runtime_mod();
|
||||||
|
quote!(#rt::Trap)
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_anonymous {
|
if is_anonymous {
|
||||||
|
|||||||
@@ -27,102 +27,31 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
|
|||||||
}
|
}
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[repr(transparent)]
|
#rt::bitflags::bitflags! {
|
||||||
#[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)]
|
pub struct #ident: #repr {
|
||||||
pub struct #ident(#repr);
|
#(const #names_ = #values_;)*
|
||||||
|
|
||||||
impl #ident {
|
|
||||||
#(pub const #names_: #ident = #ident(#values_);)*
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub const fn empty() -> Self {
|
|
||||||
#ident(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub const fn all() -> Self {
|
|
||||||
#ident(#(#values_)|*)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn contains(&self, other: &#ident) -> bool {
|
|
||||||
!*self & *other == Self::empty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::fmt::Display for #ident {
|
impl ::std::fmt::Display for #ident {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
let mut first = true;
|
f.write_str(stringify!(#ident))?;
|
||||||
#(
|
f.write_str("(")?;
|
||||||
if self.0 & #values_ == #values_ {
|
::std::fmt::Debug::fmt(self, f)?;
|
||||||
if !first {
|
f.write_str(" (0x")?;
|
||||||
f.write_str("|")?;
|
::std::fmt::LowerHex::fmt(&self.bits, f)?;
|
||||||
}
|
f.write_str("))")?;
|
||||||
first = false;
|
|
||||||
f.write_fmt(format_args!("{}", stringify!(#names_).to_lowercase()))?;
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
if first {
|
|
||||||
f.write_str("empty")?;
|
|
||||||
}
|
|
||||||
f.write_fmt(format_args!(" ({:#x})", self.0))?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::ops::BitAnd for #ident {
|
|
||||||
type Output = Self;
|
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
|
||||||
#ident(self.0 & rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::BitAndAssign for #ident {
|
|
||||||
fn bitand_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self & rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::BitOr for #ident {
|
|
||||||
type Output = Self;
|
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
|
||||||
#ident(self.0 | rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::BitOrAssign for #ident {
|
|
||||||
fn bitor_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self | rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::BitXor for #ident {
|
|
||||||
type Output = Self;
|
|
||||||
fn bitxor(self, rhs: Self) -> Self::Output {
|
|
||||||
#ident(self.0 ^ rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::BitXorAssign for #ident {
|
|
||||||
fn bitxor_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self ^ rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::ops::Not for #ident {
|
|
||||||
type Output = Self;
|
|
||||||
fn not(self) -> Self::Output {
|
|
||||||
#ident(!self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::convert::TryFrom<#repr> for #ident {
|
impl ::std::convert::TryFrom<#repr> for #ident {
|
||||||
type Error = #rt::GuestError;
|
type Error = #rt::GuestError;
|
||||||
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
|
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
|
||||||
if #repr::from(!#ident::all()) & value != 0 {
|
if #repr::from(!#ident::all()) & value != 0 {
|
||||||
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
|
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
|
||||||
} else {
|
} else {
|
||||||
Ok(#ident(value))
|
Ok(#ident { bits: value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +65,7 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
|
|||||||
|
|
||||||
impl From<#ident> for #repr {
|
impl From<#ident> for #repr {
|
||||||
fn from(e: #ident) -> #repr {
|
fn from(e: #ident) -> #repr {
|
||||||
e.0
|
e.bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use std::slice;
|
|||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub use bitflags;
|
||||||
pub use wiggle_macro::from_witx;
|
pub use wiggle_macro::from_witx;
|
||||||
|
|
||||||
#[cfg(feature = "wiggle_metadata")]
|
#[cfg(feature = "wiggle_metadata")]
|
||||||
|
|||||||
@@ -103,11 +103,11 @@ proptest! {
|
|||||||
#[test]
|
#[test]
|
||||||
fn flags_fmt() {
|
fn flags_fmt() {
|
||||||
let empty = format!("{}", types::CarConfig::empty());
|
let empty = format!("{}", types::CarConfig::empty());
|
||||||
assert_eq!(empty, "empty (0x0)");
|
assert_eq!(empty, "CarConfig((empty) (0x0))");
|
||||||
let one_flag = format!("{}", types::CarConfig::AWD);
|
let one_flag = format!("{}", types::CarConfig::AWD);
|
||||||
assert_eq!(one_flag, "awd (0x2)");
|
assert_eq!(one_flag, "CarConfig(AWD (0x2))");
|
||||||
let two_flags = format!("{}", types::CarConfig::AUTOMATIC | types::CarConfig::SUV);
|
let two_flags = format!("{}", types::CarConfig::AUTOMATIC | types::CarConfig::SUV);
|
||||||
assert_eq!(two_flags, "automatic|suv (0x5)");
|
assert_eq!(two_flags, "CarConfig(AUTOMATIC | SUV (0x5))");
|
||||||
let all = format!("{}", types::CarConfig::all());
|
let all = format!("{}", types::CarConfig::all());
|
||||||
assert_eq!(all, "automatic|awd|suv (0x7)");
|
assert_eq!(all, "CarConfig(AUTOMATIC | AWD | SUV (0x7))");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user