crossterm::ErrorKind to io::Error (#553)

This commit is contained in:
Plecra 2021-04-13 07:46:51 +01:00 committed by GitHub
parent 174de58b69
commit 58f580eaad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 58 additions and 131 deletions

View File

@ -46,8 +46,7 @@ fn read_position_raw() -> Result<(u16, u16)> {
return Err(Error::new( return Err(Error::new(
ErrorKind::Other, ErrorKind::Other,
"The cursor position could not be read within a normal duration", "The cursor position could not be read within a normal duration",
) ));
.into());
} }
Err(_) => {} Err(_) => {}
} }

View File

@ -138,8 +138,7 @@ impl ScreenBufferCursor {
"Argument Out of Range Exception when setting cursor position to X: {}", "Argument Out of Range Exception when setting cursor position to X: {}",
x x
), ),
) ));
.into());
} }
if y < 0 { if y < 0 {
@ -149,8 +148,7 @@ impl ScreenBufferCursor {
"Argument Out of Range Exception when setting cursor position to Y: {}", "Argument Out of Range Exception when setting cursor position to Y: {}",
y y
), ),
) ));
.into());
} }
let position = COORD { X: x, Y: y }; let position = COORD { X: x, Y: y };
@ -160,7 +158,7 @@ impl ScreenBufferCursor {
**self.screen_buffer.handle(), **self.screen_buffer.handle(),
position, position,
)) { )) {
return Err(io::Error::last_os_error().into()); return Err(io::Error::last_os_error());
} }
} }
Ok(()) Ok(())
@ -177,7 +175,7 @@ impl ScreenBufferCursor {
**self.screen_buffer.handle(), **self.screen_buffer.handle(),
&cursor_info, &cursor_info,
)) { )) {
return Err(io::Error::last_os_error().into()); return Err(io::Error::last_os_error());
} }
} }
Ok(()) Ok(())

View File

@ -1,50 +1,8 @@
//! Module containing error handling logic. //! Module containing error handling logic.
use std::{ use std::io;
fmt::{self, Display, Formatter},
io,
};
use crate::impl_from;
/// The `crossterm` result type. /// The `crossterm` result type.
pub type Result<T> = std::result::Result<T, ErrorKind>; pub type Result<T> = std::result::Result<T, ErrorKind>;
/// Wrapper for all errors that can occur in `crossterm`. pub type ErrorKind = io::Error;
#[derive(Debug)]
#[non_exhaustive]
pub enum ErrorKind {
IoError(io::Error),
FmtError(fmt::Error),
Utf8Error(std::string::FromUtf8Error),
ParseIntError(std::num::ParseIntError),
ResizingTerminalFailure(String),
SettingTerminalTitleFailure,
}
impl std::error::Error for ErrorKind {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ErrorKind::IoError(e) => Some(e),
ErrorKind::FmtError(e) => Some(e),
ErrorKind::Utf8Error(e) => Some(e),
ErrorKind::ParseIntError(e) => Some(e),
_ => None,
}
}
}
impl Display for ErrorKind {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match *self {
ErrorKind::IoError(_) => write!(fmt, "IO-error occurred"),
ErrorKind::ResizingTerminalFailure(_) => write!(fmt, "Cannot resize the terminal"),
_ => write!(fmt, "Some error has occurred"),
}
}
}
impl_from!(io::Error, ErrorKind::IoError);
impl_from!(fmt::Error, ErrorKind::FmtError);
impl_from!(std::string::FromUtf8Error, ErrorKind::Utf8Error);
impl_from!(std::num::ParseIntError, ErrorKind::ParseIntError);

View File

@ -7,9 +7,6 @@ use super::source::windows::WindowsEventSource;
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
use super::sys::Waker; use super::sys::Waker;
use super::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent, Result}; use super::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent, Result};
use crate::ErrorKind;
/// Can be used to read `InternalEvent`s. /// Can be used to read `InternalEvent`s.
pub(crate) struct InternalEventReader { pub(crate) struct InternalEventReader {
events: VecDeque<InternalEvent>, events: VecDeque<InternalEvent>,
@ -57,8 +54,7 @@ impl InternalEventReader {
return Err(std::io::Error::new( return Err(std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
"Failed to initialize input reader", "Failed to initialize input reader",
) ))
.into())
} }
}; };
@ -75,14 +71,13 @@ impl InternalEventReader {
None None
} }
} }
Err(ErrorKind::IoError(e)) => { Err(e) => {
if e.kind() == io::ErrorKind::Interrupted { if e.kind() == io::ErrorKind::Interrupted {
return Ok(false); return Ok(false);
} }
return Err(ErrorKind::IoError(e)); return Err(e);
} }
Err(e) => return Err(e),
}; };
if poll_timeout.elapsed() || maybe_event.is_some() { if poll_timeout.elapsed() || maybe_event.is_some() {
@ -131,6 +126,7 @@ impl InternalEventReader {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::io;
use std::{collections::VecDeque, time::Duration}; use std::{collections::VecDeque, time::Duration};
use crate::ErrorKind; use crate::ErrorKind;
@ -314,7 +310,7 @@ mod tests {
#[test] #[test]
fn test_poll_propagates_error() { fn test_poll_propagates_error() {
let source = FakeSource::with_error(ErrorKind::ResizingTerminalFailure("Foo".to_string())); let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
@ -327,16 +323,13 @@ mod tests {
.poll(Some(Duration::from_secs(0)), &InternalEventFilter) .poll(Some(Duration::from_secs(0)), &InternalEventFilter)
.err() .err()
.map(|e| format!("{:?}", &e)), .map(|e| format!("{:?}", &e)),
Some(format!( Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other)))
"{:?}",
ErrorKind::ResizingTerminalFailure("Foo".to_string())
))
); );
} }
#[test] #[test]
fn test_read_propagates_error() { fn test_read_propagates_error() {
let source = FakeSource::with_error(ErrorKind::ResizingTerminalFailure("Foo".to_string())); let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
@ -349,10 +342,7 @@ mod tests {
.read(&InternalEventFilter) .read(&InternalEventFilter)
.err() .err()
.map(|e| format!("{:?}", &e)), .map(|e| format!("{:?}", &e)),
Some(format!( Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other)))
"{:?}",
ErrorKind::ResizingTerminalFailure("Foo".to_string())
))
); );
} }
@ -360,10 +350,7 @@ mod tests {
fn test_poll_continues_after_error() { fn test_poll_continues_after_error() {
const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10)); const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10));
let source = FakeSource::new( let source = FakeSource::new(&[EVENT, EVENT], ErrorKind::from(io::ErrorKind::Other));
&[EVENT, EVENT],
ErrorKind::ResizingTerminalFailure("Foo".to_string()),
);
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
@ -382,10 +369,7 @@ mod tests {
fn test_read_continues_after_error() { fn test_read_continues_after_error() {
const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10)); const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10));
let source = FakeSource::new( let source = FakeSource::new(&[EVENT, EVENT], ErrorKind::from(io::ErrorKind::Other));
&[EVENT, EVENT],
ErrorKind::ResizingTerminalFailure("Foo".to_string()),
);
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),

View File

@ -3,7 +3,7 @@ use std::{collections::VecDeque, io, time::Duration};
use mio::{unix::SourceFd, Events, Interest, Poll, Token}; use mio::{unix::SourceFd, Events, Interest, Poll, Token};
use signal_hook::iterator::Signals; use signal_hook::iterator::Signals;
use crate::{ErrorKind, Result}; use crate::Result;
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
use super::super::sys::Waker; use super::super::sys::Waker;
@ -87,7 +87,7 @@ impl EventSource for UnixInternalEventSource {
if e.kind() == io::ErrorKind::Interrupted { if e.kind() == io::ErrorKind::Interrupted {
continue; continue;
} else { } else {
return Err(ErrorKind::IoError(e)); return Err(e);
} }
}; };
@ -109,7 +109,7 @@ impl EventSource for UnixInternalEventSource {
); );
} }
} }
Err(ErrorKind::IoError(e)) => { Err(e) => {
// No more data to read at the moment. We will receive another event // No more data to read at the moment. We will receive another event
if e.kind() == io::ErrorKind::WouldBlock { if e.kind() == io::ErrorKind::WouldBlock {
break; break;
@ -119,7 +119,6 @@ impl EventSource for UnixInternalEventSource {
continue; continue;
} }
} }
Err(e) => return Err(e),
}; };
if let Some(event) = self.parser.next() { if let Some(event) = self.parser.next() {

View File

@ -5,7 +5,7 @@ use std::{
use libc::size_t; use libc::size_t;
use crate::{ErrorKind, Result}; use crate::Result;
/// A file descriptor wrapper. /// A file descriptor wrapper.
/// ///
@ -38,7 +38,7 @@ impl FileDesc {
}; };
if result < 0 { if result < 0 {
Err(ErrorKind::IoError(io::Error::last_os_error())) Err(io::Error::last_os_error())
} else { } else {
Ok(result as usize) Ok(result as usize)
} }

View File

@ -20,10 +20,7 @@ use super::super::super::InternalEvent;
// //
fn could_not_parse_event_error() -> ErrorKind { fn could_not_parse_event_error() -> ErrorKind {
ErrorKind::IoError(io::Error::new( io::Error::new(io::ErrorKind::Other, "Could not parse an event.")
io::ErrorKind::Other,
"Could not parse an event.",
))
} }
pub(crate) fn parse_event(buffer: &[u8], input_available: bool) -> Result<Option<InternalEvent>> { pub(crate) fn parse_event(buffer: &[u8], input_available: bool) -> Result<Option<InternalEvent>> {

View File

@ -74,12 +74,11 @@ impl WinApiPoll {
// timeout elapsed // timeout elapsed
Ok(None) Ok(None)
} }
WAIT_FAILED => Err(io::Error::last_os_error().into()), WAIT_FAILED => Err(io::Error::last_os_error()),
_ => Err(io::Error::new( _ => Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"WaitForMultipleObjects returned unexpected result.", "WaitForMultipleObjects returned unexpected result.",
) )),
.into()),
} }
} }

View File

@ -117,7 +117,7 @@ macro_rules! execute {
// Queue each command, then flush // Queue each command, then flush
$crate::queue!($writer $(, $command)*) $crate::queue!($writer $(, $command)*)
.and_then(|()| { .and_then(|()| {
::std::io::Write::flush($writer.by_ref()).map_err($crate::ErrorKind::IoError) ::std::io::Write::flush($writer.by_ref())
}) })
}} }}
} }

View File

@ -10,7 +10,7 @@ use libc::{
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use crate::error::{ErrorKind, Result}; use crate::error::Result;
use crate::event::sys::unix::file_descriptor::{tty_fd, FileDesc}; use crate::event::sys::unix::file_descriptor::{tty_fd, FileDesc};
// Some(Termios) -> we're in the raw mode and this is the previous mode // Some(Termios) -> we're in the raw mode and this is the previous mode
@ -129,7 +129,7 @@ fn set_terminal_attr(fd: RawFd, termios: &Termios) -> Result<()> {
fn wrap_with_result(result: i32) -> Result<()> { fn wrap_with_result(result: i32) -> Result<()> {
if result == -1 { if result == -1 {
Err(ErrorKind::IoError(io::Error::last_os_error())) Err(io::Error::last_os_error())
} else { } else {
Ok(()) Ok(())
} }

View File

@ -1,6 +1,7 @@
//! WinAPI related logic for terminal manipulation. //! WinAPI related logic for terminal manipulation.
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::io;
use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size}; use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size};
use winapi::{ use winapi::{
@ -99,15 +100,17 @@ pub(crate) fn scroll_down(row_count: u16) -> Result<()> {
pub(crate) fn set_size(width: u16, height: u16) -> Result<()> { pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
if width <= 1 { if width <= 1 {
return Err(ErrorKind::ResizingTerminalFailure(String::from( return Err(ErrorKind::new(
"Cannot set the terminal width lower than 1.", io::ErrorKind::InvalidInput,
))); "terminal width must be at least 1",
));
} }
if height <= 1 { if height <= 1 {
return Err(ErrorKind::ResizingTerminalFailure(String::from( return Err(ErrorKind::new(
"Cannot set the terminal height lower then 1.", io::ErrorKind::InvalidInput,
))); "terminal height must be at least 1",
));
} }
// get the position of the current console window // get the position of the current console window
@ -127,9 +130,10 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
let width = width as i16; let width = width as i16;
if current_size.width < window.left + width { if current_size.width < window.left + width {
if window.left >= i16::max_value() - width { if window.left >= i16::max_value() - width {
return Err(ErrorKind::ResizingTerminalFailure(String::from( return Err(ErrorKind::new(
"Argument out of range when setting terminal width.", io::ErrorKind::InvalidInput,
))); "terminal width too large",
));
} }
new_size.width = window.left + width; new_size.width = window.left + width;
@ -138,23 +142,18 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
let height = height as i16; let height = height as i16;
if current_size.height < window.top + height { if current_size.height < window.top + height {
if window.top >= i16::max_value() - height { if window.top >= i16::max_value() - height {
return Err(ErrorKind::ResizingTerminalFailure(String::from( return Err(ErrorKind::new(
"Argument out of range when setting terminal height.", io::ErrorKind::InvalidInput,
))); "terminal height too large",
));
} }
new_size.height = window.top + height; new_size.height = window.top + height;
resize_buffer = true; resize_buffer = true;
} }
if resize_buffer if resize_buffer {
&& screen_buffer screen_buffer.set_size(new_size.width - 1, new_size.height - 1)?;
.set_size(new_size.width - 1, new_size.height - 1)
.is_err()
{
return Err(ErrorKind::ResizingTerminalFailure(String::from(
"Something went wrong when setting screen buffer size.",
)));
} }
let mut window = window; let mut window = window;
@ -165,29 +164,23 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
console.set_console_info(true, window)?; console.set_console_info(true, window)?;
// if we resized the buffer, un-resize it. // if we resized the buffer, un-resize it.
if resize_buffer if resize_buffer {
&& screen_buffer screen_buffer.set_size(current_size.width - 1, current_size.height - 1)?;
.set_size(current_size.width - 1, current_size.height - 1)
.is_err()
{
return Err(ErrorKind::ResizingTerminalFailure(String::from(
"Something went wrong when setting screen buffer size.",
)));
} }
let bounds = console.largest_window_size(); let bounds = console.largest_window_size();
if width > bounds.x { if width > bounds.x {
return Err(ErrorKind::ResizingTerminalFailure(format!( return Err(ErrorKind::new(
"Argument width: {} out of range when setting terminal width.", io::ErrorKind::InvalidInput,
width format!("terminal width {} too large", width),
))); ));
} }
if height > bounds.y { if height > bounds.y {
return Err(ErrorKind::ResizingTerminalFailure(format!( return Err(ErrorKind::new(
"Argument height: {} out of range when setting terminal height.", io::ErrorKind::InvalidInput,
width format!("terminal height {} too large", height),
))); ));
} }
Ok(()) Ok(())
@ -211,7 +204,7 @@ pub(crate) fn set_window_title(title: impl fmt::Display) -> Result<()> {
if result != 0 { if result != 0 {
Ok(()) Ok(())
} else { } else {
Err(ErrorKind::SettingTerminalTitleFailure) Err(ErrorKind::last_os_error())
} }
} }