diff --git a/src/event/source/unix/mio.rs b/src/event/source/unix/mio.rs index 8372a1dd..0368e61b 100644 --- a/src/event/source/unix/mio.rs +++ b/src/event/source/unix/mio.rs @@ -26,7 +26,7 @@ pub(crate) struct UnixInternalEventSource { events: Events, parser: Parser, tty_buffer: [u8; TTY_BUFFER_SIZE], - tty_fd: FileDesc, + tty_fd: FileDesc<'static>, signals: Signals, #[cfg(feature = "event-stream")] waker: Waker, @@ -37,7 +37,7 @@ impl UnixInternalEventSource { UnixInternalEventSource::from_file_descriptor(tty_fd()?) } - pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result { + pub(crate) fn from_file_descriptor(input_fd: FileDesc<'static>) -> io::Result { let poll = Poll::new()?; let registry = poll.registry(); diff --git a/src/event/source/unix/tty.rs b/src/event/source/unix/tty.rs index b8cbfeff..03d76b40 100644 --- a/src/event/source/unix/tty.rs +++ b/src/event/source/unix/tty.rs @@ -1,6 +1,10 @@ +#[cfg(feature = "libc")] use std::os::unix::prelude::AsRawFd; use std::{collections::VecDeque, io, os::unix::net::UnixStream, time::Duration}; +#[cfg(not(feature = "libc"))] +use rustix::fd::{AsFd, AsRawFd}; + use signal_hook::low_level::pipe; use crate::event::timeout::PollTimeout; @@ -38,7 +42,7 @@ const TTY_BUFFER_SIZE: usize = 1_024; pub(crate) struct UnixInternalEventSource { parser: Parser, tty_buffer: [u8; TTY_BUFFER_SIZE], - tty: FileDesc, + tty: FileDesc<'static>, winch_signal_receiver: UnixStream, #[cfg(feature = "event-stream")] wake_pipe: WakePipe, @@ -56,7 +60,7 @@ impl UnixInternalEventSource { UnixInternalEventSource::from_file_descriptor(tty_fd()?) } - pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result { + pub(crate) fn from_file_descriptor(input_fd: FileDesc<'static>) -> io::Result { Ok(UnixInternalEventSource { parser: Parser::default(), tty_buffer: [0u8; TTY_BUFFER_SIZE], @@ -64,7 +68,10 @@ impl UnixInternalEventSource { winch_signal_receiver: { let (receiver, sender) = nonblocking_unix_pair()?; // Unregistering is unnecessary because EventSource is a singleton + #[cfg(feature = "libc")] pipe::register(libc::SIGWINCH, sender)?; + #[cfg(not(feature = "libc"))] + pipe::register(rustix::process::Signal::Winch as i32, sender)?; receiver }, #[cfg(feature = "event-stream")] @@ -157,7 +164,10 @@ impl EventSource for UnixInternalEventSource { } } if fds[1].revents & POLLIN != 0 { + #[cfg(feature = "libc")] let fd = FileDesc::new(self.winch_signal_receiver.as_raw_fd(), false); + #[cfg(not(feature = "libc"))] + let fd = FileDesc::Borrowed(self.winch_signal_receiver.as_fd()); // drain the pipe while read_complete(&fd, &mut [0; 1024])? != 0 {} // TODO Should we remove tput? diff --git a/src/terminal/sys/file_descriptor.rs b/src/terminal/sys/file_descriptor.rs index 3212c484..baff266c 100644 --- a/src/terminal/sys/file_descriptor.rs +++ b/src/terminal/sys/file_descriptor.rs @@ -7,6 +7,7 @@ use rustix::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}; #[cfg(feature = "libc")] use std::{ fs, + marker::PhantomData, os::unix::{ io::{IntoRawFd, RawFd}, prelude::AsRawFd, @@ -19,27 +20,32 @@ use std::{ /// mainly it closes the file descriptor once dropped. #[derive(Debug)] #[cfg(feature = "libc")] -pub struct FileDesc { +pub struct FileDesc<'a> { fd: RawFd, close_on_drop: bool, + phantom: PhantomData<&'a ()>, } #[cfg(not(feature = "libc"))] -pub enum FileDesc { +pub enum FileDesc<'a> { Owned(OwnedFd), - Static(BorrowedFd<'static>), + Borrowed(BorrowedFd<'a>), } #[cfg(feature = "libc")] -impl FileDesc { +impl FileDesc<'_> { /// Constructs a new `FileDesc` with the given `RawFd`. /// /// # Arguments /// /// * `fd` - raw file descriptor /// * `close_on_drop` - specify if the raw file descriptor should be closed once the `FileDesc` is dropped - pub fn new(fd: RawFd, close_on_drop: bool) -> FileDesc { - FileDesc { fd, close_on_drop } + pub fn new(fd: RawFd, close_on_drop: bool) -> FileDesc<'static> { + FileDesc { + fd, + close_on_drop, + phantom: PhantomData, + } } pub fn read(&self, buffer: &mut [u8]) -> io::Result { @@ -65,11 +71,11 @@ impl FileDesc { } #[cfg(not(feature = "libc"))] -impl FileDesc { +impl FileDesc<'_> { pub fn read(&self, buffer: &mut [u8]) -> io::Result { let fd = match self { FileDesc::Owned(fd) => fd.as_fd(), - FileDesc::Static(fd) => fd.as_fd(), + FileDesc::Borrowed(fd) => fd.as_fd(), }; let result = rustix::io::read(fd, buffer)?; Ok(result) @@ -78,13 +84,13 @@ impl FileDesc { pub fn raw_fd(&self) -> RawFd { match self { FileDesc::Owned(fd) => fd.as_raw_fd(), - FileDesc::Static(fd) => fd.as_raw_fd(), + FileDesc::Borrowed(fd) => fd.as_raw_fd(), } } } #[cfg(feature = "libc")] -impl Drop for FileDesc { +impl Drop for FileDesc<'_> { fn drop(&mut self) { if self.close_on_drop { // Note that errors are ignored when closing a file descriptor. The @@ -97,25 +103,25 @@ impl Drop for FileDesc { } } -impl AsRawFd for FileDesc { +impl AsRawFd for FileDesc<'_> { fn as_raw_fd(&self) -> RawFd { self.raw_fd() } } #[cfg(not(feature = "libc"))] -impl AsFd for FileDesc { +impl AsFd for FileDesc<'_> { fn as_fd(&self) -> BorrowedFd<'_> { match self { FileDesc::Owned(fd) => fd.as_fd(), - FileDesc::Static(fd) => fd.as_fd(), + FileDesc::Borrowed(fd) => fd.as_fd(), } } } #[cfg(feature = "libc")] /// Creates a file descriptor pointing to the standard input or `/dev/tty`. -pub fn tty_fd() -> io::Result { +pub fn tty_fd() -> io::Result> { let (fd, close_on_drop) = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } { (libc::STDIN_FILENO, false) } else { @@ -134,12 +140,12 @@ pub fn tty_fd() -> io::Result { #[cfg(not(feature = "libc"))] /// Creates a file descriptor pointing to the standard input or `/dev/tty`. -pub fn tty_fd() -> io::Result { +pub fn tty_fd() -> io::Result> { use std::fs::File; let stdin = rustix::stdio::stdin(); let fd = if rustix::termios::isatty(stdin) { - FileDesc::Static(stdin) + FileDesc::Borrowed(stdin) } else { let dev_tty = File::options().read(true).write(true).open("/dev/tty")?; FileDesc::Owned(dev_tty.into())