From 4fc328e1dfb79a2cba14f603a5dd175d6029f30f Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 9 Mar 2021 02:50:22 -0500 Subject: add an error type --- Cargo.toml | 1 + examples/async.rs | 2 +- src/blocking/input.rs | 25 +++++++++++-------------- src/blocking/output.rs | 14 ++++++++------ src/error.rs | 10 ++++++++++ src/input.rs | 27 ++++++++++++++------------- src/lib.rs | 2 ++ src/output.rs | 14 ++++++++------ 8 files changed, 55 insertions(+), 40 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index 0ce270f..6fced2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" itoa = "0.4" nix = "0.20" terminal_size = "0.1" +thiserror = "1.0" vt100 = "0.12" blocking = { version = "1.0", optional = true } diff --git a/examples/async.rs b/examples/async.rs index af5ccb5..3ff4c92 100644 --- a/examples/async.rs +++ b/examples/async.rs @@ -1,6 +1,6 @@ use textmode::Textmode as _; -async fn run(tm: &mut textmode::Output) -> std::io::Result<()> { +async fn run(tm: &mut textmode::Output) -> textmode::Result<()> { tm.move_to(5, 5); tm.write_str("foo"); smol::Timer::after(std::time::Duration::from_secs(2)).await; diff --git a/src/blocking/input.rs b/src/blocking/input.rs index 716cfca..ff69eda 100644 --- a/src/blocking/input.rs +++ b/src/blocking/input.rs @@ -1,3 +1,5 @@ +use crate::error::*; + use std::io::Read as _; pub struct Input { @@ -49,7 +51,7 @@ impl Input { self.parse_single = parse; } - pub fn read_key(&mut self) -> std::io::Result> { + pub fn read_key(&mut self) -> Result> { if self.parse_single { self.read_single_key() } else { @@ -105,7 +107,7 @@ impl Input { } } - fn read_single_key(&mut self) -> std::io::Result> { + fn read_single_key(&mut self) -> Result> { match self.getc(true)? { Some(0) => Ok(Some(crate::Key::Byte(0))), Some(c @ 1..=26) => { @@ -148,9 +150,7 @@ impl Input { } } - fn read_escape_sequence( - &mut self, - ) -> std::io::Result> { + fn read_escape_sequence(&mut self) -> Result> { let mut seen = vec![b'\x1b']; macro_rules! fail { @@ -259,10 +259,7 @@ impl Input { } } - fn read_utf8_char( - &mut self, - initial: u8, - ) -> std::io::Result> { + fn read_utf8_char(&mut self, initial: u8) -> Result> { let mut buf = vec![initial]; macro_rules! fail { @@ -314,7 +311,7 @@ impl Input { } } - fn getc(&mut self, fill: bool) -> std::io::Result> { + fn getc(&mut self, fill: bool) -> Result> { if fill { if !self.maybe_fill_buf()? { return Ok(None); @@ -338,7 +335,7 @@ impl Input { } } - fn maybe_fill_buf(&mut self) -> std::io::Result { + fn maybe_fill_buf(&mut self) -> Result { if self.buf_is_empty() { self.fill_buf() } else { @@ -350,7 +347,7 @@ impl Input { self.pos >= self.buf.len() } - fn fill_buf(&mut self) -> std::io::Result { + fn fill_buf(&mut self) -> Result { self.buf.resize(4096, 0); self.pos = 0; let bytes = read_stdin(&mut self.buf)?; @@ -362,6 +359,6 @@ impl Input { } } -fn read_stdin(buf: &mut [u8]) -> std::io::Result { - std::io::stdin().read(buf) +fn read_stdin(buf: &mut [u8]) -> Result { + std::io::stdin().read(buf).map_err(Error::ReadStdin) } diff --git a/src/blocking/output.rs b/src/blocking/output.rs index 3049cac..fa21617 100644 --- a/src/blocking/output.rs +++ b/src/blocking/output.rs @@ -1,3 +1,5 @@ +use crate::error::*; + use std::io::Write as _; use crate::private::TextmodeImpl as _; @@ -7,7 +9,7 @@ pub struct ScreenGuard { } impl ScreenGuard { - pub fn cleanup(&mut self) -> std::io::Result<()> { + pub fn cleanup(&mut self) -> Result<()> { if self.cleaned_up { return Ok(()); } @@ -48,7 +50,7 @@ impl crate::private::TextmodeImpl for Output { impl crate::Textmode for Output {} impl Output { - pub fn new() -> std::io::Result<(Self, ScreenGuard)> { + pub fn new() -> Result<(Self, ScreenGuard)> { write_stdout(crate::INIT)?; Ok(( Self::new_without_screen(), @@ -69,7 +71,7 @@ impl Output { Self { cur, next } } - pub fn refresh(&mut self) -> std::io::Result<()> { + pub fn refresh(&mut self) -> Result<()> { let diffs = &[ self.next().screen().contents_diff(self.cur().screen()), self.next().screen().input_mode_diff(self.cur().screen()), @@ -84,9 +86,9 @@ impl Output { } } -fn write_stdout(buf: &[u8]) -> std::io::Result<()> { +fn write_stdout(buf: &[u8]) -> Result<()> { let mut stdout = std::io::stdout(); - stdout.write_all(buf)?; - stdout.flush()?; + stdout.write_all(buf).map_err(Error::WriteStdout)?; + stdout.flush().map_err(Error::WriteStdout)?; Ok(()) } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..560f5cb --- /dev/null +++ b/src/error.rs @@ -0,0 +1,10 @@ +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("error reading from stdin")] + ReadStdin(#[source] std::io::Error), + + #[error("error writing to stdout")] + WriteStdout(#[source] std::io::Error), +} + +pub type Result = std::result::Result; diff --git a/src/input.rs b/src/input.rs index cb4d0a0..8bd3b60 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,3 +1,5 @@ +use crate::error::*; + use futures_lite::io::AsyncReadExt as _; pub struct Input { @@ -49,7 +51,7 @@ impl Input { self.parse_single = parse; } - pub async fn read_key(&mut self) -> std::io::Result> { + pub async fn read_key(&mut self) -> Result> { if self.parse_single { self.read_single_key().await } else { @@ -105,9 +107,7 @@ impl Input { } } - async fn read_single_key( - &mut self, - ) -> std::io::Result> { + async fn read_single_key(&mut self) -> Result> { match self.getc(true).await? { Some(0) => Ok(Some(crate::Key::Byte(0))), Some(c @ 1..=26) => { @@ -150,9 +150,7 @@ impl Input { } } - async fn read_escape_sequence( - &mut self, - ) -> std::io::Result> { + async fn read_escape_sequence(&mut self) -> Result> { let mut seen = vec![b'\x1b']; macro_rules! fail { @@ -264,7 +262,7 @@ impl Input { async fn read_utf8_char( &mut self, initial: u8, - ) -> std::io::Result> { + ) -> Result> { let mut buf = vec![initial]; macro_rules! fail { @@ -316,7 +314,7 @@ impl Input { } } - async fn getc(&mut self, fill: bool) -> std::io::Result> { + async fn getc(&mut self, fill: bool) -> Result> { if fill { if !self.maybe_fill_buf().await? { return Ok(None); @@ -340,7 +338,7 @@ impl Input { } } - async fn maybe_fill_buf(&mut self) -> std::io::Result { + async fn maybe_fill_buf(&mut self) -> Result { if self.buf_is_empty() { self.fill_buf().await } else { @@ -352,7 +350,7 @@ impl Input { self.pos >= self.buf.len() } - async fn fill_buf(&mut self) -> std::io::Result { + async fn fill_buf(&mut self) -> Result { self.buf.resize(4096, 0); self.pos = 0; let bytes = read_stdin(&mut self.buf).await?; @@ -364,6 +362,9 @@ impl Input { } } -async fn read_stdin(buf: &mut [u8]) -> std::io::Result { - blocking::Unblock::new(std::io::stdin()).read(buf).await +async fn read_stdin(buf: &mut [u8]) -> Result { + blocking::Unblock::new(std::io::stdin()) + .read(buf) + .await + .map_err(Error::ReadStdin) } diff --git a/src/lib.rs b/src/lib.rs index 5fc2429..41561b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ pub mod blocking; pub mod color; +pub mod error; +pub use error::{Error, Result}; mod key; pub use key::Key; mod raw_guard; diff --git a/src/output.rs b/src/output.rs index 9e8c220..52495d0 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,3 +1,5 @@ +use crate::error::*; + use futures_lite::io::AsyncWriteExt as _; use super::private::TextmodeImpl as _; @@ -7,7 +9,7 @@ pub struct ScreenGuard { } impl ScreenGuard { - pub async fn cleanup(&mut self) -> std::io::Result<()> { + pub async fn cleanup(&mut self) -> Result<()> { if self.cleaned_up { return Ok(()); } @@ -50,7 +52,7 @@ impl super::private::TextmodeImpl for Output { impl super::Textmode for Output {} impl Output { - pub async fn new() -> std::io::Result<(Self, ScreenGuard)> { + pub async fn new() -> Result<(Self, ScreenGuard)> { write_stdout(super::INIT).await?; Ok(( @@ -71,7 +73,7 @@ impl Output { Self { cur, next } } - pub async fn refresh(&mut self) -> std::io::Result<()> { + pub async fn refresh(&mut self) -> Result<()> { let diffs = &[ self.next().screen().contents_diff(self.cur().screen()), self.next().screen().input_mode_diff(self.cur().screen()), @@ -86,9 +88,9 @@ impl Output { } } -async fn write_stdout(buf: &[u8]) -> std::io::Result<()> { +async fn write_stdout(buf: &[u8]) -> Result<()> { let mut stdout = blocking::Unblock::new(std::io::stdout()); - stdout.write_all(buf).await?; - stdout.flush().await?; + stdout.write_all(buf).await.map_err(Error::WriteStdout)?; + stdout.flush().await.map_err(Error::WriteStdout)?; Ok(()) } -- cgit v1.2.3