diff --git a/Cargo.toml b/Cargo.toml index 4dedf75..5384550 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "charred" -version = "2.1.1" +version = "2.2.0" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/src/error.rs b/src/error.rs index a0902fe..aa69a80 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,4 +9,7 @@ pub enum TapeError { #[error("Unexpected EOF")] EOF, + + #[error("Failed to read char at current index")] + IndexError, } diff --git a/src/input_reader.rs b/src/input_reader.rs index 2ad1acc..e15f2a9 100644 --- a/src/input_reader.rs +++ b/src/input_reader.rs @@ -11,6 +11,7 @@ pub struct InputReader { } impl InputReader { + /// Creates a new Input Reader pub fn new(inner: T) -> Self { Self { inner: Box::new(inner), @@ -22,13 +23,16 @@ impl InputReader { /// Reads the next char consuming it in the process #[inline] pub async fn consume(&mut self) -> TapeResult { - self.read_next().await + self.seek_to(self.index + 1).await?; + + self.read_current().await } /// Returns the next char without forwarding #[inline] pub async fn peek(&mut self) -> TapeResult { - let char = self.read_next().await?; + self.seek_to(self.index + 1).await?; + let char = self.read_current().await?; self.seek_to(self.index - 1).await?; Ok(char) @@ -44,18 +48,10 @@ impl InputReader { } } - /// Reads the next char returning \x00 for EOF - async fn read_next(&mut self) -> TapeResult { - self.seek_to(self.index + 1).await?; - let result = self - .buf - .get(self.index - 1..self.index) - .ok_or(TapeError::EOF)? - .chars() - .next() - .ok_or(TapeError::EOF); - - result + /// Returns the previous char + #[inline] + pub async fn previous(&mut self) -> Option { + self.read_current().await.ok() } /// Seeks to a given index @@ -83,4 +79,20 @@ impl InputReader { pub fn index(&self) -> usize { self.index } + + /// Reads the next char returning \x00 for EOF + async fn read_current(&mut self) -> TapeResult { + if self.index == 0 { + return Err(TapeError::IndexError); + } + let result = self + .buf + .get(self.index - 1..self.index) + .ok_or(TapeError::EOF)? + .chars() + .next() + .ok_or(TapeError::EOF); + + result + } } diff --git a/src/tests/test_input.rs b/src/tests/test_input.rs index 703c43e..1f8331c 100644 --- a/src/tests/test_input.rs +++ b/src/tests/test_input.rs @@ -15,6 +15,17 @@ async fn it_peeks() { assert_eq!(reader.peek().await.unwrap(), 'A'); } +#[tokio::test] +async fn it_reads_the_previous() { + let mut reader = get_reader(); + assert!(reader.previous().await.is_none()); + reader.consume().await.unwrap(); + assert_eq!(reader.previous().await.unwrap(), 'A'); + assert_eq!(reader.previous().await.unwrap(), 'A'); + reader.consume().await.unwrap(); + assert_eq!(reader.previous().await.unwrap(), 'B'); +} + #[tokio::test] async fn it_consumes() { let mut reader = get_reader();