use async_trait::async_trait;
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Context;
pub type Error = std::io::Error;
pub type Result = std::result::Result<String, Error>;
#[async_trait(?Send)]
pub trait Input {
async fn next_line(&mut self, context: &Context) -> Result;
}
pub struct Memory<'a> {
lines: std::str::SplitInclusive<'a, char>,
}
impl Memory<'_> {
pub fn new(code: &str) -> Memory<'_> {
let lines = code.split_inclusive('\n');
Memory { lines }
}
}
#[async_trait(?Send)]
impl Input for Memory<'_> {
async fn next_line(&mut self, _context: &Context) -> Result {
Ok(self.lines.next().unwrap_or("").to_owned())
}
}
#[cfg(test)]
mod tests {
use super::*;
use futures_executor::block_on;
#[test]
fn memory_empty_source() {
let mut input = Memory::new("");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "");
}
#[test]
fn memory_one_line() {
let mut input = Memory::new("one\n");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "one\n");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "");
}
#[test]
fn memory_three_lines() {
let mut input = Memory::new("one\ntwo\nthree");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "one\n");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "two\n");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "three");
let line = block_on(input.next_line(&Context)).unwrap();
assert_eq!(line, "");
}
}