Skip to content

Commit 904eecb

Browse files
author
Jakub Konka
committed
Implement AsFile for dyn Handle
This cleans up a lot of repeating boilerplate code todo with dynamic dispatch.
1 parent 256773f commit 904eecb

File tree

10 files changed

+31
-106
lines changed

10 files changed

+31
-106
lines changed

crates/wasi-common/src/sys/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::wasi::types;
2929
use osdir::OsDir;
3030
use osfile::OsFile;
3131
use osother::OsOther;
32+
use stdio::Stdio;
3233
use std::convert::TryFrom;
3334
use std::fs::File;
3435
use std::io;
@@ -39,6 +40,22 @@ pub(crate) trait AsFile {
3940
fn as_file(&self) -> ManuallyDrop<File>;
4041
}
4142

43+
impl AsFile for dyn Handle + 'static {
44+
fn as_file(&self) -> ManuallyDrop<File> {
45+
if let Some(file) = self.as_any().downcast_ref::<OsFile>() {
46+
file.as_file()
47+
} else if let Some(dir) = self.as_any().downcast_ref::<OsDir>() {
48+
dir.as_file()
49+
} else if let Some(stdio) = self.as_any().downcast_ref::<Stdio>() {
50+
stdio.as_file()
51+
} else if let Some(other) = self.as_any().downcast_ref::<OsOther>() {
52+
other.as_file()
53+
} else {
54+
panic!("non-OS resource cannot be made into a File")
55+
}
56+
}
57+
}
58+
4259
impl TryFrom<File> for Box<dyn Handle> {
4360
type Error = io::Error;
4461

crates/wasi-common/src/sys/osdir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl Handle for OsDir {
9797
) -> Result<()> {
9898
let new_handle = match new_handle.as_any().downcast_ref::<Self>() {
9999
None => {
100-
error!("Tried to link OS resource with Virtual");
100+
error!("Tried to link with handle that's not an OsDir");
101101
return Err(Errno::Badf);
102102
}
103103
Some(handle) => handle,
@@ -116,7 +116,7 @@ impl Handle for OsDir {
116116
fn rename(&self, old_path: &str, new_handle: Box<dyn Handle>, new_path: &str) -> Result<()> {
117117
let new_handle = match new_handle.as_any().downcast_ref::<Self>() {
118118
None => {
119-
error!("Tried to link OS resource with Virtual");
119+
error!("Tried to rename with handle that's not an OsDir");
120120
return Err(Errno::Badf);
121121
}
122122
Some(handle) => handle,

crates/wasi-common/src/sys/unix/osdir.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ use crate::wasi::{types, RightsExt};
55
use std::convert::TryFrom;
66
use std::fs::File;
77
use std::io;
8-
use std::ops::Deref;
9-
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
10-
11-
impl AsRawFd for OsDir {
12-
fn as_raw_fd(&self) -> RawFd {
13-
self.deref().as_raw_fd()
14-
}
15-
}
8+
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd};
169

1710
impl TryFrom<File> for OsDir {
1811
type Error = io::Error;

crates/wasi-common/src/sys/unix/osfile.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ use crate::wasi::{types, RightsExt};
55
use std::convert::TryFrom;
66
use std::fs::{File, OpenOptions};
77
use std::io;
8-
use std::ops::Deref;
9-
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
10-
11-
impl AsRawFd for OsFile {
12-
fn as_raw_fd(&self) -> RawFd {
13-
self.deref().as_raw_fd()
14-
}
15-
}
8+
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd};
169

1710
impl TryFrom<File> for OsFile {
1811
type Error = io::Error;

crates/wasi-common/src/sys/unix/osother.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,7 @@ use crate::wasi::{types, RightsExt};
66
use std::convert::TryFrom;
77
use std::fs::File;
88
use std::io;
9-
use std::ops::Deref;
10-
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
11-
12-
impl AsRawFd for OsOther {
13-
fn as_raw_fd(&self) -> RawFd {
14-
self.deref().as_raw_fd()
15-
}
16-
}
9+
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd};
1710

1811
impl TryFrom<File> for OsOther {
1912
type Error = io::Error;

crates/wasi-common/src/sys/unix/poll.rs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use crate::entry::EntryHandle;
22
use crate::poll::{ClockEventData, FdEventData};
3-
use crate::sys::osdir::OsDir;
43
use crate::sys::osfile::OsFile;
5-
use crate::sys::osother::OsOther;
6-
use crate::sys::stdio::Stdio;
74
use crate::sys::AsFile;
85
use crate::wasi::{types, Errno, Result};
96
use std::io;
@@ -32,18 +29,7 @@ pub(crate) fn oneoff(
3229
// events we filtered before. If we get something else here, the code has a serious bug.
3330
_ => unreachable!(),
3431
};
35-
let fd = if let Some(file) = event.handle.as_any().downcast_ref::<OsFile>() {
36-
file.as_raw_fd()
37-
} else if let Some(dir) = event.handle.as_any().downcast_ref::<OsDir>() {
38-
dir.as_raw_fd()
39-
} else if let Some(stdio) = event.handle.as_any().downcast_ref::<Stdio>() {
40-
stdio.as_raw_fd()
41-
} else if let Some(other) = event.handle.as_any().downcast_ref::<OsOther>() {
42-
other.as_raw_fd()
43-
} else {
44-
panic!("can poll FdEvent for OS resources only")
45-
};
46-
unsafe { PollFd::new(fd, flags) }
32+
unsafe { PollFd::new(event.handle.as_file().as_raw_fd(), flags) }
4733
})
4834
.collect();
4935

@@ -97,16 +83,9 @@ fn handle_fd_event(
9783
let meta = file.as_file().metadata()?;
9884
let len = meta.len();
9985
let host_offset = unsafe { tell(file.as_raw_fd())? };
100-
Ok(len - host_offset)
101-
} else if let Some(dir) = handle.as_any().downcast_ref::<OsDir>() {
102-
unsafe { Ok(fionread(dir.as_raw_fd())?.into()) }
103-
} else if let Some(stdio) = handle.as_any().downcast_ref::<Stdio>() {
104-
unsafe { Ok(fionread(stdio.as_raw_fd())?.into()) }
105-
} else if let Some(other) = handle.as_any().downcast_ref::<OsOther>() {
106-
unsafe { Ok(fionread(other.as_raw_fd())?.into()) }
107-
} else {
108-
panic!("can poll FdEvent for OS resources only")
86+
return Ok(len - host_offset);
10987
}
88+
Ok(unsafe { fionread(handle.as_file().as_raw_fd())?.into() })
11089
}
11190

11291
for (fd_event, poll_fd) in ready_events {

crates/wasi-common/src/sys/windows/osdir.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ use crate::wasi::{types, RightsExt};
55
use std::convert::TryFrom;
66
use std::fs::File;
77
use std::io;
8-
use std::ops::Deref;
9-
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
10-
11-
impl AsRawHandle for OsDir {
12-
fn as_raw_handle(&self) -> RawHandle {
13-
self.deref().as_raw_handle()
14-
}
15-
}
8+
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle};
169

1710
impl TryFrom<File> for OsDir {
1811
type Error = io::Error;

crates/wasi-common/src/sys/windows/osfile.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ use crate::wasi::{types, RightsExt};
55
use std::convert::TryFrom;
66
use std::fs::{File, OpenOptions};
77
use std::io;
8-
use std::ops::Deref;
9-
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
10-
11-
impl AsRawHandle for OsFile {
12-
fn as_raw_handle(&self) -> RawHandle {
13-
self.deref().as_raw_handle()
14-
}
15-
}
8+
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle};
169

1710
impl TryFrom<File> for OsFile {
1811
type Error = io::Error;

crates/wasi-common/src/sys/windows/osother.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,7 @@ use crate::wasi::{types, RightsExt};
66
use std::convert::TryFrom;
77
use std::fs::File;
88
use std::io;
9-
use std::ops::Deref;
10-
use std::os::windows::prelude::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
11-
12-
impl AsRawHandle for OsOther {
13-
fn as_raw_handle(&self) -> RawHandle {
14-
self.deref().as_raw_handle()
15-
}
16-
}
9+
use std::os::windows::prelude::{FromRawHandle, IntoRawHandle};
1710

1811
impl TryFrom<File> for OsOther {
1912
type Error = io::Error;

crates/wasi-common/src/sys/windows/poll.rs

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -145,42 +145,16 @@ fn handle_timeout_event(timeout_event: ClockEventData, events: &mut Vec<types::E
145145

146146
fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
147147
let handle = &event.handle;
148-
let size = if let Some(file) = handle.as_any().downcast_ref::<OsFile>() {
149-
if event.r#type == types::Eventtype::FdRead {
150-
file.as_file()
151-
.metadata()
152-
.map(|m| m.len())
153-
.map_err(Into::into)
154-
} else {
155-
// The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and
156-
// the implementation on Unix just returns 0 here, so it's probably fine
157-
// to do the same on Windows for now.
158-
// cf. https://github.com/WebAssembly/WASI/issues/148
159-
Ok(0)
160-
}
161-
} else if let Some(dir) = handle.as_any().downcast_ref::<OsDir>() {
162-
if event.r#type == types::Eventtype::FdRead {
163-
dir.as_file()
164-
.metadata()
165-
.map(|m| m.len())
166-
.map_err(Into::into)
167-
} else {
168-
// The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and
169-
// the implementation on Unix just returns 0 here, so it's probably fine
170-
// to do the same on Windows for now.
171-
// cf. https://github.com/WebAssembly/WASI/issues/148
172-
Ok(0)
173-
}
174-
} else if let Some(stdio) = handle.as_any().downcast_ref::<Stdio>() {
148+
let size = if let Some(stdio) = handle.as_any().downcast_ref::<Stdio>() {
175149
match stdio {
176150
// We return the only universally correct lower bound, see the comment later in the function.
177151
Stdio::In { .. } => Ok(1),
178152
// On Unix, ioctl(FIONREAD) will return 0 for stdout/stderr. Emulate the same behavior on Windows.
179153
Stdio::Out { .. } | Stdio::Err { .. } => Ok(0),
180154
}
181-
} else if let Some(other) = handle.as_any().downcast_ref::<OsOther>() {
155+
} else {
182156
if event.r#type == types::Eventtype::FdRead {
183-
other
157+
handle
184158
.as_file()
185159
.metadata()
186160
.map(|m| m.len())
@@ -192,10 +166,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
192166
// cf. https://github.com/WebAssembly/WASI/issues/148
193167
Ok(0)
194168
}
195-
} else {
196-
panic!("can poll FdEvent for OS resources only")
197169
};
198-
199170
let new_event = make_rw_event(&event, size);
200171
out_events.push(new_event);
201172
}

0 commit comments

Comments
 (0)